Loading services/core/java/com/android/server/timezonedetector/location/BinderLocationTimeZoneProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ class BinderLocationTimeZoneProvider extends LocationTimeZoneProvider { } @Override void onInitialize() { boolean onInitialize() { mProxy.initialize(new LocationTimeZoneProviderProxy.Listener() { @Override public void onReportTimeZoneProviderEvent( Loading @@ -71,6 +71,7 @@ class BinderLocationTimeZoneProvider extends LocationTimeZoneProvider { handleTemporaryFailure("onProviderUnbound()"); } }); return true; } @Override Loading services/core/java/com/android/server/timezonedetector/location/NullLocationTimeZoneProviderProxy.java→services/core/java/com/android/server/timezonedetector/location/DisabledLocationTimeZoneProvider.java +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2022 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. Loading @@ -18,57 +18,69 @@ package com.android.server.timezonedetector.location; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.SystemClock; import android.service.timezone.TimeZoneProviderEvent; import android.util.IndentingPrintWriter; import java.time.Duration; /** * A {@link LocationTimeZoneProviderProxy} that provides minimal responses needed for the {@link * BinderLocationTimeZoneProvider} to operate correctly when there is no "real" provider * configured / enabled. This can be used during development / testing, or in a production build * when the platform supports more providers than are needed for an Android deployment. * A {@link LocationTimeZoneProvider} that provides minimal responses needed to operate correctly * when there is no "real" provider configured / enabled. This is used when the platform supports * more providers than are needed for an Android deployment. * * <p>For example, if the {@link LocationTimeZoneProviderController} supports a primary * and a secondary {@link LocationTimeZoneProvider}, but only a primary is configured, the secondary * config will be left null and the {@link LocationTimeZoneProviderProxy} implementation will be * defaulted to a {@link NullLocationTimeZoneProviderProxy}. The {@link * NullLocationTimeZoneProviderProxy} sends a "permanent failure" event immediately after being * started for the first time, which ensures the {@link LocationTimeZoneProviderController} won't * expect any further {@link TimeZoneProviderEvent}s to come from it, and won't attempt to use it * again. * <p>That is, the {@link LocationTimeZoneProviderController} supports a primary and a secondary * {@link LocationTimeZoneProvider}, but if only a primary is configured, the secondary provider * config will marked as "disabled" and the {@link LocationTimeZoneProvider} implementation will use * {@link DisabledLocationTimeZoneProvider}. The {@link DisabledLocationTimeZoneProvider} fails * initialization and immediately moves to a "permanent failure" state, which ensures the {@link * LocationTimeZoneProviderController} correctly categorizes it and won't attempt to use it. */ class NullLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy { class DisabledLocationTimeZoneProvider extends LocationTimeZoneProvider { /** Creates the instance. */ NullLocationTimeZoneProviderProxy( @NonNull Context context, @NonNull ThreadingDomain threadingDomain) { super(context, threadingDomain); DisabledLocationTimeZoneProvider( @NonNull ProviderMetricsLogger providerMetricsLogger, @NonNull ThreadingDomain threadingDomain, @NonNull String providerName, boolean recordStateChanges) { super(providerMetricsLogger, threadingDomain, providerName, x -> x, recordStateChanges); } @Override void onInitialize() { // No-op boolean onInitialize() { // Fail initialization, preventing further use. return false; } @Override void onDestroy() { // No-op } @Override void setRequest(@NonNull TimeZoneProviderRequest request) { if (request.sendUpdates()) { TimeZoneProviderEvent event = TimeZoneProviderEvent.createPermanentFailureEvent( SystemClock.elapsedRealtime(), "Provider is disabled"); handleTimeZoneProviderEvent(event); void onStartUpdates(@NonNull Duration initializationTimeout, @NonNull Duration eventFilteringAgeThreshold) { throw new UnsupportedOperationException("Provider is disabled"); } @Override void onStopUpdates() { throw new UnsupportedOperationException("Provider is disabled"); } @Override public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) { synchronized (mSharedLock) { ipw.println("{NullLocationTimeZoneProviderProxy}"); ipw.println("{DisabledLocationTimeZoneProvider}"); ipw.println("mProviderName=" + mProviderName); ipw.println("mCurrentState=" + mCurrentState); } } @Override public String toString() { synchronized (mSharedLock) { return "DisabledLocationTimeZoneProvider{" + "mProviderName=" + mProviderName + ", mCurrentState=" + mCurrentState + '}'; } } } services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java +12 −16 Original line number Diff line number Diff line Loading @@ -447,12 +447,19 @@ public class LocationTimeZoneManagerService extends Binder { @NonNull LocationTimeZoneProvider createProvider() { LocationTimeZoneProviderProxy proxy = createProxy(); ProviderMetricsLogger providerMetricsLogger = new RealProviderMetricsLogger(mIndex); String mode = getMode(); if (Objects.equals(mode, PROVIDER_MODE_DISABLED)) { return new DisabledLocationTimeZoneProvider(providerMetricsLogger, mThreadingDomain, mName, mServiceConfigAccessor.getRecordStateChangesForTests()); } else { LocationTimeZoneProviderProxy proxy = createBinderProxy(); return new BinderLocationTimeZoneProvider( providerMetricsLogger, mThreadingDomain, mName, proxy, mServiceConfigAccessor.getRecordStateChangesForTests()); } } @Override public void dump(IndentingPrintWriter ipw, String[] args) { Loading @@ -460,17 +467,6 @@ public class LocationTimeZoneManagerService extends Binder { ipw.printf("getPackageName()=%s\n", getPackageName()); } @NonNull private LocationTimeZoneProviderProxy createProxy() { String mode = getMode(); if (Objects.equals(mode, PROVIDER_MODE_DISABLED)) { return new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain); } else { // mode == PROVIDER_MODE_OVERRIDE_ENABLED (or unknown). return createRealProxy(); } } /** Returns the mode of the provider (enabled/disabled). */ @NonNull private String getMode() { Loading @@ -482,7 +478,7 @@ public class LocationTimeZoneManagerService extends Binder { } @NonNull private RealLocationTimeZoneProviderProxy createRealProxy() { private RealLocationTimeZoneProviderProxy createBinderProxy() { String providerServiceAction = mServiceAction; boolean isTestProvider = isTestProvider(); String providerPackageName = getPackageName(); Loading services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProvider.java +15 −4 Original line number Diff line number Diff line Loading @@ -448,13 +448,21 @@ abstract class LocationTimeZoneProvider implements Dumpable { currentState = currentState.newState(PROVIDER_STATE_STOPPED, null, null, "initialize"); setCurrentState(currentState, false); boolean initializationSuccess; String initializationFailureReason; // Guard against uncaught exceptions due to initialization problems. try { onInitialize(); initializationSuccess = onInitialize(); initializationFailureReason = "onInitialize() returned false"; } catch (RuntimeException e) { warnLog("Unable to initialize the provider", e); warnLog("Unable to initialize the provider due to exception", e); initializationSuccess = false; initializationFailureReason = "onInitialize() threw exception:" + e.getMessage(); } if (!initializationSuccess) { currentState = currentState.newState(PROVIDER_STATE_PERM_FAILED, null, null, "Failed to initialize: " + e.getMessage()); "Failed to initialize: " + initializationFailureReason); setCurrentState(currentState, true); } } Loading @@ -462,9 +470,12 @@ abstract class LocationTimeZoneProvider implements Dumpable { /** * Implemented by subclasses to do work during {@link #initialize}. * * @return returns {@code true} on success, {@code false} if the provider should be considered * "permanently failed" / disabled */ @GuardedBy("mSharedLock") abstract void onInitialize(); abstract boolean onInitialize(); /** * Destroys the provider. Called after the provider is stopped. This instance will not be called Loading services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java +2 −4 Original line number Diff line number Diff line Loading @@ -1672,11 +1672,9 @@ public class LocationTimeZoneProviderControllerTest { } @Override void onInitialize() { boolean onInitialize() { mInitialized = true; if (mFailDuringInitialization) { throw new RuntimeException("Simulated initialization failure"); } return !mFailDuringInitialization; } @Override Loading Loading
services/core/java/com/android/server/timezonedetector/location/BinderLocationTimeZoneProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ class BinderLocationTimeZoneProvider extends LocationTimeZoneProvider { } @Override void onInitialize() { boolean onInitialize() { mProxy.initialize(new LocationTimeZoneProviderProxy.Listener() { @Override public void onReportTimeZoneProviderEvent( Loading @@ -71,6 +71,7 @@ class BinderLocationTimeZoneProvider extends LocationTimeZoneProvider { handleTemporaryFailure("onProviderUnbound()"); } }); return true; } @Override Loading
services/core/java/com/android/server/timezonedetector/location/NullLocationTimeZoneProviderProxy.java→services/core/java/com/android/server/timezonedetector/location/DisabledLocationTimeZoneProvider.java +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2022 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. Loading @@ -18,57 +18,69 @@ package com.android.server.timezonedetector.location; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.SystemClock; import android.service.timezone.TimeZoneProviderEvent; import android.util.IndentingPrintWriter; import java.time.Duration; /** * A {@link LocationTimeZoneProviderProxy} that provides minimal responses needed for the {@link * BinderLocationTimeZoneProvider} to operate correctly when there is no "real" provider * configured / enabled. This can be used during development / testing, or in a production build * when the platform supports more providers than are needed for an Android deployment. * A {@link LocationTimeZoneProvider} that provides minimal responses needed to operate correctly * when there is no "real" provider configured / enabled. This is used when the platform supports * more providers than are needed for an Android deployment. * * <p>For example, if the {@link LocationTimeZoneProviderController} supports a primary * and a secondary {@link LocationTimeZoneProvider}, but only a primary is configured, the secondary * config will be left null and the {@link LocationTimeZoneProviderProxy} implementation will be * defaulted to a {@link NullLocationTimeZoneProviderProxy}. The {@link * NullLocationTimeZoneProviderProxy} sends a "permanent failure" event immediately after being * started for the first time, which ensures the {@link LocationTimeZoneProviderController} won't * expect any further {@link TimeZoneProviderEvent}s to come from it, and won't attempt to use it * again. * <p>That is, the {@link LocationTimeZoneProviderController} supports a primary and a secondary * {@link LocationTimeZoneProvider}, but if only a primary is configured, the secondary provider * config will marked as "disabled" and the {@link LocationTimeZoneProvider} implementation will use * {@link DisabledLocationTimeZoneProvider}. The {@link DisabledLocationTimeZoneProvider} fails * initialization and immediately moves to a "permanent failure" state, which ensures the {@link * LocationTimeZoneProviderController} correctly categorizes it and won't attempt to use it. */ class NullLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy { class DisabledLocationTimeZoneProvider extends LocationTimeZoneProvider { /** Creates the instance. */ NullLocationTimeZoneProviderProxy( @NonNull Context context, @NonNull ThreadingDomain threadingDomain) { super(context, threadingDomain); DisabledLocationTimeZoneProvider( @NonNull ProviderMetricsLogger providerMetricsLogger, @NonNull ThreadingDomain threadingDomain, @NonNull String providerName, boolean recordStateChanges) { super(providerMetricsLogger, threadingDomain, providerName, x -> x, recordStateChanges); } @Override void onInitialize() { // No-op boolean onInitialize() { // Fail initialization, preventing further use. return false; } @Override void onDestroy() { // No-op } @Override void setRequest(@NonNull TimeZoneProviderRequest request) { if (request.sendUpdates()) { TimeZoneProviderEvent event = TimeZoneProviderEvent.createPermanentFailureEvent( SystemClock.elapsedRealtime(), "Provider is disabled"); handleTimeZoneProviderEvent(event); void onStartUpdates(@NonNull Duration initializationTimeout, @NonNull Duration eventFilteringAgeThreshold) { throw new UnsupportedOperationException("Provider is disabled"); } @Override void onStopUpdates() { throw new UnsupportedOperationException("Provider is disabled"); } @Override public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) { synchronized (mSharedLock) { ipw.println("{NullLocationTimeZoneProviderProxy}"); ipw.println("{DisabledLocationTimeZoneProvider}"); ipw.println("mProviderName=" + mProviderName); ipw.println("mCurrentState=" + mCurrentState); } } @Override public String toString() { synchronized (mSharedLock) { return "DisabledLocationTimeZoneProvider{" + "mProviderName=" + mProviderName + ", mCurrentState=" + mCurrentState + '}'; } } }
services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java +12 −16 Original line number Diff line number Diff line Loading @@ -447,12 +447,19 @@ public class LocationTimeZoneManagerService extends Binder { @NonNull LocationTimeZoneProvider createProvider() { LocationTimeZoneProviderProxy proxy = createProxy(); ProviderMetricsLogger providerMetricsLogger = new RealProviderMetricsLogger(mIndex); String mode = getMode(); if (Objects.equals(mode, PROVIDER_MODE_DISABLED)) { return new DisabledLocationTimeZoneProvider(providerMetricsLogger, mThreadingDomain, mName, mServiceConfigAccessor.getRecordStateChangesForTests()); } else { LocationTimeZoneProviderProxy proxy = createBinderProxy(); return new BinderLocationTimeZoneProvider( providerMetricsLogger, mThreadingDomain, mName, proxy, mServiceConfigAccessor.getRecordStateChangesForTests()); } } @Override public void dump(IndentingPrintWriter ipw, String[] args) { Loading @@ -460,17 +467,6 @@ public class LocationTimeZoneManagerService extends Binder { ipw.printf("getPackageName()=%s\n", getPackageName()); } @NonNull private LocationTimeZoneProviderProxy createProxy() { String mode = getMode(); if (Objects.equals(mode, PROVIDER_MODE_DISABLED)) { return new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain); } else { // mode == PROVIDER_MODE_OVERRIDE_ENABLED (or unknown). return createRealProxy(); } } /** Returns the mode of the provider (enabled/disabled). */ @NonNull private String getMode() { Loading @@ -482,7 +478,7 @@ public class LocationTimeZoneManagerService extends Binder { } @NonNull private RealLocationTimeZoneProviderProxy createRealProxy() { private RealLocationTimeZoneProviderProxy createBinderProxy() { String providerServiceAction = mServiceAction; boolean isTestProvider = isTestProvider(); String providerPackageName = getPackageName(); Loading
services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProvider.java +15 −4 Original line number Diff line number Diff line Loading @@ -448,13 +448,21 @@ abstract class LocationTimeZoneProvider implements Dumpable { currentState = currentState.newState(PROVIDER_STATE_STOPPED, null, null, "initialize"); setCurrentState(currentState, false); boolean initializationSuccess; String initializationFailureReason; // Guard against uncaught exceptions due to initialization problems. try { onInitialize(); initializationSuccess = onInitialize(); initializationFailureReason = "onInitialize() returned false"; } catch (RuntimeException e) { warnLog("Unable to initialize the provider", e); warnLog("Unable to initialize the provider due to exception", e); initializationSuccess = false; initializationFailureReason = "onInitialize() threw exception:" + e.getMessage(); } if (!initializationSuccess) { currentState = currentState.newState(PROVIDER_STATE_PERM_FAILED, null, null, "Failed to initialize: " + e.getMessage()); "Failed to initialize: " + initializationFailureReason); setCurrentState(currentState, true); } } Loading @@ -462,9 +470,12 @@ abstract class LocationTimeZoneProvider implements Dumpable { /** * Implemented by subclasses to do work during {@link #initialize}. * * @return returns {@code true} on success, {@code false} if the provider should be considered * "permanently failed" / disabled */ @GuardedBy("mSharedLock") abstract void onInitialize(); abstract boolean onInitialize(); /** * Destroys the provider. Called after the provider is stopped. This instance will not be called Loading
services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java +2 −4 Original line number Diff line number Diff line Loading @@ -1672,11 +1672,9 @@ public class LocationTimeZoneProviderControllerTest { } @Override void onInitialize() { boolean onInitialize() { mInitialized = true; if (mFailDuringInitialization) { throw new RuntimeException("Simulated initialization failure"); } return !mFailDuringInitialization; } @Override Loading