diff --git a/core/java/android/app/time/TimeCapabilities.java b/core/java/android/app/time/TimeCapabilities.java
index fff36c4a70962..9b9dce2bcbe4e 100644
--- a/core/java/android/app/time/TimeCapabilities.java
+++ b/core/java/android/app/time/TimeCapabilities.java
@@ -16,7 +16,10 @@
package android.app.time;
+import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.time.Capabilities.CapabilityState;
import android.os.Parcel;
import android.os.Parcelable;
@@ -54,40 +57,40 @@ public final class TimeCapabilities implements Parcelable {
*/
@NonNull
private final UserHandle mUserHandle;
- private final @CapabilityState int mConfigureAutoTimeDetectionEnabledCapability;
- private final @CapabilityState int mSuggestTimeManuallyCapability;
+ private final @CapabilityState int mConfigureAutoDetectionEnabledCapability;
+ private final @CapabilityState int mSuggestManualTimeCapability;
private TimeCapabilities(@NonNull Builder builder) {
this.mUserHandle = Objects.requireNonNull(builder.mUserHandle);
- this.mConfigureAutoTimeDetectionEnabledCapability =
+ this.mConfigureAutoDetectionEnabledCapability =
builder.mConfigureAutoDetectionEnabledCapability;
- this.mSuggestTimeManuallyCapability =
- builder.mSuggestTimeManuallyCapability;
+ this.mSuggestManualTimeCapability = builder.mSuggestManualTimeCapability;
}
@NonNull
private static TimeCapabilities createFromParcel(Parcel in) {
UserHandle userHandle = UserHandle.readFromParcel(in);
return new TimeCapabilities.Builder(userHandle)
- .setConfigureAutoTimeDetectionEnabledCapability(in.readInt())
- .setSuggestTimeManuallyCapability(in.readInt())
+ .setConfigureAutoDetectionEnabledCapability(in.readInt())
+ .setSuggestManualTimeCapability(in.readInt())
.build();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
UserHandle.writeToParcel(mUserHandle, dest);
- dest.writeInt(mConfigureAutoTimeDetectionEnabledCapability);
- dest.writeInt(mSuggestTimeManuallyCapability);
+ dest.writeInt(mConfigureAutoDetectionEnabledCapability);
+ dest.writeInt(mSuggestManualTimeCapability);
}
/**
* Returns the capability state associated with the user's ability to modify the automatic time
- * detection setting.
+ * detection setting. The setting can be updated via {@link
+ * TimeManager#updateTimeConfiguration(TimeConfiguration)}.
*/
@CapabilityState
- public int getConfigureAutoTimeDetectionEnabledCapability() {
- return mConfigureAutoTimeDetectionEnabledCapability;
+ public int getConfigureAutoDetectionEnabledCapability() {
+ return mConfigureAutoDetectionEnabledCapability;
}
/**
@@ -95,8 +98,31 @@ public final class TimeCapabilities implements Parcelable {
* device.
*/
@CapabilityState
- public int getSuggestTimeManuallyCapability() {
- return mSuggestTimeManuallyCapability;
+ public int getSuggestManualTimeCapability() {
+ return mSuggestManualTimeCapability;
+ }
+
+ /**
+ * Tries to create a new {@link TimeConfiguration} from the {@code config} and the set of
+ * {@code requestedChanges}, if {@code this} capabilities allow. The new configuration is
+ * returned. If the capabilities do not permit one or more of the requested changes then {@code
+ * null} is returned.
+ *
+ * @hide
+ */
+ @Nullable
+ public TimeConfiguration tryApplyConfigChanges(
+ @NonNull TimeConfiguration config,
+ @NonNull TimeConfiguration requestedChanges) {
+ TimeConfiguration.Builder newConfigBuilder = new TimeConfiguration.Builder(config);
+ if (requestedChanges.hasIsAutoDetectionEnabled()) {
+ if (this.getConfigureAutoDetectionEnabledCapability() < CAPABILITY_NOT_APPLICABLE) {
+ return null;
+ }
+ newConfigBuilder.setAutoDetectionEnabled(requestedChanges.isAutoDetectionEnabled());
+ }
+
+ return newConfigBuilder.build();
}
@Override
@@ -109,25 +135,25 @@ public final class TimeCapabilities implements Parcelable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimeCapabilities that = (TimeCapabilities) o;
- return mConfigureAutoTimeDetectionEnabledCapability
- == that.mConfigureAutoTimeDetectionEnabledCapability
- && mSuggestTimeManuallyCapability == that.mSuggestTimeManuallyCapability
+ return mConfigureAutoDetectionEnabledCapability
+ == that.mConfigureAutoDetectionEnabledCapability
+ && mSuggestManualTimeCapability == that.mSuggestManualTimeCapability
&& mUserHandle.equals(that.mUserHandle);
}
@Override
public int hashCode() {
- return Objects.hash(mUserHandle, mConfigureAutoTimeDetectionEnabledCapability,
- mSuggestTimeManuallyCapability);
+ return Objects.hash(mUserHandle, mConfigureAutoDetectionEnabledCapability,
+ mSuggestManualTimeCapability);
}
@Override
public String toString() {
return "TimeCapabilities{"
+ "mUserHandle=" + mUserHandle
- + ", mConfigureAutoTimeDetectionEnabledCapability="
- + mConfigureAutoTimeDetectionEnabledCapability
- + ", mSuggestTimeManuallyCapability=" + mSuggestTimeManuallyCapability
+ + ", mConfigureAutoDetectionEnabledCapability="
+ + mConfigureAutoDetectionEnabledCapability
+ + ", mSuggestManualTimeCapability=" + mSuggestManualTimeCapability
+ '}';
}
@@ -137,35 +163,32 @@ public final class TimeCapabilities implements Parcelable {
* @hide
*/
public static class Builder {
+
@NonNull private final UserHandle mUserHandle;
private @CapabilityState int mConfigureAutoDetectionEnabledCapability;
- private @CapabilityState int mSuggestTimeManuallyCapability;
-
- public Builder(@NonNull TimeCapabilities timeCapabilities) {
- Objects.requireNonNull(timeCapabilities);
- this.mUserHandle = timeCapabilities.mUserHandle;
- this.mConfigureAutoDetectionEnabledCapability =
- timeCapabilities.mConfigureAutoTimeDetectionEnabledCapability;
- this.mSuggestTimeManuallyCapability =
- timeCapabilities.mSuggestTimeManuallyCapability;
- }
+ private @CapabilityState int mSuggestManualTimeCapability;
public Builder(@NonNull UserHandle userHandle) {
this.mUserHandle = Objects.requireNonNull(userHandle);
}
- /** Sets the state for automatic time detection config. */
- public Builder setConfigureAutoTimeDetectionEnabledCapability(
- @CapabilityState int setConfigureAutoTimeDetectionEnabledCapability) {
+ public Builder(@NonNull TimeCapabilities timeCapabilities) {
+ Objects.requireNonNull(timeCapabilities);
+ this.mUserHandle = timeCapabilities.mUserHandle;
this.mConfigureAutoDetectionEnabledCapability =
- setConfigureAutoTimeDetectionEnabledCapability;
+ timeCapabilities.mConfigureAutoDetectionEnabledCapability;
+ this.mSuggestManualTimeCapability = timeCapabilities.mSuggestManualTimeCapability;
+ }
+
+ /** Sets the state for automatic time detection config. */
+ public Builder setConfigureAutoDetectionEnabledCapability(@CapabilityState int value) {
+ this.mConfigureAutoDetectionEnabledCapability = value;
return this;
}
/** Sets the state for manual time change. */
- public Builder setSuggestTimeManuallyCapability(
- @CapabilityState int suggestTimeManuallyCapability) {
- this.mSuggestTimeManuallyCapability = suggestTimeManuallyCapability;
+ public Builder setSuggestManualTimeCapability(@CapabilityState int value) {
+ this.mSuggestManualTimeCapability = value;
return this;
}
@@ -173,7 +196,7 @@ public final class TimeCapabilities implements Parcelable {
public TimeCapabilities build() {
verifyCapabilitySet(mConfigureAutoDetectionEnabledCapability,
"configureAutoDetectionEnabledCapability");
- verifyCapabilitySet(mSuggestTimeManuallyCapability, "suggestTimeManuallyCapability");
+ verifyCapabilitySet(mSuggestManualTimeCapability, "mSuggestManualTimeCapability");
return new TimeCapabilities(this);
}
diff --git a/core/java/android/app/time/TimeConfiguration.java b/core/java/android/app/time/TimeConfiguration.java
index 70aede034d27c..11f6ed2a9f880 100644
--- a/core/java/android/app/time/TimeConfiguration.java
+++ b/core/java/android/app/time/TimeConfiguration.java
@@ -27,8 +27,16 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
- * User visible settings that control the behavior of the time zone detector / manual time zone
- * entry.
+ * User visible settings that control the behavior of the time detector / manual time entry.
+ *
+ *
When reading the configuration, values for all settings will be provided. In some cases, such
+ * as when the device behavior relies on optional hardware / OEM configuration, or the value of
+ * several settings, the device behavior may not be directly affected by the setting value.
+ *
+ *
Settings can be left absent when updating configuration via {@link
+ * TimeManager#updateTimeConfiguration(TimeConfiguration)} and those settings will not be
+ * changed. Not all configuration settings can be modified by all users: see {@link
+ * TimeManager#getTimeCapabilitiesAndConfig()} and {@link TimeCapabilities} for details.
*
* @hide
*/
@@ -61,18 +69,10 @@ public final class TimeConfiguration implements Parcelable {
this.mBundle = builder.mBundle;
}
- /**
- * Returns the value of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting. This
- * controls whether a device will attempt to determine the time automatically using
- * contextual information if the device supports auto detection.
- */
- public boolean isAutoDetectionEnabled() {
- return mBundle.getBoolean(SETTING_AUTO_DETECTION_ENABLED);
- }
-
- @Override
- public int describeContents() {
- return 0;
+ private static TimeConfiguration readFromParcel(Parcel in) {
+ return new TimeConfiguration.Builder()
+ .setPropertyBundleInternal(in.readBundle())
+ .build();
}
@Override
@@ -80,10 +80,42 @@ public final class TimeConfiguration implements Parcelable {
dest.writeBundle(mBundle);
}
- private static TimeConfiguration readFromParcel(Parcel in) {
- return new TimeConfiguration.Builder()
- .merge(in.readBundle())
- .build();
+ /**
+ * Returns {@code true} if all known settings are present.
+ *
+ * @hide
+ */
+ public boolean isComplete() {
+ return hasIsAutoDetectionEnabled();
+ }
+
+ /**
+ * Returns the value of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting. This
+ * controls whether a device will attempt to determine the time automatically using
+ * contextual information if the device supports auto detection.
+ *
+ *
See {@link TimeCapabilities#getConfigureAutoDetectionEnabledCapability()} for how to
+ * tell if the setting is meaningful for the current user at this time.
+ *
+ * @throws IllegalStateException if the setting is not present
+ */
+ public boolean isAutoDetectionEnabled() {
+ enforceSettingPresent(SETTING_AUTO_DETECTION_ENABLED);
+ return mBundle.getBoolean(SETTING_AUTO_DETECTION_ENABLED);
+ }
+
+ /**
+ * Returns {@code true} if the {@link #isAutoDetectionEnabled()} setting is present.
+ *
+ * @hide
+ */
+ public boolean hasIsAutoDetectionEnabled() {
+ return mBundle.containsKey(SETTING_AUTO_DETECTION_ENABLED);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
}
@Override
@@ -106,18 +138,49 @@ public final class TimeConfiguration implements Parcelable {
+ '}';
}
+ private void enforceSettingPresent(@TimeZoneConfiguration.Setting String setting) {
+ if (!mBundle.containsKey(setting)) {
+ throw new IllegalStateException(setting + " is not set");
+ }
+ }
+
/**
* A builder for {@link TimeConfiguration} objects.
*
* @hide
*/
public static final class Builder {
+
private final Bundle mBundle = new Bundle();
+ /**
+ * Creates a new Builder with no settings held.
+ */
public Builder() {}
- public Builder(@NonNull TimeConfiguration configuration) {
- mBundle.putAll(configuration.mBundle);
+ /**
+ * Creates a new Builder by copying the settings from an existing instance.
+ */
+ public Builder(@NonNull TimeConfiguration toCopy) {
+ mergeProperties(toCopy);
+ }
+
+ /**
+ * Merges {@code other} settings into this instances, replacing existing values in this
+ * where the settings appear in both.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder mergeProperties(@NonNull TimeConfiguration toCopy) {
+ mBundle.putAll(toCopy.mBundle);
+ return this;
+ }
+
+ @NonNull
+ Builder setPropertyBundleInternal(@NonNull Bundle bundle) {
+ this.mBundle.putAll(bundle);
+ return this;
}
/** Sets whether auto detection is enabled or not. */
@@ -127,12 +190,7 @@ public final class TimeConfiguration implements Parcelable {
return this;
}
- Builder merge(@NonNull Bundle bundle) {
- mBundle.putAll(bundle);
- return this;
- }
-
- /** Returns {@link TimeConfiguration} object. */
+ /** Returns the {@link TimeConfiguration}. */
@NonNull
public TimeConfiguration build() {
return new TimeConfiguration(this);
diff --git a/core/tests/coretests/src/android/app/time/TimeCapabilitiesTest.java b/core/tests/coretests/src/android/app/time/TimeCapabilitiesTest.java
index 85073b0ecfddc..9d7dde2141bb6 100644
--- a/core/tests/coretests/src/android/app/time/TimeCapabilitiesTest.java
+++ b/core/tests/coretests/src/android/app/time/TimeCapabilitiesTest.java
@@ -17,6 +17,7 @@
package android.app.time;
+import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
@@ -24,6 +25,9 @@ import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTrip
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import android.os.UserHandle;
@@ -38,75 +42,193 @@ import org.junit.runner.RunWith;
@SmallTest
public class TimeCapabilitiesTest {
- private static final UserHandle USER_HANDLE = UserHandle.of(332211);
+ private static final UserHandle TEST_USER_HANDLE = UserHandle.of(332211);
@Test
- public void testBuilder() {
- TimeCapabilities capabilities = new TimeCapabilities.Builder(USER_HANDLE)
- .setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_NOT_APPLICABLE)
- .setSuggestTimeManuallyCapability(CAPABILITY_NOT_SUPPORTED)
- .build();
-
- assertThat(capabilities.getConfigureAutoTimeDetectionEnabledCapability())
- .isEqualTo(CAPABILITY_NOT_APPLICABLE);
- assertThat(capabilities.getSuggestTimeManuallyCapability())
- .isEqualTo(CAPABILITY_NOT_SUPPORTED);
-
- try {
- new TimeCapabilities.Builder(USER_HANDLE)
- .build();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException ignored) {
- // expected
+ public void testEquals() {
+ TimeCapabilities.Builder builder1 = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED);
+ TimeCapabilities.Builder builder2 = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED);
+ {
+ TimeCapabilities one = builder1.build();
+ TimeCapabilities two = builder2.build();
+ assertEquals(one, two);
}
- try {
- new TimeCapabilities.Builder(USER_HANDLE)
- .setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_NOT_APPLICABLE)
- .build();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException ignored) {
- // expected
+ builder2.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeCapabilities one = builder1.build();
+ TimeCapabilities two = builder2.build();
+ assertNotEquals(one, two);
}
- try {
- new TimeCapabilities.Builder(USER_HANDLE)
- .setSuggestTimeManuallyCapability(CAPABILITY_NOT_APPLICABLE)
- .build();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException ignored) {
- // expected
+ builder1.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeCapabilities one = builder1.build();
+ TimeCapabilities two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ builder2.setSuggestManualTimeCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeCapabilities one = builder1.build();
+ TimeCapabilities two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setSuggestManualTimeCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeCapabilities one = builder1.build();
+ TimeCapabilities two = builder2.build();
+ assertEquals(one, two);
}
}
@Test
public void userHandle_notIgnoredInEquals() {
TimeCapabilities firstUserCapabilities = new TimeCapabilities.Builder(UserHandle.of(1))
- .setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_POSSESSED)
- .setSuggestTimeManuallyCapability(CAPABILITY_POSSESSED)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED)
.build();
TimeCapabilities secondUserCapabilities = new TimeCapabilities.Builder(UserHandle.of(2))
- .setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_POSSESSED)
- .setSuggestTimeManuallyCapability(CAPABILITY_POSSESSED)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED)
.build();
assertThat(firstUserCapabilities).isNotEqualTo(secondUserCapabilities);
}
+ @Test
+ public void testBuilder() {
+ TimeCapabilities capabilities = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_APPLICABLE)
+ .setSuggestManualTimeCapability(CAPABILITY_NOT_SUPPORTED)
+ .build();
+
+ assertThat(capabilities.getConfigureAutoDetectionEnabledCapability())
+ .isEqualTo(CAPABILITY_NOT_APPLICABLE);
+ assertThat(capabilities.getSuggestManualTimeCapability())
+ .isEqualTo(CAPABILITY_NOT_SUPPORTED);
+
+ try {
+ new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .build();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException ignored) {
+ // expected
+ }
+
+ try {
+ new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_APPLICABLE)
+ .build();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException ignored) {
+ // expected
+ }
+
+ try {
+ new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setSuggestManualTimeCapability(CAPABILITY_NOT_APPLICABLE)
+ .build();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException ignored) {
+ // expected
+ }
+ }
+
@Test
public void testParcelable() {
- TimeCapabilities.Builder builder = new TimeCapabilities.Builder(USER_HANDLE)
- .setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_NOT_SUPPORTED)
- .setSuggestTimeManuallyCapability(CAPABILITY_NOT_SUPPORTED);
+ TimeCapabilities.Builder builder = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_SUPPORTED)
+ .setSuggestManualTimeCapability(CAPABILITY_NOT_SUPPORTED);
assertRoundTripParcelable(builder.build());
- builder.setSuggestTimeManuallyCapability(CAPABILITY_POSSESSED);
+ builder.setSuggestManualTimeCapability(CAPABILITY_POSSESSED);
assertRoundTripParcelable(builder.build());
- builder.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_POSSESSED);
+ builder.setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED);
assertRoundTripParcelable(builder.build());
}
+ @Test
+ public void testTryApplyConfigChanges_permitted() {
+ TimeConfiguration oldConfiguration =
+ new TimeConfiguration.Builder()
+ .setAutoDetectionEnabled(true)
+ .build();
+ TimeCapabilities capabilities = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED)
+ .build();
+
+ TimeConfiguration configChange = new TimeConfiguration.Builder()
+ .setAutoDetectionEnabled(false)
+ .build();
+
+ TimeConfiguration expected = new TimeConfiguration.Builder(oldConfiguration)
+ .setAutoDetectionEnabled(false)
+ .build();
+ assertEquals(expected, capabilities.tryApplyConfigChanges(oldConfiguration, configChange));
+ }
+
+ @Test
+ public void testTryApplyConfigChanges_notPermitted() {
+ TimeConfiguration oldConfiguration =
+ new TimeConfiguration.Builder()
+ .setAutoDetectionEnabled(true)
+ .build();
+ TimeCapabilities capabilities = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setSuggestManualTimeCapability(CAPABILITY_NOT_ALLOWED)
+ .build();
+
+ TimeConfiguration configChange = new TimeConfiguration.Builder()
+ .setAutoDetectionEnabled(false)
+ .build();
+
+ assertNull(capabilities.tryApplyConfigChanges(oldConfiguration, configChange));
+ }
+
+ @Test
+ public void copyBuilder_copiesAllFields() {
+ TimeCapabilities capabilities = new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setSuggestManualTimeCapability(CAPABILITY_NOT_ALLOWED)
+ .build();
+
+ {
+ TimeCapabilities updatedCapabilities =
+ new TimeCapabilities.Builder(capabilities)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .build();
+ TimeCapabilities expectedCapabilities =
+ new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeCapability(CAPABILITY_NOT_ALLOWED)
+ .build();
+
+ assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
+ }
+
+ {
+ TimeCapabilities updatedCapabilities =
+ new TimeCapabilities.Builder(capabilities)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED)
+ .build();
+
+ TimeCapabilities expectedCapabilities =
+ new TimeCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setSuggestManualTimeCapability(CAPABILITY_POSSESSED)
+ .build();
+
+ assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index f00f856c2910f..3f6e2117a1fca 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -17,8 +17,11 @@
package com.android.server.timedetector;
import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
+import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
+import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.time.Capabilities.CapabilityState;
import android.app.time.TimeCapabilities;
@@ -29,18 +32,57 @@ import android.os.UserHandle;
import java.util.Objects;
/**
- * Holds configuration values that affect time behaviour.
+ * Holds configuration values that affect user-facing time behavior and some associated logic.
+ * Some configuration is global, some is user scoped, but this class deliberately doesn't make a
+ * distinction for simplicity.
*/
public final class ConfigurationInternal {
+ private final boolean mAutoDetectionSupported;
+ private final boolean mAutoDetectionEnabledSetting;
private final @UserIdInt int mUserId;
private final boolean mUserConfigAllowed;
- private final boolean mAutoDetectionEnabled;
private ConfigurationInternal(Builder builder) {
+ mAutoDetectionSupported = builder.mAutoDetectionSupported;
+ mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;
+
mUserId = builder.mUserId;
mUserConfigAllowed = builder.mUserConfigAllowed;
- mAutoDetectionEnabled = builder.mAutoDetectionEnabled;
+ }
+
+ /** Returns true if the device supports any form of auto time detection. */
+ public boolean isAutoDetectionSupported() {
+ return mAutoDetectionSupported;
+ }
+
+ /** Returns the value of the auto time detection enabled setting. */
+ public boolean getAutoDetectionEnabledSetting() {
+ return mAutoDetectionEnabledSetting;
+ }
+
+ /**
+ * Returns true if auto time detection behavior is actually enabled, which can be distinct
+ * from the raw setting value.
+ */
+ public boolean getAutoDetectionEnabledBehavior() {
+ return isAutoDetectionSupported() && mAutoDetectionEnabledSetting;
+ }
+
+ /** Returns the ID of the user this configuration is associated with. */
+ public @UserIdInt int getUserId() {
+ return mUserId;
+ }
+
+ /** Returns the handle of the user this configuration is associated with. */
+ @NonNull
+ public UserHandle getUserHandle() {
+ return UserHandle.of(mUserId);
+ }
+
+ /** Returns true if the user allowed to modify time zone configuration. */
+ public boolean isUserConfigAllowed() {
+ return mUserConfigAllowed;
}
/** Returns a {@link TimeCapabilitiesAndConfig} objects based on configuration values. */
@@ -48,28 +90,58 @@ public final class ConfigurationInternal {
return new TimeCapabilitiesAndConfig(timeCapabilities(), timeConfiguration());
}
+ private TimeCapabilities timeCapabilities() {
+ UserHandle userHandle = UserHandle.of(mUserId);
+ TimeCapabilities.Builder builder = new TimeCapabilities.Builder(userHandle);
+
+ boolean allowConfigDateTime = isUserConfigAllowed();
+
+ boolean deviceHasAutoTimeDetection = isAutoDetectionSupported();
+ final @CapabilityState int configureAutoDetectionEnabledCapability;
+ if (!deviceHasAutoTimeDetection) {
+ configureAutoDetectionEnabledCapability = CAPABILITY_NOT_SUPPORTED;
+ } else if (!allowConfigDateTime) {
+ configureAutoDetectionEnabledCapability = CAPABILITY_NOT_ALLOWED;
+ } else {
+ configureAutoDetectionEnabledCapability = CAPABILITY_POSSESSED;
+ }
+ builder.setConfigureAutoDetectionEnabledCapability(configureAutoDetectionEnabledCapability);
+
+ // The ability to make manual time suggestions can also be restricted by policy. With the
+ // current logic above, this could lead to a situation where a device hardware does not
+ // support auto detection, the device has been forced into "auto" mode by an admin and the
+ // user is unable to disable auto detection.
+ final @CapabilityState int suggestManualTimeZoneCapability;
+ if (!allowConfigDateTime) {
+ suggestManualTimeZoneCapability = CAPABILITY_NOT_ALLOWED;
+ } else if (getAutoDetectionEnabledBehavior()) {
+ suggestManualTimeZoneCapability = CAPABILITY_NOT_APPLICABLE;
+ } else {
+ suggestManualTimeZoneCapability = CAPABILITY_POSSESSED;
+ }
+ builder.setSuggestManualTimeCapability(suggestManualTimeZoneCapability);
+
+ return builder.build();
+ }
+
+ /** Returns a {@link TimeConfiguration} from the configuration values. */
private TimeConfiguration timeConfiguration() {
return new TimeConfiguration.Builder()
- .setAutoDetectionEnabled(mAutoDetectionEnabled)
+ .setAutoDetectionEnabled(getAutoDetectionEnabledSetting())
.build();
}
- private TimeCapabilities timeCapabilities() {
- @CapabilityState int configureAutoTimeDetectionEnabledCapability =
- mUserConfigAllowed
- ? CAPABILITY_POSSESSED
- : CAPABILITY_NOT_ALLOWED;
-
- @CapabilityState int suggestTimeManuallyCapability =
- mUserConfigAllowed
- ? CAPABILITY_POSSESSED
- : CAPABILITY_NOT_ALLOWED;
-
- return new TimeCapabilities.Builder(UserHandle.of(mUserId))
- .setConfigureAutoTimeDetectionEnabledCapability(
- configureAutoTimeDetectionEnabledCapability)
- .setSuggestTimeManuallyCapability(suggestTimeManuallyCapability)
- .build();
+ /**
+ * Merges the configuration values from this with any properties set in {@code
+ * newConfiguration}. The new configuration has precedence. Used to apply user updates to
+ * internal configuration.
+ */
+ public ConfigurationInternal merge(TimeConfiguration newConfiguration) {
+ Builder builder = new Builder(this);
+ if (newConfiguration.hasIsAutoDetectionEnabled()) {
+ builder.setAutoDetectionEnabledSetting(newConfiguration.isAutoDetectionEnabled());
+ }
+ return builder.build();
}
@Override
@@ -77,44 +149,75 @@ public final class ConfigurationInternal {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConfigurationInternal that = (ConfigurationInternal) o;
- return mUserId == that.mUserId
+ return mAutoDetectionSupported == that.mAutoDetectionSupported
+ && mUserId == that.mUserId
&& mUserConfigAllowed == that.mUserConfigAllowed
- && mAutoDetectionEnabled == that.mAutoDetectionEnabled;
+ && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting;
}
@Override
public int hashCode() {
- return Objects.hash(mUserId, mUserConfigAllowed, mAutoDetectionEnabled);
+ return Objects.hash(mAutoDetectionSupported, mUserId,
+ mUserConfigAllowed, mAutoDetectionEnabledSetting);
}
@Override
public String toString() {
return "ConfigurationInternal{"
+ + "mAutoDetectionSupported=" + mAutoDetectionSupported
+ "mUserId=" + mUserId
+ ", mUserConfigAllowed=" + mUserConfigAllowed
- + ", mAutoDetectionEnabled=" + mAutoDetectionEnabled
+ + ", mAutoDetectionEnabled=" + mAutoDetectionEnabledSetting
+ '}';
}
static final class Builder {
private final @UserIdInt int mUserId;
+
private boolean mUserConfigAllowed;
- private boolean mAutoDetectionEnabled;
+ private boolean mAutoDetectionSupported;
+ private boolean mAutoDetectionEnabledSetting;
Builder(@UserIdInt int userId) {
mUserId = userId;
}
+ /**
+ * Creates a new Builder by copying values from an existing instance.
+ */
+ Builder(ConfigurationInternal toCopy) {
+ this.mUserId = toCopy.mUserId;
+ this.mUserConfigAllowed = toCopy.mUserConfigAllowed;
+ this.mAutoDetectionSupported = toCopy.mAutoDetectionSupported;
+ this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
+ }
+
+ /**
+ * Sets whether the user is allowed to configure time settings on this device.
+ */
Builder setUserConfigAllowed(boolean userConfigAllowed) {
mUserConfigAllowed = userConfigAllowed;
return this;
}
- Builder setAutoDetectionEnabled(boolean autoDetectionEnabled) {
- mAutoDetectionEnabled = autoDetectionEnabled;
+ /**
+ * Sets whether automatic time detection is supported on this device.
+ */
+ public Builder setAutoDetectionSupported(boolean supported) {
+ mAutoDetectionSupported = supported;
return this;
}
+ /**
+ * Sets the value of the automatic time detection enabled setting for this device.
+ */
+ Builder setAutoDetectionEnabledSetting(boolean autoDetectionEnabledSetting) {
+ mAutoDetectionEnabledSetting = autoDetectionEnabledSetting;
+ return this;
+ }
+
+ /** Returns a new {@link ConfigurationInternal}. */
+ @NonNull
ConfigurationInternal build() {
return new ConfigurationInternal(this);
}
diff --git a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
index 9d263516db3ab..fe4eb66922af7 100644
--- a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
@@ -17,21 +17,16 @@
package com.android.server.timedetector;
import android.annotation.NonNull;
-import android.annotation.UserIdInt;
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
-import android.database.ContentObserver;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.util.Slog;
-import com.android.internal.annotations.GuardedBy;
import com.android.server.timezonedetector.ConfigurationChangeListener;
import java.time.Instant;
@@ -52,10 +47,6 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
@NonNull private final AlarmManager mAlarmManager;
@NonNull private final UserManager mUserManager;
- // @NonNull after setConfigChangeListener() is called.
- @GuardedBy("this")
- private ConfigurationChangeListener mConfigChangeListener;
-
EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
@NonNull ServiceConfigAccessor serviceConfigAccessor) {
mContext = Objects.requireNonNull(context);
@@ -70,39 +61,14 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
mAlarmManager = Objects.requireNonNull(context.getSystemService(AlarmManager.class));
mUserManager = Objects.requireNonNull(context.getSystemService(UserManager.class));
-
- // Wire up the config change listeners. All invocations are performed on the mHandler
- // thread.
-
- ContentResolver contentResolver = context.getContentResolver();
- contentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- handleAutoTimeDetectionChangedOnHandlerThread();
- }
- });
- mServiceConfigAccessor.addListener(
- () -> mHandler.post(
- EnvironmentImpl.this::handleAutoTimeDetectionChangedOnHandlerThread));
- }
-
- /** Internal method for handling the auto time setting being changed. */
- private void handleAutoTimeDetectionChangedOnHandlerThread() {
- synchronized (this) {
- if (mConfigChangeListener == null) {
- Slog.wtf(LOG_TAG, "mConfigChangeListener is unexpectedly null");
- }
- mConfigChangeListener.onChange();
- }
}
@Override
- public void setConfigChangeListener(@NonNull ConfigurationChangeListener listener) {
- synchronized (this) {
- mConfigChangeListener = Objects.requireNonNull(listener);
- }
+ public void setConfigurationInternalChangeListener(
+ @NonNull ConfigurationChangeListener listener) {
+ ConfigurationChangeListener configurationChangeListener =
+ () -> mHandler.post(listener::onChange);
+ mServiceConfigAccessor.addConfigurationInternalChangeListener(configurationChangeListener);
}
@Override
@@ -110,15 +76,6 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
return mServiceConfigAccessor.systemClockUpdateThresholdMillis();
}
- @Override
- public boolean isAutoTimeDetectionEnabled() {
- try {
- return Settings.Global.getInt(mContentResolver, Settings.Global.AUTO_TIME) != 0;
- } catch (Settings.SettingNotFoundException snfe) {
- return true;
- }
- }
-
@Override
public Instant autoTimeLowerBound() {
return mServiceConfigAccessor.autoTimeLowerBound();
@@ -130,11 +87,8 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
}
@Override
- public ConfigurationInternal configurationInternal(@UserIdInt int userId) {
- return new ConfigurationInternal.Builder(userId)
- .setUserConfigAllowed(isUserConfigAllowed(userId))
- .setAutoDetectionEnabled(isAutoTimeDetectionEnabled())
- .build();
+ public ConfigurationInternal getCurrentUserConfigurationInternal() {
+ return mServiceConfigAccessor.getCurrentUserConfigurationInternal();
}
@Override
@@ -177,9 +131,4 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
}
}
-
- private boolean isUserConfigAllowed(@UserIdInt int userId) {
- UserHandle userHandle = UserHandle.of(userId);
- return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
- }
}
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java
index b4aa84e27b09b..05d21723f2875 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessor.java
@@ -16,6 +16,8 @@
package com.android.server.timedetector;
import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.time.TimeConfiguration;
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
import com.android.server.timezonedetector.ConfigurationChangeListener;
@@ -33,12 +35,23 @@ public interface ServiceConfigAccessor {
/**
* Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed.
* The listener is invoked on the main thread.
- *
- *
- *
Note: Only for use by long-lived objects. There is deliberately no associated remove
- * method.
*/
- void addListener(@NonNull ConfigurationChangeListener listener);
+ void addConfigurationInternalChangeListener(@NonNull ConfigurationChangeListener listener);
+
+ /**
+ * Removes a listener previously added via {@link
+ * #addConfigurationInternalChangeListener(ConfigurationChangeListener)}.
+ */
+ void removeConfigurationInternalChangeListener(@NonNull ConfigurationChangeListener listener);
+
+ /**
+ * Returns a snapshot of the {@link ConfigurationInternal} for the current user. This is only a
+ * snapshot so callers must use {@link
+ * #addConfigurationInternalChangeListener(ConfigurationChangeListener)} to be notified when it
+ * changes.
+ */
+ @NonNull
+ ConfigurationInternal getCurrentUserConfigurationInternal();
/**
* Returns the absolute threshold below which the system clock need not be updated. i.e. if
@@ -62,4 +75,20 @@ public interface ServiceConfigAccessor {
*/
@NonNull
@Origin int[] getOriginPriorities();
+
+ /**
+ * Updates the configuration properties that control a device's time behavior.
+ *
+ *
This method returns {@code true} if the configuration was changed,
+ * {@code false} otherwise.
+ */
+ boolean updateConfiguration(
+ @UserIdInt int userId, @NonNull TimeConfiguration requestedConfiguration);
+
+ /**
+ * Returns a snapshot of the configuration that controls time zone detector behavior for the
+ * specified user.
+ */
+ @NonNull
+ ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
}
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index fa654e2e3b605..b53c5124081e8 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -15,25 +15,46 @@
*/
package com.android.server.timedetector;
+import static android.content.Intent.ACTION_USER_SWITCHED;
+
import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE;
import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_EXTERNAL;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
+import android.app.time.TimeCapabilities;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
+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;
+import android.provider.Settings;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
import com.android.server.timezonedetector.ConfigurationChangeListener;
import java.time.Instant;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -75,9 +96,15 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
@NonNull private final Context mContext;
@NonNull private final ServerFlags mServerFlags;
+ @NonNull private final ContentResolver mCr;
+ @NonNull private final UserManager mUserManager;
@NonNull private final ConfigOriginPrioritiesSupplier mConfigOriginPrioritiesSupplier;
@NonNull private final ServerFlagsOriginPrioritiesSupplier mServerFlagsOriginPrioritiesSupplier;
+ @GuardedBy("this")
+ @NonNull private final List mConfigurationInternalListeners =
+ new ArrayList<>();
+
/**
* If a newly calculated system clock time and the current system clock time differs by this or
* more the system clock will actually be updated. Used to prevent the system clock being set
@@ -87,6 +114,8 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
private ServiceConfigAccessorImpl(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
+ mCr = context.getContentResolver();
+ mUserManager = context.getSystemService(UserManager.class);
mServerFlags = ServerFlags.getInstance(mContext);
mConfigOriginPrioritiesSupplier = new ConfigOriginPrioritiesSupplier(context);
mServerFlagsOriginPrioritiesSupplier =
@@ -94,6 +123,35 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
mSystemClockUpdateThresholdMillis =
SystemProperties.getInt("ro.sys.time_detector_update_diff",
SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
+
+ // Wire up the config change listeners for anything that could affect ConfigurationInternal.
+ // Use the main thread for event delivery, listeners can post to their chosen thread.
+
+ // Listen for the user changing / the user's location mode changing. Report on the main
+ // thread.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_USER_SWITCHED);
+ mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ handleConfigurationInternalChangeOnMainThread();
+ }
+ }, filter, null, null /* main thread */);
+
+ // Add async callbacks for global settings being changed.
+ ContentResolver contentResolver = mContext.getContentResolver();
+ ContentObserver contentObserver = new ContentObserver(mContext.getMainThreadHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ handleConfigurationInternalChangeOnMainThread();
+ }
+ };
+ contentResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true, contentObserver);
+
+ // Watch server flags.
+ mServerFlags.addListener(this::handleConfigurationInternalChangeOnMainThread,
+ SERVER_FLAGS_KEYS_TO_WATCH);
}
/** Returns the singleton instance. */
@@ -106,15 +164,22 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
}
}
- /**
- * Adds a listener that will be called when server flags related to this class change. The
- * callbacks are delivered on the main looper thread.
- *
- * Note: Only for use by long-lived objects. There is deliberately no associated remove
- * method.
- */
- public void addListener(@NonNull ConfigurationChangeListener listener) {
- mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
+ private synchronized void handleConfigurationInternalChangeOnMainThread() {
+ for (ConfigurationChangeListener changeListener : mConfigurationInternalListeners) {
+ changeListener.onChange();
+ }
+ }
+
+ @Override
+ public synchronized void addConfigurationInternalChangeListener(
+ @NonNull ConfigurationChangeListener listener) {
+ mConfigurationInternalListeners.add(Objects.requireNonNull(listener));
+ }
+
+ @Override
+ public synchronized void removeConfigurationInternalChangeListener(
+ @NonNull ConfigurationChangeListener listener) {
+ mConfigurationInternalListeners.remove(Objects.requireNonNull(listener));
}
@Override
@@ -144,6 +209,106 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
.orElse(TIME_LOWER_BOUND_DEFAULT);
}
+ @Override
+ @NonNull
+ public synchronized ConfigurationInternal getCurrentUserConfigurationInternal() {
+ int currentUserId =
+ LocalServices.getService(ActivityManagerInternal.class).getCurrentUserId();
+ return getConfigurationInternal(currentUserId);
+ }
+
+ @Override
+ public synchronized boolean updateConfiguration(@UserIdInt int userId,
+ @NonNull TimeConfiguration requestedConfiguration) {
+ Objects.requireNonNull(requestedConfiguration);
+
+ TimeCapabilitiesAndConfig capabilitiesAndConfig =
+ getCurrentUserConfigurationInternal().capabilitiesAndConfig();
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ TimeConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();
+
+ final TimeConfiguration newConfiguration =
+ capabilities.tryApplyConfigChanges(oldConfiguration, requestedConfiguration);
+ if (newConfiguration == null) {
+ // The changes could not be made because the user's capabilities do not allow it.
+ return false;
+ }
+
+ // Store the configuration / notify as needed. This will cause the mEnvironment to invoke
+ // handleConfigChanged() asynchronously.
+ storeConfiguration(userId, newConfiguration);
+
+ return true;
+ }
+
+ /**
+ * Stores the configuration properties contained in {@code newConfiguration}.
+ * All checks about user capabilities must be done by the caller and
+ * {@link TimeConfiguration#isComplete()} must be {@code true}.
+ */
+ @GuardedBy("this")
+ private void storeConfiguration(
+ @UserIdInt int userId, @NonNull TimeConfiguration configuration) {
+ Objects.requireNonNull(configuration);
+
+ // Avoid writing the auto detection enabled setting for devices that do not support auto
+ // time detection: if we wrote it down then we'd set the value explicitly, which would
+ // prevent detecting "default" later. That might influence what happens on later releases
+ // that support new types of auto detection on the same hardware.
+ if (isAutoDetectionSupported()) {
+ final boolean autoDetectionEnabled = configuration.isAutoDetectionEnabled();
+ setAutoDetectionEnabledIfRequired(autoDetectionEnabled);
+ }
+ }
+
+ @Override
+ @NonNull
+ public synchronized ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
+ return new ConfigurationInternal.Builder(userId)
+ .setUserConfigAllowed(isUserConfigAllowed(userId))
+ .setAutoDetectionSupported(isAutoDetectionSupported())
+ .setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
+ .build();
+ }
+
+ private void setAutoDetectionEnabledIfRequired(boolean enabled) {
+ // This check is racey, but the whole settings update process is racey. This check prevents
+ // a ConfigurationChangeListener callback triggering due to ContentObserver's still
+ // triggering *sometimes* for no-op updates. Because callbacks are async this is necessary
+ // for stable behavior during tests.
+ if (getAutoDetectionEnabledSetting() != enabled) {
+ Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME, enabled ? 1 : 0);
+ }
+ }
+
+ private boolean isUserConfigAllowed(@UserIdInt int userId) {
+ UserHandle userHandle = UserHandle.of(userId);
+ return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
+ }
+
+ private boolean getAutoDetectionEnabledSetting() {
+ return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME, 1 /* default */) > 0;
+ }
+
+ /** Returns {@code true} if any form of automatic time detection is supported. */
+ private boolean isAutoDetectionSupported() {
+ @Origin int[] originsSupported = getOriginPriorities();
+ for (@Origin int originSupported : originsSupported) {
+ if (originSupported == ORIGIN_NETWORK
+ || originSupported == ORIGIN_EXTERNAL
+ || originSupported == ORIGIN_GNSS) {
+ return true;
+ } else if (originSupported == ORIGIN_TELEPHONY) {
+ boolean deviceHasTelephony = mContext.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+ if (deviceHasTelephony) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* A base supplier of an array of time origin integers in priority order.
* It handles memoization of the result to avoid repeated string parsing when nothing has
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 51a5f5636bb6c..a6efa73d58eae 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -28,7 +28,6 @@ import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
import android.content.Context;
-import android.os.Binder;
import android.os.Handler;
import android.os.ResultReceiver;
import android.os.ShellCallback;
@@ -71,8 +70,8 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
TimeDetectorStrategy timeDetectorStrategy =
TimeDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
- TimeDetectorService service =
- new TimeDetectorService(context, handler, timeDetectorStrategy);
+ TimeDetectorService service = new TimeDetectorService(
+ context, handler, serviceConfigAccessor, timeDetectorStrategy);
// Publish the binder service so it can be accessed from other (appropriately
// permissioned) processes.
@@ -82,21 +81,26 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
@NonNull private final Handler mHandler;
@NonNull private final Context mContext;
- @NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
@NonNull private final CallerIdentityInjector mCallerIdentityInjector;
+ @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
+ @NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
@VisibleForTesting
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
+ @NonNull ServiceConfigAccessor serviceConfigAccessor,
@NonNull TimeDetectorStrategy timeDetectorStrategy) {
- this(context, handler, timeDetectorStrategy, CallerIdentityInjector.REAL);
+ this(context, handler, serviceConfigAccessor, timeDetectorStrategy,
+ CallerIdentityInjector.REAL);
}
@VisibleForTesting
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
+ @NonNull ServiceConfigAccessor serviceConfigAccessor,
@NonNull TimeDetectorStrategy timeDetectorStrategy,
@NonNull CallerIdentityInjector callerIdentityInjector) {
mContext = Objects.requireNonNull(context);
mHandler = Objects.requireNonNull(handler);
+ mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
mCallerIdentityInjector = Objects.requireNonNull(callerIdentityInjector);
}
@@ -108,13 +112,13 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
return getTimeCapabilitiesAndConfig(userId);
}
- private TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
+ TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
enforceManageTimeDetectorPermission();
final long token = mCallerIdentityInjector.clearCallingIdentity();
try {
ConfigurationInternal configurationInternal =
- mTimeDetectorStrategy.getConfigurationInternal(userId);
+ mServiceConfigAccessor.getConfigurationInternal(userId);
return configurationInternal.capabilitiesAndConfig();
} finally {
mCallerIdentityInjector.restoreCallingIdentity(token);
@@ -141,11 +145,12 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
enforceSuggestManualTimePermission();
Objects.requireNonNull(timeSignal);
- final long token = Binder.clearCallingIdentity();
+ int userId = mCallerIdentityInjector.getCallingUserId();
+ final long token = mCallerIdentityInjector.clearCallingIdentity();
try {
- return mTimeDetectorStrategy.suggestManualTime(timeSignal);
+ return mTimeDetectorStrategy.suggestManualTime(userId, timeSignal);
} finally {
- Binder.restoreCallingIdentity(token);
+ mCallerIdentityInjector.restoreCallingIdentity(token);
}
}
@@ -226,5 +231,4 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION,
"manage time and time zone detection");
}
-
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index acabb6e393a80..cec383ce77bed 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -76,7 +76,7 @@ public interface TimeDetectorStrategy extends Dumpable {
* suggestion was accepted. A suggestion that is valid but does not change the time because it
* matches the current device time is considered accepted.
*/
- boolean suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);
+ boolean suggestManualTime(@UserIdInt int userId, @NonNull ManualTimeSuggestion timeSuggestion);
/** Processes the suggested time from network sources. */
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
@@ -87,9 +87,6 @@ public interface TimeDetectorStrategy extends Dumpable {
/** Processes the suggested time from external sources. */
void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion);
- /** Returns the configuration that controls time detector behaviour for specified user. */
- ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
-
// Utility methods below are to be moved to a better home when one becomes more obvious.
/**
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 4b430114902c3..ea6dfc31c31e1 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -20,6 +20,8 @@ import static com.android.server.timedetector.TimeDetectorStrategy.originToStrin
import static java.util.stream.Collectors.joining;
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -99,6 +101,10 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@NonNull
private final Environment mEnvironment;
+ @GuardedBy("this")
+ @NonNull
+ private ConfigurationInternal mCurrentConfigurationInternal;
+
// Used to store the last time the system clock state was set automatically. It is used to
// detect (and log) issues with the realtime clock or whether the clock is being set without
// going through this strategy code.
@@ -128,32 +134,32 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
/**
- * The interface used by the strategy to interact with the surrounding service.
+ * Used by {@link TimeDetectorStrategyImpl} to interact with device configuration / settings
+ * / system properties. It can be faked for testing.
*
- *
Note: Because the system properties-derived value {@link #isAutoTimeDetectionEnabled()}
- * can be modified independently and from different threads (and processes!), its use is prone
- * to race conditions. That will be true until the responsibility for setting their values is
- * moved to {@link TimeDetectorStrategy}. There are similar issues with
- * {@link #systemClockMillis()} while any process can modify the system clock.
+ *
Note: Because the settings / system properties-derived values can currently be modified
+ * independently and from different threads (and processes!), their use is prone to race
+ * conditions.
*/
public interface Environment {
/**
* Sets a {@link ConfigurationChangeListener} that will be invoked when there are any
- * changes that could affect time detection. This is invoked during system server setup.
+ * changes that could affect the content of {@link ConfigurationInternal}.
+ * This is invoked during system server setup.
*/
- void setConfigChangeListener(@NonNull ConfigurationChangeListener listener);
+ void setConfigurationInternalChangeListener(@NonNull ConfigurationChangeListener listener);
+
+ /** Returns the {@link ConfigurationInternal} for the current user. */
+ @NonNull ConfigurationInternal getCurrentUserConfigurationInternal();
/**
- * The absolute threshold below which the system clock need not be updated. i.e. if setting
- * the system clock would adjust it by less than this (either backwards or forwards) then it
- * need not be set.
+ * Returns the absolute threshold below which the system clock need not be updated. i.e. if
+ * setting the system clock would adjust it by less than this (either backwards or forwards)
+ * then it need not be set.
*/
int systemClockUpdateThresholdMillis();
- /** Returns true if automatic time detection is enabled. */
- boolean isAutoTimeDetectionEnabled();
-
/**
* Returns a 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.
@@ -169,23 +175,19 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
*/
@Origin int[] autoOriginPriorities();
- /**
- * Returns {@link ConfigurationInternal} for specified user.
- */
- @NonNull
- ConfigurationInternal configurationInternal(@UserIdInt int userId);
-
/** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
void acquireWakeLock();
/** Returns the elapsedRealtimeMillis clock value. */
+ @ElapsedRealtimeLong
long elapsedRealtimeMillis();
/** Returns the system clock value. */
+ @CurrentTimeMillisLong
long systemClockMillis();
/** Sets the device system clock. The WakeLock must be held. */
- void setSystemClock(long newTimeMillis);
+ void setSystemClock(@CurrentTimeMillisLong long newTimeMillis);
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
void releaseWakeLock();
@@ -209,39 +211,73 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@VisibleForTesting
TimeDetectorStrategyImpl(@NonNull Environment environment) {
mEnvironment = Objects.requireNonNull(environment);
- mEnvironment.setConfigChangeListener(this::handleAutoTimeConfigChanged);
+
+ synchronized (this) {
+ mEnvironment.setConfigurationInternalChangeListener(
+ this::handleConfigurationInternalChanged);
+ mCurrentConfigurationInternal = mEnvironment.getCurrentUserConfigurationInternal();
+ }
}
@Override
- public synchronized void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
- final TimestampedValue newUnixEpochTime = timeSuggestion.getUnixEpochTime();
+ public synchronized void suggestExternalTime(@NonNull ExternalTimeSuggestion suggestion) {
+ ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
+ if (DBG) {
+ Slog.d(LOG_TAG, "External suggestion received."
+ + " currentUserConfig=" + currentUserConfig
+ + " newSuggestion=" + suggestion);
+ }
+ Objects.requireNonNull(suggestion);
- if (!validateAutoSuggestionTime(newUnixEpochTime, timeSuggestion)) {
+ final TimestampedValue newUnixEpochTime = suggestion.getUnixEpochTime();
+
+ if (!validateAutoSuggestionTime(newUnixEpochTime, suggestion)) {
return;
}
- mLastExternalSuggestion.set(timeSuggestion);
+ mLastExternalSuggestion.set(suggestion);
- String reason = "External time suggestion received: suggestion=" + timeSuggestion;
+ String reason = "External time suggestion received: suggestion=" + suggestion;
doAutoTimeDetection(reason);
}
@Override
- public synchronized void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion) {
- final TimestampedValue newUnixEpochTime = timeSuggestion.getUnixEpochTime();
+ public synchronized void suggestGnssTime(@NonNull GnssTimeSuggestion suggestion) {
+ ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
+ if (DBG) {
+ Slog.d(LOG_TAG, "GNSS suggestion received."
+ + " currentUserConfig=" + currentUserConfig
+ + " newSuggestion=" + suggestion);
+ }
+ Objects.requireNonNull(suggestion);
- if (!validateAutoSuggestionTime(newUnixEpochTime, timeSuggestion)) {
+ final TimestampedValue newUnixEpochTime = suggestion.getUnixEpochTime();
+
+ if (!validateAutoSuggestionTime(newUnixEpochTime, suggestion)) {
return;
}
- mLastGnssSuggestion.set(timeSuggestion);
+ mLastGnssSuggestion.set(suggestion);
- String reason = "GNSS time suggestion received: suggestion=" + timeSuggestion;
+ String reason = "GNSS time suggestion received: suggestion=" + suggestion;
doAutoTimeDetection(reason);
}
@Override
- public synchronized boolean suggestManualTime(@NonNull ManualTimeSuggestion suggestion) {
+ public synchronized boolean suggestManualTime(
+ @UserIdInt int userId, @NonNull ManualTimeSuggestion suggestion) {
+
+ ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
+ if (currentUserConfig.getUserId() != userId) {
+ Slog.w(LOG_TAG, "Manual suggestion received but user != current user, userId=" + userId
+ + " suggestion=" + suggestion);
+
+ // Only listen to changes from the current user.
+ return false;
+ }
+
+ Objects.requireNonNull(suggestion);
+
final TimestampedValue newUnixEpochTime = suggestion.getUnixEpochTime();
if (!validateSuggestionTime(newUnixEpochTime, suggestion)) {
@@ -253,8 +289,16 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@Override
- public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion) {
- if (!validateAutoSuggestionTime(timeSuggestion.getUnixEpochTime(), timeSuggestion)) {
+ public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion suggestion) {
+ ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
+ if (DBG) {
+ Slog.d(LOG_TAG, "Network suggestion received."
+ + " currentUserConfig=" + currentUserConfig
+ + " newSuggestion=" + suggestion);
+ }
+ Objects.requireNonNull(suggestion);
+
+ if (!validateAutoSuggestionTime(suggestion.getUnixEpochTime(), suggestion)) {
return;
}
@@ -266,13 +310,13 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
// the suggestion and device state are always re-evaluated, which might produce a different
// detected time if, for example, the age of all suggestions are considered.
NetworkTimeSuggestion lastNetworkSuggestion = mLastNetworkSuggestion.get();
- if (lastNetworkSuggestion == null || !lastNetworkSuggestion.equals(timeSuggestion)) {
- mLastNetworkSuggestion.set(timeSuggestion);
+ if (lastNetworkSuggestion == null || !lastNetworkSuggestion.equals(suggestion)) {
+ mLastNetworkSuggestion.set(suggestion);
}
// Now perform auto time detection. The new suggestion may be used to modify the system
// clock.
- String reason = "New network time suggested. timeSuggestion=" + timeSuggestion;
+ String reason = "New network time suggested. timeSuggestion=" + suggestion;
doAutoTimeDetection(reason);
}
@@ -303,17 +347,20 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
doAutoTimeDetection(reason);
}
- @Override
- @NonNull
- public ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
- return mEnvironment.configurationInternal(userId);
- }
+ private synchronized void handleConfigurationInternalChanged() {
+ ConfigurationInternal currentUserConfig =
+ mEnvironment.getCurrentUserConfigurationInternal();
+ String logMsg = "handleConfigurationInternalChanged:"
+ + " oldConfiguration=" + mCurrentConfigurationInternal
+ + ", newConfiguration=" + currentUserConfig;
+ logTimeDetectorChange(logMsg);
+ mCurrentConfigurationInternal = currentUserConfig;
- private synchronized void handleAutoTimeConfigChanged() {
- boolean enabled = mEnvironment.isAutoTimeDetectionEnabled();
+ boolean autoDetectionEnabled =
+ mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior();
// When automatic time detection is enabled we update the system clock instantly if we can.
// Conversely, when automatic time detection is disabled we leave the clock as it is.
- if (enabled) {
+ if (autoDetectionEnabled) {
String reason = "Auto time zone detection config changed.";
doAutoTimeDetection(reason);
} else {
@@ -323,14 +370,22 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
}
+ private void logTimeDetectorChange(@NonNull String logMsg) {
+ if (DBG) {
+ Slog.d(LOG_TAG, logMsg);
+ }
+ mTimeChangesLog.log(logMsg);
+ }
+
@Override
public synchronized void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
ipw.println("TimeDetectorStrategy:");
ipw.increaseIndent(); // level 1
ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
- ipw.println("mEnvironment.isAutoTimeDetectionEnabled()="
- + mEnvironment.isAutoTimeDetectionEnabled());
+ ipw.println("mCurrentConfigurationInternal=" + mCurrentConfigurationInternal);
+ ipw.println("[Capabilities=" + mCurrentConfigurationInternal.capabilitiesAndConfig()
+ + "]");
long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
ipw.printf("mEnvironment.elapsedRealtimeMillis()=%s (%s)\n",
Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
@@ -463,7 +518,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@GuardedBy("this")
private void doAutoTimeDetection(@NonNull String detectionReason) {
- if (!mEnvironment.isAutoTimeDetectionEnabled()) {
+ if (!mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
// Avoid doing unnecessary work with this (race-prone) check.
return;
}
@@ -692,7 +747,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
boolean isOriginAutomatic = isOriginAutomatic(origin);
if (isOriginAutomatic) {
- if (!mEnvironment.isAutoTimeDetectionEnabled()) {
+ if (!mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
if (DBG) {
Slog.d(LOG_TAG, "Auto time detection is not enabled."
+ " origin=" + originToString(origin)
@@ -702,7 +757,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
return false;
}
} else {
- if (mEnvironment.isAutoTimeDetectionEnabled()) {
+ if (mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
if (DBG) {
Slog.d(LOG_TAG, "Auto time detection is enabled."
+ " origin=" + originToString(origin)
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index ef4e42a6a8d35..ef99d616cbeca 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -24,6 +24,7 @@ import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
+import android.app.time.Capabilities.CapabilityState;
import android.app.time.TimeZoneCapabilities;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
@@ -205,7 +206,7 @@ public final class ConfigurationInternal {
// network available or geolocation time zone detection is possible.
boolean deviceHasAutoTimeZoneDetection = isAutoDetectionSupported();
- final int configureAutoDetectionEnabledCapability;
+ final @CapabilityState int configureAutoDetectionEnabledCapability;
if (!deviceHasAutoTimeZoneDetection) {
configureAutoDetectionEnabledCapability = CAPABILITY_NOT_SUPPORTED;
} else if (!allowConfigDateTime) {
@@ -219,7 +220,7 @@ public final class ConfigurationInternal {
// Note: allowConfigDateTime does not restrict the ability to change location time zone
// detection enabled. This is intentional as it has user privacy implications and so it
// makes sense to leave this under a user's control.
- final int configureGeolocationDetectionEnabledCapability;
+ final @CapabilityState int configureGeolocationDetectionEnabledCapability;
if (!deviceHasLocationTimeZoneDetection) {
configureGeolocationDetectionEnabledCapability = CAPABILITY_NOT_SUPPORTED;
} else if (!mAutoDetectionEnabledSetting || !getLocationEnabledSetting()) {
@@ -234,7 +235,7 @@ public final class ConfigurationInternal {
// the current logic above, this could lead to a situation where a device hardware does not
// support auto detection, the device has been forced into "auto" mode by an admin and the
// user is unable to disable auto detection.
- final int suggestManualTimeZoneCapability;
+ final @CapabilityState int suggestManualTimeZoneCapability;
if (!allowConfigDateTime) {
suggestManualTimeZoneCapability = CAPABILITY_NOT_ALLOWED;
} else if (getAutoDetectionEnabledBehavior()) {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
index d4222e6e0b63a..8425d13e36b74 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
@@ -16,13 +16,18 @@
package com.android.server.timedetector;
-import static com.google.common.truth.Truth.assertThat;
+import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
+import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
+import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
+import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
-import android.app.time.Capabilities;
import android.app.time.TimeCapabilities;
import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
-import android.os.UserHandle;
import androidx.test.runner.AndroidJUnit4;
@@ -32,25 +37,146 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class ConfigurationInternalTest {
+ private static final int ARBITRARY_USER_ID = 99999;
+
+ /**
+ * Tests when {@link ConfigurationInternal#isUserConfigAllowed()} and
+ * {@link ConfigurationInternal#isAutoDetectionSupported()} are both true.
+ */
@Test
- public void capabilitiesAndConfig() {
- int userId = 112233;
- ConfigurationInternal configurationInternal = new ConfigurationInternal.Builder(userId)
- .setAutoDetectionEnabled(true)
+ public void test_unrestricted() {
+ ConfigurationInternal
+ baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
.setUserConfigAllowed(true)
+ .setAutoDetectionSupported(true)
+ .setAutoDetectionEnabledSetting(true)
.build();
+ {
+ ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
+ .setAutoDetectionEnabledSetting(true)
+ .build();
+ assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
+ assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
- TimeCapabilities timeCapabilities = new TimeCapabilities.Builder(UserHandle.of(userId))
- .setConfigureAutoTimeDetectionEnabledCapability(Capabilities.CAPABILITY_POSSESSED)
- .setSuggestTimeManuallyCapability(Capabilities.CAPABILITY_POSSESSED)
- .build();
- TimeConfiguration timeConfiguration = new TimeConfiguration.Builder()
- .setAutoDetectionEnabled(true)
- .build();
- TimeCapabilitiesAndConfig expected =
- new TimeCapabilitiesAndConfig(timeCapabilities, timeConfiguration);
+ TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOnConfig.capabilitiesAndConfig();
- assertThat(configurationInternal.capabilitiesAndConfig()).isEqualTo(expected);
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_APPLICABLE, capabilities.getSuggestManualTimeCapability());
+
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertTrue(configuration.isAutoDetectionEnabled());
+ }
+
+ {
+ ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
+ .setAutoDetectionEnabledSetting(false)
+ .build();
+ assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
+ assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
+
+ TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOffConfig.capabilitiesAndConfig();
+
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getSuggestManualTimeCapability());
+
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertFalse(configuration.isAutoDetectionEnabled());
+ }
}
+ /** Tests when {@link ConfigurationInternal#isUserConfigAllowed()} is false */
+ @Test
+ public void test_restricted() {
+ ConfigurationInternal
+ baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
+ .setUserConfigAllowed(false)
+ .setAutoDetectionSupported(true)
+ .setAutoDetectionEnabledSetting(true)
+ .build();
+ {
+ ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
+ .setAutoDetectionEnabledSetting(true)
+ .build();
+ assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
+ assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
+
+ TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOnConfig.capabilitiesAndConfig();
+
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeCapability());
+
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertTrue(configuration.isAutoDetectionEnabled());
+ }
+
+ {
+ ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
+ .setAutoDetectionEnabledSetting(false)
+ .build();
+ assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
+ assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
+
+ TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOffConfig.capabilitiesAndConfig();
+
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeCapability());
+
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertFalse(configuration.isAutoDetectionEnabled());
+ }
+ }
+
+ /** Tests when {@link ConfigurationInternal#isAutoDetectionSupported()} is false. */
+ @Test
+ public void test_autoDetectNotSupported() {
+ ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionSupported(false)
+ .setAutoDetectionEnabledSetting(true)
+ .build();
+ {
+ ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
+ .setAutoDetectionEnabledSetting(true)
+ .build();
+ assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
+ assertFalse(autoOnConfig.getAutoDetectionEnabledBehavior());
+
+ TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOnConfig.capabilitiesAndConfig();
+
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_SUPPORTED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeCapability());
+
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertTrue(configuration.isAutoDetectionEnabled());
+ }
+ {
+ ConfigurationInternal
+ autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
+ .setAutoDetectionEnabledSetting(false)
+ .build();
+ assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
+ assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
+
+ TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOffConfig.capabilitiesAndConfig();
+
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_SUPPORTED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeCapability());
+
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertFalse(configuration.isAutoDetectionEnabled());
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java b/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
new file mode 100644
index 0000000000000..dd686f3c08401
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timedetector/FakeServiceConfigAccessor.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 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 com.android.server.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.time.TimeCapabilities;
+import android.app.time.TimeCapabilitiesAndConfig;
+import android.app.time.TimeConfiguration;
+
+import com.android.server.timezonedetector.ConfigurationChangeListener;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+/** A partially implemented, fake implementation of ServiceConfigAccessor for tests. */
+class FakeServiceConfigAccessor implements ServiceConfigAccessor {
+
+ private final List mConfigurationInternalChangeListeners =
+ new ArrayList<>();
+ private ConfigurationInternal mConfigurationInternal;
+
+ @Override
+ public void addConfigurationInternalChangeListener(ConfigurationChangeListener listener) {
+ mConfigurationInternalChangeListeners.add(listener);
+ }
+
+ @Override
+ public void removeConfigurationInternalChangeListener(ConfigurationChangeListener listener) {
+ mConfigurationInternalChangeListeners.remove(listener);
+ }
+
+ @Override
+ public ConfigurationInternal getCurrentUserConfigurationInternal() {
+ return mConfigurationInternal;
+ }
+
+ @Override
+ public boolean updateConfiguration(
+ @UserIdInt int userID, @NonNull TimeConfiguration requestedChanges) {
+ assertNotNull(mConfigurationInternal);
+ assertNotNull(requestedChanges);
+
+ // Simulate the real strategy's behavior: the new configuration will be updated to be the
+ // old configuration merged with the new if the user has the capability to up the settings.
+ // Then, if the configuration changed, the change listener is invoked.
+ TimeCapabilitiesAndConfig capabilitiesAndConfig =
+ mConfigurationInternal.capabilitiesAndConfig();
+ TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ TimeConfiguration newConfiguration =
+ capabilities.tryApplyConfigChanges(configuration, requestedChanges);
+ if (newConfiguration == null) {
+ return false;
+ }
+
+ if (!newConfiguration.equals(capabilitiesAndConfig.getConfiguration())) {
+ mConfigurationInternal = mConfigurationInternal.merge(newConfiguration);
+
+ // Note: Unlike the real strategy, the listeners are invoked synchronously.
+ simulateConfigurationChangeForTests();
+ }
+ return true;
+ }
+
+ void initializeConfiguration(ConfigurationInternal configurationInternal) {
+ mConfigurationInternal = configurationInternal;
+ }
+
+ void simulateConfigurationChangeForTests() {
+ for (ConfigurationChangeListener listener : mConfigurationInternalChangeListeners) {
+ listener.onChange();
+ }
+ }
+
+ @Override
+ public ConfigurationInternal getConfigurationInternal(int userId) {
+ assertEquals("Multi-user testing not supported currently",
+ userId, mConfigurationInternal.getUserId());
+ return mConfigurationInternal;
+ }
+
+ @Override
+ public int systemClockUpdateThresholdMillis() {
+ failUnimplemented();
+ return 0;
+ }
+
+ @Override
+ public Instant autoTimeLowerBound() {
+ failUnimplemented();
+ return null;
+ }
+
+ @Override
+ public @TimeDetectorStrategy.Origin int[] getOriginPriorities() {
+ failUnimplemented();
+ return new int[0];
+ }
+
+ @SuppressWarnings("UnusedReturnValue")
+ private static T failUnimplemented() {
+ fail("Unimplemented");
+ return null;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 4519890e72a15..ad2cb53a3fe86 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -41,6 +41,7 @@ import android.util.IndentingPrintWriter;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.timezonedetector.TestCallerIdentityInjector;
import com.android.server.timezonedetector.TestHandler;
import org.junit.After;
@@ -54,12 +55,16 @@ import java.io.StringWriter;
@RunWith(AndroidJUnit4.class)
public class TimeDetectorServiceTest {
+ private static final int ARBITRARY_USER_ID = 9999;
+
private Context mMockContext;
- private StubbedTimeDetectorStrategy mStubbedTimeDetectorStrategy;
private TimeDetectorService mTimeDetectorService;
private HandlerThread mHandlerThread;
private TestHandler mTestHandler;
+ private TestCallerIdentityInjector mTestCallerIdentityInjector;
+ private FakeServiceConfigAccessor mFakeServiceConfigAccessor;
+ private StubbedTimeDetectorStrategy mStubbedTimeDetectorStrategy;
@Before
@@ -71,10 +76,15 @@ public class TimeDetectorServiceTest {
mHandlerThread.start();
mTestHandler = new TestHandler(mHandlerThread.getLooper());
+ mTestCallerIdentityInjector = new TestCallerIdentityInjector();
+ mTestCallerIdentityInjector.initializeCallingUserId(ARBITRARY_USER_ID);
+
mStubbedTimeDetectorStrategy = new StubbedTimeDetectorStrategy();
+ mFakeServiceConfigAccessor = new FakeServiceConfigAccessor();
mTimeDetectorService = new TimeDetectorService(
- mMockContext, mTestHandler, mStubbedTimeDetectorStrategy);
+ mMockContext, mTestHandler, mFakeServiceConfigAccessor,
+ mStubbedTimeDetectorStrategy, mTestCallerIdentityInjector);
}
@After
@@ -83,6 +93,37 @@ public class TimeDetectorServiceTest {
mHandlerThread.join();
}
+ @Test(expected = SecurityException.class)
+ public void testGetCapabilitiesAndConfig_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingPermission(anyString(), any());
+
+ try {
+ mTimeDetectorService.getCapabilitiesAndConfig();
+ fail("Expected SecurityException");
+ } finally {
+ verify(mMockContext).enforceCallingPermission(
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
+ anyString());
+ }
+ }
+
+ @Test
+ public void testGetCapabilitiesAndConfig() {
+ doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
+
+ ConfigurationInternal configuration =
+ createConfigurationInternal(true /* autoDetectionEnabled*/);
+ mFakeServiceConfigAccessor.initializeConfiguration(configuration);
+
+ assertEquals(configuration.capabilitiesAndConfig(),
+ mTimeDetectorService.getCapabilitiesAndConfig());
+
+ verify(mMockContext).enforceCallingPermission(
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
+ anyString());
+ }
+
@Test(expected = SecurityException.class)
public void testSuggestTelephonyTime_withoutPermission() {
doThrow(new SecurityException("Mock"))
@@ -248,6 +289,14 @@ public class TimeDetectorServiceTest {
mStubbedTimeDetectorStrategy.verifyDumpCalled();
}
+ private static ConfigurationInternal createConfigurationInternal(boolean autoDetectionEnabled) {
+ return new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionSupported(true)
+ .setAutoDetectionEnabledSetting(autoDetectionEnabled)
+ .build();
+ }
+
private static TelephonyTimeSuggestion createTelephonyTimeSuggestion() {
int slotIndex = 1234;
TimestampedValue timeValue = new TimestampedValue<>(100L, 1_000_000L);
@@ -291,7 +340,7 @@ public class TimeDetectorServiceTest {
}
@Override
- public boolean suggestManualTime(ManualTimeSuggestion timeSuggestion) {
+ public boolean suggestManualTime(int userId, ManualTimeSuggestion timeSuggestion) {
mLastManualSuggestion = timeSuggestion;
return true;
}
@@ -311,11 +360,6 @@ public class TimeDetectorServiceTest {
mLastExternalSuggestion = timeSuggestion;
}
- @Override
- public ConfigurationInternal getConfigurationInternal(int userId) {
- throw new UnsupportedOperationException();
- }
-
@Override
public void dump(IndentingPrintWriter pw, String[] args) {
mDumpCalled = true;
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 2248ddb9e69ae..2d2b29887938b 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.annotation.UserIdInt;
import android.app.time.ExternalTimeSuggestion;
import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
@@ -52,6 +53,7 @@ import java.util.Objects;
@RunWith(AndroidJUnit4.class)
public class TimeDetectorStrategyImplTest {
+ private static final @UserIdInt int USER_ID = 9876;
private static final Instant TIME_LOWER_BOUND = createUnixEpochTime(2009, 1, 1, 12, 0, 0);
private static final TimestampedValue ARBITRARY_CLOCK_INITIALIZATION_INFO =
@@ -70,41 +72,57 @@ public class TimeDetectorStrategyImplTest {
private static final int ARBITRARY_SLOT_INDEX = 123456;
- private Script mScript;
+ private static final ConfigurationInternal CONFIG_AUTO_DISABLED =
+ new ConfigurationInternal.Builder(USER_ID)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionSupported(true)
+ .setAutoDetectionEnabledSetting(false)
+ .build();
+
+ private static final ConfigurationInternal CONFIG_AUTO_ENABLED =
+ new ConfigurationInternal.Builder(USER_ID)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionSupported(true)
+ .setAutoDetectionEnabledSetting(true)
+ .build();
+
+ private FakeEnvironment mFakeEnvironment;
@Before
public void setUp() {
- mScript = new Script();
+ mFakeEnvironment = new FakeEnvironment();
+ mFakeEnvironment.initializeConfig(CONFIG_AUTO_DISABLED);
+ mFakeEnvironment.initializeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO);
}
@Test
public void testSuggestTelephonyTime_autoTimeEnabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
- mScript.simulateTimePassing()
+ script.generateTelephonyTimeSuggestion(slotIndex, testTime);
+ script.simulateTimePassing()
.simulateTelephonyTimeSuggestion(timeSuggestion);
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
- mScript.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
+ script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
+ script.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
}
@Test
public void testSuggestTelephonyTime_emptySuggestionIgnored() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, null);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ script.generateTelephonyTimeSuggestion(slotIndex, null);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, null);
}
@@ -113,24 +131,24 @@ public class TimeDetectorStrategyImplTest {
public void testSuggestTelephonyTime_systemClockThreshold() {
final int systemClockUpdateThresholdMillis = 1000;
final int clockIncrementMillis = 100;
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeThresholds(systemClockUpdateThresholdMillis)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
// Send the first time signal. It should be used.
{
TelephonyTimeSuggestion timeSuggestion1 =
- mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
+ script.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
// Increment the device clocks to simulate the passage of time.
- mScript.simulateTimePassing(clockIncrementMillis);
+ script.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis1 =
- mScript.calculateTimeInMillisForNow(timeSuggestion1.getUnixEpochTime());
+ script.calculateTimeInMillisForNow(timeSuggestion1.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
}
@@ -139,9 +157,9 @@ public class TimeDetectorStrategyImplTest {
// stored, but not used to set the system clock.
{
int underThresholdMillis = systemClockUpdateThresholdMillis - 1;
- TelephonyTimeSuggestion timeSuggestion2 = mScript.generateTelephonyTimeSuggestion(
- slotIndex, mScript.peekSystemClockMillis() + underThresholdMillis);
- mScript.simulateTimePassing(clockIncrementMillis)
+ TelephonyTimeSuggestion timeSuggestion2 = script.generateTelephonyTimeSuggestion(
+ slotIndex, script.peekSystemClockMillis() + underThresholdMillis);
+ script.simulateTimePassing(clockIncrementMillis)
.simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
@@ -149,15 +167,15 @@ public class TimeDetectorStrategyImplTest {
// Now send another time signal, but one that is on the threshold and so should be used.
{
- TelephonyTimeSuggestion timeSuggestion3 = mScript.generateTelephonyTimeSuggestion(
+ TelephonyTimeSuggestion timeSuggestion3 = script.generateTelephonyTimeSuggestion(
slotIndex,
- mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
- mScript.simulateTimePassing(clockIncrementMillis);
+ script.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
+ script.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis3 =
- mScript.calculateTimeInMillisForNow(timeSuggestion3.getUnixEpochTime());
+ script.calculateTimeInMillisForNow(timeSuggestion3.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion3)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion3)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis3)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion3);
}
@@ -165,8 +183,8 @@ public class TimeDetectorStrategyImplTest {
@Test
public void testSuggestTelephonyTime_multipleSlotIndexsAndBucketing() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
// There are 2 slotIndexes in this test. slotIndex1 and slotIndex2 have different opinions
// about the current time. slotIndex1 < slotIndex2 (which is important because the strategy
@@ -179,63 +197,63 @@ public class TimeDetectorStrategyImplTest {
// Make a suggestion with slotIndex2.
{
TelephonyTimeSuggestion slotIndex2TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
- mScript.simulateTimePassing();
+ script.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
+ script.simulateTimePassing();
- long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(
+ long expectedSystemClockMillis = script.calculateTimeInMillisForNow(
slotIndex2TimeSuggestion.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
+ script.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestTelephonySuggestion(slotIndex1, null)
.assertLatestTelephonySuggestion(slotIndex2, slotIndex2TimeSuggestion);
}
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
// Now make a different suggestion with slotIndex1.
{
TelephonyTimeSuggestion slotIndex1TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1Time);
- mScript.simulateTimePassing();
+ script.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1Time);
+ script.simulateTimePassing();
- long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(
+ long expectedSystemClockMillis = script.calculateTimeInMillisForNow(
slotIndex1TimeSuggestion.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(slotIndex1TimeSuggestion)
+ script.simulateTelephonyTimeSuggestion(slotIndex1TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestTelephonySuggestion(slotIndex1, slotIndex1TimeSuggestion);
}
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
// Make another suggestion with slotIndex2. It should be stored but not used because the
// slotIndex1 suggestion will still "win".
{
TelephonyTimeSuggestion slotIndex2TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
- mScript.simulateTimePassing();
+ script.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
+ script.simulateTimePassing();
- mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
+ script.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex2, slotIndex2TimeSuggestion);
}
// Let enough time pass that slotIndex1's suggestion should now be too old.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.TELEPHONY_BUCKET_SIZE_MILLIS);
+ script.simulateTimePassing(TimeDetectorStrategyImpl.TELEPHONY_BUCKET_SIZE_MILLIS);
// Make another suggestion with slotIndex2. It should be used because the slotIndex1
// is in an older "bucket".
{
TelephonyTimeSuggestion slotIndex2TimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
- mScript.simulateTimePassing();
+ script.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
+ script.simulateTimePassing();
- long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(
+ long expectedSystemClockMillis = script.calculateTimeInMillisForNow(
slotIndex2TimeSuggestion.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
+ script.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestTelephonySuggestion(slotIndex2, slotIndex2TimeSuggestion);
}
@@ -243,13 +261,13 @@ public class TimeDetectorStrategyImplTest {
@Test
public void testSuggestTelephonyTime_autoTimeDisabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(false);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing()
+ script.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
+ script.simulateTimePassing()
.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
@@ -258,21 +276,21 @@ public class TimeDetectorStrategyImplTest {
@Test
public void testSuggestTelephonyTime_invalidNitzReferenceTimesIgnored() {
final int systemClockUpdateThreshold = 2000;
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeThresholds(systemClockUpdateThreshold)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
Instant testTime = ARBITRARY_TEST_TIME;
int slotIndex = ARBITRARY_SLOT_INDEX;
TelephonyTimeSuggestion timeSuggestion1 =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+ script.generateTelephonyTimeSuggestion(slotIndex, testTime);
TimestampedValue unixEpochTime1 = timeSuggestion1.getUnixEpochTime();
// Initialize the strategy / device with a time set from a telephony suggestion.
- mScript.simulateTimePassing();
- long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(unixEpochTime1);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
+ script.simulateTimePassing();
+ long expectedSystemClockMillis1 = script.calculateTimeInMillisForNow(unixEpochTime1);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -288,7 +306,7 @@ public class TimeDetectorStrategyImplTest {
referenceTimeBeforeLastSignalMillis, validUnixEpochTimeMillis);
TelephonyTimeSuggestion timeSuggestion2 =
createTelephonyTimeSuggestion(slotIndex, unixEpochTime2);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion2)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -300,7 +318,7 @@ public class TimeDetectorStrategyImplTest {
referenceTimeInFutureMillis, validUnixEpochTimeMillis);
TelephonyTimeSuggestion timeSuggestion3 =
createTelephonyTimeSuggestion(slotIndex, unixEpochTime3);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion3)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion3)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -308,27 +326,27 @@ public class TimeDetectorStrategyImplTest {
long validReferenceTimeMillis = unixEpochTime1.getReferenceTimeMillis() + 100;
TimestampedValue unixEpochTime4 = new TimestampedValue<>(
validReferenceTimeMillis, validUnixEpochTimeMillis);
- long expectedSystemClockMillis4 = mScript.calculateTimeInMillisForNow(unixEpochTime4);
+ long expectedSystemClockMillis4 = script.calculateTimeInMillisForNow(unixEpochTime4);
TelephonyTimeSuggestion timeSuggestion4 =
createTelephonyTimeSuggestion(slotIndex, unixEpochTime4);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion4)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion4)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion4);
}
@Test
public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(
+ script.generateTelephonyTimeSuggestion(
slotIndex, suggestedTime);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, null);
}
@@ -337,325 +355,326 @@ public class TimeDetectorStrategyImplTest {
public void testSuggestTelephonyTime_timeDetectionToggled() {
final int clockIncrementMillis = 100;
final int systemClockUpdateThreshold = 2000;
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeThresholds(systemClockUpdateThreshold)
- .pokeAutoTimeDetectionEnabled(false);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion timeSuggestion1 =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+ script.generateTelephonyTimeSuggestion(slotIndex, testTime);
TimestampedValue unixEpochTime1 = timeSuggestion1.getUnixEpochTime();
// Simulate time passing.
- mScript.simulateTimePassing(clockIncrementMillis);
+ script.simulateTimePassing(clockIncrementMillis);
// Simulate the time signal being received. It should not be used because auto time
// detection is off but it should be recorded.
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Simulate more time passing.
- mScript.simulateTimePassing(clockIncrementMillis);
+ script.simulateTimePassing(clockIncrementMillis);
- long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(unixEpochTime1);
+ long expectedSystemClockMillis1 = script.calculateTimeInMillisForNow(unixEpochTime1);
// Turn on auto time detection.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Turn off auto time detection.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Receive another valid time signal.
// It should be on the threshold and accounting for the clock increments.
- TelephonyTimeSuggestion timeSuggestion2 = mScript.generateTelephonyTimeSuggestion(
- slotIndex, mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
+ TelephonyTimeSuggestion timeSuggestion2 = script.generateTelephonyTimeSuggestion(
+ slotIndex, script.peekSystemClockMillis() + systemClockUpdateThreshold);
// Simulate more time passing.
- mScript.simulateTimePassing(clockIncrementMillis);
+ script.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis2 =
- mScript.calculateTimeInMillisForNow(timeSuggestion2.getUnixEpochTime());
+ script.calculateTimeInMillisForNow(timeSuggestion2.getUnixEpochTime());
// The new time, though valid, should not be set in the system clock because auto time is
// disabled.
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion2)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
// Turn on auto time detection.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
}
@Test
public void testSuggestTelephonyTime_maxSuggestionAge() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion telephonySuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+ script.generateTelephonyTimeSuggestion(slotIndex, testTime);
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(telephonySuggestion.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(telephonySuggestion)
+ script.calculateTimeInMillisForNow(telephonySuggestion.getUnixEpochTime());
+ script.simulateTelephonyTimeSuggestion(telephonySuggestion)
.verifySystemClockWasSetAndResetCallTracking(
expectedSystemClockMillis /* expectedNetworkBroadcast */)
.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
// Look inside and check what the strategy considers the current best telephony suggestion.
- assertEquals(telephonySuggestion, mScript.peekBestTelephonySuggestion());
+ assertEquals(telephonySuggestion, script.peekBestTelephonySuggestion());
// Simulate time passing, long enough that telephonySuggestion is now too old.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS);
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS);
// Look inside and check what the strategy considers the current best telephony suggestion.
// It should still be the, it's just no longer used.
- assertNull(mScript.peekBestTelephonySuggestion());
- mScript.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
+ assertNull(script.peekBestTelephonySuggestion());
+ script.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
}
@Test
public void testSuggestManualTime_autoTimeDisabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(false);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
ManualTimeSuggestion timeSuggestion =
- mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
- mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */)
+ script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
+ script.simulateManualTimeSuggestion(USER_ID, timeSuggestion, true /* expectedResult */)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@Test
public void testSuggestManualTime_retainsAutoSignal() {
// Configure the start state.
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
int slotIndex = ARBITRARY_SLOT_INDEX;
// Simulate a telephony suggestion.
Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion telephonyTimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+ script.generateTelephonyTimeSuggestion(slotIndex, testTime);
// Simulate the passage of time.
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
long expectedAutoClockMillis =
- mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
- mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ script.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
+ script.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
// Switch to manual.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
// Simulate a manual suggestion 1 day different from the auto suggestion.
Instant manualTime = testTime.plus(Duration.ofDays(1));
ManualTimeSuggestion manualTimeSuggestion =
- mScript.generateManualTimeSuggestion(manualTime);
- mScript.simulateTimePassing();
+ script.generateManualTimeSuggestion(manualTime);
+ script.simulateTimePassing();
long expectedManualClockMillis =
- mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUnixEpochTime());
- mScript.simulateManualTimeSuggestion(manualTimeSuggestion, true /* expectedResult */)
+ script.calculateTimeInMillisForNow(manualTimeSuggestion.getUnixEpochTime());
+ script.simulateManualTimeSuggestion(
+ USER_ID, manualTimeSuggestion, true /* expectedResult */)
.verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Simulate the passage of time.
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
// Switch back to auto.
- mScript.simulateAutoTimeDetectionToggle();
+ script.simulateAutoTimeDetectionToggle();
expectedAutoClockMillis =
- mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
- mScript.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
+ script.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
+ script.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Switch back to manual - nothing should happen to the clock.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
}
@Test
public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
ManualTimeSuggestion timeSuggestion =
- mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing()
- .simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */)
+ script.simulateTimePassing()
+ .simulateManualTimeSuggestion(USER_ID, timeSuggestion, false /* expectedResult */)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void manualTimeSuggestion_ignoresTimeLowerBound() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(false);
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
ManualTimeSuggestion timeSuggestion =
- mScript.generateManualTimeSuggestion(suggestedTime);
+ script.generateManualTimeSuggestion(suggestedTime);
- mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */)
+ script.simulateManualTimeSuggestion(USER_ID, timeSuggestion, true /* expectedResult */)
.verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli());
}
@Test
public void testSuggestNetworkTime_autoTimeEnabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_NETWORK)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
NetworkTimeSuggestion timeSuggestion =
- mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
- mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@Test
public void testSuggestNetworkTime_autoTimeDisabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_NETWORK)
- .pokeAutoTimeDetectionEnabled(false);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
NetworkTimeSuggestion timeSuggestion =
- mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing()
+ script.simulateTimePassing()
.simulateNetworkTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_NETWORK)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
- NetworkTimeSuggestion timeSuggestion = mScript
- .generateNetworkTimeSuggestion(suggestedTime);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(suggestedTime);
- mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestNetworkSuggestion(null);
}
@Test
public void testSuggestGnssTime_autoTimeEnabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_GNSS)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
GnssTimeSuggestion timeSuggestion =
- mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
- mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
+ script.simulateGnssTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@Test
public void testSuggestGnssTime_autoTimeDisabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_GNSS)
- .pokeAutoTimeDetectionEnabled(false);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
GnssTimeSuggestion timeSuggestion =
- mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing()
+ script.simulateTimePassing()
.simulateGnssTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void testSuggestExternalTime_autoTimeEnabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_EXTERNAL)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
ExternalTimeSuggestion timeSuggestion =
- mScript.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing();
+ script.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
- mScript.simulateExternalTimeSuggestion(timeSuggestion)
+ script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
+ script.simulateExternalTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@Test
public void testSuggestExternalTime_autoTimeDisabled() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_EXTERNAL)
- .pokeAutoTimeDetectionEnabled(false);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
ExternalTimeSuggestion timeSuggestion =
- mScript.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateTimePassing()
+ script.simulateTimePassing()
.simulateExternalTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void externalTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ Script script = new Script()
.pokeAutoOriginPriorities(ORIGIN_EXTERNAL)
- .pokeAutoTimeDetectionEnabled(true);
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
- ExternalTimeSuggestion timeSuggestion = mScript
- .generateExternalTimeSuggestion(suggestedTime);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(suggestedTime);
- mScript.simulateExternalTimeSuggestion(timeSuggestion)
+ script.simulateExternalTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestExternalSuggestion(null);
}
@Test
public void highPrioritySuggestionsBeatLowerPrioritySuggestions_telephonyNetworkOrigins() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
// Three obviously different times that could not be mistaken for each other.
@@ -668,99 +687,99 @@ public class TimeDetectorStrategyImplTest {
// A network suggestion is made. It should be used because there is no telephony suggestion.
NetworkTimeSuggestion networkTimeSuggestion1 =
- mScript.generateNetworkTimeSuggestion(networkTime1);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateNetworkTimeSuggestion(networkTime1);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(
+ script.calculateTimeInMillisForNow(
networkTimeSuggestion1.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, null)
+ script.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, null)
.assertLatestNetworkSuggestion(networkTimeSuggestion1);
- assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
- assertNull("No telephony suggestions were made:", mScript.peekBestTelephonySuggestion());
+ assertEquals(networkTimeSuggestion1, script.peekLatestValidNetworkSuggestion());
+ assertNull("No telephony suggestions were made:", script.peekBestTelephonySuggestion());
// Simulate a little time passing.
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.simulateTimePassing(smallTimeIncrementMillis)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now a telephony suggestion is made. Telephony suggestions are prioritized over network
// suggestions so it should "win".
TelephonyTimeSuggestion telephonyTimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(
+ script.calculateTimeInMillisForNow(
telephonyTimeSuggestion.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ script.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion1);
- assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
- assertEquals(telephonyTimeSuggestion, mScript.peekBestTelephonySuggestion());
+ assertEquals(networkTimeSuggestion1, script.peekLatestValidNetworkSuggestion());
+ assertEquals(telephonyTimeSuggestion, script.peekBestTelephonySuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now another network suggestion is made. Telephony suggestions are prioritized over
// network suggestions so the latest telephony suggestion should still "win".
NetworkTimeSuggestion networkTimeSuggestion2 =
- mScript.generateNetworkTimeSuggestion(networkTime2);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateNetworkTimeSuggestion(networkTime2);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ script.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion2);
- assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
- assertEquals(telephonyTimeSuggestion, mScript.peekBestTelephonySuggestion());
+ assertEquals(networkTimeSuggestion2, script.peekLatestValidNetworkSuggestion());
+ assertEquals(telephonyTimeSuggestion, script.peekBestTelephonySuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
// be used but networkTimeSuggestion2 is not.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
// suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
// to re-run the detection logic. This may change in future but until then we rely on a
// steady stream of suggestions to re-evaluate.
- mScript.verifySystemClockWasNotSetAndResetCallTracking();
+ script.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ script.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion2);
- assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(networkTimeSuggestion2, script.peekLatestValidNetworkSuggestion());
assertNull(
"Telephony suggestion should be expired:",
- mScript.peekBestTelephonySuggestion());
+ script.peekBestTelephonySuggestion());
// Toggle auto-time off and on to force the detection logic to run.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.simulateTimePassing(smallTimeIncrementMillis)
.simulateAutoTimeDetectionToggle();
// Verify the latest network time now wins.
- mScript.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(networkTimeSuggestion2.getUnixEpochTime()));
+ script.verifySystemClockWasSetAndResetCallTracking(
+ script.calculateTimeInMillisForNow(networkTimeSuggestion2.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ script.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion2);
- assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(networkTimeSuggestion2, script.peekLatestValidNetworkSuggestion());
assertNull(
"Telephony suggestion should still be expired:",
- mScript.peekBestTelephonySuggestion());
+ script.peekBestTelephonySuggestion());
}
@Test
public void highPrioritySuggestionsBeatLowerPrioritySuggestions_networkGnssOrigins() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_NETWORK, ORIGIN_GNSS);
// Three obviously different times that could not be mistaken for each other.
@@ -773,99 +792,99 @@ public class TimeDetectorStrategyImplTest {
// A gnss suggestion is made. It should be used because there is no network suggestion.
GnssTimeSuggestion gnssTimeSuggestion1 =
- mScript.generateGnssTimeSuggestion(gnssTime1);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateGnssTimeSuggestion(gnssTime1);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateGnssTimeSuggestion(gnssTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(
+ script.calculateTimeInMillisForNow(
gnssTimeSuggestion1.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestNetworkSuggestion(null)
+ script.assertLatestNetworkSuggestion(null)
.assertLatestGnssSuggestion(gnssTimeSuggestion1);
- assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion());
- assertNull("No network suggestions were made:", mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(gnssTimeSuggestion1, script.peekLatestValidGnssSuggestion());
+ assertNull("No network suggestions were made:", script.peekLatestValidNetworkSuggestion());
// Simulate a little time passing.
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.simulateTimePassing(smallTimeIncrementMillis)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now a network suggestion is made. Network suggestions are prioritized over gnss
// suggestions so it should "win".
NetworkTimeSuggestion networkTimeSuggestion =
- mScript.generateNetworkTimeSuggestion(networkTime);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateNetworkTimeSuggestion(networkTime);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(
+ script.calculateTimeInMillisForNow(
networkTimeSuggestion.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestGnssSuggestion(gnssTimeSuggestion1);
- assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion());
- assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(gnssTimeSuggestion1, script.peekLatestValidGnssSuggestion());
+ assertEquals(networkTimeSuggestion, script.peekLatestValidNetworkSuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now another gnss suggestion is made. Network suggestions are prioritized over
// gnss suggestions so the latest network suggestion should still "win".
GnssTimeSuggestion gnssTimeSuggestion2 =
- mScript.generateGnssTimeSuggestion(gnssTime2);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateGnssTimeSuggestion(gnssTime2);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateGnssTimeSuggestion(gnssTimeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestGnssSuggestion(gnssTimeSuggestion2);
- assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
- assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(gnssTimeSuggestion2, script.peekLatestValidGnssSuggestion());
+ assertEquals(networkTimeSuggestion, script.peekLatestValidNetworkSuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
// be used but networkTimeSuggestion2 is not.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
// suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
// to re-run the detection logic. This may change in future but until then we rely on a
// steady stream of suggestions to re-evaluate.
- mScript.verifySystemClockWasNotSetAndResetCallTracking();
+ script.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestGnssSuggestion(gnssTimeSuggestion2);
- assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+ assertEquals(gnssTimeSuggestion2, script.peekLatestValidGnssSuggestion());
assertNull(
"Network suggestion should be expired:",
- mScript.peekLatestValidNetworkSuggestion());
+ script.peekLatestValidNetworkSuggestion());
// Toggle auto-time off and on to force the detection logic to run.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.simulateTimePassing(smallTimeIncrementMillis)
.simulateAutoTimeDetectionToggle();
// Verify the latest gnss time now wins.
- mScript.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUnixEpochTime()));
+ script.verifySystemClockWasSetAndResetCallTracking(
+ script.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestGnssSuggestion(gnssTimeSuggestion2);
- assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+ assertEquals(gnssTimeSuggestion2, script.peekLatestValidGnssSuggestion());
assertNull(
"Network suggestion should still be expired:",
- mScript.peekLatestValidNetworkSuggestion());
+ script.peekLatestValidNetworkSuggestion());
}
@Test
public void highPrioritySuggestionsBeatLowerPrioritySuggestions_networkExternalOrigins() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_NETWORK, ORIGIN_EXTERNAL);
// Three obviously different times that could not be mistaken for each other.
@@ -878,99 +897,99 @@ public class TimeDetectorStrategyImplTest {
// A external suggestion is made. It should be used because there is no network suggestion.
ExternalTimeSuggestion externalTimeSuggestion1 =
- mScript.generateExternalTimeSuggestion(externalTime1);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateExternalTimeSuggestion(externalTime1);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateExternalTimeSuggestion(externalTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(
+ script.calculateTimeInMillisForNow(
externalTimeSuggestion1.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestNetworkSuggestion(null)
+ script.assertLatestNetworkSuggestion(null)
.assertLatestExternalSuggestion(externalTimeSuggestion1);
- assertEquals(externalTimeSuggestion1, mScript.peekLatestValidExternalSuggestion());
- assertNull("No network suggestions were made:", mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(externalTimeSuggestion1, script.peekLatestValidExternalSuggestion());
+ assertNull("No network suggestions were made:", script.peekLatestValidNetworkSuggestion());
// Simulate a little time passing.
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.simulateTimePassing(smallTimeIncrementMillis)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now a network suggestion is made. Network suggestions are prioritized over external
// suggestions so it should "win".
NetworkTimeSuggestion networkTimeSuggestion =
- mScript.generateNetworkTimeSuggestion(networkTime);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateNetworkTimeSuggestion(networkTime);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(
+ script.calculateTimeInMillisForNow(
networkTimeSuggestion.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestExternalSuggestion(externalTimeSuggestion1);
- assertEquals(externalTimeSuggestion1, mScript.peekLatestValidExternalSuggestion());
- assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(externalTimeSuggestion1, script.peekLatestValidExternalSuggestion());
+ assertEquals(networkTimeSuggestion, script.peekLatestValidNetworkSuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now another external suggestion is made. Network suggestions are prioritized over
// external suggestions so the latest network suggestion should still "win".
ExternalTimeSuggestion externalTimeSuggestion2 =
- mScript.generateExternalTimeSuggestion(externalTime2);
- mScript.simulateTimePassing(smallTimeIncrementMillis)
+ script.generateExternalTimeSuggestion(externalTime2);
+ script.simulateTimePassing(smallTimeIncrementMillis)
.simulateExternalTimeSuggestion(externalTimeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestExternalSuggestion(externalTimeSuggestion2);
- assertEquals(externalTimeSuggestion2, mScript.peekLatestValidExternalSuggestion());
- assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+ assertEquals(externalTimeSuggestion2, script.peekLatestValidExternalSuggestion());
+ assertEquals(networkTimeSuggestion, script.peekLatestValidNetworkSuggestion());
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use". This should mean that networkTimeSuggestion is now too old to
// be used but externalTimeSuggestion2 is not.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
+ script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
// suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
// to re-run the detection logic. This may change in future but until then we rely on a
// steady stream of suggestions to re-evaluate.
- mScript.verifySystemClockWasNotSetAndResetCallTracking();
+ script.verifySystemClockWasNotSetAndResetCallTracking();
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestExternalSuggestion(externalTimeSuggestion2);
- assertEquals(externalTimeSuggestion2, mScript.peekLatestValidExternalSuggestion());
+ assertEquals(externalTimeSuggestion2, script.peekLatestValidExternalSuggestion());
assertNull(
"Network suggestion should be expired:",
- mScript.peekLatestValidNetworkSuggestion());
+ script.peekLatestValidNetworkSuggestion());
// Toggle auto-time off and on to force the detection logic to run.
- mScript.simulateAutoTimeDetectionToggle()
+ script.simulateAutoTimeDetectionToggle()
.simulateTimePassing(smallTimeIncrementMillis)
.simulateAutoTimeDetectionToggle();
// Verify the latest external time now wins.
- mScript.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(externalTimeSuggestion2.getUnixEpochTime()));
+ script.verifySystemClockWasSetAndResetCallTracking(
+ script.calculateTimeInMillisForNow(externalTimeSuggestion2.getUnixEpochTime()));
// Check internal state.
- mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ script.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestExternalSuggestion(externalTimeSuggestion2);
- assertEquals(externalTimeSuggestion2, mScript.peekLatestValidExternalSuggestion());
+ assertEquals(externalTimeSuggestion2, script.peekLatestValidExternalSuggestion());
assertNull(
"Network suggestion should still be expired:",
- mScript.peekLatestValidNetworkSuggestion());
+ script.peekLatestValidNetworkSuggestion());
}
@Test
public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_EXTERNAL,
ORIGIN_GNSS);
@@ -980,15 +999,15 @@ public class TimeDetectorStrategyImplTest {
Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
NetworkTimeSuggestion networkTimeSuggestion =
- mScript.generateNetworkTimeSuggestion(networkTime);
+ script.generateNetworkTimeSuggestion(networkTime);
ExternalTimeSuggestion externalTimeSuggestion =
- mScript.generateExternalTimeSuggestion(externalTime);
+ script.generateExternalTimeSuggestion(externalTime);
GnssTimeSuggestion gnssTimeSuggestion =
- mScript.generateGnssTimeSuggestion(gnssTime);
+ script.generateGnssTimeSuggestion(gnssTime);
TelephonyTimeSuggestion telephonyTimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
- mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ script.simulateNetworkTimeSuggestion(networkTimeSuggestion)
.simulateExternalTimeSuggestion(externalTimeSuggestion)
.simulateGnssTimeSuggestion(gnssTimeSuggestion)
.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
@@ -1001,8 +1020,8 @@ public class TimeDetectorStrategyImplTest {
@Test
public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK,
ORIGIN_EXTERNAL, ORIGIN_GNSS);
@@ -1012,15 +1031,15 @@ public class TimeDetectorStrategyImplTest {
Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
NetworkTimeSuggestion networkTimeSuggestion =
- mScript.generateNetworkTimeSuggestion(networkTime);
+ script.generateNetworkTimeSuggestion(networkTime);
TelephonyTimeSuggestion telephonyTimeSuggestion =
- mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
GnssTimeSuggestion gnssTimeSuggestion =
- mScript.generateGnssTimeSuggestion(gnssTime);
+ script.generateGnssTimeSuggestion(gnssTime);
ExternalTimeSuggestion externalTimeSuggestion =
- mScript.generateExternalTimeSuggestion(externalTime);
+ script.generateExternalTimeSuggestion(externalTime);
- mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ script.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.simulateNetworkTimeSuggestion(networkTimeSuggestion)
.simulateGnssTimeSuggestion(gnssTimeSuggestion)
.simulateExternalTimeSuggestion(externalTimeSuggestion)
@@ -1033,144 +1052,144 @@ public class TimeDetectorStrategyImplTest {
@Test
public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
NetworkTimeSuggestion timeSuggestion =
- mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
.assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
}
@Test
public void whenHigherPrioritySuggestionsAreNotAvailable_fallbacksToNext() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK,
ORIGIN_EXTERNAL, ORIGIN_GNSS);
GnssTimeSuggestion timeSuggestion =
- mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ script.simulateGnssTimeSuggestion(timeSuggestion)
.assertLatestGnssSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
}
@Test
public void suggestionsFromTelephonyOriginNotInPriorityList_areIgnored() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_NETWORK);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+ script.generateTelephonyTimeSuggestion(slotIndex, testTime);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
- NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion(
+ NetworkTimeSuggestion timeSuggestion = script.generateNetworkTimeSuggestion(
ARBITRARY_TEST_TIME);
- mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
.assertLatestNetworkSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
- GnssTimeSuggestion timeSuggestion = mScript.generateGnssTimeSuggestion(
+ GnssTimeSuggestion timeSuggestion = script.generateGnssTimeSuggestion(
ARBITRARY_TEST_TIME);
- mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ script.simulateGnssTimeSuggestion(timeSuggestion)
.assertLatestGnssSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void suggestionsFromExternalOriginNotInPriorityList_areIgnored() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
- ExternalTimeSuggestion timeSuggestion = mScript.generateExternalTimeSuggestion(
+ ExternalTimeSuggestion timeSuggestion = script.generateExternalTimeSuggestion(
ARBITRARY_TEST_TIME);
- mScript.simulateExternalTimeSuggestion(timeSuggestion)
+ script.simulateExternalTimeSuggestion(timeSuggestion)
.assertLatestExternalSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void autoOriginPrioritiesList_doesNotAffectManualSuggestion() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(false)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
ManualTimeSuggestion timeSuggestion =
- mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
+ script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
- mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */)
+ script.simulateManualTimeSuggestion(USER_ID, timeSuggestion, true /* expectedResult */)
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
}
@Test
public void manualY2038SuggestionsAreRejectedOnAffectedDevices() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(false)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
.pokeDeviceHasY2038Issues(true);
Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- ManualTimeSuggestion timeSuggestion = mScript.generateManualTimeSuggestion(y2038IssueTime);
- mScript.simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */)
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(y2038IssueTime);
+ script.simulateManualTimeSuggestion(USER_ID, timeSuggestion, false /* expectedResult */)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void telephonyY2038SuggestionsAreRejectedOnAffectedDevices() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
.pokeDeviceHasY2038Issues(true);
final int slotIndex = 0;
Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
public void telephonyY2038SuggestionsAreNotRejectedOnUnaffectedDevices() {
- mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
- .pokeAutoTimeDetectionEnabled(true)
+ Script script = new Script()
+ .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY)
.pokeDeviceHasY2038Issues(false);
final int slotIndex = 0;
Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
TelephonyTimeSuggestion timeSuggestion =
- mScript.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
- mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(y2038IssueTime.toEpochMilli());
}
@@ -1179,21 +1198,31 @@ public class TimeDetectorStrategyImplTest {
* changes and behaving like the real thing should, it also asserts preconditions.
*/
private static class FakeEnvironment implements TimeDetectorStrategyImpl.Environment {
- private boolean mAutoTimeDetectionEnabled;
+
+ private ConfigurationInternal mConfigurationInternal;
private boolean mWakeLockAcquired;
private long mElapsedRealtimeMillis;
private long mSystemClockMillis;
private int mSystemClockUpdateThresholdMillis = 2000;
private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY;
- private ConfigurationChangeListener mConfigChangeListener;
+ private ConfigurationChangeListener mConfigurationInternalChangeListener;
private boolean mDeviceHas2038Issues = false;
// Tracking operations.
private boolean mSystemClockWasSet;
+ void initializeConfig(ConfigurationInternal configurationInternal) {
+ mConfigurationInternal = configurationInternal;
+ }
+
+ public void initializeFakeClocks(TimestampedValue timeInfo) {
+ pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
+ pokeSystemClockMillis(timeInfo.getValue().toEpochMilli());
+ }
+
@Override
- public void setConfigChangeListener(ConfigurationChangeListener listener) {
- mConfigChangeListener = Objects.requireNonNull(listener);
+ public void setConfigurationInternalChangeListener(ConfigurationChangeListener listener) {
+ mConfigurationInternalChangeListener = Objects.requireNonNull(listener);
}
@Override
@@ -1201,11 +1230,6 @@ public class TimeDetectorStrategyImplTest {
return mSystemClockUpdateThresholdMillis;
}
- @Override
- public boolean isAutoTimeDetectionEnabled() {
- return mAutoTimeDetectionEnabled;
- }
-
@Override
public Instant autoTimeLowerBound() {
return TIME_LOWER_BOUND;
@@ -1217,8 +1241,8 @@ public class TimeDetectorStrategyImplTest {
}
@Override
- public ConfigurationInternal configurationInternal(int userId) {
- throw new UnsupportedOperationException();
+ public ConfigurationInternal getCurrentUserConfigurationInternal() {
+ return mConfigurationInternal;
}
@Override
@@ -1263,6 +1287,11 @@ public class TimeDetectorStrategyImplTest {
// Methods below are for managing the fake's behavior.
+ void simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
+ mConfigurationInternal = configurationInternal;
+ mConfigurationInternalChangeListener.onChange();
+ }
+
void pokeSystemClockUpdateThreshold(int thresholdMillis) {
mSystemClockUpdateThresholdMillis = thresholdMillis;
}
@@ -1275,10 +1304,6 @@ public class TimeDetectorStrategyImplTest {
mSystemClockMillis = systemClockMillis;
}
- void pokeAutoTimeDetectionEnabled(boolean enabled) {
- mAutoTimeDetectionEnabled = enabled;
- }
-
void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) {
mAutoOriginPriorities = autoOriginPriorities;
}
@@ -1296,11 +1321,6 @@ public class TimeDetectorStrategyImplTest {
mSystemClockMillis += incrementMillis;
}
- void simulateAutoTimeZoneDetectionToggle() {
- mAutoTimeDetectionEnabled = !mAutoTimeDetectionEnabled;
- mConfigChangeListener.onChange();
- }
-
void verifySystemClockNotSet() {
assertFalse(
String.format("System clock was manipulated and set to %s(=%s)",
@@ -1328,7 +1348,6 @@ public class TimeDetectorStrategyImplTest {
*/
private class Script {
- private final FakeEnvironment mFakeEnvironment;
private final TimeDetectorStrategyImpl mTimeDetectorStrategy;
Script() {
@@ -1336,17 +1355,6 @@ public class TimeDetectorStrategyImplTest {
mTimeDetectorStrategy = new TimeDetectorStrategyImpl(mFakeEnvironment);
}
- Script pokeAutoTimeDetectionEnabled(boolean enabled) {
- mFakeEnvironment.pokeAutoTimeDetectionEnabled(enabled);
- return this;
- }
-
- Script pokeFakeClocks(TimestampedValue timeInfo) {
- mFakeEnvironment.pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
- mFakeEnvironment.pokeSystemClockMillis(timeInfo.getValue().toEpochMilli());
- return this;
- }
-
Script pokeThresholds(int systemClockUpdateThreshold) {
mFakeEnvironment.pokeSystemClockUpdateThreshold(systemClockUpdateThreshold);
return this;
@@ -1370,20 +1378,29 @@ public class TimeDetectorStrategyImplTest {
return mFakeEnvironment.peekSystemClockMillis();
}
+ /**
+ * Simulates the user / user's configuration changing.
+ */
+ Script simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
+ mFakeEnvironment.simulateConfigurationInternalChange(configurationInternal);
+ return this;
+ }
+
Script simulateTelephonyTimeSuggestion(TelephonyTimeSuggestion timeSuggestion) {
mTimeDetectorStrategy.suggestTelephonyTime(timeSuggestion);
return this;
}
Script simulateManualTimeSuggestion(
- ManualTimeSuggestion timeSuggestion, boolean expectedResult) {
+ @UserIdInt int userId, ManualTimeSuggestion timeSuggestion,
+ boolean expectedResult) {
String errorMessage = expectedResult
? "Manual time suggestion was ignored, but expected to be accepted."
: "Manual time suggestion was accepted, but expected to be ignored.";
assertEquals(
errorMessage,
expectedResult,
- mTimeDetectorStrategy.suggestManualTime(timeSuggestion));
+ mTimeDetectorStrategy.suggestManualTime(userId, timeSuggestion));
return this;
}
@@ -1403,7 +1420,15 @@ public class TimeDetectorStrategyImplTest {
}
Script simulateAutoTimeDetectionToggle() {
- mFakeEnvironment.simulateAutoTimeZoneDetectionToggle();
+ ConfigurationInternal configurationInternal =
+ mFakeEnvironment.getCurrentUserConfigurationInternal();
+ boolean autoDetectionEnabledSetting =
+ !configurationInternal.getAutoDetectionEnabledSetting();
+ ConfigurationInternal newConfigurationInternal =
+ new ConfigurationInternal.Builder(configurationInternal)
+ .setAutoDetectionEnabledSetting(autoDetectionEnabledSetting)
+ .build();
+ mFakeEnvironment.simulateConfigurationInternalChange(newConfigurationInternal);
return this;
}