summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Neil Fuller <nfuller@google.com> 2022-10-28 19:51:48 +0100
committer Neil Fuller <nfuller@google.com> 2022-11-29 19:45:45 +0000
commit7fbcae6efd5c02fddb1dc5ddbcd6f2868f774131 (patch)
tree388ccd0ac9bf954b99a2013336a13bcada8f5978
parentc868e22da9a216e75166439a33e4e1a6f7c68ede (diff)
Enable telephony fallback triggered by providers
Now that providers can report their status, we can use this to trigger telephony fallback mode. This opens the door to more sophisticated mechanisms for things like flight or tunnel detection. After all, providers know how they work and what they can / cannot do, and may have access to sensors and providers that the platform has not. The new "provider reported" flight mode entry cannot replace the "time_zone_detector"-level behavior entered via calls to TimeZoneDetectorStrategy as provider status is new and optional; providers are not required to report their status so it can be omitted. Bug: 236624675 Test: atest services/tests/servicestests/src/com/android/server/timezonedetector/ Change-Id: I89fb889ba98b3ddedd271670db09f1bb9df95644
-rw-r--r--core/java/android/app/time/LocationTimeZoneAlgorithmStatus.java35
-rw-r--r--core/tests/coretests/Android.bp1
-rw-r--r--core/tests/coretests/src/android/app/time/LocationTimeZoneAlgorithmStatusTest.java117
-rw-r--r--core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java63
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java6
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java2
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java64
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java62
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java201
10 files changed, 462 insertions, 91 deletions
diff --git a/core/java/android/app/time/LocationTimeZoneAlgorithmStatus.java b/core/java/android/app/time/LocationTimeZoneAlgorithmStatus.java
index ec10d8431e74..6b5e66758d94 100644
--- a/core/java/android/app/time/LocationTimeZoneAlgorithmStatus.java
+++ b/core/java/android/app/time/LocationTimeZoneAlgorithmStatus.java
@@ -19,6 +19,7 @@ package android.app.time;
import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_NOT_RUNNING;
import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED;
import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_RUNNING;
+import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_UNKNOWN;
import static android.app.time.DetectorStatusTypes.detectionAlgorithmStatusFromString;
import static android.app.time.DetectorStatusTypes.detectionAlgorithmStatusToString;
import static android.app.time.DetectorStatusTypes.requireValidDetectionAlgorithmStatus;
@@ -319,6 +320,40 @@ public final class LocationTimeZoneAlgorithmStatus implements Parcelable {
mSecondaryProviderStatus, mSecondaryProviderReportedStatus);
}
+ /**
+ * Returns {@code true} if the algorithm status could allow the time zone detector to enter
+ * telephony fallback mode.
+ */
+ public boolean couldEnableTelephonyFallback() {
+ if (mStatus == DETECTION_ALGORITHM_STATUS_UNKNOWN
+ || mStatus == DETECTION_ALGORITHM_STATUS_NOT_RUNNING
+ || mStatus == DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED) {
+ // This method is not expected to be called on objects with these statuses. Fallback
+ // should not be enabled if it is.
+ return false;
+ }
+
+ // mStatus == DETECTOR_STATUS_RUNNING.
+
+ boolean primarySuggestsFallback = false;
+ if (mPrimaryProviderStatus == PROVIDER_STATUS_NOT_PRESENT) {
+ primarySuggestsFallback = true;
+ } else if (mPrimaryProviderStatus == PROVIDER_STATUS_IS_UNCERTAIN
+ && mPrimaryProviderReportedStatus != null) {
+ primarySuggestsFallback = mPrimaryProviderReportedStatus.couldEnableTelephonyFallback();
+ }
+
+ boolean secondarySuggestsFallback = false;
+ if (mSecondaryProviderStatus == PROVIDER_STATUS_NOT_PRESENT) {
+ secondarySuggestsFallback = true;
+ } else if (mSecondaryProviderStatus == PROVIDER_STATUS_IS_UNCERTAIN
+ && mSecondaryProviderReportedStatus != null) {
+ secondarySuggestsFallback =
+ mSecondaryProviderReportedStatus.couldEnableTelephonyFallback();
+ }
+ return primarySuggestsFallback && secondarySuggestsFallback;
+ }
+
/** @hide */
@VisibleForTesting
@NonNull
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 48cfc87d7d55..37605e422c9c 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -47,6 +47,7 @@ android_test {
"androidx.test.ext.junit",
"androidx.test.runner",
"androidx.test.rules",
+ "junit-params",
"kotlin-test",
"mockito-target-minus-junit4",
"ub-uiautomator",
diff --git a/core/tests/coretests/src/android/app/time/LocationTimeZoneAlgorithmStatusTest.java b/core/tests/coretests/src/android/app/time/LocationTimeZoneAlgorithmStatusTest.java
index a648a885aea2..fc69f6914658 100644
--- a/core/tests/coretests/src/android/app/time/LocationTimeZoneAlgorithmStatusTest.java
+++ b/core/tests/coretests/src/android/app/time/LocationTimeZoneAlgorithmStatusTest.java
@@ -17,19 +17,26 @@
package android.app.time;
import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_NOT_RUNNING;
+import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED;
import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_RUNNING;
+import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_UNKNOWN;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_IS_CERTAIN;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_IS_UNCERTAIN;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_PRESENT;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_READY;
import static android.app.time.ParcelableTestSupport.assertEqualsAndHashCode;
import static android.app.time.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_NOT_APPLICABLE;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_NOT_APPLICABLE;
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import android.app.time.LocationTimeZoneAlgorithmStatus.ProviderStatus;
import android.service.timezone.TimeZoneProviderStatus;
@@ -207,4 +214,114 @@ public class LocationTimeZoneAlgorithmStatusTest {
assertEquals(status,
LocationTimeZoneAlgorithmStatus.parseCommandlineArg(status.toString()));
}
+
+ @Test
+ public void testCouldEnableTelephonyFallback_notRunning() {
+ LocationTimeZoneAlgorithmStatus notRunning =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_NOT_RUNNING,
+ PROVIDER_STATUS_NOT_READY, null, PROVIDER_STATUS_NOT_READY, null);
+ assertFalse(notRunning.couldEnableTelephonyFallback());
+ }
+
+ @Test
+ public void testCouldEnableTelephonyFallback_unknown() {
+ // DETECTION_ALGORITHM_STATUS_UNKNOWN must never allow fallback
+ LocationTimeZoneAlgorithmStatus unknown =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_UNKNOWN,
+ PROVIDER_STATUS_NOT_READY, null, PROVIDER_STATUS_NOT_READY, null);
+ assertFalse(unknown.couldEnableTelephonyFallback());
+ }
+
+ @Test
+ public void testCouldEnableTelephonyFallback_notSupported() {
+ // DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED must never allow fallback
+ LocationTimeZoneAlgorithmStatus notSupported =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED,
+ PROVIDER_STATUS_NOT_READY, null, PROVIDER_STATUS_NOT_READY, null);
+ assertFalse(notSupported.couldEnableTelephonyFallback());
+ }
+
+ @Test
+ public void testCouldEnableTelephonyFallback_running() {
+ // DETECTION_ALGORITHM_STATUS_RUNNING may allow fallback
+
+ // Sample provider-reported statuses that do / do not enable fallback.
+ TimeZoneProviderStatus enableTelephonyFallbackProviderStatus =
+ new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionDependencyStatus(
+ DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
+ .setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
+ .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_NOT_APPLICABLE)
+ .build();
+ assertTrue(enableTelephonyFallbackProviderStatus.couldEnableTelephonyFallback());
+
+ TimeZoneProviderStatus notEnableTelephonyFallbackProviderStatus =
+ new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
+ .setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
+ .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_NOT_APPLICABLE)
+ .build();
+ assertFalse(notEnableTelephonyFallbackProviderStatus.couldEnableTelephonyFallback());
+
+ // Provider not ready: Never enable fallback
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_NOT_READY, null, PROVIDER_STATUS_NOT_READY, null);
+ assertFalse(status.couldEnableTelephonyFallback());
+ }
+
+ // Provider uncertain without reported status: Never enable fallback
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, null, PROVIDER_STATUS_NOT_READY, null);
+ assertFalse(status.couldEnableTelephonyFallback());
+ }
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, null, PROVIDER_STATUS_NOT_PRESENT, null);
+ assertFalse(status.couldEnableTelephonyFallback());
+ }
+
+ // Provider uncertain with reported status: Fallback is based on the status for present
+ // providers that report their status. All present providers must have reported status and
+ // agree that fallback is a good idea.
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, enableTelephonyFallbackProviderStatus,
+ PROVIDER_STATUS_NOT_READY, null);
+ assertFalse(status.couldEnableTelephonyFallback());
+ }
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, enableTelephonyFallbackProviderStatus,
+ PROVIDER_STATUS_NOT_PRESENT, null);
+ assertTrue(status.couldEnableTelephonyFallback());
+ }
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, enableTelephonyFallbackProviderStatus,
+ PROVIDER_STATUS_IS_UNCERTAIN, enableTelephonyFallbackProviderStatus);
+ assertTrue(status.couldEnableTelephonyFallback());
+ }
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, enableTelephonyFallbackProviderStatus,
+ PROVIDER_STATUS_IS_UNCERTAIN, notEnableTelephonyFallbackProviderStatus);
+ assertFalse(status.couldEnableTelephonyFallback());
+ }
+ {
+ LocationTimeZoneAlgorithmStatus status =
+ new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_NOT_PRESENT, null,
+ PROVIDER_STATUS_IS_UNCERTAIN, enableTelephonyFallbackProviderStatus);
+ assertTrue(status.couldEnableTelephonyFallback());
+ }
+ }
}
diff --git a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java
index 9006cd91d616..0c1630e8fefd 100644
--- a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java
+++ b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java
@@ -16,15 +16,31 @@
package android.service.timezone;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_UNKNOWN;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_UNKNOWN;
import static org.junit.Assert.assertEquals;
+import android.service.timezone.TimeZoneProviderStatus.DependencyStatus;
+import android.service.timezone.TimeZoneProviderStatus.OperationStatus;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
/** Non-SDK tests. See CTS for SDK API tests. */
+@RunWith(JUnitParamsRunner.class)
public class TimeZoneProviderStatusTest {
@Test
@@ -37,4 +53,51 @@ public class TimeZoneProviderStatusTest {
assertEquals(status, TimeZoneProviderStatus.parseProviderStatus(status.toString()));
}
+
+ @Test
+ @Parameters(method = "couldEnableTelephonyFallbackParams")
+ public void couldEnableTelephonyFallback(@DependencyStatus int locationDetectionStatus,
+ @DependencyStatus int connectivityStatus, @OperationStatus int tzResolutionStatus) {
+ TimeZoneProviderStatus providerStatus =
+ new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionDependencyStatus(locationDetectionStatus)
+ .setConnectivityDependencyStatus(connectivityStatus)
+ .setTimeZoneResolutionOperationStatus(tzResolutionStatus)
+ .build();
+ boolean locationDetectionStatusCouldEnableFallback =
+ (locationDetectionStatus == DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT
+ || locationDetectionStatus == DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS);
+ boolean connectivityStatusCouldEnableFallback =
+ (connectivityStatus == DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT
+ || connectivityStatus == DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS);
+ boolean tzResolutionStatusCouldEnableFallback = false;
+
+ assertEquals(locationDetectionStatusCouldEnableFallback
+ || connectivityStatusCouldEnableFallback
+ || tzResolutionStatusCouldEnableFallback,
+ providerStatus.couldEnableTelephonyFallback());
+ }
+
+ public static Integer[][] couldEnableTelephonyFallbackParams() {
+ List<Integer[]> params = new ArrayList<>();
+ @DependencyStatus int[] dependencyStatuses =
+ IntStream.rangeClosed(
+ DEPENDENCY_STATUS_UNKNOWN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS).toArray();
+ @OperationStatus int[] operationStatuses =
+ IntStream.rangeClosed(OPERATION_STATUS_UNKNOWN, OPERATION_STATUS_FAILED).toArray();
+
+ // Cartesian product: dependencyStatus x dependencyStatus x operationStatus
+ for (@DependencyStatus int locationDetectionStatus : dependencyStatuses) {
+ for (@DependencyStatus int connectivityStatus : dependencyStatuses) {
+ for (@OperationStatus int tzResolutionStatus : operationStatuses) {
+ params.add(new Integer[] {
+ locationDetectionStatus,
+ connectivityStatus,
+ tzResolutionStatus
+ });
+ }
+ }
+ }
+ return params.toArray(new Integer[0][0]);
+ }
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index f8c1c9269ff3..10cd5d1a0669 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -91,7 +91,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
deviceActivityMonitor.addListener(new DeviceActivityMonitor.Listener() {
@Override
public void onFlightComplete() {
- timeZoneDetectorStrategy.enableTelephonyTimeZoneFallback();
+ timeZoneDetectorStrategy.enableTelephonyTimeZoneFallback("onFlightComplete()");
}
});
@@ -402,9 +402,9 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
* Sends a signal to enable telephony fallback. Provided for command-line access for use
* during tests. This is not exposed as a binder API.
*/
- void enableTelephonyFallback() {
+ void enableTelephonyFallback(@NonNull String reason) {
enforceManageTimeZoneDetectorPermission();
- mTimeZoneDetectorStrategy.enableTelephonyTimeZoneFallback();
+ mTimeZoneDetectorStrategy.enableTelephonyTimeZoneFallback(reason);
}
/**
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
index 69274dba7825..ab68e834d337 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
@@ -189,7 +189,7 @@ class TimeZoneDetectorShellCommand extends ShellCommand {
}
private int runEnableTelephonyFallback() {
- mInterface.enableTelephonyFallback();
+ mInterface.enableTelephonyFallback("Command line");
return 0;
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 5768a6bfa0dc..37e67c921634 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -35,13 +35,13 @@ import android.util.IndentingPrintWriter;
* <p>Devices can have zero, one or two automatic time zone detection algorithms available at any
* point in time.
*
- * <p>The two automatic detection algorithms supported are "telephony" and "geolocation". Algorithm
+ * <p>The two automatic detection algorithms supported are "telephony" and "location". Algorithm
* availability and use depends on several factors:
* <ul>
* <li>Telephony is only available on devices with a telephony stack.
- * <li>Geolocation is also optional and configured at image creation time. When enabled on a
- * device, its availability depends on the current user's settings, so switching between users can
- * change the automatic algorithm used by the device.</li>
+ * <li>Location is also optional and configured at image creation time. When enabled on a device,
+ * its availability depends on the current user's settings, so switching between users can change
+ * the automatic detection algorithm used by the device.</li>
* </ul>
*
* <p>If there are no automatic time zone detections algorithms available then the user can usually
@@ -56,14 +56,14 @@ import android.util.IndentingPrintWriter;
* slotIndexes must have an empty suggestion submitted in order to "withdraw" their previous
* suggestion otherwise it will remain in use.
*
- * <p>Geolocation detection is dependent on the current user and their settings. The device retains
- * at most one geolocation suggestion. Generally, use of a device's location is dependent on the
- * user's "location toggle", but even when that is enabled the user may choose to enable / disable
- * the use of geolocation for device time zone detection. If the current user changes to one that
- * does not have geolocation detection enabled, or the user turns off geolocation detection, then
- * the strategy discards the latest geolocation suggestion. Devices that lose a location fix must
- * have an empty suggestion submitted in order to "withdraw" their previous suggestion otherwise it
- * will remain in use.
+ * <p>Location-based detection is dependent on the current user and their settings. The device
+ * retains at most one geolocation suggestion. Generally, use of a device's location is dependent on
+ * the user's "location toggle", but even when that is enabled the user may choose to enable /
+ * disable the use of location for device time zone detection. If the current user changes to one
+ * that does not have location-based detection enabled, or the user turns off the location-based
+ * detection, then the strategy will be sent an event that clears the latest suggestion. Devices
+ * that lose their location fix must have an empty suggestion submitted in order to "withdraw" their
+ * previous suggestion otherwise it will remain in use.
*
* <p>The strategy uses only one algorithm at a time and does not attempt consensus even when
* more than one is available on a device. This "use only one" behavior is deliberate as different
@@ -72,25 +72,27 @@ import android.util.IndentingPrintWriter;
* users enter areas without the necessary signals. Ultimately, with no perfect algorithm available,
* the user is left to choose which algorithm works best for their circumstances.
*
- * <p>When geolocation detection is supported and enabled, in certain circumstances, such as during
- * international travel, it makes sense to prioritize speed of detection via telephony (when
- * available) Vs waiting for the geolocation algorithm to reach certainty. Geolocation detection can
- * sometimes be slow to get a location fix and can require network connectivity (which cannot be
- * assumed when users are travelling) for server-assisted location detection or time zone lookup.
- * Therefore, as a restricted form of prioritization between geolocation and telephony algorithms,
- * the strategy provides "telephony fallback" behavior, which can be set to "supported" via device
- * config. Fallback mode is toggled on at runtime via {@link #enableTelephonyTimeZoneFallback()} in
- * response to signals outside of the scope of this class. Telephony fallback allows the use of
- * telephony suggestions to help with faster detection but only until geolocation detection
- * provides a concrete, "certain" suggestion. After geolocation has made the first certain
- * suggestion, telephony fallback is disabled until the next call to {@link
- * #enableTelephonyTimeZoneFallback()}.
+ * <p>When the location detection algorithm is supported and enabled, in certain circumstances, such
+ * as during international travel, it makes sense to prioritize speed of detection via telephony
+ * (when available) Vs waiting for the location-based detection algorithm to reach certainty.
+ * Location-based detection can sometimes be slow to get a location fix and can require network
+ * connectivity (which cannot be assumed when users are travelling) for server-assisted location
+ * detection or time zone lookup. Therefore, as a restricted form of prioritization between location
+ * and telephony algorithms, the strategy provides "telephony fallback mode" behavior, which can be
+ * set to "supported" via device config. Fallback mode is entered at runtime in response to signals
+ * from outside of the strategy, e.g. from a call to {@link
+ * #enableTelephonyTimeZoneFallback(String)}, or from information in the latest {@link
+ * LocationAlgorithmEvent}. For telephony fallback mode to actually use a telephony suggestion, the
+ * location algorithm <em>must</em> report it is uncertain. Telephony fallback allows the use of
+ * telephony suggestions to help with faster detection but only until the location algorithm
+ * provides a concrete, "certain" suggestion. After the location algorithm has made a certain
+ * suggestion, telephony fallback mode is disabled.
*
* <p>Threading:
*
* <p>Implementations of this class must be thread-safe as calls calls like {@link
* #generateMetricsState()} and {@link #dump(IndentingPrintWriter, String[])} may be called on
- * differents thread concurrently with other operations.
+ * different threads concurrently with other operations.
*
* @hide
*/
@@ -181,11 +183,11 @@ public interface TimeZoneDetectorStrategy extends Dumpable {
void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion suggestion);
/**
- * Tells the strategy that it can fall back to telephony detection while geolocation detection
- * remains uncertain. {@link #handleLocationAlgorithmEvent(LocationAlgorithmEvent)} can
- * disable it again. See {@link TimeZoneDetectorStrategy} for details.
+ * Tells the strategy that it can fall back to telephony detection while the location detection
+ * algorithm remains uncertain. {@link #handleLocationAlgorithmEvent(LocationAlgorithmEvent)}
+ * can disable it again. See {@link TimeZoneDetectorStrategy} for details.
*/
- void enableTelephonyTimeZoneFallback();
+ void enableTelephonyTimeZoneFallback(@NonNull String reason);
/** Generates a state snapshot for metrics. */
@NonNull
@@ -194,6 +196,6 @@ public interface TimeZoneDetectorStrategy extends Dumpable {
/** Returns {@code true} if the device supports telephony time zone detection. */
boolean isTelephonyTimeZoneDetectionSupported();
- /** Returns {@code true} if the device supports geolocation time zone detection. */
+ /** Returns {@code true} if the device supports location-based time zone detection. */
boolean isGeoTimeZoneDetectionSupported();
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index fa811efcfec0..e0e3565e1b0b 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -63,12 +63,8 @@ import java.util.Objects;
public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrategy {
/**
- * Used by {@link TimeZoneDetectorStrategyImpl} to interact with device configuration / settings
- * / system properties. It can be faked for testing.
- *
- * <p>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.
+ * Used by {@link TimeZoneDetectorStrategyImpl} to interact with device state besides that
+ * available from {@link #mServiceConfigAccessor}. It can be faked for testing.
*/
@VisibleForTesting
public interface Environment {
@@ -234,7 +230,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
* allows).
*
* <p>This field is only actually used when telephony time zone fallback is supported, but the
- * value is maintained even when it isn't supported as it can be turned on at any time via
+ * value is maintained even when it isn't supported as support can be turned on at any time via
* server flags. The elapsed realtime when the mode last changed is used to help ordering
* between fallback mode switches and suggestions.
*
@@ -421,10 +417,15 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
notifyStateChangeListenersAsynchronously();
}
- // Update the mTelephonyTimeZoneFallbackEnabled state if needed: a certain suggestion
- // will usually disable telephony fallback mode if it is currently enabled.
- // TODO(b/236624675)Some provider status codes can be used to enable telephony fallback.
- disableTelephonyFallbackIfNeeded();
+ // Manage telephony fallback state.
+ if (event.getAlgorithmStatus().couldEnableTelephonyFallback()) {
+ // An event may trigger entry into telephony fallback mode if the status
+ // indicates the location algorithm cannot work and is likely to stay not working.
+ enableTelephonyTimeZoneFallback("handleLocationAlgorithmEvent(), event=" + event);
+ } else {
+ // A certain suggestion will exit telephony fallback mode.
+ disableTelephonyFallbackIfNeeded();
+ }
// Now perform auto time zone detection. The new event may be used to modify the time zone
// setting.
@@ -497,38 +498,41 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
}
@Override
- public synchronized void enableTelephonyTimeZoneFallback() {
- // Only do any work if fallback is currently not enabled.
+ public synchronized void enableTelephonyTimeZoneFallback(@NonNull String reason) {
+ // Only do any work to enter fallback mode if fallback is currently not already enabled.
if (!mTelephonyTimeZoneFallbackEnabled.getValue()) {
ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
final boolean fallbackEnabled = true;
mTelephonyTimeZoneFallbackEnabled = new TimestampedValue<>(
mEnvironment.elapsedRealtimeMillis(), fallbackEnabled);
- String logMsg = "enableTelephonyTimeZoneFallbackMode: "
- + " currentUserConfig=" + currentUserConfig
- + ", mTelephonyTimeZoneFallbackEnabled="
- + mTelephonyTimeZoneFallbackEnabled;
+ String logMsg = "enableTelephonyTimeZoneFallback: "
+ + " reason=" + reason
+ + ", currentUserConfig=" + currentUserConfig
+ + ", mTelephonyTimeZoneFallbackEnabled=" + mTelephonyTimeZoneFallbackEnabled;
logTimeZoneDebugInfo(logMsg);
// mTelephonyTimeZoneFallbackEnabled and mLatestLocationAlgorithmEvent interact.
- // If the latest event contains a "certain" geolocation suggestion, then the telephony
- // fallback value needs to be considered after changing it.
+ // If the latest location algorithm event contains a "certain" geolocation suggestion,
+ // then the telephony fallback mode needs to be (re)considered after changing it.
+ //
// With the way that the mTelephonyTimeZoneFallbackEnabled time is currently chosen
// above, and the fact that geolocation suggestions should never have a time in the
- // future, the following call will be a no-op, and telephony fallback will remain
- // enabled. This comment / call is left as a reminder that it is possible for there to
- // be a current, "certain" geolocation suggestion when this signal arrives and it is
- // intentional that fallback stays enabled in this case. The choice to do this
- // is mostly for symmetry WRT the case where fallback is enabled and an old "certain"
- // geolocation is received; that would also leave telephony fallback enabled.
- // This choice means that telephony fallback will remain enabled until a new "certain"
- // geolocation suggestion is received. If, instead, the next geolocation is "uncertain",
- // then telephony fallback will occur.
+ // future, the following call will usually be a no-op, and telephony fallback mode will
+ // remain enabled. This comment / call is left as a reminder that it is possible in some
+ // cases for there to be a current, "certain" geolocation suggestion when an attempt is
+ // made to enable telephony fallback mode and it is intentional that fallback mode stays
+ // enabled in this case. The choice to do this is mostly for symmetry WRT the case where
+ // fallback is enabled and then an old "certain" geolocation suggestion is received;
+ // that would also leave telephony fallback mode enabled.
+ //
+ // This choice means that telephony fallback mode remains enabled if there is an
+ // existing "certain" suggestion until a new "certain" geolocation suggestion is
+ // received. If, instead, the next geolocation suggestion is "uncertain", then telephony
+ // fallback, i.e. the use of a telephony suggestion, will actually occur.
disableTelephonyFallbackIfNeeded();
if (currentUserConfig.isTelephonyFallbackSupported()) {
- String reason = "enableTelephonyTimeZoneFallbackMode";
doAutoTimeZoneDetection(currentUserConfig, reason);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
index bcdc65c19330..1e72369ac3a6 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
@@ -111,7 +111,7 @@ public class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
}
@Override
- public void enableTelephonyTimeZoneFallback() {
+ public void enableTelephonyTimeZoneFallback(String reason) {
throw new UnsupportedOperationException();
}
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 74efdb5d6d98..1c014d19d776 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -29,6 +29,9 @@ import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYP
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_UNKNOWN;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_UNKNOWN;
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_LOW;
@@ -65,6 +68,7 @@ import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
import android.os.HandlerThread;
+import android.service.timezone.TimeZoneProviderStatus;
import com.android.server.SystemTimeZone.TimeZoneConfidence;
import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
@@ -1148,7 +1152,7 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Test
- public void testTelephonyFallback() {
+ public void testTelephonyFallback_enableTelephonyTimeZoneFallbackCalled() {
ConfigurationInternal config = new ConfigurationInternal.Builder(
CONFIG_AUTO_ENABLED_GEO_ENABLED)
.setTelephonyFallbackSupported(true)
@@ -1178,19 +1182,21 @@ public class TimeZoneDetectorStrategyImplTest {
// Receiving an "uncertain" geolocation suggestion should have no effect.
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent = createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneNotChanged()
.verifyTelephonyFallbackIsEnabled(true);
}
// Receiving a "certain" geolocation suggestion should disable telephony fallback mode.
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent =
createCertainLocationAlgorithmEvent("Europe/London");
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneChangedAndReset(locationAlgorithmEvent)
.verifyTelephonyFallbackIsEnabled(false);
}
@@ -1214,17 +1220,19 @@ public class TimeZoneDetectorStrategyImplTest {
// Geolocation suggestions should continue to be used as normal (previous telephony
// suggestions are not used, even when the geolocation suggestion is uncertain).
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent certainLocationAlgorithmEvent =
createCertainLocationAlgorithmEvent("Europe/Rome");
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(certainLocationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(certainLocationAlgorithmEvent)
.verifyTimeZoneChangedAndReset(certainLocationAlgorithmEvent)
.verifyTelephonyFallbackIsEnabled(false);
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent uncertainLocationAlgorithmEvent =
createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(uncertainLocationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(uncertainLocationAlgorithmEvent)
.verifyTimeZoneNotChanged()
.verifyTelephonyFallbackIsEnabled(false);
@@ -1246,19 +1254,21 @@ public class TimeZoneDetectorStrategyImplTest {
// Make the geolocation algorithm uncertain.
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent = createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneChangedAndReset(lastTelephonySuggestion)
.verifyTelephonyFallbackIsEnabled(true);
}
// Make the geolocation algorithm certain, disabling telephony fallback.
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent =
createCertainLocationAlgorithmEvent("Europe/Lisbon");
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneChangedAndReset(locationAlgorithmEvent)
.verifyTelephonyFallbackIsEnabled(false);
@@ -1267,9 +1277,10 @@ public class TimeZoneDetectorStrategyImplTest {
// Demonstrate what happens when geolocation is uncertain when telephony fallback is
// enabled.
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent = createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneNotChanged()
.verifyTelephonyFallbackIsEnabled(false)
.simulateEnableTelephonyFallback()
@@ -1279,6 +1290,132 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Test
+ public void testTelephonyFallback_locationAlgorithmEventSuggestsFallback() {
+ ConfigurationInternal config = new ConfigurationInternal.Builder(
+ CONFIG_AUTO_ENABLED_GEO_ENABLED)
+ .setTelephonyFallbackSupported(true)
+ .build();
+
+ Script script = new Script()
+ .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS)
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW)
+ .simulateConfigurationInternalChange(config)
+ .resetConfigurationTracking();
+
+ // Confirm initial state is as expected.
+ script.verifyTelephonyFallbackIsEnabled(true)
+ .verifyTimeZoneNotChanged();
+
+ // Although geolocation detection is enabled, telephony fallback should be used initially
+ // and until a suitable "certain" geolocation suggestion is received.
+ {
+ TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion(
+ SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
+ "Europe/Paris");
+ script.simulateIncrementClock()
+ .simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
+ .verifyTimeZoneChangedAndReset(telephonySuggestion)
+ .verifyTelephonyFallbackIsEnabled(true);
+ }
+
+ // Receiving an "uncertain" geolocation suggestion without a status should have no effect.
+ {
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ LocationAlgorithmEvent locationAlgorithmEvent = createUncertainLocationAlgorithmEvent();
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ .verifyTimeZoneNotChanged()
+ .verifyTelephonyFallbackIsEnabled(true);
+ }
+
+ // Receiving a "certain" geolocation suggestion should disable telephony fallback mode.
+ {
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ LocationAlgorithmEvent locationAlgorithmEvent =
+ createCertainLocationAlgorithmEvent("Europe/London");
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ .verifyTimeZoneChangedAndReset(locationAlgorithmEvent)
+ .verifyTelephonyFallbackIsEnabled(false);
+ }
+
+ // Used to record the last telephony suggestion received, which will be used when fallback
+ // takes place.
+ TelephonyTimeZoneSuggestion lastTelephonySuggestion;
+
+ // Telephony suggestions should now be ignored and geolocation detection is "in control".
+ {
+ TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion(
+ SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
+ "Europe/Berlin");
+ script.simulateIncrementClock()
+ .simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
+ .verifyTimeZoneNotChanged()
+ .verifyTelephonyFallbackIsEnabled(false);
+ lastTelephonySuggestion = telephonySuggestion;
+ }
+
+ // Geolocation suggestions should continue to be used as normal (previous telephony
+ // suggestions are not used, even when the geolocation suggestion is uncertain).
+ {
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ LocationAlgorithmEvent certainLocationAlgorithmEvent =
+ createCertainLocationAlgorithmEvent("Europe/Rome");
+ script.simulateLocationAlgorithmEvent(certainLocationAlgorithmEvent)
+ .verifyTimeZoneChangedAndReset(certainLocationAlgorithmEvent)
+ .verifyTelephonyFallbackIsEnabled(false);
+
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ LocationAlgorithmEvent uncertainLocationAlgorithmEvent =
+ createUncertainLocationAlgorithmEvent();
+ script.simulateLocationAlgorithmEvent(uncertainLocationAlgorithmEvent)
+ .verifyTimeZoneNotChanged()
+ .verifyTelephonyFallbackIsEnabled(false);
+
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ LocationAlgorithmEvent certainLocationAlgorithmEvent2 =
+ createCertainLocationAlgorithmEvent("Europe/Rome");
+ script.simulateLocationAlgorithmEvent(certainLocationAlgorithmEvent2)
+ // No change needed, device will already be set to Europe/Rome.
+ .verifyTimeZoneNotChanged()
+ .verifyTelephonyFallbackIsEnabled(false);
+ }
+
+ // Enable telephony fallback via a LocationAlgorithmEvent containing an "uncertain"
+ // suggestion.
+ {
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ TimeZoneProviderStatus primaryProviderReportedStatus =
+ new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionDependencyStatus(
+ DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS)
+ .setConnectivityDependencyStatus(DEPENDENCY_STATUS_UNKNOWN)
+ .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_UNKNOWN)
+ .build();
+ LocationAlgorithmEvent uncertainEventBlockedBySettings =
+ createUncertainLocationAlgorithmEvent(primaryProviderReportedStatus);
+ script.simulateLocationAlgorithmEvent(uncertainEventBlockedBySettings)
+ .verifyTimeZoneChangedAndReset(lastTelephonySuggestion)
+ .verifyTelephonyFallbackIsEnabled(true);
+ }
+
+ // Make the geolocation algorithm certain, disabling telephony fallback.
+ {
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
+ LocationAlgorithmEvent locationAlgorithmEvent =
+ createCertainLocationAlgorithmEvent("Europe/Lisbon");
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ .verifyTimeZoneChangedAndReset(locationAlgorithmEvent)
+ .verifyTelephonyFallbackIsEnabled(false);
+ }
+ }
+
+ @Test
public void testTelephonyFallback_noTelephonySuggestionToFallBackTo() {
ConfigurationInternal config = new ConfigurationInternal.Builder(
CONFIG_AUTO_ENABLED_GEO_ENABLED)
@@ -1297,9 +1434,10 @@ public class TimeZoneDetectorStrategyImplTest {
// Receiving an "uncertain" geolocation suggestion should have no effect.
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent = createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneNotChanged()
.verifyTelephonyFallbackIsEnabled(true);
}
@@ -1307,9 +1445,10 @@ public class TimeZoneDetectorStrategyImplTest {
// Make an uncertain geolocation suggestion, there is no telephony suggestion to fall back
// to
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent locationAlgorithmEvent = createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(locationAlgorithmEvent)
+ script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneNotChanged()
.verifyTelephonyFallbackIsEnabled(true);
}
@@ -1319,16 +1458,18 @@ public class TimeZoneDetectorStrategyImplTest {
// Geolocation suggestions should continue to be used as normal (previous telephony
// suggestions are not used, even when the geolocation suggestion is uncertain).
{
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent certainEvent =
createCertainLocationAlgorithmEvent("Europe/Rome");
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(certainEvent)
+ script.simulateLocationAlgorithmEvent(certainEvent)
.verifyTimeZoneChangedAndReset(certainEvent)
.verifyTelephonyFallbackIsEnabled(false);
+ // Increment the clock before creating the event: the clock's value is used by the event
+ script.simulateIncrementClock();
LocationAlgorithmEvent uncertainEvent = createUncertainLocationAlgorithmEvent();
- script.simulateIncrementClock()
- .simulateLocationAlgorithmEvent(uncertainEvent)
+ script.simulateLocationAlgorithmEvent(uncertainEvent)
.verifyTimeZoneNotChanged()
.verifyTelephonyFallbackIsEnabled(false);
@@ -1549,9 +1690,16 @@ public class TimeZoneDetectorStrategyImplTest {
}
private LocationAlgorithmEvent createUncertainLocationAlgorithmEvent() {
+ TimeZoneProviderStatus primaryProviderReportedStatus = null;
+ return createUncertainLocationAlgorithmEvent(primaryProviderReportedStatus);
+ }
+
+ private LocationAlgorithmEvent createUncertainLocationAlgorithmEvent(
+ TimeZoneProviderStatus primaryProviderReportedStatus) {
GeolocationTimeZoneSuggestion suggestion = createUncertainGeolocationSuggestion();
LocationTimeZoneAlgorithmStatus algorithmStatus = new LocationTimeZoneAlgorithmStatus(
- DETECTION_ALGORITHM_STATUS_RUNNING, PROVIDER_STATUS_IS_UNCERTAIN, null,
+ DETECTION_ALGORITHM_STATUS_RUNNING,
+ PROVIDER_STATUS_IS_UNCERTAIN, primaryProviderReportedStatus,
PROVIDER_STATUS_NOT_PRESENT, null);
LocationAlgorithmEvent event = new LocationAlgorithmEvent(algorithmStatus, suggestion);
event.addDebugInfo("Test uncertain event");
@@ -1744,11 +1892,12 @@ public class TimeZoneDetectorStrategyImplTest {
}
/**
- * Simulates the time zone detection strategty receiving a signal that allows it to do
+ * Simulates the time zone detection strategy receiving a signal that allows it to do
* telephony fallback.
*/
Script simulateEnableTelephonyFallback() {
- mTimeZoneDetectorStrategy.enableTelephonyTimeZoneFallback();
+ mTimeZoneDetectorStrategy.enableTelephonyTimeZoneFallback(
+ "simulateEnableTelephonyFallback()");
return this;
}