Loading services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java +25 −11 Original line number Diff line number Diff line Loading @@ -303,8 +303,7 @@ class LocationTimeZoneProviderController implements Dumpable { private void reportSuggestionEvent( @NonNull GeolocationTimeZoneSuggestion suggestion, @NonNull String reason) { LocationTimeZoneAlgorithmStatus algorithmStatus = generateCurrentAlgorithmStatus(); LocationAlgorithmEvent event = new LocationAlgorithmEvent( algorithmStatus, suggestion); LocationAlgorithmEvent event = new LocationAlgorithmEvent(algorithmStatus, suggestion); event.addDebugInfo(reason); reportEvent(event); } Loading Loading @@ -728,6 +727,20 @@ class LocationTimeZoneProviderController implements Dumpable { // Start the uncertainty timeout if needed to ensure the controller will eventually make an // uncertain suggestion if no success event arrives in time to counteract it. if (!mUncertaintyTimeoutQueue.hasQueued()) { if (STATE_UNCERTAIN.equals(mState.get())) { // If the controller is already uncertain, there's no reason to start a timeout; // just forward the suggestion immediately to make it obvious in the logs what has // happened. Making a new suggestion potentially captures new LTZP status info. GeolocationTimeZoneSuggestion suggestion = GeolocationTimeZoneSuggestion.createUncertainSuggestion( uncertaintyStartedElapsedMillis); String debugInfo = "Uncertainty received from " + provider.getName() + ":" + " primary=" + mPrimaryProvider + ", secondary=" + mSecondaryProvider + ", uncertaintyStarted=" + Duration.ofMillis(uncertaintyStartedElapsedMillis); reportSuggestionEvent(suggestion, debugInfo); } else { debugLog("Starting uncertainty timeout: reason=" + reason); Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay(); Loading @@ -736,12 +749,13 @@ class LocationTimeZoneProviderController implements Dumpable { provider, uncertaintyStartedElapsedMillis, uncertaintyDelay), uncertaintyDelay.toMillis()); } } if (provider == mPrimaryProvider) { // (Try to) start the secondary. It could already be started, or enabling might not // succeed if the provider has previously reported it is perm failed. The uncertainty // timeout (set above) is used to ensure that an uncertain suggestion will be made if // the secondary cannot generate a success event in time. // timeout (may be set above) is used to ensure that an uncertain suggestion will be // made if the secondary cannot generate a success event in time. tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration); } } Loading services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java +163 −18 Original line number Diff line number Diff line Loading @@ -88,18 +88,21 @@ public class LocationTimeZoneProviderControllerTest { private static final long ARBITRARY_TIME_MILLIS = 12345L; private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 = createSuggestionEvent(asList("Europe/London")); createSuggestionEvent(ARBITRARY_TIME_MILLIS, asList("Europe/London")); private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 = createSuggestionEvent(asList("Europe/Paris")); createSuggestionEvent(ARBITRARY_TIME_MILLIS + 1, asList("Europe/Paris")); private static final TimeZoneProviderStatus UNCERTAIN_PROVIDER_STATUS = new TimeZoneProviderStatus.Builder() .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE) .setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK) .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_UNKNOWN) .build(); private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT = private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1 = TimeZoneProviderEvent.createUncertainEvent( ARBITRARY_TIME_MILLIS, UNCERTAIN_PROVIDER_STATUS); private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2 = TimeZoneProviderEvent.createUncertainEvent( ARBITRARY_TIME_MILLIS + 1, UNCERTAIN_PROVIDER_STATUS); private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT = TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test"); Loading Loading @@ -328,7 +331,7 @@ public class LocationTimeZoneProviderControllerTest { // Finally, the uncertainty timeout should cause the controller to make an uncertain // suggestion. mTestThreadingDomain.executeNext(); mTestThreadingDomain.executeAll(); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -649,7 +652,7 @@ public class LocationTimeZoneProviderControllerTest { // cause a suggestion to be made straight away, but the uncertainty timeout should be // started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -680,7 +683,7 @@ public class LocationTimeZoneProviderControllerTest { // cause a suggestion to be made straight away, but the uncertainty timeout should be // started. Both providers are now started, with no initialization timeout set. mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading @@ -693,7 +696,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate time passing. This means the uncertainty timeout should fire and the uncertain // suggestion should be made. mTestThreadingDomain.executeNext(); mTestThreadingDomain.executeAll(); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading @@ -702,7 +705,7 @@ public class LocationTimeZoneProviderControllerTest { PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN); mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); } Loading Loading @@ -744,7 +747,7 @@ public class LocationTimeZoneProviderControllerTest { // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty // timeout should be started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading @@ -771,6 +774,147 @@ public class LocationTimeZoneProviderControllerTest { assertFalse(controller.isUncertaintyTimeoutSet()); } @Test public void enabled_uncertaintyDuringUncertaintyTimeoutTriggersNoSuggestion() { LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController( mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */); TestEnvironment testEnvironment = new TestEnvironment( mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED); // Initialize and check initial state. controller.initialize(testEnvironment, mTestCallback); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit( STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING); mTestCallback.assertEventWithNoSuggestionReportedAndCommit( DETECTION_ALGORITHM_STATUS_RUNNING); assertFalse(controller.isUncertaintyTimeoutSet()); // Simulate a location event being received from the primary provider. This should cause a // suggestion to be made. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN); mTestCallback.assertEventWithCertainSuggestionReportedAndCommit( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty // timeout should be started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertNoEventReported(); assertUncertaintyTimeoutSet(testEnvironment, controller); // Another uncertain suggestion from the primary during the uncertainty timeout should have // no effect. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertNoEventReported(); assertUncertaintyTimeoutSet(testEnvironment, controller); } @Test public void enabled_uncertaintyAfterUncertaintyTimeoutTriggersImmediateSuggestion() { LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController( mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */); TestEnvironment testEnvironment = new TestEnvironment( mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED); // Initialize and check initial state. controller.initialize(testEnvironment, mTestCallback); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit( STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING); mTestCallback.assertEventWithNoSuggestionReportedAndCommit( DETECTION_ALGORITHM_STATUS_RUNNING); assertFalse(controller.isUncertaintyTimeoutSet()); // Simulate a location event being received from the primary provider. This should cause a // suggestion to be made. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN); mTestCallback.assertEventWithCertainSuggestionReportedAndCommit( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty // timeout should be started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertNoEventReported(); assertUncertaintyTimeoutSet(testEnvironment, controller); // Simulate time passing. This means the uncertainty timeout should fire and the uncertain // suggestion should be made. mTestThreadingDomain.executeAll(); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN); mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); // Another uncertain suggestion from the primary should cause an immediate suggestion. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2); assertFalse(controller.isUncertaintyTimeoutSet()); } @Test public void configChanges_enableAndDisableWithNoPreviousSuggestion() { LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController( Loading Loading @@ -965,7 +1109,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate uncertainty from the secondary. mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit(); Loading @@ -991,7 +1135,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate uncertainty from the secondary. mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit(); Loading Loading @@ -1085,7 +1229,7 @@ public class LocationTimeZoneProviderControllerTest { // give this test the opportunity to simulate its failure. Then it will be possible to // demonstrate controller behavior with only the primary working. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -1124,7 +1268,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate uncertainty from the primary. The secondary cannot be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -1160,7 +1304,7 @@ public class LocationTimeZoneProviderControllerTest { // give this test the opportunity to simulate its failure. Then it will be possible to // demonstrate controller behavior with only the primary working. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -1282,7 +1426,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate an uncertain event from the primary. This will start the secondary. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); { LocationTimeZoneManagerServiceState state = controller.getStateForTests(); Loading Loading @@ -1471,18 +1615,19 @@ public class LocationTimeZoneProviderControllerTest { controller.getUncertaintyTimeoutDelayMillis()); } private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) { private static TimeZoneProviderEvent createSuggestionEvent( long elapsedRealtimeMillis, @NonNull List<String> timeZoneIds) { TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder() .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE) .setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE) .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK) .build(); TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder() .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS) .setElapsedRealtimeMillis(elapsedRealtimeMillis) .setTimeZoneIds(timeZoneIds) .build(); return TimeZoneProviderEvent.createSuggestionEvent( ARBITRARY_TIME_MILLIS, suggestion, providerStatus); elapsedRealtimeMillis, suggestion, providerStatus); } private static void assertControllerState(LocationTimeZoneProviderController controller, Loading services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java +6 −0 Original line number Diff line number Diff line Loading @@ -142,4 +142,10 @@ class TestThreadingDomain extends ThreadingDomain { mCurrentTimeMillis = queued.executionTimeMillis; queued.runnable.run(); } void executeAll() { while (!mQueue.isEmpty()) { executeNext(); } } } Loading
services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java +25 −11 Original line number Diff line number Diff line Loading @@ -303,8 +303,7 @@ class LocationTimeZoneProviderController implements Dumpable { private void reportSuggestionEvent( @NonNull GeolocationTimeZoneSuggestion suggestion, @NonNull String reason) { LocationTimeZoneAlgorithmStatus algorithmStatus = generateCurrentAlgorithmStatus(); LocationAlgorithmEvent event = new LocationAlgorithmEvent( algorithmStatus, suggestion); LocationAlgorithmEvent event = new LocationAlgorithmEvent(algorithmStatus, suggestion); event.addDebugInfo(reason); reportEvent(event); } Loading Loading @@ -728,6 +727,20 @@ class LocationTimeZoneProviderController implements Dumpable { // Start the uncertainty timeout if needed to ensure the controller will eventually make an // uncertain suggestion if no success event arrives in time to counteract it. if (!mUncertaintyTimeoutQueue.hasQueued()) { if (STATE_UNCERTAIN.equals(mState.get())) { // If the controller is already uncertain, there's no reason to start a timeout; // just forward the suggestion immediately to make it obvious in the logs what has // happened. Making a new suggestion potentially captures new LTZP status info. GeolocationTimeZoneSuggestion suggestion = GeolocationTimeZoneSuggestion.createUncertainSuggestion( uncertaintyStartedElapsedMillis); String debugInfo = "Uncertainty received from " + provider.getName() + ":" + " primary=" + mPrimaryProvider + ", secondary=" + mSecondaryProvider + ", uncertaintyStarted=" + Duration.ofMillis(uncertaintyStartedElapsedMillis); reportSuggestionEvent(suggestion, debugInfo); } else { debugLog("Starting uncertainty timeout: reason=" + reason); Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay(); Loading @@ -736,12 +749,13 @@ class LocationTimeZoneProviderController implements Dumpable { provider, uncertaintyStartedElapsedMillis, uncertaintyDelay), uncertaintyDelay.toMillis()); } } if (provider == mPrimaryProvider) { // (Try to) start the secondary. It could already be started, or enabling might not // succeed if the provider has previously reported it is perm failed. The uncertainty // timeout (set above) is used to ensure that an uncertain suggestion will be made if // the secondary cannot generate a success event in time. // timeout (may be set above) is used to ensure that an uncertain suggestion will be // made if the secondary cannot generate a success event in time. tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration); } } Loading
services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java +163 −18 Original line number Diff line number Diff line Loading @@ -88,18 +88,21 @@ public class LocationTimeZoneProviderControllerTest { private static final long ARBITRARY_TIME_MILLIS = 12345L; private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 = createSuggestionEvent(asList("Europe/London")); createSuggestionEvent(ARBITRARY_TIME_MILLIS, asList("Europe/London")); private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 = createSuggestionEvent(asList("Europe/Paris")); createSuggestionEvent(ARBITRARY_TIME_MILLIS + 1, asList("Europe/Paris")); private static final TimeZoneProviderStatus UNCERTAIN_PROVIDER_STATUS = new TimeZoneProviderStatus.Builder() .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE) .setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK) .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_UNKNOWN) .build(); private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT = private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1 = TimeZoneProviderEvent.createUncertainEvent( ARBITRARY_TIME_MILLIS, UNCERTAIN_PROVIDER_STATUS); private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2 = TimeZoneProviderEvent.createUncertainEvent( ARBITRARY_TIME_MILLIS + 1, UNCERTAIN_PROVIDER_STATUS); private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT = TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test"); Loading Loading @@ -328,7 +331,7 @@ public class LocationTimeZoneProviderControllerTest { // Finally, the uncertainty timeout should cause the controller to make an uncertain // suggestion. mTestThreadingDomain.executeNext(); mTestThreadingDomain.executeAll(); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -649,7 +652,7 @@ public class LocationTimeZoneProviderControllerTest { // cause a suggestion to be made straight away, but the uncertainty timeout should be // started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -680,7 +683,7 @@ public class LocationTimeZoneProviderControllerTest { // cause a suggestion to be made straight away, but the uncertainty timeout should be // started. Both providers are now started, with no initialization timeout set. mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading @@ -693,7 +696,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate time passing. This means the uncertainty timeout should fire and the uncertain // suggestion should be made. mTestThreadingDomain.executeNext(); mTestThreadingDomain.executeAll(); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading @@ -702,7 +705,7 @@ public class LocationTimeZoneProviderControllerTest { PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN); mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); } Loading Loading @@ -744,7 +747,7 @@ public class LocationTimeZoneProviderControllerTest { // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty // timeout should be started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading @@ -771,6 +774,147 @@ public class LocationTimeZoneProviderControllerTest { assertFalse(controller.isUncertaintyTimeoutSet()); } @Test public void enabled_uncertaintyDuringUncertaintyTimeoutTriggersNoSuggestion() { LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController( mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */); TestEnvironment testEnvironment = new TestEnvironment( mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED); // Initialize and check initial state. controller.initialize(testEnvironment, mTestCallback); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit( STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING); mTestCallback.assertEventWithNoSuggestionReportedAndCommit( DETECTION_ALGORITHM_STATUS_RUNNING); assertFalse(controller.isUncertaintyTimeoutSet()); // Simulate a location event being received from the primary provider. This should cause a // suggestion to be made. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN); mTestCallback.assertEventWithCertainSuggestionReportedAndCommit( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty // timeout should be started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertNoEventReported(); assertUncertaintyTimeoutSet(testEnvironment, controller); // Another uncertain suggestion from the primary during the uncertainty timeout should have // no effect. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertNoEventReported(); assertUncertaintyTimeoutSet(testEnvironment, controller); } @Test public void enabled_uncertaintyAfterUncertaintyTimeoutTriggersImmediateSuggestion() { LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController( mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */); TestEnvironment testEnvironment = new TestEnvironment( mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED); // Initialize and check initial state. controller.initialize(testEnvironment, mTestCallback); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit( STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING); mTestCallback.assertEventWithNoSuggestionReportedAndCommit( DETECTION_ALGORITHM_STATUS_RUNNING); assertFalse(controller.isUncertaintyTimeoutSet()); // Simulate a location event being received from the primary provider. This should cause a // suggestion to be made. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit(); mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN); mTestCallback.assertEventWithCertainSuggestionReportedAndCommit( USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty // timeout should be started and the secondary should be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertNoEventReported(); assertUncertaintyTimeoutSet(testEnvironment, controller); // Simulate time passing. This means the uncertainty timeout should fire and the uncertain // suggestion should be made. mTestThreadingDomain.executeAll(); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN); mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertFalse(controller.isUncertaintyTimeoutSet()); // Another uncertain suggestion from the primary should cause an immediate suggestion. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2); assertControllerState(controller, STATE_UNCERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED); mTestMetricsLogger.assertStateChangesAndCommit(); mTestCallback.assertEventWithUncertainSuggestionReportedAndCommit( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT2); assertFalse(controller.isUncertaintyTimeoutSet()); } @Test public void configChanges_enableAndDisableWithNoPreviousSuggestion() { LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController( Loading Loading @@ -965,7 +1109,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate uncertainty from the secondary. mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit(); Loading @@ -991,7 +1135,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate uncertainty from the secondary. mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit(); Loading Loading @@ -1085,7 +1229,7 @@ public class LocationTimeZoneProviderControllerTest { // give this test the opportunity to simulate its failure. Then it will be possible to // demonstrate controller behavior with only the primary working. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -1124,7 +1268,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate uncertainty from the primary. The secondary cannot be started. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_CERTAIN); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -1160,7 +1304,7 @@ public class LocationTimeZoneProviderControllerTest { // give this test the opportunity to simulate its failure. Then it will be possible to // demonstrate controller behavior with only the primary working. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); assertControllerState(controller, STATE_INITIALIZING); mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit( Loading Loading @@ -1282,7 +1426,7 @@ public class LocationTimeZoneProviderControllerTest { // Simulate an uncertain event from the primary. This will start the secondary. mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent( USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT); USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT1); { LocationTimeZoneManagerServiceState state = controller.getStateForTests(); Loading Loading @@ -1471,18 +1615,19 @@ public class LocationTimeZoneProviderControllerTest { controller.getUncertaintyTimeoutDelayMillis()); } private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) { private static TimeZoneProviderEvent createSuggestionEvent( long elapsedRealtimeMillis, @NonNull List<String> timeZoneIds) { TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder() .setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE) .setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE) .setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK) .build(); TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder() .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS) .setElapsedRealtimeMillis(elapsedRealtimeMillis) .setTimeZoneIds(timeZoneIds) .build(); return TimeZoneProviderEvent.createSuggestionEvent( ARBITRARY_TIME_MILLIS, suggestion, providerStatus); elapsedRealtimeMillis, suggestion, providerStatus); } private static void assertControllerState(LocationTimeZoneProviderController controller, Loading
services/tests/servicestests/src/com/android/server/timezonedetector/location/TestThreadingDomain.java +6 −0 Original line number Diff line number Diff line Loading @@ -142,4 +142,10 @@ class TestThreadingDomain extends ThreadingDomain { mCurrentTimeMillis = queued.executionTimeMillis; queued.runnable.run(); } void executeAll() { while (!mQueue.isEmpty()) { executeNext(); } } }