diff --git a/core/java/android/app/timedetector/TimeDetectorHelper.java b/core/java/android/app/timedetector/TimeDetectorHelper.java
new file mode 100644
index 0000000000000..8752ee07067a6
--- /dev/null
+++ b/core/java/android/app/timedetector/TimeDetectorHelper.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.timedetector;
+
+import android.annotation.NonNull;
+import android.os.Build;
+
+import java.time.Instant;
+
+/**
+ * A utility class for fundamental time detector-related logic that doesn't need to communicate with
+ * the time detector service, i.e. because it can use SDK APIs or hard-coded facts, and doesn't need
+ * permissions or singleton state. Putting logic here avoids the need to expose binder-based calls
+ * or to duplicate code to share related logic (since android.app.timedetector classes are visible
+ * to all processes).
+ *
+ * @hide
+ */
+// Not final for easy replacement / mocking during tests.
+public class TimeDetectorHelper {
+
+ /**
+ * See {@link #getManualDateSelectionYearMin()}. Chosen to produce Unix epoch times be greater
+ * than {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+ */
+ private static final int MANUAL_SUGGESTION_YEAR_MIN = 2008;
+
+ /**
+ * The maximum gregorian calendar year to allow for manual date selection on devices unlikely to
+ * have Y2038 issues. This serves as a sensible UI-enforced limit though the system server may
+ * support a larger upper bound. Users besides future archeologists are unlikely to need higher
+ * values, for a few years at least.
+ */
+ private static final int MANUAL_SUGGESTION_YEAR_MAX_WITHOUT_Y2038_ISSUE = 2100;
+
+ /**
+ * The maximum gregorian calendar year to allow for manual date selection on devices that may
+ * have Y2038 issues. This serves as a sensible UI-enforced limit though the system server may
+ * support a larger upper bound. That is, the signed 32-bit milliseconds value is
+ * 03:14:07 UTC on 19 January 2038, but this constant means users can only enter dates up to
+ * 2037-12-31. See {@link #MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE}.
+ *
+ *
Note: This UI limit also doesn't prevent devices reaching the Y2038 roll-over time through
+ * the natural passage of time, it just prevents users potentially causing issues in the years
+ * leading up to it accidentally via the UI.
+ */
+ private static final int MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE = 2037;
+
+ /**
+ * The upper bound for valid suggestions when the Y2038 issue is a risk. This is the instant
+ * when the Y2038 issue occurs.
+ */
+ private static final Instant SUGGESTION_UPPER_BOUND_WITH_Y2038_ISSUE =
+ Instant.ofEpochMilli(1000L * Integer.MAX_VALUE);
+
+ /**
+ * The upper bound for valid suggestions when the Y2038 issue is not a risk. This values means
+ * there is no practical upper bound.
+ *
+ *
Make sure this value remains in the value representable as a signed int64 Unix epoch
+ * millis value as in various places {@link Instant#toEpochMilli()} is called, and that throws
+ * an exception if the value is too large.
+ */
+ private static final Instant SUGGESTION_UPPER_BOUND_WIITHOUT_Y2038_ISSUE =
+ Instant.ofEpochMilli(Long.MAX_VALUE);
+
+ /** See {@link #getManualSuggestionLowerBound()}. */
+ private static final Instant MANUAL_SUGGESTION_LOWER_BOUND =
+ Instant.ofEpochMilli(1194220800000L); // Nov 5, 2007, 0:00 UTC
+
+ /**
+ * The lowest value in Unix epoch milliseconds that is considered a valid automatic suggestion.
+ * See also {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+ *
+ *
Note that this is a default value. The lower value enforced can be overridden to be
+ * lower in the system server with flags for testing.
+ */
+ private static final Instant AUTO_SUGGESTION_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
+ Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
+
+ /** The singleton instance of this class. */
+ public static final TimeDetectorHelper INSTANCE = new TimeDetectorHelper();
+
+ /** Constructor present for subclassing in tests. Use {@link #INSTANCE} in production code. */
+ protected TimeDetectorHelper() {}
+
+ /**
+ * Returns the minimum gregorian calendar year to offer for manual date selection. This serves
+ * as a sensible UI-enforced lower limit, the system server may support a smaller lower bound.
+ */
+ public int getManualDateSelectionYearMin() {
+ return MANUAL_SUGGESTION_YEAR_MIN;
+ }
+
+ /**
+ * Returns the maximum gregorian calendar year to offer for manual date selection. This serves
+ * as a sensible UI-enforced lower limit, the system server may support a larger upper bound.
+ */
+ public int getManualDateSelectionYearMax() {
+ return getDeviceHasY2038Issue()
+ ? MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE
+ : MANUAL_SUGGESTION_YEAR_MAX_WITHOUT_Y2038_ISSUE;
+ }
+
+ /**
+ * Returns the lowest value in Unix epoch milliseconds that is considered a valid manual
+ * suggestion. For historical reasons Android has a different lower limit for manual input than
+ * automatic. This may change in the future to align with automatic suggestions, but has been
+ * kept initially to avoid breaking manual tests that are hard-coded with old dates real users
+ * will never want to use.
+ */
+ @NonNull
+ public Instant getManualSuggestionLowerBound() {
+ return MANUAL_SUGGESTION_LOWER_BOUND;
+ }
+
+ /**
+ * Returns the lowest value in Unix epoch milliseconds that is considered a valid automatic
+ * suggestion. See also {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+ *
+ *
Note that this is a default value. The lower value enforced can be overridden to be
+ * different in the system server with server flags.
+ */
+ @NonNull
+ public Instant getAutoSuggestionLowerBoundDefault() {
+ return AUTO_SUGGESTION_LOWER_BOUND_DEFAULT;
+ }
+
+ /** Returns the upper bound to enforce for all time suggestions (manual and automatic). */
+ @NonNull
+ public Instant getSuggestionUpperBound() {
+ return getDeviceHasY2038Issue()
+ ? SUGGESTION_UPPER_BOUND_WITH_Y2038_ISSUE
+ : SUGGESTION_UPPER_BOUND_WIITHOUT_Y2038_ISSUE;
+ }
+
+ /**
+ * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
+ * defines time_t as a 32-bit signed integer for 32-bit processes).
+ */
+ private boolean getDeviceHasY2038Issue() {
+ return Build.SUPPORTED_32_BIT_ABIS.length > 0;
+ }
+}
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index 683eaeb961b04..372bcc6b07cae 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -46,9 +46,10 @@ public final class ConfigurationInternal {
private final boolean mAutoDetectionSupported;
private final int mSystemClockUpdateThresholdMillis;
- private final Instant mAutoTimeLowerBound;
+ private final Instant mAutoSuggestionLowerBound;
+ private final Instant mManualSuggestionLowerBound;
+ private final Instant mSuggestionUpperBound;
private final @Origin int[] mOriginPriorities;
- private final boolean mDeviceHasY2038Issue;
private final boolean mAutoDetectionEnabledSetting;
private final @UserIdInt int mUserId;
private final boolean mUserConfigAllowed;
@@ -56,9 +57,10 @@ public final class ConfigurationInternal {
private ConfigurationInternal(Builder builder) {
mAutoDetectionSupported = builder.mAutoDetectionSupported;
mSystemClockUpdateThresholdMillis = builder.mSystemClockUpdateThresholdMillis;
- mAutoTimeLowerBound = Objects.requireNonNull(builder.mAutoTimeLowerBound);
+ mAutoSuggestionLowerBound = Objects.requireNonNull(builder.mAutoSuggestionLowerBound);
+ mManualSuggestionLowerBound = Objects.requireNonNull(builder.mManualSuggestionLowerBound);
+ mSuggestionUpperBound = Objects.requireNonNull(builder.mSuggestionUpperBound);
mOriginPriorities = Objects.requireNonNull(builder.mOriginPriorities);
- mDeviceHasY2038Issue = builder.mDeviceHasY2038Issue;
mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;
mUserId = builder.mUserId;
@@ -80,14 +82,31 @@ public final class ConfigurationInternal {
}
/**
- * Returns the lower bound for valid automatic times. It is guaranteed to be in the past,
- * i.e. it is unrelated to the current system clock time.
+ * Returns the lower bound for valid automatic time suggestions. It is guaranteed to be in the
+ * past, i.e. it is unrelated to the current system clock time.
* It holds no other meaning; it could be related to when the device system image was built,
* or could be updated by a mainline module.
*/
@NonNull
- public Instant getAutoTimeLowerBound() {
- return mAutoTimeLowerBound;
+ public Instant getAutoSuggestionLowerBound() {
+ return mAutoSuggestionLowerBound;
+ }
+
+ /**
+ * Returns the lower bound for valid manual time suggestions. It is guaranteed to be in the
+ * past, i.e. it is unrelated to the current system clock time.
+ */
+ @NonNull
+ public Instant getManualSuggestionLowerBound() {
+ return mManualSuggestionLowerBound;
+ }
+
+ /**
+ * Returns the upper bound for valid time suggestions (manual and automatic).
+ */
+ @NonNull
+ public Instant getSuggestionUpperBound() {
+ return mSuggestionUpperBound;
}
/**
@@ -98,14 +117,6 @@ public final class ConfigurationInternal {
return mOriginPriorities;
}
- /**
- * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
- * defines time_t as a 32-bit signed integer for 32-bit processes).
- */
- public boolean getDeviceHasY2038Issue() {
- return mDeviceHasY2038Issue;
- }
-
/** Returns the value of the auto time detection enabled setting. */
public boolean getAutoDetectionEnabledSetting() {
return mAutoDetectionEnabledSetting;
@@ -207,16 +218,17 @@ public final class ConfigurationInternal {
&& mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
&& mUserId == that.mUserId && mUserConfigAllowed == that.mUserConfigAllowed
&& mSystemClockUpdateThresholdMillis == that.mSystemClockUpdateThresholdMillis
- && mAutoTimeLowerBound.equals(that.mAutoTimeLowerBound)
- && mDeviceHasY2038Issue == that.mDeviceHasY2038Issue
+ && mAutoSuggestionLowerBound.equals(that.mAutoSuggestionLowerBound)
+ && mManualSuggestionLowerBound.equals(that.mManualSuggestionLowerBound)
+ && mSuggestionUpperBound.equals(that.mSuggestionUpperBound)
&& Arrays.equals(mOriginPriorities, that.mOriginPriorities);
}
@Override
public int hashCode() {
int result = Objects.hash(mAutoDetectionSupported, mAutoDetectionEnabledSetting, mUserId,
- mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoTimeLowerBound,
- mDeviceHasY2038Issue);
+ mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoSuggestionLowerBound,
+ mManualSuggestionLowerBound, mSuggestionUpperBound);
result = 31 * result + Arrays.hashCode(mOriginPriorities);
return result;
}
@@ -230,10 +242,13 @@ public final class ConfigurationInternal {
return "ConfigurationInternal{"
+ "mAutoDetectionSupported=" + mAutoDetectionSupported
+ ", mSystemClockUpdateThresholdMillis=" + mSystemClockUpdateThresholdMillis
- + ", mAutoTimeLowerBound=" + mAutoTimeLowerBound
- + "(" + mAutoTimeLowerBound.toEpochMilli() + ")"
+ + ", mAutoSuggestionLowerBound=" + mAutoSuggestionLowerBound
+ + "(" + mAutoSuggestionLowerBound.toEpochMilli() + ")"
+ + ", mManualSuggestionLowerBound=" + mManualSuggestionLowerBound
+ + "(" + mManualSuggestionLowerBound.toEpochMilli() + ")"
+ + ", mSuggestionUpperBound=" + mSuggestionUpperBound
+ + "(" + mSuggestionUpperBound.toEpochMilli() + ")"
+ ", mOriginPriorities=" + originPrioritiesString
- + ", mDeviceHasY2038Issue=" + mDeviceHasY2038Issue
+ ", mAutoDetectionEnabled=" + mAutoDetectionEnabledSetting
+ ", mUserId=" + mUserId
+ ", mUserConfigAllowed=" + mUserConfigAllowed
@@ -243,9 +258,10 @@ public final class ConfigurationInternal {
static final class Builder {
private boolean mAutoDetectionSupported;
private int mSystemClockUpdateThresholdMillis;
- @NonNull private Instant mAutoTimeLowerBound;
+ @NonNull private Instant mAutoSuggestionLowerBound;
+ @NonNull private Instant mManualSuggestionLowerBound;
+ @NonNull private Instant mSuggestionUpperBound;
@NonNull private @Origin int[] mOriginPriorities;
- private boolean mDeviceHasY2038Issue;
private boolean mAutoDetectionEnabledSetting;
private final @UserIdInt int mUserId;
@@ -263,9 +279,10 @@ public final class ConfigurationInternal {
this.mUserConfigAllowed = toCopy.mUserConfigAllowed;
this.mAutoDetectionSupported = toCopy.mAutoDetectionSupported;
this.mSystemClockUpdateThresholdMillis = toCopy.mSystemClockUpdateThresholdMillis;
- this.mAutoTimeLowerBound = toCopy.mAutoTimeLowerBound;
+ this.mAutoSuggestionLowerBound = toCopy.mAutoSuggestionLowerBound;
+ this.mManualSuggestionLowerBound = toCopy.mManualSuggestionLowerBound;
+ this.mSuggestionUpperBound = toCopy.mSuggestionUpperBound;
this.mOriginPriorities = toCopy.mOriginPriorities;
- this.mDeviceHasY2038Issue = toCopy.mDeviceHasY2038Issue;
this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
}
@@ -296,10 +313,26 @@ public final class ConfigurationInternal {
}
/**
- * Sets the lower bound for valid automatic times.
+ * Sets the lower bound for valid automatic time suggestions.
*/
- public Builder setAutoTimeLowerBound(@NonNull Instant autoTimeLowerBound) {
- mAutoTimeLowerBound = Objects.requireNonNull(autoTimeLowerBound);
+ public Builder setAutoSuggestionLowerBound(@NonNull Instant autoSuggestionLowerBound) {
+ mAutoSuggestionLowerBound = Objects.requireNonNull(autoSuggestionLowerBound);
+ return this;
+ }
+
+ /**
+ * Sets the lower bound for valid manual time suggestions.
+ */
+ public Builder setManualSuggestionLowerBound(@NonNull Instant manualSuggestionLowerBound) {
+ mManualSuggestionLowerBound = Objects.requireNonNull(manualSuggestionLowerBound);
+ return this;
+ }
+
+ /**
+ * Sets the upper bound for valid time suggestions (manual and automatic).
+ */
+ public Builder setSuggestionUpperBound(@NonNull Instant suggestionUpperBound) {
+ mSuggestionUpperBound = Objects.requireNonNull(suggestionUpperBound);
return this;
}
@@ -320,15 +353,6 @@ public final class ConfigurationInternal {
return this;
}
- /**
- * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
- * defines time_t as a 32-bit signed integer for 32-bit processes).
- */
- Builder setDeviceHasY2038Issue(boolean deviceHasY2038Issue) {
- mDeviceHasY2038Issue = deviceHasY2038Issue;
- return this;
- }
-
/** Returns a new {@link ConfigurationInternal}. */
@NonNull
ConfigurationInternal build() {
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index e4f3a80c03b5c..888304aa199b2 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -31,6 +31,7 @@ import android.app.ActivityManagerInternal;
import android.app.time.TimeCapabilities;
import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
+import android.app.timedetector.TimeDetectorHelper;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,7 +39,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
-import android.os.Build;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -74,13 +74,6 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
private static final @Origin int[]
DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
- /**
- * Time in the past. If an automatic time suggestion is before this point, it is sure to be
- * incorrect.
- */
- private static final Instant TIME_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
- Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
-
/** Device config keys that affect the {@link TimeDetectorService}. */
private static final Set SERVER_FLAGS_KEYS_TO_WATCH = Set.of(
KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE,
@@ -237,14 +230,16 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
@Override
@NonNull
public synchronized ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
+ TimeDetectorHelper timeDetectorHelper = TimeDetectorHelper.INSTANCE;
return new ConfigurationInternal.Builder(userId)
.setUserConfigAllowed(isUserConfigAllowed(userId))
.setAutoDetectionSupported(isAutoDetectionSupported())
.setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
.setSystemClockUpdateThresholdMillis(getSystemClockUpdateThresholdMillis())
- .setAutoTimeLowerBound(getAutoTimeLowerBound())
+ .setAutoSuggestionLowerBound(getAutoSuggestionLowerBound())
+ .setManualSuggestionLowerBound(timeDetectorHelper.getManualSuggestionLowerBound())
+ .setSuggestionUpperBound(timeDetectorHelper.getSuggestionUpperBound())
.setOriginPriorities(getOriginPriorities())
- .setDeviceHasY2038Issue(getDeviceHasY2038Issue())
.build();
}
@@ -291,9 +286,9 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
}
@NonNull
- private Instant getAutoTimeLowerBound() {
+ private Instant getAutoSuggestionLowerBound() {
return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
- .orElse(TIME_LOWER_BOUND_DEFAULT);
+ .orElse(TimeDetectorHelper.INSTANCE.getAutoSuggestionLowerBoundDefault());
}
@NonNull
@@ -310,10 +305,6 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
}
- private boolean getDeviceHasY2038Issue() {
- return Build.SUPPORTED_32_BIT_ABIS.length > 0;
- }
-
/**
* A base supplier of an array of time origin integers in priority order.
* It handles memoization of the result to avoid repeated string parsing when nothing has
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 017306a5039dc..547cf9d32aa1d 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -84,9 +84,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
*/
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
- /** The value in Unix epoch milliseconds of the Y2038 issue. */
- private static final long Y2038_LIMIT_IN_MILLIS = 1000L * Integer.MAX_VALUE;
-
/**
* A log that records the decisions / decision metadata that affected the device's system clock
* time. This is logged in bug reports to assist with debugging issues with detection.
@@ -248,7 +245,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
final TimestampedValue newUnixEpochTime = suggestion.getUnixEpochTime();
- if (!validateSuggestionTime(newUnixEpochTime, suggestion)) {
+ if (!validateManualSuggestionTime(newUnixEpochTime, suggestion)) {
return false;
}
@@ -424,7 +421,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@GuardedBy("this")
- private boolean validateSuggestionTime(
+ private boolean validateSuggestionCommon(
@NonNull TimestampedValue newUnixEpochTime, @NonNull Object suggestion) {
if (newUnixEpochTime.getValue() == null) {
Slog.w(LOG_TAG, "Suggested time value is null. suggestion=" + suggestion);
@@ -441,8 +438,8 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return false;
}
- if (newUnixEpochTime.getValue() > Y2038_LIMIT_IN_MILLIS
- && mCurrentConfigurationInternal.getDeviceHasY2038Issue()) {
+ if (newUnixEpochTime.getValue()
+ > mCurrentConfigurationInternal.getSuggestionUpperBound().toEpochMilli()) {
// This check won't prevent a device's system clock exceeding Integer.MAX_VALUE Unix
// seconds through the normal passage of time, but it will stop it jumping above 2038
// because of a "bad" suggestion. b/204193177
@@ -453,20 +450,40 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return true;
}
+ /**
+ * Returns {@code true} if an automatic time suggestion time is valid.
+ * See also {@link #validateManualSuggestionTime(TimestampedValue, Object)}.
+ */
@GuardedBy("this")
private boolean validateAutoSuggestionTime(
@NonNull TimestampedValue newUnixEpochTime, @NonNull Object suggestion) {
- return validateSuggestionTime(newUnixEpochTime, suggestion)
- && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion);
+ Instant lowerBound = mCurrentConfigurationInternal.getAutoSuggestionLowerBound();
+ return validateSuggestionCommon(newUnixEpochTime, suggestion)
+ && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion,
+ lowerBound);
+ }
+
+ /**
+ * Returns {@code true} if a manual time suggestion time is valid.
+ * See also {@link #validateAutoSuggestionTime(TimestampedValue, Object)}.
+ */
+ @GuardedBy("this")
+ private boolean validateManualSuggestionTime(
+ @NonNull TimestampedValue newUnixEpochTime, @NonNull Object suggestion) {
+ Instant lowerBound = mCurrentConfigurationInternal.getManualSuggestionLowerBound();
+
+ // Suggestion is definitely wrong if it comes before lower time bound.
+ return validateSuggestionCommon(newUnixEpochTime, suggestion)
+ && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion, lowerBound);
}
@GuardedBy("this")
private boolean validateSuggestionAgainstLowerBound(
- @NonNull TimestampedValue newUnixEpochTime, @NonNull Object suggestion) {
- Instant lowerBound = mCurrentConfigurationInternal.getAutoTimeLowerBound();
+ @NonNull TimestampedValue newUnixEpochTime, @NonNull Object suggestion,
+ @NonNull Instant lowerBound) {
// Suggestion is definitely wrong if it comes before lower time bound.
- if (lowerBound.isAfter(Instant.ofEpochMilli(newUnixEpochTime.getValue()))) {
+ if (lowerBound.toEpochMilli() > newUnixEpochTime.getValue()) {
Slog.w(LOG_TAG, "Suggestion points to time before lower bound, skipping it. "
+ "suggestion=" + suggestion + ", lower bound=" + lowerBound);
return false;
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
index c3d40daef412b..208f99ad63a91 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
@@ -45,7 +45,9 @@ public class ConfigurationInternalTest {
private static final int ARBITRARY_USER_ID = 99999;
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
- private static final Instant ARBITRARY_AUTO_TIME_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
+ Instant.ofEpochMilli(Long.MAX_VALUE);
private static final @Origin int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
/**
@@ -59,9 +61,10 @@ public class ConfigurationInternalTest {
.setUserConfigAllowed(true)
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
{
@@ -110,9 +113,10 @@ public class ConfigurationInternalTest {
.setUserConfigAllowed(false)
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
{
@@ -159,9 +163,10 @@ public class ConfigurationInternalTest {
.setUserConfigAllowed(true)
.setAutoDetectionSupported(false)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
{
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index b9c74baaf3d3a..67c8c4fc102fe 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -69,7 +69,9 @@ public class TimeDetectorServiceTest {
private static final int ARBITRARY_USER_ID = 9999;
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
- private static final Instant ARBITRARY_AUTO_TIME_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
+ Instant.ofEpochMilli(Long.MAX_VALUE);
private static final int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
private Context mMockContext;
@@ -444,9 +446,10 @@ public class TimeDetectorServiceTest {
.setUserConfigAllowed(true)
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(autoDetectionEnabled)
.build();
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index aeb5c65c8692f..1aea6727d3a17 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -53,7 +53,16 @@ public class TimeDetectorStrategyImplTest {
private static final @UserIdInt int ARBITRARY_USER_ID = 9876;
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
- private static final Instant TIME_LOWER_BOUND = createUnixEpochTime(2009, 1, 1, 12, 0, 0);
+ private static final Instant DEFAULT_SUGGESTION_LOWER_BOUND =
+ createUnixEpochTime(2005, 1, 1, 1, 0, 0);
+ /** A value after {@link #DEFAULT_SUGGESTION_LOWER_BOUND} */
+ private static final Instant TEST_SUGGESTION_LOWER_BOUND =
+ createUnixEpochTime(2006, 1, 1, 1, 0, 0);
+ private static final Instant DEFAULT_SUGGESTION_UPPER_BOUND =
+ createUnixEpochTime(2099, 12, 1, 1, 0, 0);
+ /** A value before {@link #DEFAULT_SUGGESTION_UPPER_BOUND} */
+ private static final Instant TEST_SUGGESTION_UPPER_BOUND =
+ createUnixEpochTime(2037, 12, 1, 1, 0, 0);
private static final TimestampedValue ARBITRARY_CLOCK_INITIALIZATION_INFO =
new TimestampedValue<>(
@@ -77,9 +86,10 @@ public class TimeDetectorStrategyImplTest {
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(false)
.build();
@@ -89,9 +99,10 @@ public class TimeDetectorStrategyImplTest {
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
@@ -343,22 +354,6 @@ public class TimeDetectorStrategyImplTest {
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion4);
}
- @Test
- public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
-
- int slotIndex = ARBITRARY_SLOT_INDEX;
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
-
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(
- slotIndex, suggestedTime);
-
- script.simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestTelephonySuggestion(slotIndex, null);
- }
-
@Test
public void testSuggestTelephonyTime_timeDetectionToggled() {
final int clockIncrementMillis = 100;
@@ -452,6 +447,70 @@ public class TimeDetectorStrategyImplTest {
script.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
}
+ @Test
+ public void testSuggestTelephonyTime_rejectedBelowLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowLowerBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestTelephonyTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveLowerBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestTelephonyTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveUpperBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestTelephonyTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowUpperBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+ }
+
@Test
public void testSuggestManualTime_autoTimeDisabled() {
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
@@ -530,7 +589,7 @@ public class TimeDetectorStrategyImplTest {
}
@Test
- public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() {
+ public void testSuggestManualTime_isIgnored_whenAutoTimeEnabled() {
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
ManualTimeSuggestion timeSuggestion =
@@ -543,16 +602,63 @@ public class TimeDetectorStrategyImplTest {
}
@Test
- public void manualTimeSuggestion_ignoresTimeLowerBound() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
-
- ManualTimeSuggestion timeSuggestion =
- script.generateManualTimeSuggestion(suggestedTime);
+ public void testSuggestManualTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveUpperBound);
script.simulateManualTimeSuggestion(
- ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
- .verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli());
+ ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestManualTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowUpperBound);
+ script.simulateManualTimeSuggestion(
+ ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestManualTime_rejectedBelowLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowLowerBound);
+ script.simulateManualTimeSuggestion(
+ ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestManualTimes_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveLowerBound);
+ script.simulateManualTimeSuggestion(
+ ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@Test
@@ -591,20 +697,67 @@ public class TimeDetectorStrategyImplTest {
}
@Test
- public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ public void testSuggestNetworkTime_rejectedBelowLowerBound() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_NETWORK)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
Script script = new Script().simulateConfigurationInternalChange(configInternal);
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
NetworkTimeSuggestion timeSuggestion =
- script.generateNetworkTimeSuggestion(suggestedTime);
-
+ script.generateNetworkTimeSuggestion(belowLowerBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestNetworkSuggestion(null);
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestNetworkTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(aboveLowerBound);
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestNetworkTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(aboveUpperBound);
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestNetworkTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(belowUpperBound);
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@Test
@@ -642,6 +795,70 @@ public class TimeDetectorStrategyImplTest {
.verifySystemClockWasNotSetAndResetCallTracking();
}
+ @Test
+ public void testSuggestGnssTime_rejectedBelowLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(belowLowerBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestGnssTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(aboveLowerBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestGnssTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(aboveUpperBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestGnssTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(belowUpperBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+ }
+
@Test
public void testSuggestExternalTime_autoTimeEnabled() {
ConfigurationInternal configInternal =
@@ -678,20 +895,67 @@ public class TimeDetectorStrategyImplTest {
}
@Test
- public void externalTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ public void testSuggestExternalTime_rejectedBelowLowerBound() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_EXTERNAL)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
Script script = new Script().simulateConfigurationInternalChange(configInternal);
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
ExternalTimeSuggestion timeSuggestion =
- script.generateExternalTimeSuggestion(suggestedTime);
-
+ script.generateExternalTimeSuggestion(belowLowerBound);
script.simulateExternalTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestExternalSuggestion(null);
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestExternalTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_EXTERNAL)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(aboveLowerBound);
+ script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestExternalTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_EXTERNAL)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(aboveUpperBound);
+ script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestExternalTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_EXTERNAL)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(belowUpperBound);
+ script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@Test
@@ -1198,56 +1462,6 @@ public class TimeDetectorStrategyImplTest {
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
}
- @Test
- public void manualY2038SuggestionsAreRejectedOnAffectedDevices() {
- ConfigurationInternal configInternal =
- new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
- .setOriginPriorities(ORIGIN_TELEPHONY)
- .setDeviceHasY2038Issue(true)
- .build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
- Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(y2038IssueTime);
- script.simulateManualTimeSuggestion(
- ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- @Test
- public void telephonyY2038SuggestionsAreRejectedOnAffectedDevices() {
- ConfigurationInternal configInternal =
- new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
- .setOriginPriorities(ORIGIN_TELEPHONY)
- .setDeviceHasY2038Issue(true)
- .build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
- final int slotIndex = 0;
- Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
- script.simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- @Test
- public void telephonyY2038SuggestionsAreNotRejectedOnUnaffectedDevices() {
- ConfigurationInternal configInternal =
- new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
- .setOriginPriorities(ORIGIN_TELEPHONY)
- .setDeviceHasY2038Issue(false)
- .build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
- final int slotIndex = 0;
- Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
- script.simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(y2038IssueTime.toEpochMilli());
- }
-
/**
* A fake implementation of {@link TimeDetectorStrategyImpl.Environment}. Besides tracking
* changes and behaving like the real thing should, it also asserts preconditions.