summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java670
-rw-r--r--services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java52
-rw-r--r--services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java657
-rw-r--r--services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerCallbackImpl.java (renamed from services/core/java/com/android/server/timezonedetector/location/ControllerCallbackImpl.java)7
-rw-r--r--services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerEnvironmentImpl.java (renamed from services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java)7
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java)369
6 files changed, 867 insertions, 895 deletions
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
deleted file mode 100644
index b9da2ebd3663..000000000000
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.timezonedetector.location;
-
-import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
-import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
-
-import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.debugLog;
-import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.warnLog;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
-
-import android.annotation.DurationMillisLong;
-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;
-import com.android.server.timezonedetector.ConfigurationInternal;
-import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
-import com.android.server.timezonedetector.location.ThreadingDomain.SingleRunnableQueue;
-
-import java.time.Duration;
-import java.util.Objects;
-
-/**
- * A real implementation of {@link LocationTimeZoneProviderController} that supports a primary and a
- * secondary {@link LocationTimeZoneProvider}.
- *
- * <p>The primary is used until it fails or becomes uncertain. The secondary will then be started.
- * The controller will immediately make suggestions based on "certain" {@link
- * TimeZoneProviderEvent}s, i.e. events that demonstrate the provider is certain what the time zone
- * is. The controller will not make immediate suggestions based on "uncertain" events, giving
- * providers time to change their mind. This also gives the secondary provider time to initialize
- * when the primary becomes uncertain.
- */
-class ControllerImpl extends LocationTimeZoneProviderController {
-
- @NonNull private final LocationTimeZoneProvider mPrimaryProvider;
-
- @NonNull private final LocationTimeZoneProvider mSecondaryProvider;
-
- @GuardedBy("mSharedLock")
- // Non-null after initialize()
- private ConfigurationInternal mCurrentUserConfiguration;
-
- @GuardedBy("mSharedLock")
- // Non-null after initialize()
- private Environment mEnvironment;
-
- @GuardedBy("mSharedLock")
- // Non-null after initialize()
- private Callback mCallback;
-
- /** Indicates both providers have completed initialization. */
- @GuardedBy("mSharedLock")
- private boolean mProvidersInitialized;
-
- /**
- * Used for scheduling uncertainty timeouts, i.e after a provider has reported uncertainty.
- * This timeout is not provider-specific: it is started when the controller becomes uncertain
- * due to events it has received from one or other provider.
- */
- @NonNull private final SingleRunnableQueue mUncertaintyTimeoutQueue;
-
- /** Contains the last suggestion actually made, if there is one. */
- @GuardedBy("mSharedLock")
- @Nullable
- private GeolocationTimeZoneSuggestion mLastSuggestion;
-
- ControllerImpl(@NonNull ThreadingDomain threadingDomain,
- @NonNull LocationTimeZoneProvider primaryProvider,
- @NonNull LocationTimeZoneProvider secondaryProvider) {
- super(threadingDomain);
- mUncertaintyTimeoutQueue = threadingDomain.createSingleRunnableQueue();
- mPrimaryProvider = Objects.requireNonNull(primaryProvider);
- mSecondaryProvider = Objects.requireNonNull(secondaryProvider);
- }
-
- @Override
- void initialize(@NonNull Environment environment, @NonNull Callback callback) {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- debugLog("initialize()");
- mEnvironment = Objects.requireNonNull(environment);
- mCallback = Objects.requireNonNull(callback);
- mCurrentUserConfiguration = environment.getCurrentUserConfigurationInternal();
-
- LocationTimeZoneProvider.ProviderListener providerListener =
- ControllerImpl.this::onProviderStateChange;
- mPrimaryProvider.initialize(providerListener);
- mSecondaryProvider.initialize(providerListener);
- mProvidersInitialized = true;
-
- alterProvidersStartedStateIfRequired(
- null /* oldConfiguration */, mCurrentUserConfiguration);
- }
- }
-
- @Override
- void onConfigurationInternalChanged() {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- debugLog("onConfigChanged()");
-
- ConfigurationInternal oldConfig = mCurrentUserConfiguration;
- ConfigurationInternal newConfig = mEnvironment.getCurrentUserConfigurationInternal();
- mCurrentUserConfiguration = newConfig;
-
- if (!newConfig.equals(oldConfig)) {
- if (newConfig.getUserId() != oldConfig.getUserId()) {
- // If the user changed, stop the providers if needed. They may be re-started
- // for the new user immediately afterwards if their settings allow.
- debugLog("User changed. old=" + oldConfig.getUserId()
- + ", new=" + newConfig.getUserId() + ": Stopping providers");
- stopProviders();
-
- alterProvidersStartedStateIfRequired(null /* oldConfiguration */, newConfig);
- } else {
- alterProvidersStartedStateIfRequired(oldConfig, newConfig);
- }
- }
- }
- }
-
- @Override
- boolean isUncertaintyTimeoutSet() {
- return mUncertaintyTimeoutQueue.hasQueued();
- }
-
- @Override
- @DurationMillisLong
- long getUncertaintyTimeoutDelayMillis() {
- return mUncertaintyTimeoutQueue.getQueuedDelayMillis();
- }
-
- @Override
- void destroy() {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- stopProviders();
- mPrimaryProvider.destroy();
- mSecondaryProvider.destroy();
- }
- }
-
- @GuardedBy("mSharedLock")
- private void stopProviders() {
- stopProviderIfStarted(mPrimaryProvider);
- stopProviderIfStarted(mSecondaryProvider);
-
- // By definition, if both providers are stopped, the controller is uncertain.
- cancelUncertaintyTimeout();
-
- // If a previous "certain" suggestion has been made, then a new "uncertain"
- // suggestion must now be made to indicate the controller {does not / no longer has}
- // an opinion and will not be sending further updates (until at least the providers are
- // re-started).
- if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
- GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
- mEnvironment.elapsedRealtimeMillis(), "Providers are stopping");
- makeSuggestion(suggestion);
- }
- }
-
- @GuardedBy("mSharedLock")
- private void stopProviderIfStarted(@NonNull LocationTimeZoneProvider provider) {
- if (provider.getCurrentState().isStarted()) {
- stopProvider(provider);
- }
- }
-
- @GuardedBy("mSharedLock")
- private void stopProvider(@NonNull LocationTimeZoneProvider provider) {
- ProviderState providerState = provider.getCurrentState();
- switch (providerState.stateEnum) {
- case PROVIDER_STATE_STOPPED: {
- debugLog("No need to stop " + provider + ": already stopped");
- break;
- }
- case PROVIDER_STATE_STARTED_INITIALIZING:
- case PROVIDER_STATE_STARTED_CERTAIN:
- case PROVIDER_STATE_STARTED_UNCERTAIN: {
- debugLog("Stopping " + provider);
- provider.stopUpdates();
- break;
- }
- case PROVIDER_STATE_PERM_FAILED:
- case PROVIDER_STATE_DESTROYED: {
- debugLog("Unable to stop " + provider + ": it is terminated.");
- break;
- }
- default: {
- warnLog("Unknown provider state: " + provider);
- break;
- }
- }
- }
-
- /**
- * Sets the providers into the correct started/stopped state for the {@code newConfiguration}
- * and, if there is a provider state change, makes any suggestions required to inform the
- * downstream time zone detection code.
- *
- * <p>This is a utility method that exists to avoid duplicated logic for the various cases when
- * provider started / stopped state may need to be set or changed, e.g. during initialization
- * or when a new configuration has been received.
- */
- @GuardedBy("mSharedLock")
- private void alterProvidersStartedStateIfRequired(
- @Nullable ConfigurationInternal oldConfiguration,
- @NonNull ConfigurationInternal newConfiguration) {
-
- // Provider started / stopped states only need to be changed if geoDetectionEnabled has
- // changed.
- boolean oldGeoDetectionEnabled = oldConfiguration != null
- && oldConfiguration.getGeoDetectionEnabledBehavior();
- boolean newGeoDetectionEnabled = newConfiguration.getGeoDetectionEnabledBehavior();
- if (oldGeoDetectionEnabled == newGeoDetectionEnabled) {
- return;
- }
-
- // The check above ensures that the logic below only executes if providers are going from
- // {started *} -> {stopped}, or {stopped} -> {started initializing}. If this changes in
- // future and there could be {started *} -> {started *} cases, or cases where the provider
- // can't be assumed to go straight to the {started initializing} state, then the logic below
- // would need to cover extra conditions, for example:
- // 1) If the primary is in {started uncertain}, the secondary should be started.
- // 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
- // timeout started when the primary entered {started uncertain} should be cancelled.
-
- if (newGeoDetectionEnabled) {
- // Try to start the primary provider.
- tryStartProvider(mPrimaryProvider, newConfiguration);
-
- // The secondary should only ever be started if the primary now isn't started (i.e. it
- // couldn't become {started initializing} because it is {perm failed}).
- ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
- if (!newPrimaryState.isStarted()) {
- // If the primary provider is {perm failed} then the controller must try to start
- // the secondary.
- tryStartProvider(mSecondaryProvider, newConfiguration);
-
- ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
- if (!newSecondaryState.isStarted()) {
- // 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());
- makeSuggestion(suggestion);
- }
- }
- } else {
- stopProviders();
- }
- }
-
- @GuardedBy("mSharedLock")
- private void tryStartProvider(@NonNull LocationTimeZoneProvider provider,
- @NonNull ConfigurationInternal configuration) {
- ProviderState providerState = provider.getCurrentState();
- switch (providerState.stateEnum) {
- case PROVIDER_STATE_STOPPED: {
- debugLog("Enabling " + provider);
- provider.startUpdates(configuration,
- mEnvironment.getProviderInitializationTimeout(),
- mEnvironment.getProviderInitializationTimeoutFuzz(),
- mEnvironment.getProviderEventFilteringAgeThreshold());
- break;
- }
- case PROVIDER_STATE_STARTED_INITIALIZING:
- case PROVIDER_STATE_STARTED_CERTAIN:
- case PROVIDER_STATE_STARTED_UNCERTAIN: {
- debugLog("No need to start " + provider + ": already started");
- break;
- }
- case PROVIDER_STATE_PERM_FAILED:
- case PROVIDER_STATE_DESTROYED: {
- debugLog("Unable to start " + provider + ": it is terminated");
- break;
- }
- default: {
- throw new IllegalStateException("Unknown provider state:"
- + " provider=" + provider);
- }
- }
- }
-
- void onProviderStateChange(@NonNull ProviderState providerState) {
- mThreadingDomain.assertCurrentThread();
- LocationTimeZoneProvider provider = providerState.provider;
- assertProviderKnown(provider);
-
- synchronized (mSharedLock) {
- // Ignore provider state changes during initialization. e.g. if the primary provider
- // moves to PROVIDER_STATE_PERM_FAILED during initialization, the secondary will not
- // be ready to take over yet.
- if (!mProvidersInitialized) {
- warnLog("onProviderStateChange: Ignoring provider state change because both"
- + " providers have not yet completed initialization."
- + " providerState=" + providerState);
- return;
- }
-
- switch (providerState.stateEnum) {
- case PROVIDER_STATE_STARTED_INITIALIZING:
- case PROVIDER_STATE_STOPPED:
- case PROVIDER_STATE_DESTROYED: {
- // This should never happen: entering initializing, stopped or destroyed are
- // triggered by the controller so and should not trigger a state change
- // callback.
- warnLog("onProviderStateChange: Unexpected state change for provider,"
- + " provider=" + provider);
- break;
- }
- case PROVIDER_STATE_STARTED_CERTAIN:
- case PROVIDER_STATE_STARTED_UNCERTAIN: {
- // These are valid and only happen if an event is received while the provider is
- // started.
- debugLog("onProviderStateChange: Received notification of a state change while"
- + " started, provider=" + provider);
- handleProviderStartedStateChange(providerState);
- break;
- }
- case PROVIDER_STATE_PERM_FAILED: {
- debugLog("Received notification of permanent failure for"
- + " provider=" + provider);
- handleProviderFailedStateChange(providerState);
- break;
- }
- default: {
- warnLog("onProviderStateChange: Unexpected provider=" + provider);
- }
- }
- }
- }
-
- private void assertProviderKnown(@NonNull LocationTimeZoneProvider provider) {
- if (provider != mPrimaryProvider && provider != mSecondaryProvider) {
- throw new IllegalArgumentException("Unknown provider: " + provider);
- }
- }
-
- /**
- * Called when a provider has reported that it has failed permanently.
- */
- @GuardedBy("mSharedLock")
- private void handleProviderFailedStateChange(@NonNull ProviderState providerState) {
- LocationTimeZoneProvider failedProvider = providerState.provider;
- ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
- ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
-
- // If a provider has failed, the other may need to be started.
- if (failedProvider == mPrimaryProvider) {
- if (!secondaryCurrentState.isTerminated()) {
- // Try to start the secondary. This does nothing if the provider is already
- // started, and will leave the provider in {started initializing} if the provider is
- // stopped.
- tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
- }
- } else if (failedProvider == mSecondaryProvider) {
- // No-op: The secondary will only be active if the primary is uncertain or is
- // terminated. So, there the primary should not need to be started when the secondary
- // fails.
- if (primaryCurrentState.stateEnum != PROVIDER_STATE_STARTED_UNCERTAIN
- && !primaryCurrentState.isTerminated()) {
- warnLog("Secondary provider unexpected reported a failure:"
- + " failed provider=" + failedProvider.getName()
- + ", primary provider=" + mPrimaryProvider
- + ", secondary provider=" + mSecondaryProvider);
- }
- }
-
- // If both providers are now terminated, the controller needs to tell the next component in
- // the time zone detection process.
- if (primaryCurrentState.isTerminated() && secondaryCurrentState.isTerminated()) {
-
- // If both providers are newly terminated then the controller is uncertain by definition
- // and it will never recover so it can send a suggestion immediately.
- cancelUncertaintyTimeout();
-
- // 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);
- makeSuggestion(suggestion);
- }
- }
-
- /**
- * Called when a provider has changed state but just moved from one started state to another
- * started state, usually as a result of a new {@link TimeZoneProviderEvent} being received.
- * However, there are rare cases where the event can also be null.
- */
- @GuardedBy("mSharedLock")
- private void handleProviderStartedStateChange(@NonNull ProviderState providerState) {
- LocationTimeZoneProvider provider = providerState.provider;
- TimeZoneProviderEvent event = providerState.event;
- if (event == null) {
- // Implicit uncertainty, i.e. where the provider is started, but a problem has been
- // detected without having received an event. For example, if the process has detected
- // 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.
- long uncertaintyStartedElapsedMillis = mEnvironment.elapsedRealtimeMillis();
- handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
- "provider=" + provider + ", implicit uncertainty, event=null");
- return;
- }
-
- if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
- // This should not happen: the provider should not be in an started state if the user
- // does not have geodetection enabled.
- warnLog("Provider=" + provider + " is started, but"
- + " currentUserConfiguration=" + mCurrentUserConfiguration
- + " suggests it shouldn't be.");
- }
-
- 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");
- break;
- }
- case EVENT_TYPE_UNCERTAIN: {
- long uncertaintyStartedElapsedMillis = event.getCreationElapsedMillis();
- handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
- "provider=" + provider + ", explicit uncertainty. event=" + event);
- break;
- }
- case EVENT_TYPE_SUGGESTION: {
- handleProviderSuggestion(provider, event);
- break;
- }
- default: {
- warnLog("Unknown eventType=" + event.getType());
- break;
- }
- }
- }
-
- /**
- * Called when a provider has become "certain" about the time zone(s).
- */
- @GuardedBy("mSharedLock")
- private void handleProviderSuggestion(
- @NonNull LocationTimeZoneProvider provider,
- @NonNull TimeZoneProviderEvent providerEvent) {
-
- // By definition, the controller is now certain.
- cancelUncertaintyTimeout();
-
- if (provider == mPrimaryProvider) {
- stopProviderIfStarted(mSecondaryProvider);
- }
-
- 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
- public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
- synchronized (mSharedLock) {
- ipw.println("LocationTimeZoneProviderController:");
-
- ipw.increaseIndent(); // level 1
- ipw.println("mCurrentUserConfiguration=" + mCurrentUserConfiguration);
- ipw.println("providerInitializationTimeout="
- + mEnvironment.getProviderInitializationTimeout());
- ipw.println("providerInitializationTimeoutFuzz="
- + mEnvironment.getProviderInitializationTimeoutFuzz());
- ipw.println("uncertaintyDelay=" + mEnvironment.getUncertaintyDelay());
- ipw.println("mLastSuggestion=" + mLastSuggestion);
-
- ipw.println("Primary Provider:");
- ipw.increaseIndent(); // level 2
- mPrimaryProvider.dump(ipw, args);
- ipw.decreaseIndent(); // level 2
-
- ipw.println("Secondary Provider:");
- ipw.increaseIndent(); // level 2
- mSecondaryProvider.dump(ipw, args);
- ipw.decreaseIndent(); // level 2
-
- ipw.decreaseIndent(); // level 1
- }
- }
-
- /** Sends an immediate suggestion, updating mLastSuggestion. */
- @GuardedBy("mSharedLock")
- private void makeSuggestion(@NonNull GeolocationTimeZoneSuggestion suggestion) {
- debugLog("makeSuggestion: suggestion=" + suggestion);
- mCallback.suggest(suggestion);
- mLastSuggestion = suggestion;
- }
-
- /** Clears the uncertainty timeout. */
- @GuardedBy("mSharedLock")
- private void cancelUncertaintyTimeout() {
- mUncertaintyTimeoutQueue.cancel();
- }
-
- /**
- * Called when a provider has become "uncertain" about the time zone.
- *
- * <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
- * this enables the most flexibility for the controller to start other providers when there are
- * multiple ones available. The controller is therefore responsible for deciding when to make a
- * "uncertain" suggestion to the downstream time zone detector.
- *
- * <p>This method schedules an "uncertainty" timeout (if one isn't already scheduled) to be
- * triggered later if nothing else preempts it. It can be preempted if the provider becomes
- * certain (or does anything else that calls {@link
- * #makeSuggestion(GeolocationTimeZoneSuggestion)}) within {@link
- * Environment#getUncertaintyDelay()}. Preemption causes the scheduled
- * "uncertainty" timeout to be cancelled. If the provider repeatedly sends uncertainty events
- * within the uncertainty delay period, those events are effectively ignored (i.e. the timeout
- * is not reset each time).
- */
- @GuardedBy("mSharedLock")
- void handleProviderUncertainty(
- @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
- // uncertain suggestion if no success event arrives in time to counteract it.
- if (!mUncertaintyTimeoutQueue.hasQueued()) {
- debugLog("Starting uncertainty timeout: reason=" + reason);
-
- Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
- mUncertaintyTimeoutQueue.runDelayed(
- () -> onProviderUncertaintyTimeout(
- 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.
- tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
- }
- }
-
- 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
- + ", uncertaintyStarted="
- + Duration.ofMillis(uncertaintyStartedElapsedMillis)
- + ", afterUncertaintyTimeout="
- + Duration.ofMillis(afterUncertaintyTimeoutElapsedMillis)
- + ", uncertaintyDelay=" + uncertaintyDelay
- );
- makeSuggestion(suggestion);
- }
- }
-
- @NonNull
- private static GeolocationTimeZoneSuggestion createUncertainSuggestion(
- @ElapsedRealtimeLong long effectiveFromElapsedMillis,
- @NonNull String reason) {
- GeolocationTimeZoneSuggestion suggestion =
- GeolocationTimeZoneSuggestion.createUncertainSuggestion(
- effectiveFromElapsedMillis);
- suggestion.addDebugInfo(reason);
- return suggestion;
- }
-
- /**
- * Clears recorded provider state changes (for use during tests).
- */
- void clearRecordedProviderStates() {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- mPrimaryProvider.clearRecordedStates();
- mSecondaryProvider.clearRecordedStates();
- }
- }
-
- /**
- * Returns a snapshot of the current controller state for tests.
- */
- @NonNull
- LocationTimeZoneManagerServiceState getStateForTests() {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- LocationTimeZoneManagerServiceState.Builder builder =
- new LocationTimeZoneManagerServiceState.Builder();
- if (mLastSuggestion != null) {
- builder.setLastSuggestion(mLastSuggestion);
- }
- builder.setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
- .setSecondaryProviderStateChanges(mSecondaryProvider.getRecordedStates());
- return builder.build();
- }
- }
-}
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
index ddbeac4e458a..af8cf6e05a84 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -147,16 +147,16 @@ public class LocationTimeZoneManagerService extends Binder {
/** The shared lock from {@link #mThreadingDomain}. */
@NonNull private final Object mSharedLock;
- @NonNull
- private final ServiceConfigAccessor mServiceConfigAccessor;
+ @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
// Lazily initialized. Can be null if the service has been stopped.
@GuardedBy("mSharedLock")
- private ControllerImpl mLocationTimeZoneDetectorController;
+ private LocationTimeZoneProviderController mLocationTimeZoneProviderController;
// Lazily initialized. Can be null if the service has been stopped.
@GuardedBy("mSharedLock")
- private ControllerEnvironmentImpl mEnvironment;
+ private LocationTimeZoneProviderControllerEnvironmentImpl
+ mLocationTimeZoneProviderControllerEnvironment;
LocationTimeZoneManagerService(@NonNull Context context,
@NonNull ServiceConfigAccessor serviceConfigAccessor) {
@@ -190,7 +190,7 @@ public class LocationTimeZoneManagerService extends Binder {
// Avoid starting the service if it is currently stopped. This is required because
// server flags are used by tests to set behavior with the service stopped, and we don't
// want the service being restarted after each flag is set.
- if (mLocationTimeZoneDetectorController != null) {
+ if (mLocationTimeZoneProviderController != null) {
// Stop and start the service, waiting until completion.
stopOnDomainThread();
startOnDomainThread();
@@ -278,19 +278,22 @@ public class LocationTimeZoneManagerService extends Binder {
return;
}
- if (mLocationTimeZoneDetectorController == null) {
+ if (mLocationTimeZoneProviderController == null) {
LocationTimeZoneProvider primary = mPrimaryProviderConfig.createProvider();
LocationTimeZoneProvider secondary = mSecondaryProviderConfig.createProvider();
- ControllerImpl controller =
- new ControllerImpl(mThreadingDomain, primary, secondary);
- ControllerEnvironmentImpl environment = new ControllerEnvironmentImpl(
- mThreadingDomain, mServiceConfigAccessor, controller);
- ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
+ LocationTimeZoneProviderController controller =
+ new LocationTimeZoneProviderController(
+ mThreadingDomain, primary, secondary);
+ LocationTimeZoneProviderControllerEnvironmentImpl environment =
+ new LocationTimeZoneProviderControllerEnvironmentImpl(
+ mThreadingDomain, mServiceConfigAccessor, controller);
+ LocationTimeZoneProviderControllerCallbackImpl callback =
+ new LocationTimeZoneProviderControllerCallbackImpl(mThreadingDomain);
controller.initialize(environment, callback);
- mEnvironment = environment;
- mLocationTimeZoneDetectorController = controller;
+ mLocationTimeZoneProviderControllerEnvironment = environment;
+ mLocationTimeZoneProviderController = controller;
}
}
}
@@ -312,11 +315,11 @@ public class LocationTimeZoneManagerService extends Binder {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
- if (mLocationTimeZoneDetectorController != null) {
- mLocationTimeZoneDetectorController.destroy();
- mLocationTimeZoneDetectorController = null;
- mEnvironment.destroy();
- mEnvironment = null;
+ if (mLocationTimeZoneProviderController != null) {
+ mLocationTimeZoneProviderController.destroy();
+ mLocationTimeZoneProviderController = null;
+ mLocationTimeZoneProviderControllerEnvironment.destroy();
+ mLocationTimeZoneProviderControllerEnvironment = null;
// Clear test state so it won't be used the next time the service is started.
mServiceConfigAccessor.resetVolatileTestConfig();
@@ -338,8 +341,8 @@ public class LocationTimeZoneManagerService extends Binder {
mThreadingDomain.postAndWait(() -> {
synchronized (mSharedLock) {
- if (mLocationTimeZoneDetectorController != null) {
- mLocationTimeZoneDetectorController.clearRecordedProviderStates();
+ if (mLocationTimeZoneProviderController != null) {
+ mLocationTimeZoneProviderController.clearRecordedProviderStates();
}
}
}, BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -357,10 +360,10 @@ public class LocationTimeZoneManagerService extends Binder {
return mThreadingDomain.postAndWait(
() -> {
synchronized (mSharedLock) {
- if (mLocationTimeZoneDetectorController == null) {
+ if (mLocationTimeZoneProviderController == null) {
return null;
}
- return mLocationTimeZoneDetectorController.getStateForTests();
+ return mLocationTimeZoneProviderController.getStateForTests();
}
},
BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -390,10 +393,10 @@ public class LocationTimeZoneManagerService extends Binder {
mSecondaryProviderConfig.dump(ipw, args);
ipw.decreaseIndent();
- if (mLocationTimeZoneDetectorController == null) {
+ if (mLocationTimeZoneProviderController == null) {
ipw.println("{Stopped}");
} else {
- mLocationTimeZoneDetectorController.dump(ipw, args);
+ mLocationTimeZoneProviderController.dump(ipw, args);
}
ipw.decreaseIndent();
}
@@ -450,7 +453,6 @@ public class LocationTimeZoneManagerService extends Binder {
mServiceConfigAccessor.getRecordProviderStateChanges());
}
- @GuardedBy("mSharedLock")
@Override
public void dump(IndentingPrintWriter ipw, String[] args) {
ipw.printf("getMode()=%s\n", getMode());
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 4dff02e8ab6f..dbd3877debfe 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
@@ -16,31 +16,57 @@
package com.android.server.timezonedetector.location;
+import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
+import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
+import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
+
+import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.debugLog;
+import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.warnLog;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+
import android.annotation.DurationMillisLong;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
-import android.os.Handler;
+import android.annotation.Nullable;
+import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderSuggestion;
+import android.util.IndentingPrintWriter;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.timezonedetector.ConfigurationInternal;
import com.android.server.timezonedetector.Dumpable;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
-import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
+import com.android.server.timezonedetector.location.ThreadingDomain.SingleRunnableQueue;
import java.time.Duration;
import java.util.Objects;
/**
- * An base class for the component responsible handling events from {@link
- * LocationTimeZoneProvider}s and synthesizing time zone ID suggestions for sending to the time zone
- * detector. This interface primarily exists to extract testable detection logic, i.e. with
- * a minimal number of threading considerations or dependencies on Android infrastructure.
+ * The component responsible handling events from {@link LocationTimeZoneProvider}s and synthesizing
+ * time zone ID suggestions for sending to the time zone detector.
+ *
+ * <p>This class primarily exists to extract unit-testable logic from the surrounding service class,
+ * i.e. with a minimal number of threading considerations or direct dependencies on Android
+ * infrastructure.
+ *
+ * <p>This class supports a primary and a secondary {@link LocationTimeZoneProvider}. The primary is
+ * used until it fails or becomes uncertain. The secondary will then be started. The controller will
+ * immediately make suggestions based on "certain" {@link TimeZoneProviderEvent}s, i.e. events that
+ * demonstrate the provider is certain what the time zone is. The controller will not make immediate
+ * suggestions based on "uncertain" events, giving providers time to change their mind. This also
+ * gives the secondary provider time to initialize when the primary becomes uncertain.
*
* <p>The controller interacts with the following components:
* <ul>
- * <li>The surrounding service, which calls {@link #initialize(Environment, Callback)} and
- * {@link #onConfigurationInternalChanged()}.</li>
- * <li>The {@link Environment} through which obtains information it needs.</li>
+ * <li>The surrounding service, which calls {@link #initialize(Environment, Callback)}.
+ * <li>The {@link Environment} through which it obtains information it needs.</li>
* <li>The {@link Callback} through which it makes time zone suggestions.</li>
* <li>Any {@link LocationTimeZoneProvider} instances it owns, which communicate via the
* {@link LocationTimeZoneProvider.ProviderListener#onProviderStateChange(ProviderState)}
@@ -49,8 +75,9 @@ import java.util.Objects;
*
* <p>All incoming calls except for {@link
* LocationTimeZoneProviderController#dump(android.util.IndentingPrintWriter, String[])} must be
- * made on the {@link Handler} thread of the {@link ThreadingDomain} passed to {@link
- * #LocationTimeZoneProviderController(ThreadingDomain)}.
+ * made on the {@link android.os.Handler} thread of the {@link ThreadingDomain} passed to {@link
+ * #LocationTimeZoneProviderController(ThreadingDomain, LocationTimeZoneProvider,
+ * LocationTimeZoneProvider)}.
*
* <p>Provider / controller integration notes:
*
@@ -59,43 +86,631 @@ import java.util.Objects;
* different from the certainty that there are no time zone IDs for the current location. A provider
* can be certain about there being no time zone IDs for a location for good reason, e.g. for
* disputed areas and oceans. Distinguishing uncertainty allows the controller to try other
- * providers (or give up), where as certainty means it should not.
+ * providers (or give up), whereas certainty means it should not.
*
* <p>A provider can fail permanently. A permanent failure will stop the provider until next
* boot.
*/
-abstract class LocationTimeZoneProviderController implements Dumpable {
+class LocationTimeZoneProviderController implements Dumpable {
+
+ @NonNull private final ThreadingDomain mThreadingDomain;
+ @NonNull private final Object mSharedLock;
+ /**
+ * Used for scheduling uncertainty timeouts, i.e. after a provider has reported uncertainty.
+ * This timeout is not provider-specific: it is started when the controller becomes uncertain
+ * due to events it has received from one or other provider.
+ */
+ @NonNull private final SingleRunnableQueue mUncertaintyTimeoutQueue;
+
+ @NonNull private final LocationTimeZoneProvider mPrimaryProvider;
+ @NonNull private final LocationTimeZoneProvider mSecondaryProvider;
+
+ @GuardedBy("mSharedLock")
+ // Non-null after initialize()
+ private ConfigurationInternal mCurrentUserConfiguration;
- @NonNull protected final ThreadingDomain mThreadingDomain;
- @NonNull protected final Object mSharedLock;
+ @GuardedBy("mSharedLock")
+ // Non-null after initialize()
+ private Environment mEnvironment;
- LocationTimeZoneProviderController(@NonNull ThreadingDomain threadingDomain) {
+ @GuardedBy("mSharedLock")
+ // Non-null after initialize()
+ private Callback mCallback;
+
+ /** Indicates both providers have completed initialization. */
+ @GuardedBy("mSharedLock")
+ private boolean mProvidersInitialized;
+
+
+ /** Contains the last suggestion actually made, if there is one. */
+ @GuardedBy("mSharedLock")
+ @Nullable
+ private GeolocationTimeZoneSuggestion mLastSuggestion;
+
+ LocationTimeZoneProviderController(@NonNull ThreadingDomain threadingDomain,
+ @NonNull LocationTimeZoneProvider primaryProvider,
+ @NonNull LocationTimeZoneProvider secondaryProvider) {
mThreadingDomain = Objects.requireNonNull(threadingDomain);
mSharedLock = threadingDomain.getLockObject();
+ mUncertaintyTimeoutQueue = threadingDomain.createSingleRunnableQueue();
+ mPrimaryProvider = Objects.requireNonNull(primaryProvider);
+ mSecondaryProvider = Objects.requireNonNull(secondaryProvider);
}
/**
* Called to initialize the controller during boot. Called once only.
* {@link LocationTimeZoneProvider#initialize} must be called by this method.
*/
- abstract void initialize(@NonNull Environment environment, @NonNull Callback callback);
+ void initialize(@NonNull Environment environment, @NonNull Callback callback) {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ debugLog("initialize()");
+ mEnvironment = Objects.requireNonNull(environment);
+ mCallback = Objects.requireNonNull(callback);
+ mCurrentUserConfiguration = environment.getCurrentUserConfigurationInternal();
+
+ LocationTimeZoneProvider.ProviderListener providerListener =
+ LocationTimeZoneProviderController.this::onProviderStateChange;
+ mPrimaryProvider.initialize(providerListener);
+ mSecondaryProvider.initialize(providerListener);
+ mProvidersInitialized = true;
+
+ alterProvidersStartedStateIfRequired(
+ null /* oldConfiguration */, mCurrentUserConfiguration);
+ }
+ }
/**
* Called when the content of the {@link ConfigurationInternal} may have changed. The receiver
* should call {@link Environment#getCurrentUserConfigurationInternal()} to get the current
* user's config. This call must be made on the {@link ThreadingDomain} handler thread.
*/
- abstract void onConfigurationInternalChanged();
+ void onConfigurationInternalChanged() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ debugLog("onConfigChanged()");
+
+ ConfigurationInternal oldConfig = mCurrentUserConfiguration;
+ ConfigurationInternal newConfig = mEnvironment.getCurrentUserConfigurationInternal();
+ mCurrentUserConfiguration = newConfig;
+
+ if (!newConfig.equals(oldConfig)) {
+ if (newConfig.getUserId() != oldConfig.getUserId()) {
+ // If the user changed, stop the providers if needed. They may be re-started
+ // for the new user immediately afterwards if their settings allow.
+ debugLog("User changed. old=" + oldConfig.getUserId()
+ + ", new=" + newConfig.getUserId() + ": Stopping providers");
+ stopProviders();
+
+ alterProvidersStartedStateIfRequired(null /* oldConfiguration */, newConfig);
+ } else {
+ alterProvidersStartedStateIfRequired(oldConfig, newConfig);
+ }
+ }
+ }
+ }
@VisibleForTesting
- abstract boolean isUncertaintyTimeoutSet();
+ boolean isUncertaintyTimeoutSet() {
+ return mUncertaintyTimeoutQueue.hasQueued();
+ }
@VisibleForTesting
@DurationMillisLong
- abstract long getUncertaintyTimeoutDelayMillis();
+ long getUncertaintyTimeoutDelayMillis() {
+ return mUncertaintyTimeoutQueue.getQueuedDelayMillis();
+ }
/** Called if the geolocation time zone detection is being reconfigured. */
- abstract void destroy();
+ void destroy() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ stopProviders();
+ mPrimaryProvider.destroy();
+ mSecondaryProvider.destroy();
+ }
+ }
+
+ @GuardedBy("mSharedLock")
+ private void stopProviders() {
+ stopProviderIfStarted(mPrimaryProvider);
+ stopProviderIfStarted(mSecondaryProvider);
+
+ // By definition, if both providers are stopped, the controller is uncertain.
+ cancelUncertaintyTimeout();
+
+ // If a previous "certain" suggestion has been made, then a new "uncertain"
+ // suggestion must now be made to indicate the controller {does not / no longer has}
+ // an opinion and will not be sending further updates (until at least the providers are
+ // re-started).
+ if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
+ GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+ mEnvironment.elapsedRealtimeMillis(), "Providers are stopping");
+ makeSuggestion(suggestion);
+ }
+ }
+
+ @GuardedBy("mSharedLock")
+ private void stopProviderIfStarted(@NonNull LocationTimeZoneProvider provider) {
+ if (provider.getCurrentState().isStarted()) {
+ stopProvider(provider);
+ }
+ }
+
+ @GuardedBy("mSharedLock")
+ private void stopProvider(@NonNull LocationTimeZoneProvider provider) {
+ ProviderState providerState = provider.getCurrentState();
+ switch (providerState.stateEnum) {
+ case PROVIDER_STATE_STOPPED: {
+ debugLog("No need to stop " + provider + ": already stopped");
+ break;
+ }
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
+ debugLog("Stopping " + provider);
+ provider.stopUpdates();
+ break;
+ }
+ case PROVIDER_STATE_PERM_FAILED:
+ case PROVIDER_STATE_DESTROYED: {
+ debugLog("Unable to stop " + provider + ": it is terminated.");
+ break;
+ }
+ default: {
+ warnLog("Unknown provider state: " + provider);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Sets the providers into the correct started/stopped state for the {@code newConfiguration}
+ * and, if there is a provider state change, makes any suggestions required to inform the
+ * downstream time zone detection code.
+ *
+ * <p>This is a utility method that exists to avoid duplicated logic for the various cases when
+ * provider started / stopped state may need to be set or changed, e.g. during initialization
+ * or when a new configuration has been received.
+ */
+ @GuardedBy("mSharedLock")
+ private void alterProvidersStartedStateIfRequired(
+ @Nullable ConfigurationInternal oldConfiguration,
+ @NonNull ConfigurationInternal newConfiguration) {
+
+ // Provider started / stopped states only need to be changed if geoDetectionEnabled has
+ // changed.
+ boolean oldGeoDetectionEnabled = oldConfiguration != null
+ && oldConfiguration.getGeoDetectionEnabledBehavior();
+ boolean newGeoDetectionEnabled = newConfiguration.getGeoDetectionEnabledBehavior();
+ if (oldGeoDetectionEnabled == newGeoDetectionEnabled) {
+ return;
+ }
+
+ // The check above ensures that the logic below only executes if providers are going from
+ // {started *} -> {stopped}, or {stopped} -> {started initializing}. If this changes in
+ // future and there could be {started *} -> {started *} cases, or cases where the provider
+ // can't be assumed to go straight to the {started initializing} state, then the logic below
+ // would need to cover extra conditions, for example:
+ // 1) If the primary is in {started uncertain}, the secondary should be started.
+ // 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
+ // timeout started when the primary entered {started uncertain} should be cancelled.
+
+ if (newGeoDetectionEnabled) {
+ // Try to start the primary provider.
+ tryStartProvider(mPrimaryProvider, newConfiguration);
+
+ // The secondary should only ever be started if the primary now isn't started (i.e. it
+ // couldn't become {started initializing} because it is {perm failed}).
+ ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
+ if (!newPrimaryState.isStarted()) {
+ // If the primary provider is {perm failed} then the controller must try to start
+ // the secondary.
+ tryStartProvider(mSecondaryProvider, newConfiguration);
+
+ ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
+ if (!newSecondaryState.isStarted()) {
+ // 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());
+ makeSuggestion(suggestion);
+ }
+ }
+ } else {
+ stopProviders();
+ }
+ }
+
+ @GuardedBy("mSharedLock")
+ private void tryStartProvider(@NonNull LocationTimeZoneProvider provider,
+ @NonNull ConfigurationInternal configuration) {
+ ProviderState providerState = provider.getCurrentState();
+ switch (providerState.stateEnum) {
+ case PROVIDER_STATE_STOPPED: {
+ debugLog("Enabling " + provider);
+ provider.startUpdates(configuration,
+ mEnvironment.getProviderInitializationTimeout(),
+ mEnvironment.getProviderInitializationTimeoutFuzz(),
+ mEnvironment.getProviderEventFilteringAgeThreshold());
+ break;
+ }
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
+ debugLog("No need to start " + provider + ": already started");
+ break;
+ }
+ case PROVIDER_STATE_PERM_FAILED:
+ case PROVIDER_STATE_DESTROYED: {
+ debugLog("Unable to start " + provider + ": it is terminated");
+ break;
+ }
+ default: {
+ throw new IllegalStateException("Unknown provider state:"
+ + " provider=" + provider);
+ }
+ }
+ }
+
+ void onProviderStateChange(@NonNull ProviderState providerState) {
+ mThreadingDomain.assertCurrentThread();
+ LocationTimeZoneProvider provider = providerState.provider;
+ assertProviderKnown(provider);
+
+ synchronized (mSharedLock) {
+ // Ignore provider state changes during initialization. e.g. if the primary provider
+ // moves to PROVIDER_STATE_PERM_FAILED during initialization, the secondary will not
+ // be ready to take over yet.
+ if (!mProvidersInitialized) {
+ warnLog("onProviderStateChange: Ignoring provider state change because both"
+ + " providers have not yet completed initialization."
+ + " providerState=" + providerState);
+ return;
+ }
+
+ switch (providerState.stateEnum) {
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STOPPED:
+ case PROVIDER_STATE_DESTROYED: {
+ // This should never happen: entering initializing, stopped or destroyed are
+ // triggered by the controller so and should not trigger a state change
+ // callback.
+ warnLog("onProviderStateChange: Unexpected state change for provider,"
+ + " provider=" + provider);
+ break;
+ }
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
+ // These are valid and only happen if an event is received while the provider is
+ // started.
+ debugLog("onProviderStateChange: Received notification of a state change while"
+ + " started, provider=" + provider);
+ handleProviderStartedStateChange(providerState);
+ break;
+ }
+ case PROVIDER_STATE_PERM_FAILED: {
+ debugLog("Received notification of permanent failure for"
+ + " provider=" + provider);
+ handleProviderFailedStateChange(providerState);
+ break;
+ }
+ default: {
+ warnLog("onProviderStateChange: Unexpected provider=" + provider);
+ }
+ }
+ }
+ }
+
+ private void assertProviderKnown(@NonNull LocationTimeZoneProvider provider) {
+ if (provider != mPrimaryProvider && provider != mSecondaryProvider) {
+ throw new IllegalArgumentException("Unknown provider: " + provider);
+ }
+ }
+
+ /**
+ * Called when a provider has reported that it has failed permanently.
+ */
+ @GuardedBy("mSharedLock")
+ private void handleProviderFailedStateChange(@NonNull ProviderState providerState) {
+ LocationTimeZoneProvider failedProvider = providerState.provider;
+ ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
+ ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
+
+ // If a provider has failed, the other may need to be started.
+ if (failedProvider == mPrimaryProvider) {
+ if (!secondaryCurrentState.isTerminated()) {
+ // Try to start the secondary. This does nothing if the provider is already
+ // started, and will leave the provider in {started initializing} if the provider is
+ // stopped.
+ tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
+ }
+ } else if (failedProvider == mSecondaryProvider) {
+ // No-op: The secondary will only be active if the primary is uncertain or is
+ // terminated. So, there the primary should not need to be started when the secondary
+ // fails.
+ if (primaryCurrentState.stateEnum != PROVIDER_STATE_STARTED_UNCERTAIN
+ && !primaryCurrentState.isTerminated()) {
+ warnLog("Secondary provider unexpected reported a failure:"
+ + " failed provider=" + failedProvider.getName()
+ + ", primary provider=" + mPrimaryProvider
+ + ", secondary provider=" + mSecondaryProvider);
+ }
+ }
+
+ // If both providers are now terminated, the controller needs to tell the next component in
+ // the time zone detection process.
+ if (primaryCurrentState.isTerminated() && secondaryCurrentState.isTerminated()) {
+
+ // If both providers are newly terminated then the controller is uncertain by definition
+ // and it will never recover so it can send a suggestion immediately.
+ cancelUncertaintyTimeout();
+
+ // 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);
+ makeSuggestion(suggestion);
+ }
+ }
+
+ /**
+ * Called when a provider has changed state but just moved from one started state to another
+ * started state, usually as a result of a new {@link TimeZoneProviderEvent} being received.
+ * However, there are rare cases where the event can also be null.
+ */
+ @GuardedBy("mSharedLock")
+ private void handleProviderStartedStateChange(@NonNull ProviderState providerState) {
+ LocationTimeZoneProvider provider = providerState.provider;
+ TimeZoneProviderEvent event = providerState.event;
+ if (event == null) {
+ // Implicit uncertainty, i.e. where the provider is started, but a problem has been
+ // detected without having received an event. For example, if the process has detected
+ // 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.
+ long uncertaintyStartedElapsedMillis = mEnvironment.elapsedRealtimeMillis();
+ handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
+ "provider=" + provider + ", implicit uncertainty, event=null");
+ return;
+ }
+
+ if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
+ // This should not happen: the provider should not be in an started state if the user
+ // does not have geodetection enabled.
+ warnLog("Provider=" + provider + " is started, but"
+ + " currentUserConfiguration=" + mCurrentUserConfiguration
+ + " suggests it shouldn't be.");
+ }
+
+ 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");
+ break;
+ }
+ case EVENT_TYPE_UNCERTAIN: {
+ long uncertaintyStartedElapsedMillis = event.getCreationElapsedMillis();
+ handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
+ "provider=" + provider + ", explicit uncertainty. event=" + event);
+ break;
+ }
+ case EVENT_TYPE_SUGGESTION: {
+ handleProviderSuggestion(provider, event);
+ break;
+ }
+ default: {
+ warnLog("Unknown eventType=" + event.getType());
+ break;
+ }
+ }
+ }
+
+ /**
+ * Called when a provider has become "certain" about the time zone(s).
+ */
+ @GuardedBy("mSharedLock")
+ private void handleProviderSuggestion(
+ @NonNull LocationTimeZoneProvider provider,
+ @NonNull TimeZoneProviderEvent providerEvent) {
+
+ // By definition, the controller is now certain.
+ cancelUncertaintyTimeout();
+
+ if (provider == mPrimaryProvider) {
+ stopProviderIfStarted(mSecondaryProvider);
+ }
+
+ 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
+ public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
+ synchronized (mSharedLock) {
+ ipw.println("LocationTimeZoneProviderController:");
+
+ ipw.increaseIndent(); // level 1
+ ipw.println("mCurrentUserConfiguration=" + mCurrentUserConfiguration);
+ ipw.println("providerInitializationTimeout="
+ + mEnvironment.getProviderInitializationTimeout());
+ ipw.println("providerInitializationTimeoutFuzz="
+ + mEnvironment.getProviderInitializationTimeoutFuzz());
+ ipw.println("uncertaintyDelay=" + mEnvironment.getUncertaintyDelay());
+ ipw.println("mLastSuggestion=" + mLastSuggestion);
+
+ ipw.println("Primary Provider:");
+ ipw.increaseIndent(); // level 2
+ mPrimaryProvider.dump(ipw, args);
+ ipw.decreaseIndent(); // level 2
+
+ ipw.println("Secondary Provider:");
+ ipw.increaseIndent(); // level 2
+ mSecondaryProvider.dump(ipw, args);
+ ipw.decreaseIndent(); // level 2
+
+ ipw.decreaseIndent(); // level 1
+ }
+ }
+
+ /** Sends an immediate suggestion, updating mLastSuggestion. */
+ @GuardedBy("mSharedLock")
+ private void makeSuggestion(@NonNull GeolocationTimeZoneSuggestion suggestion) {
+ debugLog("makeSuggestion: suggestion=" + suggestion);
+ mCallback.suggest(suggestion);
+ mLastSuggestion = suggestion;
+ }
+
+ /** Clears the uncertainty timeout. */
+ @GuardedBy("mSharedLock")
+ private void cancelUncertaintyTimeout() {
+ mUncertaintyTimeoutQueue.cancel();
+ }
+
+ /**
+ * Called when a provider has become "uncertain" about the time zone.
+ *
+ * <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
+ * this enables the most flexibility for the controller to start other providers when there are
+ * multiple ones available. The controller is therefore responsible for deciding when to make a
+ * "uncertain" suggestion to the downstream time zone detector.
+ *
+ * <p>This method schedules an "uncertainty" timeout (if one isn't already scheduled) to be
+ * triggered later if nothing else preempts it. It can be preempted if the provider becomes
+ * certain (or does anything else that calls {@link
+ * #makeSuggestion(GeolocationTimeZoneSuggestion)}) within {@link
+ * Environment#getUncertaintyDelay()}. Preemption causes the scheduled
+ * "uncertainty" timeout to be cancelled. If the provider repeatedly sends uncertainty events
+ * within the uncertainty delay period, those events are effectively ignored (i.e. the timeout
+ * is not reset each time).
+ */
+ @GuardedBy("mSharedLock")
+ void handleProviderUncertainty(
+ @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
+ // uncertain suggestion if no success event arrives in time to counteract it.
+ if (!mUncertaintyTimeoutQueue.hasQueued()) {
+ debugLog("Starting uncertainty timeout: reason=" + reason);
+
+ Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
+ mUncertaintyTimeoutQueue.runDelayed(
+ () -> onProviderUncertaintyTimeout(
+ 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.
+ tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
+ }
+ }
+
+ 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
+ + ", uncertaintyStarted="
+ + Duration.ofMillis(uncertaintyStartedElapsedMillis)
+ + ", afterUncertaintyTimeout="
+ + Duration.ofMillis(afterUncertaintyTimeoutElapsedMillis)
+ + ", uncertaintyDelay=" + uncertaintyDelay
+ );
+ makeSuggestion(suggestion);
+ }
+ }
+
+ @NonNull
+ private static GeolocationTimeZoneSuggestion createUncertainSuggestion(
+ @ElapsedRealtimeLong long effectiveFromElapsedMillis,
+ @NonNull String reason) {
+ GeolocationTimeZoneSuggestion suggestion =
+ GeolocationTimeZoneSuggestion.createUncertainSuggestion(
+ effectiveFromElapsedMillis);
+ suggestion.addDebugInfo(reason);
+ return suggestion;
+ }
+
+ /**
+ * Clears recorded provider state changes (for use during tests).
+ */
+ void clearRecordedProviderStates() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ mPrimaryProvider.clearRecordedStates();
+ mSecondaryProvider.clearRecordedStates();
+ }
+ }
+
+ /**
+ * Returns a snapshot of the current controller state for tests.
+ */
+ @NonNull
+ LocationTimeZoneManagerServiceState getStateForTests() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ LocationTimeZoneManagerServiceState.Builder builder =
+ new LocationTimeZoneManagerServiceState.Builder();
+ if (mLastSuggestion != null) {
+ builder.setLastSuggestion(mLastSuggestion);
+ }
+ builder.setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
+ .setSecondaryProviderStateChanges(mSecondaryProvider.getRecordedStates());
+ return builder.build();
+ }
+ }
/**
* Used by {@link LocationTimeZoneProviderController} to obtain information from the surrounding
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerCallbackImpl.java
index 46eaad075b54..0c751aaa62c7 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerCallbackImpl.java
@@ -24,11 +24,12 @@ import com.android.server.timezonedetector.TimeZoneDetectorInternal;
/**
* The real implementation of {@link LocationTimeZoneProviderController.Callback} used by
- * {@link ControllerImpl} to interact with other server components.
+ * {@link LocationTimeZoneProviderController} to interact with other server components.
*/
-class ControllerCallbackImpl extends LocationTimeZoneProviderController.Callback {
+class LocationTimeZoneProviderControllerCallbackImpl
+ extends LocationTimeZoneProviderController.Callback {
- ControllerCallbackImpl(@NonNull ThreadingDomain threadingDomain) {
+ LocationTimeZoneProviderControllerCallbackImpl(@NonNull ThreadingDomain threadingDomain) {
super(threadingDomain);
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerEnvironmentImpl.java
index 33cdc5f66def..e7d16c85b1c6 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerEnvironmentImpl.java
@@ -29,14 +29,15 @@ import java.util.Objects;
/**
* The real implementation of {@link LocationTimeZoneProviderController.Environment} used by
- * {@link ControllerImpl} to interact with other server components.
+ * {@link LocationTimeZoneProviderController} to interact with other server components.
*/
-class ControllerEnvironmentImpl extends LocationTimeZoneProviderController.Environment {
+class LocationTimeZoneProviderControllerEnvironmentImpl
+ extends LocationTimeZoneProviderController.Environment {
@NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
@NonNull private final ConfigurationChangeListener mConfigurationInternalChangeListener;
- ControllerEnvironmentImpl(@NonNull ThreadingDomain threadingDomain,
+ LocationTimeZoneProviderControllerEnvironmentImpl(@NonNull ThreadingDomain threadingDomain,
@NonNull ServiceConfigAccessor serviceConfigAccessor,
@NonNull LocationTimeZoneProviderController controller) {
super(threadingDomain);
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
index 463ac5281eb4..20c25a04715b 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
@@ -57,9 +57,9 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
-/** Tests for {@link ControllerImpl}. */
+/** Tests for {@link LocationTimeZoneProviderController}. */
@Presubmit
-public class ControllerImplTest {
+public class LocationTimeZoneProviderControllerTest {
private static final long ARBITRARY_TIME_MILLIS = 12345L;
@@ -95,10 +95,11 @@ public class ControllerImplTest {
@Test
public void initializationFailure_primary() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
@@ -106,7 +107,7 @@ public class ControllerImplTest {
// Initialize. After initialization the providers must be initialized and one should be
// started.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
@@ -116,15 +117,16 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void initializationFailure_secondary() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
@@ -132,7 +134,7 @@ public class ControllerImplTest {
// Initialize. After initialization the providers must be initialized and one should be
// started.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
@@ -142,22 +144,23 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void initializationFailure_both() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.setFailDuringInitialization(true);
mTestSecondaryLocationTimeZoneProvider.setFailDuringInitialization(true);
// Initialize. After initialization the providers must be initialized and one should be
// started.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
@@ -165,21 +168,22 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertUncertainSuggestionMadeAndCommit();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void initialState_started() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
// Initialize. After initialization the providers must be initialized and one should be
// started.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
@@ -189,19 +193,20 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void initialState_disabled() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
// Initialize. After initialization the providers must be initialized but neither should be
// started.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
@@ -209,24 +214,25 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_uncertaintySuggestionSentIfNoEventReceived() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
@@ -238,7 +244,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate time passing with no provider event being received from either the primary or
// secondary.
@@ -251,7 +257,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Finally, the uncertainty timeout should cause the controller to make an uncertain
// suggestion.
@@ -262,24 +268,25 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_eventReceivedBeforeInitializationTimeout() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made.
@@ -291,24 +298,25 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_eventReceivedFromPrimaryAfterInitializationTimeout() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
@@ -318,7 +326,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made and the secondary to be shut down.
@@ -330,24 +338,25 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_eventReceivedFromSecondaryAfterInitializationTimeout() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
@@ -357,7 +366,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate a location event being received from the secondary provider. This should cause a
// suggestion to be made.
@@ -370,24 +379,25 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_repeatedPrimaryCertainty() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made.
@@ -399,7 +409,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// A second, identical event should not cause another suggestion.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -409,7 +419,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// And a third, different event should cause another suggestion.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -420,24 +430,25 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_repeatedSecondaryCertainty() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate time passing with no provider event being received from the primary.
mTestThreadingDomain.executeNext();
@@ -447,7 +458,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate a location event being received from the secondary provider. This should cause a
// suggestion to be made.
@@ -460,7 +471,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// A second, identical event should not cause another suggestion.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -471,7 +482,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// And a third, different event should cause another suggestion.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -483,24 +494,25 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_uncertaintyTriggersASuggestionAfterUncertaintyTimeout() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made and ensure the primary is considered initialized.
@@ -512,7 +524,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the primary provider. This should not
// cause a suggestion to be made straight away, but the uncertainty timeout should be
@@ -525,7 +537,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate a location event being received from the secondary provider. This should cause a
// suggestion to be made, cancel the uncertainty timeout and ensure the secondary is
@@ -539,7 +551,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the secondary provider. This should not
// cause a suggestion to be made straight away, but the uncertainty timeout should be
@@ -552,7 +564,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate time passing. This means the uncertainty timeout should fire and the uncertain
// suggestion should be made.
@@ -564,24 +576,25 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertUncertainSuggestionMadeFromEventAndCommit(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void enabled_briefUncertaintyTriggersNoSuggestion() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made.
@@ -593,7 +606,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ 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.
@@ -605,7 +618,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// And a success event from the primary provider should cause the controller to make another
// suggestion, the uncertainty timeout should be cancelled and the secondary should be
@@ -618,23 +631,24 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void configChanges_enableAndDisableWithNoPreviousSuggestion() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -643,7 +657,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
@@ -651,23 +665,24 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void configChanges_enableAndDisableWithPreviousSuggestion() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -676,7 +691,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a success event being received from the primary provider.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -687,7 +702,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
// Because there had been a previous suggestion, the controller should withdraw it
@@ -698,24 +713,25 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertUncertainSuggestionMadeAndCommit();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void configChanges_userSwitch_enabledToEnabled() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate the primary provider suggesting a time zone.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -728,7 +744,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate the user change (but geo detection still enabled).
testEnvironment.simulateConfigChange(USER2_CONFIG_GEO_DETECTION_ENABLED);
@@ -744,24 +760,25 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfig(
PROVIDER_STATE_STARTED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void primaryPermFailure_secondaryEventsReceived() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a failure location event being received from the primary provider. This should
// cause the secondary to be started.
@@ -772,7 +789,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate uncertainty from the secondary.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -782,7 +799,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// And a success event from the secondary provider should cause the controller to make
// another suggestion, the uncertainty timeout should be cancelled.
@@ -794,7 +811,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate uncertainty from the secondary.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -804,24 +821,25 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
}
@Test
public void primaryPermFailure_disableAndEnable() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a failure location event being received from the primary provider. This should
// cause the secondary to be started.
@@ -832,7 +850,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
@@ -840,7 +858,7 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -849,24 +867,25 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void secondaryPermFailure_primaryEventsReceived() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate an uncertain event from the primary. This will start the secondary, which will
// give this test the opportunity to simulate its failure. Then it will be possible to
@@ -879,7 +898,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate failure event from the secondary. This should just affect the secondary's state.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -889,7 +908,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// And a success event from the primary provider should cause the controller to make
// a suggestion, the uncertainty timeout should be cancelled.
@@ -901,7 +920,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate uncertainty from the primary. The secondary cannot be started.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -911,24 +930,25 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
}
@Test
public void secondaryPermFailure_disableAndEnable() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate an uncertain event from the primary. This will start the secondary, which will
// give this test the opportunity to simulate its failure. Then it will be possible to
@@ -941,7 +961,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Simulate failure event from the secondary. This should just affect the secondary's state.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -951,7 +971,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ assertUncertaintyTimeoutSet(testEnvironment, controller);
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
@@ -959,7 +979,7 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled. Only the primary can be
// started.
@@ -969,24 +989,25 @@ public class ControllerImplTest {
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void bothPermFailure_disableAndEnable() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate a failure event from the primary. This will start the secondary.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -996,7 +1017,7 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate failure event from the secondary.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -1005,28 +1026,29 @@ public class ControllerImplTest {
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertUncertainSuggestionMadeAndCommit();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
@Test
public void stateRecording() {
// The test provider enables state recording by default.
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial states.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
{
- LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+ LocationTimeZoneManagerServiceState state = controller.getStateForTests();
assertNull(state.getLastSuggestion());
assertProviderStates(state.getPrimaryProviderStates(),
PROVIDER_STATE_STOPPED, PROVIDER_STATE_STARTED_INITIALIZING);
assertProviderStates(state.getSecondaryProviderStates(), PROVIDER_STATE_STOPPED);
}
- controllerImpl.clearRecordedProviderStates();
+ controller.clearRecordedProviderStates();
// Simulate some provider behavior that will show up in the state recording.
@@ -1035,21 +1057,21 @@ public class ControllerImplTest {
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
{
- LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+ LocationTimeZoneManagerServiceState state = controller.getStateForTests();
assertNull(state.getLastSuggestion());
assertProviderStates(
state.getPrimaryProviderStates(), PROVIDER_STATE_STARTED_UNCERTAIN);
assertProviderStates(
state.getSecondaryProviderStates(), PROVIDER_STATE_STARTED_INITIALIZING);
}
- controllerImpl.clearRecordedProviderStates();
+ controller.clearRecordedProviderStates();
// Simulate a certain event from the secondary.
mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
{
- LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+ LocationTimeZoneManagerServiceState state = controller.getStateForTests();
assertEquals(USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds(),
state.getLastSuggestion().getZoneIds());
assertProviderStates(state.getPrimaryProviderStates());
@@ -1057,9 +1079,9 @@ public class ControllerImplTest {
state.getSecondaryProviderStates(), PROVIDER_STATE_STARTED_CERTAIN);
}
- controllerImpl.clearRecordedProviderStates();
+ controller.clearRecordedProviderStates();
{
- LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+ LocationTimeZoneManagerServiceState state = controller.getStateForTests();
assertEquals(USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds(),
state.getLastSuggestion().getZoneIds());
assertProviderStates(state.getPrimaryProviderStates());
@@ -1078,19 +1100,20 @@ public class ControllerImplTest {
@Test
public void destroy() {
- ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+ mTestThreadingDomain, mTestPrimaryLocationTimeZoneProvider,
+ mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
- mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
// Initialize and check initial state.
- controllerImpl.initialize(testEnvironment, mTestCallback);
+ controller.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Simulate the primary provider suggesting a time zone.
mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -1103,10 +1126,10 @@ public class ControllerImplTest {
mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
// Trigger destroy().
- controllerImpl.destroy();
+ controller.destroy();
// Confirm that the previous suggestion was overridden.
mTestCallback.assertUncertainSuggestionMadeAndCommit();
@@ -1115,7 +1138,7 @@ public class ControllerImplTest {
PROVIDER_STATE_STOPPED, PROVIDER_STATE_DESTROYED);
mTestSecondaryLocationTimeZoneProvider.assertStateChangesAndCommit(
PROVIDER_STATE_DESTROYED);
- assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ assertFalse(controller.isUncertaintyTimeoutSet());
}
private static void assertUncertaintyTimeoutSet(