diff --git a/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java b/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
index 1867ee207958b..3b3254985abca 100644
--- a/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
+++ b/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
@@ -16,9 +16,11 @@
package com.android.server.timezonedetector;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.ShellCommand;
+import android.os.SystemClock;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -29,27 +31,39 @@ import java.util.Objects;
import java.util.StringTokenizer;
/**
- * A time zone suggestion from a geolocation source.
+ * A time zone suggestion from the location_time_zone_manager service to the time_zone_detector
+ * service.
*
- *
Geolocation-based suggestions have the following properties:
+ *
Geolocation-based suggestions have the following properties:
*
*
+ * - {@code effectiveFromElapsedMillis}: The time according to the elapsed realtime clock
+ * after which the suggestion should be considered in effect. For example, when a location fix
+ * used to establish the time zone is old, then the suggestion
+ * {@code effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
+ * detected / correct at that time. The time_zone_detector is only expected to use the latest
+ * suggestion it has received, and so later suggestions always counteract previous suggestions.
+ * The inclusion of this information means that the time_zone_detector can take into account
+ * ordering when comparing suggestions from different sources.
+ *
Note: Because the times can be back-dated, time_zone_detector can be sent a sequence of
+ * suggestions where the {@code effectiveFromElapsedMillis} of later suggestions is before
+ * the {@code effectiveFromElapsedMillis} of an earlier one.
* - {@code zoneIds}. When not {@code null}, {@code zoneIds} contains a list of suggested time
* zone IDs, e.g. ["America/Phoenix", "America/Denver"]. Usually there will be a single zoneId.
* When there are multiple, this indicates multiple answers are possible for the current
- * location / accuracy, i.e. if there is a nearby time zone border. The detection logic
- * receiving the suggestion is expected to use the first element in the absence of other
- * information, but one of the others may be used if there is supporting evidence / preferences
- * such as a device setting or corroborating signals from another source.
+ * location / accuracy, e.g. if there is a nearby time zone border. The time_zone_detector is
+ * expected to use the first element in the absence of other information, but one of the other
+ * zone IDs may be used if there is supporting evidence / preferences such as a device setting
+ * or corroborating signals from another source.
*
{@code zoneIds} can be empty if the current location has been determined to have no
* time zone. For example, oceans or disputed areas. This is considered a strong signal and the
- * received need not look for time zone from other sources.
- *
{@code zoneIds} can be {@code null} to indicate that the geolocation source has entered
- * an "un-opinionated" state and any previous suggestion is being withdrawn. This indicates the
- * source cannot provide a valid suggestion due to technical limitations. For example, a
- * geolocation source may become un-opinionated if the device's location is no longer known with
- * sufficient accuracy, or if the location is known but no time zone can be determined because
- * no time zone mapping information is available.
+ * time_zone_detector need not look for time zone from other sources.
+ *
{@code zoneIds} can be {@code null} to indicate that the location_time_zone_manager has
+ * entered an "uncertain" state and any previous suggestion is being withdrawn. This indicates
+ * the location_time_zone_manager cannot provide a valid suggestion. For example, the
+ * location_time_zone_manager may become uncertain if components further downstream cannot
+ * determine the device's location with sufficient accuracy, or if the location is known but no
+ * time zone can be determined because no time zone mapping information is available.
* - {@code debugInfo} contains debugging metadata associated with the suggestion. This is
* used to record why the suggestion exists and how it was obtained. This information exists
* only to aid in debugging and therefore is used by {@link #toString()}, but it is not for use
@@ -61,10 +75,14 @@ import java.util.StringTokenizer;
*/
public final class GeolocationTimeZoneSuggestion {
+ @ElapsedRealtimeLong private final long mEffectiveFromElapsedMillis;
@Nullable private final List mZoneIds;
@Nullable private ArrayList mDebugInfo;
- public GeolocationTimeZoneSuggestion(@Nullable List zoneIds) {
+ private GeolocationTimeZoneSuggestion(
+ @ElapsedRealtimeLong long effectiveFromElapsedMillis,
+ @Nullable List zoneIds) {
+ mEffectiveFromElapsedMillis = effectiveFromElapsedMillis;
if (zoneIds == null) {
// Unopinionated
mZoneIds = null;
@@ -73,6 +91,34 @@ public final class GeolocationTimeZoneSuggestion {
}
}
+ /**
+ * Creates a "uncertain" suggestion instance.
+ */
+ @NonNull
+ public static GeolocationTimeZoneSuggestion createUncertainSuggestion(
+ @ElapsedRealtimeLong long effectiveFromElapsedMillis) {
+ return new GeolocationTimeZoneSuggestion(effectiveFromElapsedMillis, null);
+ }
+
+ /**
+ * Creates a "certain" suggestion instance.
+ */
+ @NonNull
+ public static GeolocationTimeZoneSuggestion createCertainSuggestion(
+ @ElapsedRealtimeLong long effectiveFromElapsedMillis,
+ @NonNull List zoneIds) {
+ return new GeolocationTimeZoneSuggestion(effectiveFromElapsedMillis, zoneIds);
+ }
+
+ /**
+ * Returns the "effective from" time associated with the suggestion. See {@link
+ * GeolocationTimeZoneSuggestion} for details.
+ */
+ @ElapsedRealtimeLong
+ public long getEffectiveFromElapsedMillis() {
+ return mEffectiveFromElapsedMillis;
+ }
+
/**
* Returns the zone Ids being suggested. See {@link GeolocationTimeZoneSuggestion} for details.
*/
@@ -110,18 +156,20 @@ public final class GeolocationTimeZoneSuggestion {
}
GeolocationTimeZoneSuggestion
that = (GeolocationTimeZoneSuggestion) o;
- return Objects.equals(mZoneIds, that.mZoneIds);
+ return mEffectiveFromElapsedMillis == that.mEffectiveFromElapsedMillis
+ && Objects.equals(mZoneIds, that.mZoneIds);
}
@Override
public int hashCode() {
- return Objects.hash(mZoneIds);
+ return Objects.hash(mEffectiveFromElapsedMillis, mZoneIds);
}
@Override
public String toString() {
return "GeolocationTimeZoneSuggestion{"
- + "mZoneIds=" + mZoneIds
+ + "mEffectiveFromElapsedMillis=" + mEffectiveFromElapsedMillis
+ + ", mZoneIds=" + mZoneIds
+ ", mDebugInfo=" + mDebugInfo
+ '}';
}
@@ -141,8 +189,11 @@ public final class GeolocationTimeZoneSuggestion {
}
}
}
+
+ long elapsedRealtimeMillis = SystemClock.elapsedRealtime();
List zoneIds = parseZoneIdsArg(zoneIdsString);
- GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(zoneIds);
+ GeolocationTimeZoneSuggestion suggestion =
+ new GeolocationTimeZoneSuggestion(elapsedRealtimeMillis, zoneIds);
suggestion.addDebugInfo("Command line injection");
return suggestion;
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
index 551a05950b27c..20fb61ddf83d1 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
@@ -16,7 +16,9 @@
package com.android.server.timezonedetector.location;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
+import android.os.SystemClock;
import com.android.server.LocalServices;
import com.android.server.timezonedetector.ConfigurationChangeListener;
@@ -83,4 +85,9 @@ class ControllerEnvironmentImpl extends LocationTimeZoneProviderController.Envir
Duration getProviderEventFilteringAgeThreshold() {
return mServiceConfigAccessor.getLocationTimeZoneProviderEventFilteringAgeThreshold();
}
+
+ @Override
+ @ElapsedRealtimeLong long elapsedRealtimeMillis() {
+ return SystemClock.elapsedRealtime();
+ }
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
index 1d58cea1be3d5..466a0391746f7 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
@@ -31,10 +31,11 @@ import static com.android.server.timezonedetector.location.LocationTimeZoneProvi
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
import android.annotation.DurationMillisLong;
-import android.annotation.IntRange;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderSuggestion;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
@@ -43,7 +44,6 @@ import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
import com.android.server.timezonedetector.location.ThreadingDomain.SingleRunnableQueue;
import java.time.Duration;
-import java.util.List;
import java.util.Objects;
/**
@@ -184,7 +184,7 @@ class ControllerImpl extends LocationTimeZoneProviderController {
// re-started).
if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
- "Providers are stopping");
+ mEnvironment.elapsedRealtimeMillis(), "Providers are stopping");
makeSuggestion(suggestion);
}
}
@@ -272,6 +272,7 @@ class ControllerImpl extends LocationTimeZoneProviderController {
// If both providers are {perm failed} then the controller immediately
// becomes uncertain.
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+ mEnvironment.elapsedRealtimeMillis(),
"Providers are failed:"
+ " primary=" + mPrimaryProvider.getCurrentState()
+ " secondary=" + mPrimaryProvider.getCurrentState());
@@ -410,6 +411,7 @@ class ControllerImpl extends LocationTimeZoneProviderController {
// If both providers are now terminated, then a suggestion must be sent informing the
// time zone detector that there are no further updates coming in future.
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+ mEnvironment.elapsedRealtimeMillis(),
"Both providers are terminated:"
+ " primary=" + primaryCurrentState.provider
+ ", secondary=" + secondaryCurrentState.provider);
@@ -432,8 +434,9 @@ class ControllerImpl extends LocationTimeZoneProviderController {
// the loss of a binder-based provider, or initialization took too long. This is treated
// the same as explicit uncertainty, i.e. where the provider has explicitly told this
// process it is uncertain.
- handleProviderUncertainty(provider, "provider=" + provider
- + ", implicit uncertainty, event=null");
+ long uncertaintyStartedElapsedMillis = mEnvironment.elapsedRealtimeMillis();
+ handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
+ "provider=" + provider + ", implicit uncertainty, event=null");
return;
}
@@ -448,18 +451,17 @@ class ControllerImpl extends LocationTimeZoneProviderController {
switch (event.getType()) {
case EVENT_TYPE_PERMANENT_FAILURE: {
// This shouldn't happen. A provider cannot be started and have this event type.
- warnLog("Provider=" + provider
- + " is started, but event suggests it shouldn't be");
+ warnLog("Provider=" + provider + " is started, but event suggests it shouldn't be");
break;
}
case EVENT_TYPE_UNCERTAIN: {
- handleProviderUncertainty(provider, "provider=" + provider
- + ", explicit uncertainty. event=" + event);
+ long uncertaintyStartedElapsedMillis = event.getCreationElapsedMillis();
+ handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
+ "provider=" + provider + ", explicit uncertainty. event=" + event);
break;
}
case EVENT_TYPE_SUGGESTION: {
- handleProviderSuggestion(provider, event.getSuggestion().getTimeZoneIds(),
- "Event received provider=" + provider + ", event=" + event);
+ handleProviderSuggestion(provider, event);
break;
}
default: {
@@ -475,8 +477,8 @@ class ControllerImpl extends LocationTimeZoneProviderController {
@GuardedBy("mSharedLock")
private void handleProviderSuggestion(
@NonNull LocationTimeZoneProvider provider,
- @Nullable List timeZoneIds,
- @NonNull String reason) {
+ @NonNull TimeZoneProviderEvent providerEvent) {
+
// By definition, the controller is now certain.
cancelUncertaintyTimeout();
@@ -484,10 +486,25 @@ class ControllerImpl extends LocationTimeZoneProviderController {
stopProviderIfStarted(mSecondaryProvider);
}
- GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(timeZoneIds);
- suggestion.addDebugInfo(reason);
- // Rely on the receiver to dedupe suggestions. It is better to over-communicate.
- makeSuggestion(suggestion);
+ TimeZoneProviderSuggestion providerSuggestion = providerEvent.getSuggestion();
+
+ // For the suggestion's effectiveFromElapsedMillis, use the time embedded in the provider's
+ // suggestion (which indicates the time when the provider detected the location used to
+ // establish the time zone).
+ //
+ // An alternative would be to use the current time or the providerEvent creation time, but
+ // this would hinder the ability for the time_zone_detector to judge which suggestions are
+ // based on newer information when comparing suggestions between different sources.
+ long effectiveFromElapsedMillis = providerSuggestion.getElapsedRealtimeMillis();
+ GeolocationTimeZoneSuggestion geoSuggestion =
+ GeolocationTimeZoneSuggestion.createCertainSuggestion(
+ effectiveFromElapsedMillis, providerSuggestion.getTimeZoneIds());
+
+ String debugInfo = "Event received provider=" + provider
+ + ", providerEvent=" + providerEvent
+ + ", suggestionCreationTime=" + mEnvironment.elapsedRealtimeMillis();
+ geoSuggestion.addDebugInfo(debugInfo);
+ makeSuggestion(geoSuggestion);
}
@Override
@@ -551,7 +568,9 @@ class ControllerImpl extends LocationTimeZoneProviderController {
*/
@GuardedBy("mSharedLock")
void handleProviderUncertainty(
- @NonNull LocationTimeZoneProvider provider, @NonNull String reason) {
+ @NonNull LocationTimeZoneProvider provider,
+ @ElapsedRealtimeLong long uncertaintyStartedElapsedMillis,
+ @NonNull String reason) {
Objects.requireNonNull(provider);
// Start the uncertainty timeout if needed to ensure the controller will eventually make an
@@ -559,9 +578,11 @@ class ControllerImpl extends LocationTimeZoneProviderController {
if (!mUncertaintyTimeoutQueue.hasQueued()) {
debugLog("Starting uncertainty timeout: reason=" + reason);
- Duration delay = mEnvironment.getUncertaintyDelay();
- mUncertaintyTimeoutQueue.runDelayed(() -> onProviderUncertaintyTimeout(provider),
- delay.toMillis());
+ Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
+ mUncertaintyTimeoutQueue.runDelayed(
+ () -> onProviderUncertaintyTimeout(
+ provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
+ uncertaintyDelay.toMillis());
}
if (provider == mPrimaryProvider) {
@@ -573,21 +594,45 @@ class ControllerImpl extends LocationTimeZoneProviderController {
}
}
- private void onProviderUncertaintyTimeout(@NonNull LocationTimeZoneProvider provider) {
+ private void onProviderUncertaintyTimeout(
+ @NonNull LocationTimeZoneProvider provider,
+ @ElapsedRealtimeLong long uncertaintyStartedElapsedMillis,
+ @NonNull Duration uncertaintyDelay) {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
+ long afterUncertaintyTimeoutElapsedMillis = mEnvironment.elapsedRealtimeMillis();
+
+ // For the effectiveFromElapsedMillis suggestion property, use the
+ // uncertaintyStartedElapsedMillis. This is the time when the provider first reported
+ // uncertainty, i.e. before the uncertainty timeout.
+ //
+ // afterUncertaintyTimeoutElapsedMillis could be used instead, which is the time when
+ // the location_time_zone_manager finally confirms that the time zone was uncertain,
+ // but the suggestion property allows the information to be back-dated, which should
+ // help when comparing suggestions from different sources.
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+ uncertaintyStartedElapsedMillis,
"Uncertainty timeout triggered for " + provider.getName() + ":"
+ " primary=" + mPrimaryProvider
- + ", secondary=" + mSecondaryProvider);
+ + ", secondary=" + mSecondaryProvider
+ + ", uncertaintyStarted="
+ + Duration.ofMillis(uncertaintyStartedElapsedMillis)
+ + ", afterUncertaintyTimeout="
+ + Duration.ofMillis(afterUncertaintyTimeoutElapsedMillis)
+ + ", uncertaintyDelay=" + uncertaintyDelay
+ );
makeSuggestion(suggestion);
}
}
@NonNull
- private static GeolocationTimeZoneSuggestion createUncertainSuggestion(@NonNull String reason) {
- GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(null);
+ private static GeolocationTimeZoneSuggestion createUncertainSuggestion(
+ @ElapsedRealtimeLong long effectiveFromElapsedMillis,
+ @NonNull String reason) {
+ GeolocationTimeZoneSuggestion suggestion =
+ GeolocationTimeZoneSuggestion.createUncertainSuggestion(
+ effectiveFromElapsedMillis);
suggestion.addDebugInfo(reason);
return suggestion;
}
@@ -622,19 +667,4 @@ class ControllerImpl extends LocationTimeZoneProviderController {
return builder.build();
}
}
-
- @Nullable
- private LocationTimeZoneProvider getLocationTimeZoneProvider(
- @IntRange(from = 0, to = 1) int providerIndex) {
- LocationTimeZoneProvider targetProvider;
- if (providerIndex == 0) {
- targetProvider = mPrimaryProvider;
- } else if (providerIndex == 1) {
- targetProvider = mSecondaryProvider;
- } else {
- warnLog("Bad providerIndex=" + providerIndex);
- targetProvider = null;
- }
- return targetProvider;
- }
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
index d2fd9a9f307e3..fdb9c14e7c597 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
@@ -17,6 +17,7 @@
package com.android.server.timezonedetector.location;
import android.annotation.DurationMillisLong;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.os.Handler;
@@ -140,6 +141,12 @@ abstract class LocationTimeZoneProviderController implements Dumpable {
* passed on.
*/
abstract Duration getUncertaintyDelay();
+
+ /**
+ * Returns the elapsed realtime as millis, the same as {@link
+ * android.os.SystemClock#elapsedRealtime()}.
+ */
+ abstract @ElapsedRealtimeLong long elapsedRealtimeMillis();
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/GeolocationTimeZoneSuggestionTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/GeolocationTimeZoneSuggestionTest.java
index 5870a70c49ae9..79f8b0e8d4c8d 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/GeolocationTimeZoneSuggestionTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/GeolocationTimeZoneSuggestionTest.java
@@ -34,26 +34,36 @@ public class GeolocationTimeZoneSuggestionTest {
@Test
public void testEquals() {
- GeolocationTimeZoneSuggestion one = new GeolocationTimeZoneSuggestion(ARBITRARY_ZONE_IDS1);
- assertEquals(one, one);
+ long time1 = 1111L;
+ GeolocationTimeZoneSuggestion certain1v1 =
+ GeolocationTimeZoneSuggestion.createCertainSuggestion(time1, ARBITRARY_ZONE_IDS1);
+ assertEquals(certain1v1, certain1v1);
- GeolocationTimeZoneSuggestion two = new GeolocationTimeZoneSuggestion(ARBITRARY_ZONE_IDS1);
- assertEquals(one, two);
- assertEquals(two, one);
-
- GeolocationTimeZoneSuggestion nullZone = new GeolocationTimeZoneSuggestion(null);
- assertNotEquals(one, nullZone);
- assertNotEquals(nullZone, one);
- assertEquals(nullZone, nullZone);
-
- GeolocationTimeZoneSuggestion three =
- new GeolocationTimeZoneSuggestion(ARBITRARY_ZONE_IDS2);
- assertNotEquals(one, three);
- assertNotEquals(three, one);
+ GeolocationTimeZoneSuggestion certain1v2 =
+ GeolocationTimeZoneSuggestion.createCertainSuggestion(time1, ARBITRARY_ZONE_IDS1);
+ assertEquals(certain1v1, certain1v2);
+ assertEquals(certain1v2, certain1v1);
// DebugInfo must not be considered in equals().
- one.addDebugInfo("Debug info 1");
- two.addDebugInfo("Debug info 2");
- assertEquals(one, two);
+ certain1v1.addDebugInfo("Debug info 1");
+ certain1v2.addDebugInfo("Debug info 2");
+ assertEquals(certain1v1, certain1v2);
+
+ long time2 = 2222L;
+ GeolocationTimeZoneSuggestion certain2 =
+ GeolocationTimeZoneSuggestion.createCertainSuggestion(time2, ARBITRARY_ZONE_IDS1);
+ assertNotEquals(certain1v1, certain2);
+ assertNotEquals(certain2, certain1v1);
+
+ GeolocationTimeZoneSuggestion uncertain =
+ GeolocationTimeZoneSuggestion.createUncertainSuggestion(time1);
+ assertNotEquals(certain1v1, uncertain);
+ assertNotEquals(uncertain, certain1v1);
+ assertEquals(uncertain, uncertain);
+
+ GeolocationTimeZoneSuggestion certain3 =
+ GeolocationTimeZoneSuggestion.createCertainSuggestion(time1, ARBITRARY_ZONE_IDS2);
+ assertNotEquals(certain1v1, certain3);
+ assertNotEquals(certain3, certain1v1);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
index 918babca677ed..586462006ee28 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
@@ -35,6 +35,7 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class TimeZoneDetectorInternalImplTest {
+ private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L;
private static final List ARBITRARY_ZONE_IDS = Arrays.asList("TestZoneId");
private Context mMockContext;
@@ -99,6 +100,7 @@ public class TimeZoneDetectorInternalImplTest {
}
private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() {
- return new GeolocationTimeZoneSuggestion(ARBITRARY_ZONE_IDS);
+ return GeolocationTimeZoneSuggestion.createCertainSuggestion(
+ ARBITRARY_ELAPSED_REALTIME_MILLIS, ARBITRARY_ZONE_IDS);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index 28838ae14f2f2..773abf86e18ab 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -50,11 +50,14 @@ import org.junit.runner.RunWith;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
+import java.util.List;
@RunWith(AndroidJUnit4.class)
public class TimeZoneDetectorServiceTest {
private static final int ARBITRARY_USER_ID = 9999;
+ private static final List ARBITRARY_TIME_ZONE_IDS = Arrays.asList("TestZoneId");
+ private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L;
private Context mMockContext;
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
@@ -374,7 +377,8 @@ public class TimeZoneDetectorServiceTest {
}
private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() {
- return new GeolocationTimeZoneSuggestion(Arrays.asList("TestZoneId"));
+ return GeolocationTimeZoneSuggestion.createCertainSuggestion(
+ ARBITRARY_ELAPSED_REALTIME_MILLIS, ARBITRARY_TIME_ZONE_IDS);
}
private static ManualTimeZoneSuggestion createManualTimeZoneSuggestion() {
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index 331f76cf7dc26..e2e875507c93a 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -33,10 +33,13 @@ import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.T
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.time.TimeZoneConfiguration;
@@ -171,6 +174,8 @@ public class TimeZoneDetectorStrategyImplTest {
private FakeEnvironment mFakeEnvironment;
private MockConfigChangeListener mMockConfigChangeListener;
+ // A fake source of time for suggestions. This will typically be incremented after every use.
+ @ElapsedRealtimeLong private long mElapsedRealtimeMillis;
@Before
public void setUp() {
@@ -487,7 +492,7 @@ public class TimeZoneDetectorStrategyImplTest {
*/
// Each test case will have the same or lower score than the last.
- List descendingCasesByScore = list(TELEPHONY_TEST_CASES);
+ List descendingCasesByScore = Arrays.asList(TELEPHONY_TEST_CASES);
Collections.reverse(descendingCasesByScore);
for (TelephonyTestCase testCase : descendingCasesByScore) {
@@ -750,7 +755,7 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
- GeolocationTimeZoneSuggestion uncertainSuggestion = createUncertainGeoLocationSuggestion();
+ GeolocationTimeZoneSuggestion uncertainSuggestion = createUncertainGeolocationSuggestion();
script.simulateGeolocationTimeZoneSuggestion(uncertainSuggestion)
.verifyTimeZoneNotChanged();
@@ -766,7 +771,7 @@ public class TimeZoneDetectorStrategyImplTest {
.initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
- GeolocationTimeZoneSuggestion noZonesSuggestion = createGeoLocationSuggestion(list());
+ GeolocationTimeZoneSuggestion noZonesSuggestion = createCertainGeolocationSuggestion();
script.simulateGeolocationTimeZoneSuggestion(noZonesSuggestion)
.verifyTimeZoneNotChanged();
@@ -778,7 +783,7 @@ public class TimeZoneDetectorStrategyImplTest {
@Test
public void testGeoSuggestion_oneZone() {
GeolocationTimeZoneSuggestion suggestion =
- createGeoLocationSuggestion(list("Europe/London"));
+ createCertainGeolocationSuggestion("Europe/London");
Script script = new Script()
.initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
@@ -799,11 +804,11 @@ public class TimeZoneDetectorStrategyImplTest {
@Test
public void testGeoSuggestion_multiZone() {
GeolocationTimeZoneSuggestion londonOnlySuggestion =
- createGeoLocationSuggestion(list("Europe/London"));
+ createCertainGeolocationSuggestion("Europe/London");
GeolocationTimeZoneSuggestion londonOrParisSuggestion =
- createGeoLocationSuggestion(list("Europe/Paris", "Europe/London"));
+ createCertainGeolocationSuggestion("Europe/Paris", "Europe/London");
GeolocationTimeZoneSuggestion parisOnlySuggestion =
- createGeoLocationSuggestion(list("Europe/Paris"));
+ createCertainGeolocationSuggestion("Europe/Paris");
Script script = new Script()
.initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
@@ -836,7 +841,7 @@ public class TimeZoneDetectorStrategyImplTest {
@Test
public void testGeoSuggestion_togglingGeoDetectionClearsLastSuggestion() {
GeolocationTimeZoneSuggestion suggestion =
- createGeoLocationSuggestion(list("Europe/London"));
+ createCertainGeolocationSuggestion("Europe/London");
Script script = new Script()
.initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
@@ -863,7 +868,7 @@ public class TimeZoneDetectorStrategyImplTest {
@Test
public void testChangingGeoDetectionEnabled() {
GeolocationTimeZoneSuggestion geolocationSuggestion =
- createGeoLocationSuggestion(list("Europe/London"));
+ createCertainGeolocationSuggestion("Europe/London");
TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion(
SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
"Europe/Paris");
@@ -960,7 +965,7 @@ public class TimeZoneDetectorStrategyImplTest {
createTelephonySuggestion(0 /* slotIndex */, MATCH_TYPE_NETWORK_COUNTRY_ONLY,
QUALITY_SINGLE_ZONE, "Zone2");
GeolocationTimeZoneSuggestion geolocationTimeZoneSuggestion =
- createGeoLocationSuggestion(Arrays.asList("Zone3", "Zone2"));
+ createCertainGeolocationSuggestion("Zone3", "Zone2");
script.simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
.verifyTimeZoneNotChanged()
.simulateGeolocationTimeZoneSuggestion(geolocationTimeZoneSuggestion)
@@ -1052,13 +1057,18 @@ public class TimeZoneDetectorStrategyImplTest {
return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX2).build();
}
- private static GeolocationTimeZoneSuggestion createUncertainGeoLocationSuggestion() {
- return createGeoLocationSuggestion(null);
+ private GeolocationTimeZoneSuggestion createUncertainGeolocationSuggestion() {
+ return GeolocationTimeZoneSuggestion.createCertainSuggestion(
+ mElapsedRealtimeMillis++, null);
}
- private static GeolocationTimeZoneSuggestion createGeoLocationSuggestion(
- @Nullable List zoneIds) {
- GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(zoneIds);
+ private GeolocationTimeZoneSuggestion createCertainGeolocationSuggestion(
+ @NonNull String... zoneIds) {
+ assertNotNull(zoneIds);
+
+ GeolocationTimeZoneSuggestion suggestion =
+ GeolocationTimeZoneSuggestion.createCertainSuggestion(
+ mElapsedRealtimeMillis++, Arrays.asList(zoneIds));
suggestion.addDebugInfo("Test suggestion");
return suggestion;
}
@@ -1321,8 +1331,4 @@ public class TimeZoneDetectorStrategyImplTest {
mOnChangeCalled = false;
}
}
-
- private static List list(T... values) {
- return Arrays.asList(values);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java
index 27d95461ee618..7d6772ef7bd01 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java
@@ -33,8 +33,10 @@ import static org.junit.Assert.fail;
import static java.util.Arrays.asList;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.service.timezone.TimeZoneProviderEvent;
import android.service.timezone.TimeZoneProviderSuggestion;
@@ -287,8 +289,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -326,8 +328,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -366,8 +368,8 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -395,8 +397,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// A second, identical event should not cause another suggestion.
@@ -416,8 +418,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -456,8 +458,8 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// A second, identical event should not cause another suggestion.
@@ -479,8 +481,8 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -508,8 +510,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the primary provider. This should not
@@ -535,8 +537,8 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the secondary provider. This should not
@@ -560,7 +562,8 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestCallback.assertUncertainSuggestionMadeAndCommit();
+ mTestCallback.assertUncertainSuggestionMadeFromEventAndCommit(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -588,8 +591,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
@@ -613,8 +616,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -682,8 +685,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
@@ -723,8 +726,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate the user change (but geo detection still enabled).
@@ -789,8 +792,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate uncertainty from the secondary.
@@ -896,8 +899,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate uncertainty from the primary. The secondary cannot be started.
@@ -1098,8 +1101,8 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
+ mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Trigger destroy().
@@ -1186,6 +1189,13 @@ public class ControllerImplTest {
return UNCERTAINTY_DELAY;
}
+ @Override
+ long elapsedRealtimeMillis() {
+ // The properties of the real clock will also work for tests, i.e. it doesn't go
+ // backwards.
+ return SystemClock.elapsedRealtime();
+ }
+
void simulateConfigChange(ConfigurationInternal newConfig) {
ConfigurationInternal oldConfig = mConfigurationInternal;
mConfigurationInternal = Objects.requireNonNull(newConfig);
@@ -1209,19 +1219,52 @@ public class ControllerImplTest {
mLatestSuggestion.set(suggestion);
}
- void assertSuggestionMadeAndCommit(@Nullable List expectedZoneIds) {
- mLatestSuggestion.assertHasBeenSet();
- assertEquals(expectedZoneIds, mLatestSuggestion.getLatest().getZoneIds());
- mLatestSuggestion.commitLatest();
+ void assertCertainSuggestionMadeFromEventAndCommit(TimeZoneProviderEvent event) {
+ // Test coding error if this fails.
+ assertEquals(TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION, event.getType());
+
+ TimeZoneProviderSuggestion suggestion = event.getSuggestion();
+ assertSuggestionMadeAndCommit(
+ suggestion.getElapsedRealtimeMillis(),
+ suggestion.getTimeZoneIds());
}
void assertNoSuggestionMade() {
mLatestSuggestion.assertHasNotBeenSet();
}
+ /** Asserts that an uncertain suggestion has been made from the supplied event. */
+ void assertUncertainSuggestionMadeFromEventAndCommit(TimeZoneProviderEvent event) {
+ // Test coding error if this fails.
+ assertEquals(TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN, event.getType());
+
+ assertSuggestionMadeAndCommit(event.getCreationElapsedMillis(), null);
+ }
+
+ /**
+ * Asserts that an uncertain suggestion has been made.
+ * Ignores the suggestion's effectiveFromElapsedMillis.
+ */
void assertUncertainSuggestionMadeAndCommit() {
// An "uncertain" suggestion has null time zone IDs.
- assertSuggestionMadeAndCommit(null);
+ assertSuggestionMadeAndCommit(null, null);
+ }
+
+ /**
+ * Asserts that a suggestion has been made and some properties of that suggestion.
+ * When expectedEffectiveFromElapsedMillis is null then its value isn't checked.
+ */
+ private void assertSuggestionMadeAndCommit(
+ @Nullable @ElapsedRealtimeLong Long expectedEffectiveFromElapsedMillis,
+ @Nullable List expectedZoneIds) {
+ mLatestSuggestion.assertHasBeenSet();
+ if (expectedEffectiveFromElapsedMillis != null) {
+ assertEquals(
+ expectedEffectiveFromElapsedMillis.longValue(),
+ mLatestSuggestion.getLatest().getEffectiveFromElapsedMillis());
+ }
+ assertEquals(expectedZoneIds, mLatestSuggestion.getLatest().getZoneIds());
+ mLatestSuggestion.commitLatest();
}
}