Merge "Centralize upper/lower time bound logic"
This commit is contained in:
158
core/java/android/app/timedetector/TimeDetectorHelper.java
Normal file
158
core/java/android/app/timedetector/TimeDetectorHelper.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user