diff --git a/core/java/android/app/time/LocationTimeZoneManager.java b/core/java/android/app/time/LocationTimeZoneManager.java
index f506f12a7ba03..17e9e939f03b1 100644
--- a/core/java/android/app/time/LocationTimeZoneManager.java
+++ b/core/java/android/app/time/LocationTimeZoneManager.java
@@ -50,10 +50,10 @@ public final class LocationTimeZoneManager {
public static final String SHELL_COMMAND_STOP = "stop";
/**
- * A shell command that tells the service to record state information during tests. The next
- * argument value is "true" or "false".
+ * A shell command that clears recorded provider state information during tests.
*/
- public static final String SHELL_COMMAND_RECORD_PROVIDER_STATES = "record_provider_states";
+ public static final String SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES =
+ "clear_recorded_provider_states";
/**
* A shell command that tells the service to dump its current state.
@@ -65,44 +65,15 @@ public final class LocationTimeZoneManager {
*/
public static final String DUMP_STATE_OPTION_PROTO = "--proto";
- /**
- * A shell command that sends test commands to a provider
- */
- public static final String SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND =
- "send_provider_test_command";
+ /** A shell command that starts the location_time_zone_manager with named test providers. */
+ public static final String SHELL_COMMAND_START_WITH_TEST_PROVIDERS =
+ "start_with_test_providers";
/**
- * Simulated provider test command that simulates the bind succeeding.
+ * The token that can be passed to {@link #SHELL_COMMAND_START_WITH_TEST_PROVIDERS} to indicate
+ * there is no provider.
*/
- public static final String SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND = "on_bind";
-
- /**
- * Simulated provider test command that simulates the provider unbinding.
- */
- public static final String SIMULATED_PROVIDER_TEST_COMMAND_ON_UNBIND = "on_unbind";
-
- /**
- * Simulated provider test command that simulates the provider entering the "permanent failure"
- * state.
- */
- public static final String SIMULATED_PROVIDER_TEST_COMMAND_PERM_FAILURE = "perm_fail";
-
- /**
- * Simulated provider test command that simulates the provider entering the "success" (time
- * zone(s) detected) state.
- */
- public static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS = "success";
-
- /**
- * Argument for {@link #SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS} to specify TZDB time zone IDs.
- */
- public static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ = "tz";
-
- /**
- * Simulated provider test command that simulates the provider entering the "uncertain"
- * state.
- */
- public static final String SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN = "uncertain";
+ public static final String NULL_PACKAGE_NAME_TOKEN = "@null";
private LocationTimeZoneManager() {
// No need to instantiate.
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
index 2be8e355b0161..58281306c0859 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
@@ -46,18 +46,11 @@ import java.util.Set;
public final class ServiceConfigAccessor {
@StringDef(prefix = "PROVIDER_MODE_",
- value = { PROVIDER_MODE_SIMULATED, PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED})
+ value = { PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED})
@Retention(RetentionPolicy.SOURCE)
@Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
@interface ProviderMode {}
- /**
- * The "simulated" provider mode.
- * For use with {@link #getPrimaryLocationTimeZoneProviderMode()} and {@link
- * #getSecondaryLocationTimeZoneProviderMode()}.
- */
- public static final @ProviderMode String PROVIDER_MODE_SIMULATED = "simulated";
-
/**
* The "disabled" provider mode. For use with {@link #getPrimaryLocationTimeZoneProviderMode()}
* and {@link #getSecondaryLocationTimeZoneProviderMode()}.
@@ -110,6 +103,47 @@ public final class ServiceConfigAccessor {
@NonNull private final ServerFlags mServerFlags;
+ /**
+ * The mode to use for the primary location time zone provider in a test. Setting this
+ * disables some permission checks.
+ * This state is volatile: it is never written to storage / never survives a reboot. This is to
+ * avoid a test provider accidentally being left configured on a device.
+ * See also {@link #resetVolatileTestConfig()}.
+ */
+ @Nullable
+ private String mTestPrimaryLocationTimeZoneProviderMode;
+
+ /**
+ * The package name to use for the primary location time zone provider in a test.
+ * This state is volatile: it is never written to storage / never survives a reboot. This is to
+ * avoid a test provider accidentally being left configured on a device.
+ * See also {@link #resetVolatileTestConfig()}.
+ */
+ @Nullable
+ private String mTestPrimaryLocationTimeZoneProviderPackageName;
+
+ /**
+ * See {@link #mTestPrimaryLocationTimeZoneProviderMode}; this is the equivalent for the
+ * secondary provider.
+ */
+ @Nullable
+ private String mTestSecondaryLocationTimeZoneProviderMode;
+
+ /**
+ * See {@link #mTestPrimaryLocationTimeZoneProviderPackageName}; this is the equivalent for the
+ * secondary provider.
+ */
+ @Nullable
+ private String mTestSecondaryLocationTimeZoneProviderPackageName;
+
+ /**
+ * Whether to record state changes for tests.
+ * This state is volatile: it is never written to storage / never survives a reboot. This is to
+ * avoid a test state accidentally being left configured on a device.
+ * See also {@link #resetVolatileTestConfig()}.
+ */
+ private boolean mRecordProviderStateChanges;
+
private ServiceConfigAccessor(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
@@ -200,23 +234,98 @@ public final class ServiceConfigAccessor {
defaultEnabled);
}
+ /** Returns the package name of the app hosting the primary location time zone provider. */
@NonNull
public String getPrimaryLocationTimeZoneProviderPackageName() {
+ if (mTestPrimaryLocationTimeZoneProviderMode != null) {
+ // In test mode: use the test setting value.
+ return mTestPrimaryLocationTimeZoneProviderPackageName;
+ }
return mContext.getResources().getString(
R.string.config_primaryLocationTimeZoneProviderPackageName);
}
+ /**
+ * Sets the package name of the app hosting the primary location time zone provider for tests.
+ * Setting a {@code null} value means the provider is to be disabled.
+ * The values are reset with {@link #resetVolatileTestConfig()}.
+ */
+ public void setTestPrimaryLocationTimeZoneProviderPackageName(
+ @Nullable String testPrimaryLocationTimeZoneProviderPackageName) {
+ mTestPrimaryLocationTimeZoneProviderPackageName =
+ testPrimaryLocationTimeZoneProviderPackageName;
+ mTestPrimaryLocationTimeZoneProviderMode =
+ mTestPrimaryLocationTimeZoneProviderPackageName == null
+ ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED;
+ }
+
+ /**
+ * Returns {@code true} if the usual permission checks are to be bypassed for the primary
+ * provider. Returns {@code true} only if {@link
+ * #setTestPrimaryLocationTimeZoneProviderPackageName} has been called.
+ */
+ public boolean isTestPrimaryLocationTimeZoneProvider() {
+ return mTestPrimaryLocationTimeZoneProviderMode != null;
+ }
+
+ /** Returns the package name of the app hosting the secondary location time zone provider. */
@NonNull
public String getSecondaryLocationTimeZoneProviderPackageName() {
+ if (mTestSecondaryLocationTimeZoneProviderMode != null) {
+ // In test mode: use the test setting value.
+ return mTestSecondaryLocationTimeZoneProviderPackageName;
+ }
return mContext.getResources().getString(
R.string.config_secondaryLocationTimeZoneProviderPackageName);
}
/**
- * Returns {@code true} if the primary location time zone provider can be used.
+ * Sets the package name of the app hosting the secondary location time zone provider for tests.
+ * Setting a {@code null} value means the provider is to be disabled.
+ * The values are reset with {@link #resetVolatileTestConfig()}.
+ */
+ public void setTestSecondaryLocationTimeZoneProviderPackageName(
+ @Nullable String testSecondaryLocationTimeZoneProviderPackageName) {
+ mTestSecondaryLocationTimeZoneProviderPackageName =
+ testSecondaryLocationTimeZoneProviderPackageName;
+ mTestSecondaryLocationTimeZoneProviderMode =
+ mTestSecondaryLocationTimeZoneProviderPackageName == null
+ ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED;
+ }
+
+ /**
+ * Returns {@code true} if the usual permission checks are to be bypassed for the secondary
+ * provider. Returns {@code true} only if {@link
+ * #setTestSecondaryLocationTimeZoneProviderPackageName} has been called.
+ */
+ public boolean isTestSecondaryLocationTimeZoneProvider() {
+ return mTestSecondaryLocationTimeZoneProviderMode != null;
+ }
+
+ /**
+ * Enables/disables the state recording mode for tests. The value is reset with {@link
+ * #resetVolatileTestConfig()}.
+ */
+ public void setRecordProviderStateChanges(boolean enabled) {
+ mRecordProviderStateChanges = enabled;
+ }
+
+ /**
+ * Returns {@code true} if providers are expected to record their state changes for tests.
+ */
+ public boolean getRecordProviderStateChanges() {
+ return mRecordProviderStateChanges;
+ }
+
+ /**
+ * Returns the mode for the primary location time zone provider.
*/
@NonNull
public @ProviderMode String getPrimaryLocationTimeZoneProviderMode() {
+ if (mTestPrimaryLocationTimeZoneProviderMode != null) {
+ // In test mode: use the test setting value.
+ return mTestPrimaryLocationTimeZoneProviderMode;
+ }
return mServerFlags.getOptionalString(
ServerFlags.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE)
.orElse(getPrimaryLocationTimeZoneProviderModeFromConfig());
@@ -230,9 +339,13 @@ public final class ServiceConfigAccessor {
}
/**
- * Returns the mode for the secondary location time zone provider can be used.
+ * Returns the mode for the secondary location time zone provider.
*/
public @ProviderMode String getSecondaryLocationTimeZoneProviderMode() {
+ if (mTestSecondaryLocationTimeZoneProviderMode != null) {
+ // In test mode: use the test setting value.
+ return mTestSecondaryLocationTimeZoneProviderMode;
+ }
return mServerFlags.getOptionalString(
ServerFlags.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE)
.orElse(getSecondaryLocationTimeZoneProviderModeFromConfig());
@@ -298,6 +411,15 @@ public final class ServiceConfigAccessor {
DEFAULT_PROVIDER_UNCERTAINTY_DELAY);
}
+ /** Clears all in-memory test config. */
+ public void resetVolatileTestConfig() {
+ mTestPrimaryLocationTimeZoneProviderPackageName = null;
+ mTestPrimaryLocationTimeZoneProviderMode = null;
+ mTestSecondaryLocationTimeZoneProviderPackageName = null;
+ mTestSecondaryLocationTimeZoneProviderMode = null;
+ mRecordProviderStateChanges = false;
+ }
+
private boolean getConfigBoolean(int providerEnabledConfigId) {
Resources resources = mContext.getResources();
return resources.getBoolean(providerEnabledConfigId);
diff --git a/services/core/java/com/android/server/timezonedetector/location/BinderLocationTimeZoneProvider.java b/services/core/java/com/android/server/timezonedetector/location/BinderLocationTimeZoneProvider.java
index 59df6ff3582e8..9d340e4fde86f 100644
--- a/services/core/java/com/android/server/timezonedetector/location/BinderLocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/timezonedetector/location/BinderLocationTimeZoneProvider.java
@@ -26,7 +26,6 @@ import static com.android.server.timezonedetector.location.LocationTimeZoneProvi
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.RemoteCallback;
import android.util.IndentingPrintWriter;
import java.time.Duration;
@@ -45,9 +44,10 @@ class BinderLocationTimeZoneProvider extends LocationTimeZoneProvider {
@NonNull ProviderMetricsLogger providerMetricsLogger,
@NonNull ThreadingDomain threadingDomain,
@NonNull String providerName,
- @NonNull LocationTimeZoneProviderProxy proxy) {
+ @NonNull LocationTimeZoneProviderProxy proxy,
+ boolean recordStateChanges) {
super(providerMetricsLogger, threadingDomain, providerName,
- new ZoneInfoDbTimeZoneProviderEventPreProcessor());
+ new ZoneInfoDbTimeZoneProviderEventPreProcessor(), recordStateChanges);
mProxy = Objects.requireNonNull(proxy);
}
@@ -125,16 +125,6 @@ class BinderLocationTimeZoneProvider extends LocationTimeZoneProvider {
mProxy.setRequest(request);
}
- /**
- * Passes the supplied test command to the current proxy.
- */
- @Override
- void handleTestCommand(@NonNull TestCommand testCommand, @Nullable RemoteCallback callback) {
- mThreadingDomain.assertCurrentThread();
-
- mProxy.handleTestCommand(testCommand, callback);
- }
-
@Override
public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
synchronized (mSharedLock) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
index b1019f3fa4295..76ef958baf220 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
@@ -33,7 +33,6 @@ import android.annotation.DurationMillisLong;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.RemoteCallback;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
@@ -590,41 +589,14 @@ class ControllerImpl extends LocationTimeZoneProviderController {
}
/**
- * Passes a test command to the specified provider. If the provider name does not match a
- * known provider, then the command is logged and discarded.
+ * Clears recorded provider state changes (for use during tests).
*/
- void handleProviderTestCommand(
- @IntRange(from = 0, to = 1) int providerIndex, @NonNull TestCommand testCommand,
- @Nullable RemoteCallback callback) {
- mThreadingDomain.assertCurrentThread();
-
- LocationTimeZoneProvider targetProvider = getLocationTimeZoneProvider(providerIndex);
- if (targetProvider == null) {
- warnLog("Unable to process test command:"
- + " providerIndex=" + providerIndex + ", testCommand=" + testCommand);
- return;
- }
-
- synchronized (mSharedLock) {
- try {
- targetProvider.handleTestCommand(testCommand, callback);
- } catch (Exception e) {
- warnLog("Unable to process test command:"
- + " providerIndex=" + providerIndex + ", testCommand=" + testCommand, e);
- }
- }
- }
-
- /**
- * Sets whether the controller should record provider state changes for later dumping via
- * {@link #getStateForTests()}.
- */
- void setProviderStateRecordingEnabled(boolean enabled) {
+ void clearRecordedProviderStates() {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
- mPrimaryProvider.setStateChangeRecordingEnabled(enabled);
- mSecondaryProvider.setStateChangeRecordingEnabled(enabled);
+ mPrimaryProvider.clearRecordedStates();
+ mSecondaryProvider.clearRecordedStates();
}
}
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 d8d44d47be624..8dbc520c583cc 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -19,16 +19,13 @@ package com.android.server.timezonedetector.location;
import static android.app.time.LocationTimeZoneManager.SERVICE_NAME;
import static com.android.server.timezonedetector.ServiceConfigAccessor.PROVIDER_MODE_DISABLED;
-import static com.android.server.timezonedetector.ServiceConfigAccessor.PROVIDER_MODE_SIMULATED;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Binder;
-import android.os.Bundle;
import android.os.Handler;
-import android.os.RemoteCallback;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.service.timezone.TimeZoneProviderService;
@@ -50,9 +47,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
/**
* A service class that acts as a container for the {@link LocationTimeZoneProviderController},
@@ -70,12 +64,6 @@ import java.util.concurrent.atomic.AtomicReference;
* one indicated by {@link ThreadingDomain}. Because methods like {@link #dump} can be invoked on
* another thread, the service and its related objects must still be thread-safe.
*
- *
For testing / reproduction of bugs, it is possible to put providers into "simulation
- * mode" where the real binder clients are replaced by {@link
- * SimulatedLocationTimeZoneProviderProxy}. This means that the real client providers are never
- * bound (ensuring no real location events will be received) and simulated events / behaviors
- * can be injected via the command line.
- *
*
See {@code adb shell cmd location_time_zone_manager help}" for details and more options.
*/
public class LocationTimeZoneManagerService extends Binder {
@@ -247,6 +235,36 @@ public class LocationTimeZoneManagerService extends Binder {
}
}
+ /**
+ * Starts the service with fake provider package names configured for tests. The config is
+ * cleared when the service next stops.
+ *
+ *
Because this method posts work to the {@code mThreadingDomain} thread and waits for
+ * completion, it cannot be called from the {@code mThreadingDomain} thread.
+ */
+ void startWithTestProviders(@Nullable String testPrimaryProviderPackageName,
+ @Nullable String testSecondaryProviderPackageName,
+ boolean recordProviderStateChanges) {
+ enforceManageTimeZoneDetectorPermission();
+
+ if (testPrimaryProviderPackageName == null && testSecondaryProviderPackageName == null) {
+ throw new IllegalArgumentException("One or both test package names must be provided.");
+ }
+
+ mThreadingDomain.postAndWait(() -> {
+ synchronized (mSharedLock) {
+ stopOnDomainThread();
+
+ mServiceConfigAccessor.setTestPrimaryLocationTimeZoneProviderPackageName(
+ testPrimaryProviderPackageName);
+ mServiceConfigAccessor.setTestSecondaryLocationTimeZoneProviderPackageName(
+ testSecondaryProviderPackageName);
+ mServiceConfigAccessor.setRecordProviderStateChanges(recordProviderStateChanges);
+ startOnDomainThread();
+ }
+ }, BLOCKING_OP_WAIT_DURATION_MILLIS);
+ }
+
private void startOnDomainThread() {
mThreadingDomain.assertCurrentThread();
@@ -295,6 +313,9 @@ public class LocationTimeZoneManagerService extends Binder {
mLocationTimeZoneDetectorController = null;
mEnvironment.destroy();
mEnvironment = null;
+
+ // Clear test state so it won't be used the next time the service is started.
+ mServiceConfigAccessor.resetVolatileTestConfig();
}
}
}
@@ -307,14 +328,14 @@ public class LocationTimeZoneManagerService extends Binder {
this, in, out, err, args, callback, resultReceiver);
}
- /** Sets this service into provider state recording mode for tests. */
- void setProviderStateRecordingEnabled(boolean enabled) {
+ /** Clears recorded provider state for tests. */
+ void clearRecordedProviderStates() {
enforceManageTimeZoneDetectorPermission();
mThreadingDomain.postAndWait(() -> {
synchronized (mSharedLock) {
if (mLocationTimeZoneDetectorController != null) {
- mLocationTimeZoneDetectorController.setProviderStateRecordingEnabled(enabled);
+ mLocationTimeZoneDetectorController.clearRecordedProviderStates();
}
}
}, BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -344,48 +365,6 @@ public class LocationTimeZoneManagerService extends Binder {
}
}
- /**
- * Passes a {@link TestCommand} to the specified provider and waits for the response.
- */
- @NonNull
- Bundle handleProviderTestCommand(@IntRange(from = 0, to = 1) int providerIndex,
- @NonNull TestCommand testCommand) {
- enforceManageTimeZoneDetectorPermission();
-
- // Because this method blocks and posts work to the threading domain thread, it would cause
- // a deadlock if it were called by the threading domain thread.
- mThreadingDomain.assertNotCurrentThread();
-
- AtomicReference resultReference = new AtomicReference<>();
- CountDownLatch latch = new CountDownLatch(1);
- RemoteCallback remoteCallback = new RemoteCallback(x -> {
- resultReference.set(x);
- latch.countDown();
- });
-
- mThreadingDomain.post(() -> {
- synchronized (mSharedLock) {
- if (mLocationTimeZoneDetectorController == null) {
- remoteCallback.sendResult(null);
- return;
- }
- mLocationTimeZoneDetectorController.handleProviderTestCommand(
- providerIndex, testCommand, remoteCallback);
- }
- });
-
- try {
- // Wait, but not indefinitely.
- if (!latch.await(BLOCKING_OP_WAIT_DURATION_MILLIS, TimeUnit.MILLISECONDS)) {
- throw new RuntimeException("Command did not complete in time");
- }
- } catch (InterruptedException e) {
- throw new AssertionError(e);
- }
-
- return resultReference.get();
- }
-
@Override
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
@Nullable String[] args) {
@@ -463,7 +442,8 @@ public class LocationTimeZoneManagerService extends Binder {
LocationTimeZoneProviderProxy proxy = createProxy();
ProviderMetricsLogger providerMetricsLogger = new RealProviderMetricsLogger(mIndex);
return new BinderLocationTimeZoneProvider(
- providerMetricsLogger, mThreadingDomain, mName, proxy);
+ providerMetricsLogger, mThreadingDomain, mName, proxy,
+ mServiceConfigAccessor.getRecordProviderStateChanges());
}
@GuardedBy("mSharedLock")
@@ -476,9 +456,7 @@ public class LocationTimeZoneManagerService extends Binder {
@NonNull
private LocationTimeZoneProviderProxy createProxy() {
String mode = getMode();
- if (Objects.equals(mode, PROVIDER_MODE_SIMULATED)) {
- return new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
- } else if (Objects.equals(mode, PROVIDER_MODE_DISABLED)) {
+ if (Objects.equals(mode, PROVIDER_MODE_DISABLED)) {
return new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
} else {
// mode == PROVIDER_MODE_OVERRIDE_ENABLED (or unknown).
@@ -486,7 +464,7 @@ public class LocationTimeZoneManagerService extends Binder {
}
}
- /** Returns the mode of the provider. */
+ /** Returns the mode of the provider (enabled/disabled). */
@NonNull
private String getMode() {
if (mIndex == 0) {
@@ -499,10 +477,19 @@ public class LocationTimeZoneManagerService extends Binder {
@NonNull
private RealLocationTimeZoneProviderProxy createRealProxy() {
String providerServiceAction = mServiceAction;
+ boolean isTestProvider = isTestProvider();
String providerPackageName = getPackageName();
return new RealLocationTimeZoneProviderProxy(
mContext, mHandler, mThreadingDomain, providerServiceAction,
- providerPackageName);
+ providerPackageName, isTestProvider);
+ }
+
+ private boolean isTestProvider() {
+ if (mIndex == 0) {
+ return mServiceConfigAccessor.isTestPrimaryLocationTimeZoneProvider();
+ } else {
+ return mServiceConfigAccessor.isTestSecondaryLocationTimeZoneProvider();
+ }
}
@NonNull
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
index 0f0de5004be9b..3488956af5715 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
@@ -16,11 +16,12 @@
package com.android.server.timezonedetector.location;
import static android.app.time.LocationTimeZoneManager.DUMP_STATE_OPTION_PROTO;
+import static android.app.time.LocationTimeZoneManager.NULL_PACKAGE_NAME_TOKEN;
import static android.app.time.LocationTimeZoneManager.SERVICE_NAME;
+import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES;
import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_DUMP_STATE;
-import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_RECORD_PROVIDER_STATES;
-import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND;
import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_START;
+import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_START_WITH_TEST_PROVIDERS;
import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_STOP;
import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
@@ -31,7 +32,6 @@ import static com.android.server.timedetector.ServerFlags.KEY_PRIMARY_LOCATION_T
import static com.android.server.timedetector.ServerFlags.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE;
import static com.android.server.timezonedetector.ServiceConfigAccessor.PROVIDER_MODE_DISABLED;
import static com.android.server.timezonedetector.ServiceConfigAccessor.PROVIDER_MODE_ENABLED;
-import static com.android.server.timezonedetector.ServiceConfigAccessor.PROVIDER_MODE_SIMULATED;
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;
@@ -41,12 +41,12 @@ import static com.android.server.timezonedetector.location.LocationTimeZoneProvi
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_UNKNOWN;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.time.GeolocationTimeZoneSuggestionProto;
import android.app.time.LocationTimeZoneManagerProto;
import android.app.time.LocationTimeZoneManagerServiceStateProto;
import android.app.time.TimeZoneProviderStateProto;
import android.app.timezonedetector.TimeZoneDetector;
-import android.os.Bundle;
import android.os.ShellCommand;
import android.util.IndentingPrintWriter;
import android.util.proto.ProtoOutputStream;
@@ -79,14 +79,14 @@ class LocationTimeZoneManagerShellCommand extends ShellCommand {
case SHELL_COMMAND_START: {
return runStart();
}
+ case SHELL_COMMAND_START_WITH_TEST_PROVIDERS: {
+ return runStartWithTestProviders();
+ }
case SHELL_COMMAND_STOP: {
return runStop();
}
- case SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND: {
- return runSendProviderTestCommand();
- }
- case SHELL_COMMAND_RECORD_PROVIDER_STATES: {
- return runRecordProviderStates();
+ case SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES: {
+ return runClearRecordedProviderStates();
}
case SHELL_COMMAND_DUMP_STATE: {
return runDumpControllerState();
@@ -105,47 +105,33 @@ class LocationTimeZoneManagerShellCommand extends ShellCommand {
pw.printf(" Print this help text.\n");
pw.printf(" %s\n", SHELL_COMMAND_START);
pw.printf(" Starts the service, creating location time zone providers.\n");
+ pw.printf(" %s "
+ + " \n",
+ SHELL_COMMAND_START_WITH_TEST_PROVIDERS, NULL_PACKAGE_NAME_TOKEN);
+ pw.printf(" Starts the service with test provider packages configured / provider"
+ + " permission checks disabled.\n");
+ pw.printf(" - true|false, determines whether state recording is enabled."
+ + "\n");
+ pw.printf(" See %s and %s.\n", SHELL_COMMAND_DUMP_STATE,
+ SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES);
pw.printf(" %s\n", SHELL_COMMAND_STOP);
pw.printf(" Stops the service, destroying location time zone providers.\n");
- pw.printf(" %s (true|false)\n", SHELL_COMMAND_RECORD_PROVIDER_STATES);
- pw.printf(" Enables / disables provider state recording mode. See also %s. The default"
- + " state is always \"false\".\n", SHELL_COMMAND_DUMP_STATE);
- pw.printf(" Note: When enabled, this mode consumes memory and it is only intended for"
- + " testing.\n");
- pw.printf(" It should be disabled after use, or the device can be rebooted to"
- + " reset the mode to disabled.\n");
- pw.printf(" Disabling (or enabling repeatedly) clears any existing stored states.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_CLEAR_RECORDED_PROVIDER_STATES);
+ pw.printf(" Clears recorded provider state. See also %s and %s.\n",
+ SHELL_COMMAND_START_WITH_TEST_PROVIDERS, SHELL_COMMAND_DUMP_STATE);
+ pw.printf(" Note: This is only intended for use during testing.\n");
pw.printf(" %s [%s]\n", SHELL_COMMAND_DUMP_STATE, DUMP_STATE_OPTION_PROTO);
pw.printf(" Dumps service state for tests as text or binary proto form.\n");
pw.printf(" See the LocationTimeZoneManagerServiceStateProto definition for details.\n");
- pw.printf(" %s \n",
- SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND);
- pw.printf(" Passes a test command to the named provider.\n");
- pw.println();
- pw.printf(" = 0 (primary), 1 (secondary)\n");
- pw.println();
- pw.printf("%s details:\n", SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND);
- pw.println();
- pw.printf("Provider encoding:\n");
- pw.println();
- TestCommand.printShellCommandEncodingHelp(pw);
- pw.println();
- pw.printf("Simulated provider mode can be used to test the system server behavior or to"
- + " reproduce bugs without the complexity of using real providers.\n");
- pw.println();
- pw.printf("The test commands for simulated providers are:\n");
- SimulatedLocationTimeZoneProviderProxy.printTestCommandShellHelp(pw);
- pw.println();
- pw.printf("Test commands cannot currently be passed to real provider implementations.\n");
pw.println();
pw.printf("This service is also affected by the following device_config flags in the"
+ " %s namespace:\n", NAMESPACE_SYSTEM_TIME);
pw.printf(" %s\n", KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE);
- pw.printf(" Overrides the mode of the primary provider. Values=%s|%s|%s\n",
- PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED, PROVIDER_MODE_SIMULATED);
+ pw.printf(" Overrides the mode of the primary provider. Values=%s|%s\n",
+ PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED);
pw.printf(" %s\n", KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE);
- pw.printf(" Overrides the mode of the secondary provider. Values=%s|%s|%s\n",
- PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED, PROVIDER_MODE_SIMULATED);
+ pw.printf(" Overrides the mode of the secondary provider. Values=%s|%s\n",
+ PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED);
pw.printf(" %s\n", KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS);
pw.printf(" Sets the amount of time the service waits when uncertain before making an"
+ " 'uncertain' suggestion to the time zone detector.\n");
@@ -178,6 +164,23 @@ class LocationTimeZoneManagerShellCommand extends ShellCommand {
return 0;
}
+ private int runStartWithTestProviders() {
+ String testPrimaryProviderPackageName = parseProviderPackageName(getNextArgRequired());
+ String testSecondaryProviderPackageName = parseProviderPackageName(getNextArgRequired());
+ boolean recordProviderStateChanges = Boolean.parseBoolean(getNextArgRequired());
+
+ try {
+ mService.startWithTestProviders(testPrimaryProviderPackageName,
+ testSecondaryProviderPackageName, recordProviderStateChanges);
+ } catch (RuntimeException e) {
+ reportError(e);
+ return 1;
+ }
+ PrintWriter outPrintWriter = getOutPrintWriter();
+ outPrintWriter.println("Service started (test mode)");
+ return 0;
+ }
+
private int runStop() {
try {
mService.stop();
@@ -190,20 +193,9 @@ class LocationTimeZoneManagerShellCommand extends ShellCommand {
return 0;
}
- private int runRecordProviderStates() {
- PrintWriter outPrintWriter = getOutPrintWriter();
- boolean enabled;
+ private int runClearRecordedProviderStates() {
try {
- String nextArg = getNextArgRequired();
- enabled = Boolean.parseBoolean(nextArg);
- } catch (RuntimeException e) {
- reportError(e);
- return 1;
- }
-
- outPrintWriter.println("Setting provider state recording to " + enabled);
- try {
- mService.setProviderStateRecordingEnabled(enabled);
+ mService.clearRecordedProviderStates();
} catch (IllegalStateException e) {
reportError(e);
return 2;
@@ -293,47 +285,17 @@ class LocationTimeZoneManagerShellCommand extends ShellCommand {
}
}
- private int runSendProviderTestCommand() {
- PrintWriter outPrintWriter = getOutPrintWriter();
-
- int providerIndex;
- TestCommand testCommand;
- try {
- providerIndex = parseProviderIndex(getNextArgRequired());
- testCommand = createTestCommandFromNextShellArg();
- } catch (RuntimeException e) {
- reportError(e);
- return 1;
- }
-
- outPrintWriter.println("Injecting testCommand=" + testCommand
- + " to providerIndex=" + providerIndex);
- try {
- Bundle result = mService.handleProviderTestCommand(providerIndex, testCommand);
- outPrintWriter.println(result);
- } catch (RuntimeException e) {
- reportError(e);
- return 2;
- }
- return 0;
- }
-
- @NonNull
- private TestCommand createTestCommandFromNextShellArg() {
- return TestCommand.createFromShellCommandArgs(this);
- }
-
- private void reportError(Throwable e) {
+ private void reportError(@NonNull Throwable e) {
PrintWriter errPrintWriter = getErrPrintWriter();
errPrintWriter.println("Error: ");
e.printStackTrace(errPrintWriter);
}
- private static int parseProviderIndex(@NonNull String providerIndexString) {
- int providerIndex = Integer.parseInt(providerIndexString);
- if (providerIndex < 0 || providerIndex > 1) {
- throw new IllegalArgumentException(providerIndexString);
+ @Nullable
+ private static String parseProviderPackageName(@NonNull String providerPackageNameString) {
+ if (providerPackageNameString.equals(NULL_PACKAGE_NAME_TOKEN)) {
+ return null;
}
- return providerIndex;
+ return providerPackageNameString;
}
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProvider.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProvider.java
index c0fd6b1d79fad..4e878333fe66d 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProvider.java
@@ -16,9 +16,6 @@
package com.android.server.timezonedetector.location;
-import static android.service.timezone.TimeZoneProviderService.TEST_COMMAND_RESULT_ERROR_KEY;
-import static android.service.timezone.TimeZoneProviderService.TEST_COMMAND_RESULT_SUCCESS_KEY;
-
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.PROVIDER_STATE_DESTROYED;
@@ -35,9 +32,7 @@ import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Bundle;
import android.os.Handler;
-import android.os.RemoteCallback;
import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
@@ -358,8 +353,7 @@ abstract class LocationTimeZoneProvider implements Dumpable {
/**
* Usually {@code false} but can be set to {@code true} for testing.
*/
- @GuardedBy("mSharedLock")
- private boolean mStateChangeRecording;
+ private final boolean mRecordStateChanges;
@GuardedBy("mSharedLock")
@NonNull
@@ -385,7 +379,8 @@ abstract class LocationTimeZoneProvider implements Dumpable {
LocationTimeZoneProvider(@NonNull ProviderMetricsLogger providerMetricsLogger,
@NonNull ThreadingDomain threadingDomain,
@NonNull String providerName,
- @NonNull TimeZoneProviderEventPreProcessor timeZoneProviderEventPreProcessor) {
+ @NonNull TimeZoneProviderEventPreProcessor timeZoneProviderEventPreProcessor,
+ boolean recordStateChanges) {
mThreadingDomain = Objects.requireNonNull(threadingDomain);
mProviderMetricsLogger = Objects.requireNonNull(providerMetricsLogger);
mInitializationTimeoutQueue = threadingDomain.createSingleRunnableQueue();
@@ -393,6 +388,7 @@ abstract class LocationTimeZoneProvider implements Dumpable {
mProviderName = Objects.requireNonNull(providerName);
mTimeZoneProviderEventPreProcessor =
Objects.requireNonNull(timeZoneProviderEventPreProcessor);
+ mRecordStateChanges = recordStateChanges;
}
/**
@@ -456,12 +452,11 @@ abstract class LocationTimeZoneProvider implements Dumpable {
abstract void onDestroy();
/**
- * Sets the provider into state recording mode for tests.
+ * Clears recorded state changes.
*/
- final void setStateChangeRecordingEnabled(boolean enabled) {
+ final void clearRecordedStates() {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
- mStateChangeRecording = enabled;
mRecordedStates.clear();
mRecordedStates.trimToSize();
}
@@ -478,12 +473,11 @@ abstract class LocationTimeZoneProvider implements Dumpable {
}
/**
- * Set the current state, for use by this class and subclasses only. If {@code #notifyChanges}
- * is {@code true} and {@code newState} is not equal to the old state, then {@link
- * ProviderListener#onProviderStateChange(ProviderState)} must be called on
- * {@link #mProviderListener}.
+ * Sets the current state. If {@code #notifyChanges} is {@code true} and {@code newState} is not
+ * equal to the old state, then {@link ProviderListener#onProviderStateChange(ProviderState)}
+ * will be called on {@link #mProviderListener}.
*/
- final void setCurrentState(@NonNull ProviderState newState, boolean notifyChanges) {
+ private void setCurrentState(@NonNull ProviderState newState, boolean notifyChanges) {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
ProviderState oldState = mCurrentState.get();
@@ -491,7 +485,7 @@ abstract class LocationTimeZoneProvider implements Dumpable {
onSetCurrentState(newState);
if (!Objects.equals(newState, oldState)) {
mProviderMetricsLogger.onProviderStateChanged(newState.stateEnum);
- if (mStateChangeRecording) {
+ if (mRecordStateChanges) {
mRecordedStates.add(newState);
}
if (notifyChanges) {
@@ -609,23 +603,6 @@ abstract class LocationTimeZoneProvider implements Dumpable {
*/
abstract void onStopUpdates();
- /**
- * Overridden by subclasses to handle the supplied {@link TestCommand}. If {@code callback} is
- * non-null, the default implementation sends a result {@link Bundle} with {@link
- * android.service.timezone.TimeZoneProviderService#TEST_COMMAND_RESULT_SUCCESS_KEY} set to
- * {@code false} and a "Not implemented" error message.
- */
- void handleTestCommand(@NonNull TestCommand testCommand, @Nullable RemoteCallback callback) {
- Objects.requireNonNull(testCommand);
-
- if (callback != null) {
- Bundle result = new Bundle();
- result.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, false);
- result.putString(TEST_COMMAND_RESULT_ERROR_KEY, "Not implemented");
- callback.sendResult(result);
- }
- }
-
/** For subclasses to invoke when a {@link TimeZoneProviderEvent} has been received. */
final void handleTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
mThreadingDomain.assertCurrentThread();
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderProxy.java
index 43b1b5f017b21..7b1a77ce77d50 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderProxy.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
-import android.os.RemoteCallback;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
@@ -112,13 +111,6 @@ abstract class LocationTimeZoneProviderProxy implements Dumpable {
*/
abstract void setRequest(@NonNull TimeZoneProviderRequest request);
- /**
- * Processes the supplied test command. An optional callback can be supplied to listen for a
- * response.
- */
- abstract void handleTestCommand(@NonNull TestCommand testCommand,
- @Nullable RemoteCallback callback);
-
/**
* Handles a {@link TimeZoneProviderEvent} from a remote process.
*/
diff --git a/services/core/java/com/android/server/timezonedetector/location/NullLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/NullLocationTimeZoneProviderProxy.java
index 1f45e828aad4c..4ef819fdee217 100644
--- a/services/core/java/com/android/server/timezonedetector/location/NullLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/timezonedetector/location/NullLocationTimeZoneProviderProxy.java
@@ -19,9 +19,6 @@ package com.android.server.timezonedetector.location;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.os.Bundle;
-import android.os.RemoteCallback;
-import android.service.timezone.TimeZoneProviderService;
import android.util.IndentingPrintWriter;
/**
@@ -66,17 +63,6 @@ class NullLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy {
}
}
- @Override
- void handleTestCommand(@NonNull TestCommand testCommand, @Nullable RemoteCallback callback) {
- if (callback != null) {
- Bundle result = new Bundle();
- result.putBoolean(TimeZoneProviderService.TEST_COMMAND_RESULT_SUCCESS_KEY, false);
- result.putString(TimeZoneProviderService.TEST_COMMAND_RESULT_ERROR_KEY,
- "Provider is disabled");
- callback.sendResult(result);
- }
- }
-
@Override
public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
synchronized (mSharedLock) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
index b7ff733eabbc8..fcac3e8569132 100644
--- a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
@@ -18,16 +18,12 @@ package com.android.server.timezonedetector.location;
import static android.Manifest.permission.BIND_TIME_ZONE_PROVIDER_SERVICE;
import static android.Manifest.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE;
-import static android.service.timezone.TimeZoneProviderService.TEST_COMMAND_RESULT_ERROR_KEY;
-import static android.service.timezone.TimeZoneProviderService.TEST_COMMAND_RESULT_SUCCESS_KEY;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.RemoteCallback;
import android.service.timezone.ITimeZoneProvider;
import android.service.timezone.ITimeZoneProviderManager;
import android.service.timezone.TimeZoneProviderSuggestion;
@@ -62,19 +58,27 @@ class RealLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy im
RealLocationTimeZoneProviderProxy(
@NonNull Context context, @NonNull Handler handler,
@NonNull ThreadingDomain threadingDomain, @NonNull String action,
- @NonNull String providerPackageName) {
+ @NonNull String providerPackageName, boolean isTestProvider) {
super(context, threadingDomain);
mManagerProxy = null;
mRequest = TimeZoneProviderRequest.createStopUpdatesRequest();
Objects.requireNonNull(providerPackageName);
- mServiceWatcher = ServiceWatcher.create(context,
- handler,
- "RealLocationTimeZoneProviderProxy",
- CurrentUserServiceSupplier.create(context, action,
- providerPackageName, BIND_TIME_ZONE_PROVIDER_SERVICE,
- INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE),
- this);
+
+ CurrentUserServiceSupplier serviceSupplier;
+ if (isTestProvider) {
+ // For tests it is possible to bypass the provider service permission checks, since
+ // the tests are expected to install fake providers.
+ serviceSupplier = CurrentUserServiceSupplier.createUnsafeForTestsOnly(
+ context, action, providerPackageName, BIND_TIME_ZONE_PROVIDER_SERVICE,
+ /*servicePermission=*/null);
+ } else {
+ serviceSupplier = CurrentUserServiceSupplier.create(context, action,
+ providerPackageName, BIND_TIME_ZONE_PROVIDER_SERVICE,
+ INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE);
+ }
+ mServiceWatcher = ServiceWatcher.create(
+ context, handler, "RealLocationTimeZoneProviderProxy", serviceSupplier, this);
}
@Override
@@ -155,21 +159,6 @@ class RealLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy im
});
}
- /**
- * A stubbed implementation.
- */
- @Override
- void handleTestCommand(@NonNull TestCommand testCommand, @Nullable RemoteCallback callback) {
- mThreadingDomain.assertCurrentThread();
-
- if (callback != null) {
- Bundle result = new Bundle();
- result.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, false);
- result.putString(TEST_COMMAND_RESULT_ERROR_KEY, "Not implemented");
- callback.sendResult(result);
- }
- }
-
@Override
public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
synchronized (mSharedLock) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/SimulatedLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/SimulatedLocationTimeZoneProviderProxy.java
deleted file mode 100644
index 02b0a849c1b13..0000000000000
--- a/services/core/java/com/android/server/timezonedetector/location/SimulatedLocationTimeZoneProviderProxy.java
+++ /dev/null
@@ -1,211 +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.app.time.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND;
-import static android.app.time.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_ON_UNBIND;
-import static android.app.time.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_PERM_FAILURE;
-import static android.app.time.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS;
-import static android.app.time.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ;
-import static android.app.time.LocationTimeZoneManager.SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN;
-import static android.service.timezone.TimeZoneProviderService.TEST_COMMAND_RESULT_ERROR_KEY;
-import static android.service.timezone.TimeZoneProviderService.TEST_COMMAND_RESULT_SUCCESS_KEY;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.RemoteCallback;
-import android.os.SystemClock;
-import android.service.timezone.TimeZoneProviderSuggestion;
-import android.util.IndentingPrintWriter;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.timezonedetector.ReferenceWithHistory;
-
-import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * A replacement for a real binder proxy for use during integration testing
- * that can be used to inject simulated {@link LocationTimeZoneProviderProxy} behavior.
- */
-class SimulatedLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy {
-
- @GuardedBy("mSharedLock")
- @NonNull private TimeZoneProviderRequest mRequest;
-
- @GuardedBy("mSharedLock")
- @NonNull private final ReferenceWithHistory mLastEvent = new ReferenceWithHistory<>(50);
-
- SimulatedLocationTimeZoneProviderProxy(
- @NonNull Context context, @NonNull ThreadingDomain threadingDomain) {
- super(context, threadingDomain);
- mRequest = TimeZoneProviderRequest.createStopUpdatesRequest();
- }
-
- @Override
- void onInitialize() {
- // No-op - nothing to do for the simulated provider.
- }
-
- @Override
- void onDestroy() {
- // No-op - nothing to do for the simulated provider.
- }
-
- void handleTestCommand(@NonNull TestCommand testCommand, @Nullable RemoteCallback callback) {
- mThreadingDomain.assertCurrentThread();
-
- Objects.requireNonNull(testCommand);
-
- synchronized (mSharedLock) {
- Bundle resultBundle = new Bundle();
- switch (testCommand.getName()) {
- case SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND: {
- mLastEvent.set("Simulating onProviderBound(), testCommand=" + testCommand);
- mThreadingDomain.post(this::onBindOnHandlerThread);
- resultBundle.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, true);
- break;
- }
- case SIMULATED_PROVIDER_TEST_COMMAND_ON_UNBIND: {
- mLastEvent.set("Simulating onProviderUnbound(), testCommand=" + testCommand);
- mThreadingDomain.post(this::onUnbindOnHandlerThread);
- resultBundle.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, true);
- break;
- }
- case SIMULATED_PROVIDER_TEST_COMMAND_PERM_FAILURE:
- case SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN:
- case SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS: {
- if (!mRequest.sendUpdates()) {
- String errorMsg = "testCommand=" + testCommand
- + " is testing an invalid case:"
- + " updates are off. mRequest=" + mRequest;
- mLastEvent.set(errorMsg);
- resultBundle.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, false);
- resultBundle.putString(TEST_COMMAND_RESULT_ERROR_KEY, errorMsg);
- break;
- }
- mLastEvent.set("Simulating TimeZoneProviderEvent, testCommand=" + testCommand);
- TimeZoneProviderEvent timeZoneProviderEvent =
- createTimeZoneProviderEventFromTestCommand(testCommand);
- handleTimeZoneProviderEvent(timeZoneProviderEvent);
- resultBundle.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, true);
- break;
- }
- default: {
- String errorMsg = "Unknown test event type. testCommand=" + testCommand;
- mLastEvent.set(errorMsg);
- resultBundle.putBoolean(TEST_COMMAND_RESULT_SUCCESS_KEY, false);
- resultBundle.putString(TEST_COMMAND_RESULT_ERROR_KEY, errorMsg);
- break;
- }
- }
- if (callback != null) {
- callback.sendResult(resultBundle);
- }
- }
- }
-
- private void onBindOnHandlerThread() {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- mListener.onProviderBound();
- }
- }
-
- private void onUnbindOnHandlerThread() {
- mThreadingDomain.assertCurrentThread();
-
- synchronized (mSharedLock) {
- mListener.onProviderUnbound();
- }
- }
-
- @Override
- final void setRequest(@NonNull TimeZoneProviderRequest request) {
- mThreadingDomain.assertCurrentThread();
-
- Objects.requireNonNull(request);
- synchronized (mSharedLock) {
- mLastEvent.set("Request received: " + request);
- mRequest = request;
- }
- }
-
- @Override
- public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
- synchronized (mSharedLock) {
- ipw.println("{SimulatedLocationTimeZoneProviderProxy}");
- ipw.println("mRequest=" + mRequest);
- ipw.println("mLastEvent=" + mLastEvent);
-
- ipw.increaseIndent();
- ipw.println("Last event history:");
- mLastEvent.dump(ipw);
- ipw.decreaseIndent();
- }
- }
-
- /**
- * Prints the command line options that to create a {@link TestCommand} that can be passed to
- * {@link #createTimeZoneProviderEventFromTestCommand(TestCommand)}.
- */
- static void printTestCommandShellHelp(@NonNull PrintWriter pw) {
- pw.printf("%s\n", SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND);
- pw.printf("%s\n", SIMULATED_PROVIDER_TEST_COMMAND_ON_UNBIND);
- pw.printf("%s\n", SIMULATED_PROVIDER_TEST_COMMAND_PERM_FAILURE);
- pw.printf("%s\n", SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN);
- pw.printf("%s %s=string_array: