Centralize upper/lower time bound logic

Move the upper / lower bound constants for valid time suggestions into a
single class TimeDetectorHelper, which can be accessed by both server
and client (SettingsUI) code. This reduces the number of places that
need to be touched when we change those values.

See also the associated change in packages/apps/Settings which removes
bounds checks from the client code and switches that code over to use
TimeDetectorHelper methods.

Test: services/tests/servicestests/src/com/android/server/timedetector/
Bug: 228967927
Change-Id: I952ecd4fc2e0d80ffeda4e288fb838253142953e
This commit is contained in:
Neil Fuller
2022-07-18 13:43:35 +01:00
parent 422354c931
commit 1341519762
7 changed files with 581 additions and 169 deletions

View File

@@ -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}.
*
* <p>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.
*
* <p>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}.
*
* <p>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}.
*
* <p>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;
}
}

View File

@@ -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() {

View File

@@ -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<String> 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

View File

@@ -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<Long> 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<Long> 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<Long> 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<Long> 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<Long> newUnixEpochTime, @NonNull Object suggestion) {
Instant lowerBound = mCurrentConfigurationInternal.getAutoTimeLowerBound();
@NonNull TimestampedValue<Long> 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;

View File

@@ -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();
{

View File

@@ -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();
}

View File

@@ -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<Instant> 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.