Merge "Fix behavior when primary fails initialization"
This commit is contained in:
@@ -73,6 +73,10 @@ class ControllerImpl extends LocationTimeZoneProviderController {
|
||||
// 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
|
||||
@@ -108,6 +112,7 @@ class ControllerImpl extends LocationTimeZoneProviderController {
|
||||
ControllerImpl.this::onProviderStateChange;
|
||||
mPrimaryProvider.initialize(providerListener);
|
||||
mSecondaryProvider.initialize(providerListener);
|
||||
mProvidersInitialized = true;
|
||||
|
||||
alterProvidersStartedStateIfRequired(
|
||||
null /* oldConfiguration */, mCurrentUserConfiguration);
|
||||
@@ -322,6 +327,16 @@ class ControllerImpl extends LocationTimeZoneProviderController {
|
||||
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:
|
||||
|
||||
@@ -88,6 +88,81 @@ public class ControllerImplTest {
|
||||
new TestLocationTimeZoneProvider(mTestThreadingDomain, "secondary");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializationFailure_primary() {
|
||||
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
|
||||
mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
|
||||
TestEnvironment testEnvironment = new TestEnvironment(
|
||||
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
|
||||
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
|
||||
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.setFailDuringInitialization(true);
|
||||
|
||||
// Initialize. After initialization the providers must be initialized and one should be
|
||||
// started.
|
||||
controllerImpl.initialize(testEnvironment, mTestCallback);
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
|
||||
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
|
||||
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
|
||||
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
|
||||
mTestSecondaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
|
||||
mTestCallback.assertNoSuggestionMade();
|
||||
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializationFailure_secondary() {
|
||||
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
|
||||
mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
|
||||
TestEnvironment testEnvironment = new TestEnvironment(
|
||||
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
|
||||
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
|
||||
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
|
||||
|
||||
mTestSecondaryLocationTimeZoneProvider.setFailDuringInitialization(true);
|
||||
|
||||
// Initialize. After initialization the providers must be initialized and one should be
|
||||
// started.
|
||||
controllerImpl.initialize(testEnvironment, mTestCallback);
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
|
||||
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
|
||||
PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
|
||||
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
|
||||
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
|
||||
mTestCallback.assertNoSuggestionMade();
|
||||
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializationFailure_both() {
|
||||
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
|
||||
mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
|
||||
TestEnvironment testEnvironment = new TestEnvironment(
|
||||
mTestThreadingDomain, controllerImpl, 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);
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
|
||||
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
|
||||
|
||||
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
|
||||
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
|
||||
mTestCallback.assertUncertainSuggestionMadeAndCommit();
|
||||
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialState_started() {
|
||||
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
|
||||
@@ -1097,6 +1172,7 @@ public class ControllerImplTest {
|
||||
|
||||
/** Used to track historic provider states for tests. */
|
||||
private final TestState<ProviderState> mTestProviderState = new TestState<>();
|
||||
private boolean mFailDuringInitialization;
|
||||
private boolean mInitialized;
|
||||
private boolean mDestroyed;
|
||||
|
||||
@@ -1107,9 +1183,16 @@ public class ControllerImplTest {
|
||||
super(threadingDomain, providerName);
|
||||
}
|
||||
|
||||
public void setFailDuringInitialization(boolean failInitialization) {
|
||||
mFailDuringInitialization = failInitialization;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onInitialize() {
|
||||
mInitialized = true;
|
||||
if (mFailDuringInitialization) {
|
||||
throw new RuntimeException("Simulated initialization failure");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user