summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Neil Fuller <nfuller@google.com> 2020-09-30 14:46:11 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-09-30 14:46:11 +0000
commite23fca65cd63c96fe31bd84a06d3095fcef5b412 (patch)
tree9ab463517a6a2fb0f1969dd4b0380042aec715e8
parentb3e2b63d91c20345c279f9cbd257167efba23383 (diff)
parent02d943f44d4ed11a7cde1fa33a4c0c07b9cb7e3c (diff)
Merge "Get ready to add System APIs for use by SUW"
-rw-r--r--core/java/android/app/SystemServiceRegistry.java9
-rw-r--r--core/java/android/app/time/ITimeZoneDetectorListener.aidl (renamed from core/java/android/app/timezonedetector/ITimeZoneConfigurationListener.aidl)6
-rw-r--r--core/java/android/app/time/TEST_MAPPING12
-rw-r--r--core/java/android/app/time/TimeManager.java216
-rw-r--r--core/java/android/app/time/TimeZoneCapabilities.aidl (renamed from core/java/android/app/timezonedetector/TimeZoneCapabilities.aidl)2
-rw-r--r--core/java/android/app/time/TimeZoneCapabilities.java (renamed from core/java/android/app/timezonedetector/TimeZoneCapabilities.java)176
-rw-r--r--core/java/android/app/time/TimeZoneCapabilitiesAndConfig.aidl19
-rw-r--r--core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java119
-rw-r--r--core/java/android/app/time/TimeZoneConfiguration.aidl (renamed from core/java/android/app/timezonedetector/TimeZoneConfiguration.aidl)2
-rw-r--r--core/java/android/app/time/TimeZoneConfiguration.java (renamed from core/java/android/app/timezonedetector/TimeZoneConfiguration.java)125
-rw-r--r--core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl12
-rw-r--r--core/java/android/app/timezonedetector/TimeZoneDetector.java64
-rw-r--r--core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java97
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java160
-rw-r--r--core/tests/coretests/src/android/app/time/TimeZoneConfigurationTest.java (renamed from core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java)40
-rw-r--r--core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java186
-rw-r--r--services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java43
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java5
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java93
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java5
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java34
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java139
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java52
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java62
26 files changed, 988 insertions, 717 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d50cdeed6d73..9100d577fd68 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -33,6 +33,7 @@ import android.app.prediction.AppPredictionManager;
import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.app.slice.SliceManager;
+import android.app.time.TimeManager;
import android.app.timedetector.TimeDetector;
import android.app.timedetector.TimeDetectorImpl;
import android.app.timezone.RulesManager;
@@ -1218,6 +1219,14 @@ public final class SystemServiceRegistry {
return new TimeZoneDetectorImpl();
}});
+ registerService(Context.TIME_MANAGER, TimeManager.class,
+ new CachedServiceFetcher<TimeManager>() {
+ @Override
+ public TimeManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ return new TimeManager();
+ }});
+
registerService(Context.PERMISSION_SERVICE, PermissionManager.class,
new CachedServiceFetcher<PermissionManager>() {
@Override
diff --git a/core/java/android/app/timezonedetector/ITimeZoneConfigurationListener.aidl b/core/java/android/app/time/ITimeZoneDetectorListener.aidl
index 6d0fe72b9de1..723ad5969afc 100644
--- a/core/java/android/app/timezonedetector/ITimeZoneConfigurationListener.aidl
+++ b/core/java/android/app/time/ITimeZoneDetectorListener.aidl
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package android.app.timezonedetector;
-
-import android.app.timezonedetector.TimeZoneConfiguration;
+package android.app.time;
/** {@hide} */
-oneway interface ITimeZoneConfigurationListener {
+oneway interface ITimeZoneDetectorListener {
void onChange();
} \ No newline at end of file
diff --git a/core/java/android/app/time/TEST_MAPPING b/core/java/android/app/time/TEST_MAPPING
new file mode 100644
index 000000000000..951905bcbac5
--- /dev/null
+++ b/core/java/android/app/time/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.app.time."
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
new file mode 100644
index 000000000000..9864afba534a
--- /dev/null
+++ b/core/java/android/app/time/TimeManager.java
@@ -0,0 +1,216 @@
+/*
+ * 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 android.app.time;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.app.timezonedetector.ITimeZoneDetectorService;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.concurrent.Executor;
+
+/**
+ * The interface through which system components can interact with time and time zone services.
+ *
+ * @hide
+ */
+// @SystemApi
+@SystemService(Context.TIME_MANAGER)
+public final class TimeManager {
+ private static final String TAG = "time.TimeManager";
+ private static final boolean DEBUG = false;
+
+ private final Object mLock = new Object();
+ private final ITimeZoneDetectorService mITimeZoneDetectorService;
+
+ @GuardedBy("mLock")
+ private ITimeZoneDetectorListener mTimeZoneDetectorReceiver;
+
+ /**
+ * The registered listeners. The key is the actual listener that was registered, the value is a
+ * wrapper that ensures the listener is executed on the correct Executor.
+ */
+ @GuardedBy("mLock")
+ private ArrayMap<TimeZoneDetectorListener, TimeZoneDetectorListener> mTimeZoneDetectorListeners;
+
+ /** @hide */
+ public TimeManager() throws ServiceNotFoundException {
+ // TimeManager is an API over one or possibly more services. At least until there's an
+ // internal refactoring.
+ mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
+ }
+
+ /**
+ * Returns the calling user's time zone capabilities and configuration.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
+ @NonNull
+ public TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig() {
+ if (DEBUG) {
+ Log.d(TAG, "getTimeZoneCapabilities called");
+ }
+ try {
+ return mITimeZoneDetectorService.getCapabilitiesAndConfig();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Modifies the time zone detection configuration.
+ *
+ * <p>Configuration settings vary in scope: some may be global (affect all users), others may be
+ * specific to the current user.
+ *
+ * <p>The ability to modify configuration settings can be subject to restrictions. For
+ * example, they may be determined by device hardware, general policy (i.e. only the primary
+ * user can set them), or by a managed device policy. Use {@link
+ * #getTimeZoneCapabilitiesAndConfig()} to obtain information at runtime about the user's
+ * capabilities.
+ *
+ * <p>Attempts to modify configuration settings with capabilities that are {@link
+ * TimeZoneCapabilities#CAPABILITY_NOT_SUPPORTED} or {@link
+ * TimeZoneCapabilities#CAPABILITY_NOT_ALLOWED} will have no effect and a {@code false}
+ * will be returned. Modifying configuration settings with capabilities that are {@link
+ * TimeZoneCapabilities#CAPABILITY_NOT_APPLICABLE} or {@link
+ * TimeZoneCapabilities#CAPABILITY_POSSESSED} will succeed. See {@link
+ * TimeZoneCapabilities} for further details.
+ *
+ * <p>If the supplied configuration only has some values set, then only the specified settings
+ * will be updated (where the user's capabilities allow) and other settings will be left
+ * unchanged.
+ *
+ * @return {@code true} if all the configuration settings specified have been set to the
+ * new values, {@code false} if none have
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
+ public boolean updateTimeZoneConfiguration(@NonNull TimeZoneConfiguration configuration) {
+ if (DEBUG) {
+ Log.d(TAG, "updateConfiguration called: " + configuration);
+ }
+ try {
+ return mITimeZoneDetectorService.updateConfiguration(configuration);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * An interface that can be used to listen for changes to the time zone detector behavior.
+ */
+ @FunctionalInterface
+ public interface TimeZoneDetectorListener {
+ /**
+ * Called when something about the time zone detector behavior on the device has changed.
+ * For example, this could be because the current user has switched, one of the global or
+ * user's settings been changed, or something that could affect a user's capabilities with
+ * respect to the time zone detector has changed. Because different users can have different
+ * configuration and capabilities, this method may be called when nothing has changed for
+ * the receiving user.
+ */
+ void onChange();
+ }
+
+ /**
+ * Registers a listener that will be informed when something about the time zone detector
+ * behavior changes.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
+ public void addTimeZoneDetectorListener(@NonNull Executor executor,
+ @NonNull TimeZoneDetectorListener listener) {
+
+ if (DEBUG) {
+ Log.d(TAG, "addTimeZoneDetectorListener called: " + listener);
+ }
+ synchronized (mLock) {
+ if (mTimeZoneDetectorListeners == null) {
+ mTimeZoneDetectorListeners = new ArrayMap<>();
+ } else if (mTimeZoneDetectorListeners.containsKey(listener)) {
+ return;
+ }
+
+ if (mTimeZoneDetectorReceiver == null) {
+ ITimeZoneDetectorListener iListener = new ITimeZoneDetectorListener.Stub() {
+ @Override
+ public void onChange() {
+ notifyTimeZoneDetectorListeners();
+ }
+ };
+ mTimeZoneDetectorReceiver = iListener;
+ try {
+ mITimeZoneDetectorService.addListener(mTimeZoneDetectorReceiver);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ mTimeZoneDetectorListeners.put(listener, () -> executor.execute(listener::onChange));
+ }
+ }
+
+ private void notifyTimeZoneDetectorListeners() {
+ ArrayMap<TimeZoneDetectorListener, TimeZoneDetectorListener> timeZoneDetectorListeners;
+ synchronized (mLock) {
+ if (mTimeZoneDetectorListeners == null || mTimeZoneDetectorListeners.isEmpty()) {
+ return;
+ }
+ timeZoneDetectorListeners = new ArrayMap<>(mTimeZoneDetectorListeners);
+ }
+ int size = timeZoneDetectorListeners.size();
+ for (int i = 0; i < size; i++) {
+ timeZoneDetectorListeners.valueAt(i).onChange();
+ }
+ }
+
+ /**
+ * Removes a listener previously passed to
+ * {@link #addTimeZoneDetectorListener(Executor, TimeZoneDetectorListener)}
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
+ public void removeTimeZoneDetectorListener(@NonNull TimeZoneDetectorListener listener) {
+ if (DEBUG) {
+ Log.d(TAG, "removeConfigurationListener called: " + listener);
+ }
+
+ synchronized (mLock) {
+ if (mTimeZoneDetectorListeners == null || mTimeZoneDetectorListeners.isEmpty()) {
+ return;
+ }
+ mTimeZoneDetectorListeners.remove(listener);
+
+ // If the last local listener has been removed, remove and discard the
+ // mTimeZoneDetectorReceiver.
+ if (mTimeZoneDetectorListeners.isEmpty()) {
+ try {
+ mITimeZoneDetectorService.removeListener(mTimeZoneDetectorReceiver);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ mTimeZoneDetectorReceiver = null;
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/timezonedetector/TimeZoneCapabilities.aidl b/core/java/android/app/time/TimeZoneCapabilities.aidl
index fede6458318a..f744bf162c67 100644
--- a/core/java/android/app/timezonedetector/TimeZoneCapabilities.aidl
+++ b/core/java/android/app/time/TimeZoneCapabilities.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.app.timezonedetector;
+package android.app.time;
parcelable TimeZoneCapabilities;
diff --git a/core/java/android/app/timezonedetector/TimeZoneCapabilities.java b/core/java/android/app/time/TimeZoneCapabilities.java
index 09fffe9f4f25..c62c2b34f35d 100644
--- a/core/java/android/app/timezonedetector/TimeZoneCapabilities.java
+++ b/core/java/android/app/time/TimeZoneCapabilities.java
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package android.app.timezonedetector;
-
-import static android.app.timezonedetector.TimeZoneConfiguration.SETTING_AUTO_DETECTION_ENABLED;
-import static android.app.timezonedetector.TimeZoneConfiguration.SETTING_GEO_DETECTION_ENABLED;
+package android.app.time;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.timezonedetector.ManualTimeZoneSuggestion;
+import android.app.timezonedetector.TimeZoneDetector;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -42,15 +42,18 @@ import java.util.Objects;
* <p>Actions have associated methods, see the documentation for each action for details.
*
* <p>For configuration settings capabilities, the associated settings value can be found via
- * {@link #getConfiguration()} and may be changed using {@link
- * TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} (if the user's capabilities allow).
+ * {@link TimeManager#getTimeZoneCapabilitiesAndConfig()} and may be changed using {@link
+ * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)} (if the user's capabilities
+ * allow).
*
* <p>Note: Capabilities are independent of app permissions required to call the associated APIs.
*
* @hide
*/
+// @SystemApi
public final class TimeZoneCapabilities implements Parcelable {
+ /** @hide */
@IntDef({ CAPABILITY_NOT_SUPPORTED, CAPABILITY_NOT_ALLOWED, CAPABILITY_NOT_APPLICABLE,
CAPABILITY_POSSESSED })
@Retention(RetentionPolicy.SOURCE)
@@ -94,64 +97,60 @@ public final class TimeZoneCapabilities implements Parcelable {
}
};
-
- @NonNull private final TimeZoneConfiguration mConfiguration;
- private final @CapabilityState int mConfigureAutoDetectionEnabled;
- private final @CapabilityState int mConfigureGeoDetectionEnabled;
- private final @CapabilityState int mSuggestManualTimeZone;
+ /**
+ * The user the capabilities are for. This is used for object equality and debugging but there
+ * is no accessor.
+ */
+ @NonNull private final UserHandle mUserHandle;
+ private final @CapabilityState int mConfigureAutoDetectionEnabledCapability;
+ private final @CapabilityState int mConfigureGeoDetectionEnabledCapability;
+ private final @CapabilityState int mSuggestManualTimeZoneCapability;
private TimeZoneCapabilities(@NonNull Builder builder) {
- this.mConfiguration = Objects.requireNonNull(builder.mConfiguration);
- this.mConfigureAutoDetectionEnabled = builder.mConfigureAutoDetectionEnabled;
- this.mConfigureGeoDetectionEnabled = builder.mConfigureGeoDetectionEnabled;
- this.mSuggestManualTimeZone = builder.mSuggestManualTimeZone;
+ this.mUserHandle = Objects.requireNonNull(builder.mUserHandle);
+ this.mConfigureAutoDetectionEnabledCapability =
+ builder.mConfigureAutoDetectionEnabledCapability;
+ this.mConfigureGeoDetectionEnabledCapability =
+ builder.mConfigureGeoDetectionEnabledCapability;
+ this.mSuggestManualTimeZoneCapability = builder.mSuggestManualTimeZoneCapability;
}
@NonNull
private static TimeZoneCapabilities createFromParcel(Parcel in) {
- return new TimeZoneCapabilities.Builder()
- .setConfiguration(in.readParcelable(null))
- .setConfigureAutoDetectionEnabled(in.readInt())
- .setConfigureGeoDetectionEnabled(in.readInt())
- .setSuggestManualTimeZone(in.readInt())
+ UserHandle userHandle = UserHandle.readFromParcel(in);
+ return new TimeZoneCapabilities.Builder(userHandle)
+ .setConfigureAutoDetectionEnabledCapability(in.readInt())
+ .setConfigureGeoDetectionEnabledCapability(in.readInt())
+ .setSuggestManualTimeZoneCapability(in.readInt())
.build();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mConfiguration, flags);
- dest.writeInt(mConfigureAutoDetectionEnabled);
- dest.writeInt(mConfigureGeoDetectionEnabled);
- dest.writeInt(mSuggestManualTimeZone);
- }
-
- /**
- * Returns the user's time zone behavior configuration.
- */
- public @NonNull TimeZoneConfiguration getConfiguration() {
- return mConfiguration;
+ UserHandle.writeToParcel(mUserHandle, dest);
+ dest.writeInt(mConfigureAutoDetectionEnabledCapability);
+ dest.writeInt(mConfigureGeoDetectionEnabledCapability);
+ dest.writeInt(mSuggestManualTimeZoneCapability);
}
/**
* Returns the capability state associated with the user's ability to modify the automatic time
* zone detection setting. The setting can be updated via {@link
- * TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and accessed via {@link
- * #getConfiguration()}.
+ * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)}.
*/
@CapabilityState
- public int getConfigureAutoDetectionEnabled() {
- return mConfigureAutoDetectionEnabled;
+ public int getConfigureAutoDetectionEnabledCapability() {
+ return mConfigureAutoDetectionEnabledCapability;
}
/**
* Returns the capability state associated with the user's ability to modify the geolocation
* detection setting. The setting can be updated via {@link
- * TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and accessed via {@link
- * #getConfiguration()}.
+ * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)}.
*/
@CapabilityState
- public int getConfigureGeoDetectionEnabled() {
- return mConfigureGeoDetectionEnabled;
+ public int getConfigureGeoDetectionEnabledCapability() {
+ return mConfigureGeoDetectionEnabledCapability;
}
/**
@@ -160,36 +159,37 @@ public final class TimeZoneCapabilities implements Parcelable {
*
* <p>The suggestion will be ignored in all cases unless the value is {@link
* #CAPABILITY_POSSESSED}. See also {@link TimeZoneConfiguration#isAutoDetectionEnabled()}.
+ *
+ * @hide
*/
@CapabilityState
- public int getSuggestManualTimeZone() {
- return mSuggestManualTimeZone;
+ public int getSuggestManualTimeZoneCapability() {
+ return mSuggestManualTimeZoneCapability;
}
/**
- * Constructs a new {@link TimeZoneConfiguration} from an {@code oldConfiguration} and a set of
- * {@code requestedChanges}, if the current capabilities allow. The new configuration is
- * returned and the capabilities are left unchanged. If the capabilities do not permit one or
- * more of the changes then {@code null} is returned.
+ * Tries to create a new {@link TimeZoneConfiguration} from the {@code config} and the set of
+ * {@code requestedChanges}, if {@code this} capabilities allow. The new configuration is
+ * returned. If the capabilities do not permit one or more of the requested changes then {@code
+ * null} is returned.
+ *
+ * @hide
*/
@Nullable
- public TimeZoneConfiguration applyUpdate(TimeZoneConfiguration requestedChanges) {
- if (requestedChanges.getUserId() != mConfiguration.getUserId()) {
- throw new IllegalArgumentException("User does not match:"
- + " this=" + mConfiguration + ", other=" + requestedChanges);
- }
-
+ public TimeZoneConfiguration tryApplyConfigChanges(
+ @NonNull TimeZoneConfiguration config,
+ @NonNull TimeZoneConfiguration requestedChanges) {
TimeZoneConfiguration.Builder newConfigBuilder =
- new TimeZoneConfiguration.Builder(mConfiguration);
- if (requestedChanges.hasSetting(SETTING_AUTO_DETECTION_ENABLED)) {
- if (getConfigureAutoDetectionEnabled() < CAPABILITY_NOT_APPLICABLE) {
+ new TimeZoneConfiguration.Builder(config);
+ if (requestedChanges.hasIsAutoDetectionEnabled()) {
+ if (this.getConfigureAutoDetectionEnabledCapability() < CAPABILITY_NOT_APPLICABLE) {
return null;
}
newConfigBuilder.setAutoDetectionEnabled(requestedChanges.isAutoDetectionEnabled());
}
- if (requestedChanges.hasSetting(SETTING_GEO_DETECTION_ENABLED)) {
- if (getConfigureGeoDetectionEnabled() < CAPABILITY_NOT_APPLICABLE) {
+ if (requestedChanges.hasIsGeoDetectionEnabled()) {
+ if (this.getConfigureGeoDetectionEnabledCapability() < CAPABILITY_NOT_APPLICABLE) {
return null;
}
newConfigBuilder.setGeoDetectionEnabled(requestedChanges.isGeoDetectionEnabled());
@@ -212,71 +212,71 @@ public final class TimeZoneCapabilities implements Parcelable {
return false;
}
TimeZoneCapabilities that = (TimeZoneCapabilities) o;
- return Objects.equals(mConfiguration, that.mConfiguration)
- && mConfigureAutoDetectionEnabled == that.mConfigureAutoDetectionEnabled
- && mConfigureGeoDetectionEnabled == that.mConfigureGeoDetectionEnabled
- && mSuggestManualTimeZone == that.mSuggestManualTimeZone;
+ return mUserHandle.equals(that.mUserHandle)
+ && mConfigureAutoDetectionEnabledCapability
+ == that.mConfigureAutoDetectionEnabledCapability
+ && mConfigureGeoDetectionEnabledCapability
+ == that.mConfigureGeoDetectionEnabledCapability
+ && mSuggestManualTimeZoneCapability == that.mSuggestManualTimeZoneCapability;
}
@Override
public int hashCode() {
- return Objects.hash(mConfiguration,
- mConfigureAutoDetectionEnabled,
- mConfigureGeoDetectionEnabled,
- mSuggestManualTimeZone);
+ return Objects.hash(mUserHandle, mConfigureAutoDetectionEnabledCapability,
+ mConfigureGeoDetectionEnabledCapability, mSuggestManualTimeZoneCapability);
}
@Override
public String toString() {
return "TimeZoneDetectorCapabilities{"
- + "mConfiguration=" + mConfiguration
- + ", mConfigureAutomaticDetectionEnabled=" + mConfigureAutoDetectionEnabled
- + ", mConfigureGeoDetectionEnabled=" + mConfigureGeoDetectionEnabled
- + ", mSuggestManualTimeZone=" + mSuggestManualTimeZone
+ + "mUserHandle=" + mUserHandle
+ + ", mConfigureAutoDetectionEnabledCapability="
+ + mConfigureAutoDetectionEnabledCapability
+ + ", mConfigureGeoDetectionEnabledCapability="
+ + mConfigureGeoDetectionEnabledCapability
+ + ", mSuggestManualTimeZoneCapability=" + mSuggestManualTimeZoneCapability
+ '}';
}
/** @hide */
public static class Builder {
- private TimeZoneConfiguration mConfiguration;
- private @CapabilityState int mConfigureAutoDetectionEnabled;
- private @CapabilityState int mConfigureGeoDetectionEnabled;
- private @CapabilityState int mSuggestManualTimeZone;
+ @NonNull private UserHandle mUserHandle;
+ private @CapabilityState int mConfigureAutoDetectionEnabledCapability;
+ private @CapabilityState int mConfigureGeoDetectionEnabledCapability;
+ private @CapabilityState int mSuggestManualTimeZoneCapability;
- /** Sets the user-visible configuration settings. */
- public Builder setConfiguration(@NonNull TimeZoneConfiguration configuration) {
- if (!configuration.isComplete()) {
- throw new IllegalArgumentException(configuration + " is not complete");
- }
- this.mConfiguration = configuration;
- return this;
+ public Builder(@NonNull UserHandle userHandle) {
+ mUserHandle = Objects.requireNonNull(userHandle);
}
/** Sets the state for the automatic time zone detection enabled config. */
- public Builder setConfigureAutoDetectionEnabled(@CapabilityState int value) {
- this.mConfigureAutoDetectionEnabled = value;
+ public Builder setConfigureAutoDetectionEnabledCapability(@CapabilityState int value) {
+ this.mConfigureAutoDetectionEnabledCapability = value;
return this;
}
/** Sets the state for the geolocation time zone detection enabled config. */
- public Builder setConfigureGeoDetectionEnabled(@CapabilityState int value) {
- this.mConfigureGeoDetectionEnabled = value;
+ public Builder setConfigureGeoDetectionEnabledCapability(@CapabilityState int value) {
+ this.mConfigureGeoDetectionEnabledCapability = value;
return this;
}
/** Sets the state for the suggestManualTimeZone action. */
- public Builder setSuggestManualTimeZone(@CapabilityState int value) {
- this.mSuggestManualTimeZone = value;
+ public Builder setSuggestManualTimeZoneCapability(@CapabilityState int value) {
+ this.mSuggestManualTimeZoneCapability = value;
return this;
}
/** Returns the {@link TimeZoneCapabilities}. */
@NonNull
public TimeZoneCapabilities build() {
- verifyCapabilitySet(mConfigureAutoDetectionEnabled, "configureAutoDetectionEnabled");
- verifyCapabilitySet(mConfigureGeoDetectionEnabled, "configureGeoDetectionEnabled");
- verifyCapabilitySet(mSuggestManualTimeZone, "suggestManualTimeZone");
+ verifyCapabilitySet(mConfigureAutoDetectionEnabledCapability,
+ "configureAutoDetectionEnabledCapability");
+ verifyCapabilitySet(mConfigureGeoDetectionEnabledCapability,
+ "configureGeoDetectionEnabledCapability");
+ verifyCapabilitySet(mSuggestManualTimeZoneCapability,
+ "suggestManualTimeZoneCapability");
return new TimeZoneCapabilities(this);
}
diff --git a/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.aidl b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.aidl
new file mode 100644
index 000000000000..d7b6b58bf85a
--- /dev/null
+++ b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.app.time;
+
+parcelable TimeZoneCapabilitiesAndConfig;
diff --git a/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
new file mode 100644
index 000000000000..6a04f3f277ed
--- /dev/null
+++ b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
@@ -0,0 +1,119 @@
+/*
+ * 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 android.app.time;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A pair containing a user's {@link TimeZoneCapabilities} and {@link TimeZoneConfiguration}.
+ *
+ * @hide
+ */
+// @SystemApi
+public final class TimeZoneCapabilitiesAndConfig implements Parcelable {
+
+ public static final @NonNull Creator<TimeZoneCapabilitiesAndConfig> CREATOR =
+ new Creator<TimeZoneCapabilitiesAndConfig>() {
+ public TimeZoneCapabilitiesAndConfig createFromParcel(Parcel in) {
+ return TimeZoneCapabilitiesAndConfig.createFromParcel(in);
+ }
+
+ public TimeZoneCapabilitiesAndConfig[] newArray(int size) {
+ return new TimeZoneCapabilitiesAndConfig[size];
+ }
+ };
+
+
+ @NonNull private final TimeZoneCapabilities mCapabilities;
+ @NonNull private final TimeZoneConfiguration mConfiguration;
+
+ /**
+ * Creates a new instance.
+ *
+ * @hide
+ */
+ public TimeZoneCapabilitiesAndConfig(
+ @NonNull TimeZoneCapabilities capabilities,
+ @NonNull TimeZoneConfiguration configuration) {
+ this.mCapabilities = Objects.requireNonNull(capabilities);
+ this.mConfiguration = Objects.requireNonNull(configuration);
+ }
+
+ @NonNull
+ private static TimeZoneCapabilitiesAndConfig createFromParcel(Parcel in) {
+ TimeZoneCapabilities capabilities = in.readParcelable(null);
+ TimeZoneConfiguration configuration = in.readParcelable(null);
+ return new TimeZoneCapabilitiesAndConfig(capabilities, configuration);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mCapabilities, flags);
+ dest.writeParcelable(mConfiguration, flags);
+ }
+
+ /**
+ * Returns the user's time zone behavior capabilities.
+ */
+ @NonNull
+ public TimeZoneCapabilities getCapabilities() {
+ return mCapabilities;
+ }
+
+ /**
+ * Returns the user's time zone behavior configuration.
+ */
+ @NonNull
+ public TimeZoneConfiguration getConfiguration() {
+ return mConfiguration;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeZoneCapabilitiesAndConfig that = (TimeZoneCapabilitiesAndConfig) o;
+ return mCapabilities.equals(that.mCapabilities)
+ && mConfiguration.equals(that.mConfiguration);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCapabilities, mConfiguration);
+ }
+
+ @Override
+ public String toString() {
+ return "TimeZoneDetectorCapabilitiesAndConfig{"
+ + "mCapabilities=" + mCapabilities
+ + ", mConfiguration=" + mConfiguration
+ + '}';
+ }
+}
diff --git a/core/java/android/app/timezonedetector/TimeZoneConfiguration.aidl b/core/java/android/app/time/TimeZoneConfiguration.aidl
index 62240ba5946b..8e859299d073 100644
--- a/core/java/android/app/timezonedetector/TimeZoneConfiguration.aidl
+++ b/core/java/android/app/time/TimeZoneConfiguration.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.app.timezonedetector;
+package android.app.time;
parcelable TimeZoneConfiguration;
diff --git a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java b/core/java/android/app/time/TimeZoneConfiguration.java
index e879091cd68e..488818a528ef 100644
--- a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java
+++ b/core/java/android/app/time/TimeZoneConfiguration.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package android.app.timezonedetector;
+package android.app.time;
import android.annotation.NonNull;
import android.annotation.StringDef;
-import android.annotation.UserIdInt;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,15 +35,13 @@ import java.util.Objects;
* several settings, the device behavior may not be directly affected by the setting value.
*
* <p>Settings can be left absent when updating configuration via {@link
- * TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and those settings will not be
+ * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)} and those settings will not be
* changed. Not all configuration settings can be modified by all users: see {@link
- * TimeZoneDetector#getCapabilities()} and {@link TimeZoneCapabilities} for details.
- *
- * <p>See {@link #hasSetting(String)} with {@code PROPERTY_} constants for testing for the presence
- * of individual settings.
+ * TimeManager#getTimeZoneCapabilitiesAndConfig()} and {@link TimeZoneCapabilities} for details.
*
* @hide
*/
+// @SystemApi
public final class TimeZoneConfiguration implements Parcelable {
public static final @NonNull Creator<TimeZoneConfiguration> CREATOR =
@@ -58,53 +55,48 @@ public final class TimeZoneConfiguration implements Parcelable {
}
};
- /** All configuration properties */
+ /**
+ * All configuration properties
+ *
+ * @hide
+ */
@StringDef({ SETTING_AUTO_DETECTION_ENABLED, SETTING_GEO_DETECTION_ENABLED })
@Retention(RetentionPolicy.SOURCE)
@interface Setting {}
/** See {@link TimeZoneConfiguration#isAutoDetectionEnabled()} for details. */
@Setting
- public static final String SETTING_AUTO_DETECTION_ENABLED = "autoDetectionEnabled";
+ private static final String SETTING_AUTO_DETECTION_ENABLED = "autoDetectionEnabled";
/** See {@link TimeZoneConfiguration#isGeoDetectionEnabled()} for details. */
@Setting
- public static final String SETTING_GEO_DETECTION_ENABLED = "geoDetectionEnabled";
+ private static final String SETTING_GEO_DETECTION_ENABLED = "geoDetectionEnabled";
- private final @UserIdInt int mUserId;
@NonNull private final Bundle mBundle;
private TimeZoneConfiguration(Builder builder) {
- this.mUserId = builder.mUserId;
this.mBundle = Objects.requireNonNull(builder.mBundle);
}
private static TimeZoneConfiguration createFromParcel(Parcel in) {
- return new TimeZoneConfiguration.Builder(in.readInt())
+ return new TimeZoneConfiguration.Builder()
.setPropertyBundleInternal(in.readBundle())
.build();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mUserId);
dest.writeBundle(mBundle);
}
- /** Returns the ID of the user this configuration is associated with. */
- public @UserIdInt int getUserId() {
- return mUserId;
- }
-
- /** Returns {@code true} if all known settings are present. */
+ /**
+ * Returns {@code true} if all known settings are present.
+ *
+ * @hide
+ */
public boolean isComplete() {
- return hasSetting(SETTING_AUTO_DETECTION_ENABLED)
- && hasSetting(SETTING_GEO_DETECTION_ENABLED);
- }
-
- /** Returns true if the specified setting is set. */
- public boolean hasSetting(@Setting String setting) {
- return mBundle.containsKey(setting);
+ return hasIsAutoDetectionEnabled()
+ && hasIsGeoDetectionEnabled();
}
/**
@@ -112,9 +104,10 @@ public final class TimeZoneConfiguration implements Parcelable {
* controls whether a device will attempt to determine the time zone automatically using
* contextual information if the device supports auto detection.
*
- * <p>This setting is global and can be updated by some users.
+ * <p>See {@link TimeZoneCapabilities#getConfigureAutoDetectionEnabledCapability()} for how to
+ * tell if the setting is meaningful for the current user at this time.
*
- * @throws IllegalStateException if the setting has not been set
+ * @throws IllegalStateException if the setting is not present
*/
public boolean isAutoDetectionEnabled() {
enforceSettingPresent(SETTING_AUTO_DETECTION_ENABLED);
@@ -122,21 +115,39 @@ public final class TimeZoneConfiguration implements Parcelable {
}
/**
+ * Returns {@code true} if the {@link #isAutoDetectionEnabled()} setting is present.
+ *
+ * @hide
+ */
+ public boolean hasIsAutoDetectionEnabled() {
+ return mBundle.containsKey(SETTING_AUTO_DETECTION_ENABLED);
+ }
+
+ /**
* Returns the value of the {@link #SETTING_GEO_DETECTION_ENABLED} setting. This
- * controls whether a device can use geolocation to determine time zone. Only used when
- * {@link #isAutoDetectionEnabled()} is {@code true} and when the user has allowed their
- * location to be used.
+ * controls whether the device can use geolocation to determine time zone. This value may only
+ * be used by Android under some circumstances. For example, it is not used when
+ * {@link #isGeoDetectionEnabled()} is {@code false}.
*
- * <p>This setting is user-scoped and can be updated by some users.
- * See {@link TimeZoneCapabilities#getConfigureGeoDetectionEnabled()}.
+ * <p>See {@link TimeZoneCapabilities#getConfigureGeoDetectionEnabledCapability()} for how to
+ * tell if the setting is meaningful for the current user at this time.
*
- * @throws IllegalStateException if the setting has not been set
+ * @throws IllegalStateException if the setting is not present
*/
public boolean isGeoDetectionEnabled() {
enforceSettingPresent(SETTING_GEO_DETECTION_ENABLED);
return mBundle.getBoolean(SETTING_GEO_DETECTION_ENABLED);
}
+ /**
+ * Returns {@code true} if the {@link #isGeoDetectionEnabled()} setting is present.
+ *
+ * @hide
+ */
+ public boolean hasIsGeoDetectionEnabled() {
+ return mBundle.containsKey(SETTING_GEO_DETECTION_ENABLED);
+ }
+
@Override
public int describeContents() {
return 0;
@@ -151,20 +162,18 @@ public final class TimeZoneConfiguration implements Parcelable {
return false;
}
TimeZoneConfiguration that = (TimeZoneConfiguration) o;
- return mUserId == that.mUserId
- && mBundle.kindofEquals(that.mBundle);
+ return mBundle.kindofEquals(that.mBundle);
}
@Override
public int hashCode() {
- return Objects.hash(mUserId, mBundle);
+ return Objects.hash(mBundle);
}
@Override
public String toString() {
return "TimeZoneConfiguration{"
- + "mUserId=" + mUserId
- + ", mBundle=" + mBundle
+ + "mBundle=" + mBundle
+ '}';
}
@@ -174,43 +183,43 @@ public final class TimeZoneConfiguration implements Parcelable {
}
}
- /** @hide */
- public static class Builder {
+ /**
+ * A builder for {@link TimeZoneConfiguration} objects.
+ *
+ * @hide
+ */
+ // @SystemApi
+ public static final class Builder {
- private final @UserIdInt int mUserId;
private final Bundle mBundle = new Bundle();
/**
- * Creates a new Builder for a userId with no settings held.
+ * Creates a new Builder with no settings held.
*/
- public Builder(@UserIdInt int userId) {
- mUserId = userId;
+ public Builder() {
}
/**
- * Creates a new Builder by copying the user ID and settings from an existing instance.
+ * Creates a new Builder by copying the settings from an existing instance.
*/
- public Builder(TimeZoneConfiguration toCopy) {
- this.mUserId = toCopy.mUserId;
+ public Builder(@NonNull TimeZoneConfiguration toCopy) {
mergeProperties(toCopy);
}
/**
* Merges {@code other} settings into this instances, replacing existing values in this
* where the settings appear in both.
+ *
+ * @hide
*/
- public Builder mergeProperties(TimeZoneConfiguration other) {
- if (mUserId != other.mUserId) {
- throw new IllegalArgumentException(
- "Cannot merge configurations for different user IDs."
- + " this.mUserId=" + this.mUserId
- + ", other.mUserId=" + other.mUserId);
- }
+ @NonNull
+ public Builder mergeProperties(@NonNull TimeZoneConfiguration other) {
this.mBundle.putAll(other.mBundle);
return this;
}
- Builder setPropertyBundleInternal(Bundle bundle) {
+ @NonNull
+ Builder setPropertyBundleInternal(@NonNull Bundle bundle) {
this.mBundle.putAll(bundle);
return this;
}
@@ -218,6 +227,7 @@ public final class TimeZoneConfiguration implements Parcelable {
/**
* Sets the state of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting.
*/
+ @NonNull
public Builder setAutoDetectionEnabled(boolean enabled) {
this.mBundle.putBoolean(SETTING_AUTO_DETECTION_ENABLED, enabled);
return this;
@@ -226,6 +236,7 @@ public final class TimeZoneConfiguration implements Parcelable {
/**
* Sets the state of the {@link #SETTING_GEO_DETECTION_ENABLED} setting.
*/
+ @NonNull
public Builder setGeoDetectionEnabled(boolean enabled) {
this.mBundle.putBoolean(SETTING_GEO_DETECTION_ENABLED, enabled);
return this;
diff --git a/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl b/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
index 4f7e1f62928a..af0389a14c4b 100644
--- a/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
+++ b/core/java/android/app/timezonedetector/ITimeZoneDetectorService.aidl
@@ -16,11 +16,11 @@
package android.app.timezonedetector;
-import android.app.timezonedetector.ITimeZoneConfigurationListener;
+import android.app.time.ITimeZoneDetectorListener;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.app.timezonedetector.TimeZoneCapabilities;
-import android.app.timezonedetector.TimeZoneConfiguration;
/**
* System private API to communicate with time zone detector service.
@@ -35,9 +35,9 @@ import android.app.timezonedetector.TimeZoneConfiguration;
* {@hide}
*/
interface ITimeZoneDetectorService {
- TimeZoneCapabilities getCapabilities();
- void addConfigurationListener(ITimeZoneConfigurationListener listener);
- void removeConfigurationListener(ITimeZoneConfigurationListener listener);
+ TimeZoneCapabilitiesAndConfig getCapabilitiesAndConfig();
+ void addListener(ITimeZoneDetectorListener listener);
+ void removeListener(ITimeZoneDetectorListener listener);
boolean updateConfiguration(in TimeZoneConfiguration configuration);
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index 2b1cbf259c55..486232d0f6ed 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -30,70 +30,6 @@ import android.content.Context;
public interface TimeZoneDetector {
/**
- * Returns the current user's time zone capabilities. See {@link TimeZoneCapabilities}.
- */
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- @NonNull
- TimeZoneCapabilities getCapabilities();
-
- /**
- * Modifies the time zone detection configuration.
- *
- * <p>Configuration settings vary in scope: some may be global (affect all users), others may be
- * specific to the current user.
- *
- * <p>The ability to modify configuration settings can be subject to restrictions. For
- * example, they may be determined by device hardware, general policy (i.e. only the primary
- * user can set them), or by a managed device policy. Use {@link #getCapabilities()} to obtain
- * information at runtime about the user's capabilities.
- *
- * <p>Attempts to modify configuration settings with capabilities that are {@link
- * TimeZoneCapabilities#CAPABILITY_NOT_SUPPORTED} or {@link
- * TimeZoneCapabilities#CAPABILITY_NOT_ALLOWED} will have no effect and a {@code false}
- * will be returned. Modifying configuration settings with capabilities that are {@link
- * TimeZoneCapabilities#CAPABILITY_NOT_APPLICABLE} or {@link
- * TimeZoneCapabilities#CAPABILITY_POSSESSED} will succeed. See {@link
- * TimeZoneCapabilities} for further details.
- *
- * <p>If the supplied configuration only has some values set, then only the specified settings
- * will be updated (where the user's capabilities allow) and other settings will be left
- * unchanged.
- *
- * @return {@code true} if all the configuration settings specified have been set to the
- * new values, {@code false} if none have
- */
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- boolean updateConfiguration(@NonNull TimeZoneConfiguration configuration);
-
- /**
- * An interface that can be used to listen for changes to the time zone detector configuration.
- */
- @FunctionalInterface
- interface TimeZoneConfigurationListener {
- /**
- * Called when something about the time zone configuration on the device has changed.
- * This could be because the current user has changed, one of the device's relevant settings
- * has changed, or something that could affect a user's capabilities has changed.
- * There are no guarantees about the thread used.
- */
- void onChange();
- }
-
- /**
- * Registers a listener that will be informed when something about the time zone configuration
- * changes.
- */
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- void addConfigurationListener(@NonNull TimeZoneConfigurationListener listener);
-
- /**
- * Removes a listener previously passed to
- * {@link #addConfigurationListener(ITimeZoneConfigurationListener)}
- */
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- void removeConfigurationListener(@NonNull TimeZoneConfigurationListener listener);
-
- /**
* A shared utility method to create a {@link ManualTimeZoneSuggestion}.
*
* @hide
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java b/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java
index 4c69732abec9..3bd6b4bd692a 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetectorImpl.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
-import android.util.ArraySet;
import android.util.Log;
/**
@@ -35,108 +34,12 @@ public final class TimeZoneDetectorImpl implements TimeZoneDetector {
private final ITimeZoneDetectorService mITimeZoneDetectorService;
- private ITimeZoneConfigurationListener mConfigurationReceiver;
- private ArraySet<TimeZoneConfigurationListener> mConfigurationListeners;
-
public TimeZoneDetectorImpl() throws ServiceNotFoundException {
mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
}
@Override
- @NonNull
- public TimeZoneCapabilities getCapabilities() {
- if (DEBUG) {
- Log.d(TAG, "getCapabilities called");
- }
- try {
- return mITimeZoneDetectorService.getCapabilities();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- @Override
- public boolean updateConfiguration(@NonNull TimeZoneConfiguration configuration) {
- if (DEBUG) {
- Log.d(TAG, "updateConfiguration called: " + configuration);
- }
- try {
- return mITimeZoneDetectorService.updateConfiguration(configuration);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- @Override
- public void addConfigurationListener(@NonNull TimeZoneConfigurationListener listener) {
- if (DEBUG) {
- Log.d(TAG, "addConfigurationListener called: " + listener);
- }
- synchronized (this) {
- if (mConfigurationListeners.contains(listener)) {
- return;
- }
- if (mConfigurationReceiver == null) {
- ITimeZoneConfigurationListener iListener =
- new ITimeZoneConfigurationListener.Stub() {
- @Override
- public void onChange() {
- notifyConfigurationListeners();
- }
- };
- mConfigurationReceiver = iListener;
- }
- if (mConfigurationListeners == null) {
- mConfigurationListeners = new ArraySet<>();
- }
-
- boolean wasEmpty = mConfigurationListeners.isEmpty();
- mConfigurationListeners.add(listener);
- if (wasEmpty) {
- try {
- mITimeZoneDetectorService.addConfigurationListener(mConfigurationReceiver);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- }
-
- private void notifyConfigurationListeners() {
- final ArraySet<TimeZoneConfigurationListener> configurationListeners;
- synchronized (this) {
- configurationListeners = new ArraySet<>(mConfigurationListeners);
- }
- int size = configurationListeners.size();
- for (int i = 0; i < size; i++) {
- configurationListeners.valueAt(i).onChange();
- }
- }
-
- @Override
- public void removeConfigurationListener(@NonNull TimeZoneConfigurationListener listener) {
- if (DEBUG) {
- Log.d(TAG, "removeConfigurationListener called: " + listener);
- }
-
- synchronized (this) {
- if (mConfigurationListeners == null) {
- return;
- }
- boolean wasEmpty = mConfigurationListeners.isEmpty();
- mConfigurationListeners.remove(listener);
- if (mConfigurationListeners.isEmpty() && !wasEmpty) {
- try {
- mITimeZoneDetectorService.removeConfigurationListener(mConfigurationReceiver);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- }
-
- @Override
public boolean suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
if (DEBUG) {
Log.d(TAG, "suggestManualTimeZone called: " + timeZoneSuggestion);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 005648ffec36..666ba32d0e4f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -40,6 +40,7 @@ import android.app.ActivityManager;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.VrManager;
+import android.app.time.TimeManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -5090,6 +5091,14 @@ public abstract class Context {
public static final String TIME_ZONE_DETECTOR_SERVICE = "time_zone_detector";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an {@link TimeManager}.
+ * @hide
+ *
+ * @see #getSystemService(String)
+ */
+ public static final String TIME_MANAGER = "time_manager";
+
+ /**
* Binder service name for {@link AppBindingService}.
* @hide
*/
diff --git a/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java b/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java
new file mode 100644
index 000000000000..01a25b27baf6
--- /dev/null
+++ b/core/tests/coretests/src/android/app/time/TimeZoneCapabilitiesTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 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 android.app.time;
+
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import android.os.UserHandle;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TimeZoneCapabilitiesTest {
+
+ private static final UserHandle TEST_USER_HANDLE = UserHandle.of(12345);
+
+ @Test
+ public void testEquals() {
+ TimeZoneCapabilities.Builder builder1 = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeZoneCapability(CAPABILITY_POSSESSED);
+ TimeZoneCapabilities.Builder builder2 = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeZoneCapability(CAPABILITY_POSSESSED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ builder2.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ builder2.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertEquals(one, two);
+ }
+
+ builder2.setSuggestManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setSuggestManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertEquals(one, two);
+ }
+ }
+
+ @Test
+ public void testParcelable() {
+ TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeZoneCapability(CAPABILITY_POSSESSED);
+ assertRoundTripParcelable(builder.build());
+
+ builder.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ assertRoundTripParcelable(builder.build());
+
+ builder.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ assertRoundTripParcelable(builder.build());
+
+ builder.setSuggestManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED);
+ assertRoundTripParcelable(builder.build());
+ }
+
+ @Test
+ public void testTryApplyConfigChanges_permitted() {
+ TimeZoneConfiguration oldConfiguration =
+ new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(true)
+ .setGeoDetectionEnabled(true)
+ .build();
+ TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
+ .setSuggestManualTimeZoneCapability(CAPABILITY_POSSESSED)
+ .build();
+
+ TimeZoneConfiguration configChange = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(false)
+ .build();
+
+ TimeZoneConfiguration expected = new TimeZoneConfiguration.Builder(oldConfiguration)
+ .setAutoDetectionEnabled(false)
+ .build();
+ assertEquals(expected, capabilities.tryApplyConfigChanges(oldConfiguration, configChange));
+ }
+
+ @Test
+ public void testTryApplyConfigChanges_notPermitted() {
+ TimeZoneConfiguration oldConfiguration =
+ new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(true)
+ .setGeoDetectionEnabled(true)
+ .build();
+ TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setSuggestManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .build();
+
+ TimeZoneConfiguration configChange = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(false)
+ .build();
+
+ assertNull(capabilities.tryApplyConfigChanges(oldConfiguration, configChange));
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java b/core/tests/coretests/src/android/app/time/TimeZoneConfigurationTest.java
index faf908de8d4a..3948eb86c4f6 100644
--- a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java
+++ b/core/tests/coretests/src/android/app/time/TimeZoneConfigurationTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.app.timezonedetector;
+package android.app.time;
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
@@ -23,16 +23,20 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Test;
+import org.junit.runner.RunWith;
+@RunWith(AndroidJUnit4.class)
+@SmallTest
public class TimeZoneConfigurationTest {
- private static final int ARBITRARY_USER_ID = 9876;
-
@Test
public void testBuilder_copyConstructor() {
TimeZoneConfiguration.Builder builder1 =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
+ new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.setGeoDetectionEnabled(true);
TimeZoneConfiguration configuration1 = builder1.build();
@@ -45,27 +49,27 @@ public class TimeZoneConfigurationTest {
@Test
public void testIntrospectionMethods() {
- TimeZoneConfiguration empty = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID).build();
+ TimeZoneConfiguration empty = new TimeZoneConfiguration.Builder().build();
assertFalse(empty.isComplete());
- assertFalse(empty.hasSetting(TimeZoneConfiguration.SETTING_AUTO_DETECTION_ENABLED));
+ assertFalse(empty.hasIsAutoDetectionEnabled());
- TimeZoneConfiguration completeConfig = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
+ TimeZoneConfiguration completeConfig = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.setGeoDetectionEnabled(true)
.build();
assertTrue(completeConfig.isComplete());
- assertTrue(completeConfig.hasSetting(TimeZoneConfiguration.SETTING_AUTO_DETECTION_ENABLED));
+ assertTrue(completeConfig.hasIsGeoDetectionEnabled());
}
@Test
public void testBuilder_mergeProperties() {
- TimeZoneConfiguration configuration1 = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
+ TimeZoneConfiguration configuration1 = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.build();
{
TimeZoneConfiguration mergedEmptyAnd1 =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
+ new TimeZoneConfiguration.Builder()
.mergeProperties(configuration1)
.build();
assertEquals(configuration1, mergedEmptyAnd1);
@@ -73,7 +77,7 @@ public class TimeZoneConfigurationTest {
{
TimeZoneConfiguration configuration2 =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
+ new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(false)
.build();
@@ -90,22 +94,14 @@ public class TimeZoneConfigurationTest {
@Test
public void testEquals() {
TimeZoneConfiguration.Builder builder1 =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID);
+ new TimeZoneConfiguration.Builder();
{
TimeZoneConfiguration one = builder1.build();
assertEquals(one, one);
}
- {
- TimeZoneConfiguration.Builder differentUserBuilder =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID + 1);
- TimeZoneConfiguration one = builder1.build();
- TimeZoneConfiguration two = differentUserBuilder.build();
- assertNotEquals(one, two);
- }
-
TimeZoneConfiguration.Builder builder2 =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID);
+ new TimeZoneConfiguration.Builder();
{
TimeZoneConfiguration one = builder1.build();
TimeZoneConfiguration two = builder2.build();
@@ -159,7 +155,7 @@ public class TimeZoneConfigurationTest {
@Test
public void testParcelable() {
TimeZoneConfiguration.Builder builder =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID);
+ new TimeZoneConfiguration.Builder();
assertRoundTripParcelable(builder.build());
builder.setAutoDetectionEnabled(true);
diff --git a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java
deleted file mode 100644
index db127c6cb9ed..000000000000
--- a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 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 android.app.timezonedetector;
-
-import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_POSSESSED;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-public class TimeZoneCapabilitiesTest {
-
- private static final int ARBITRARY_USER_ID = 12345;
-
- @Test
- public void testEquals() {
- TimeZoneConfiguration configuration1 = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(true)
- .setGeoDetectionEnabled(true)
- .build();
- TimeZoneConfiguration configuration2 = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(false)
- .setGeoDetectionEnabled(false)
- .build();
-
- TimeZoneCapabilities.Builder builder1 = new TimeZoneCapabilities.Builder()
- .setConfiguration(configuration1)
- .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
- .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
- .setSuggestManualTimeZone(CAPABILITY_POSSESSED);
- TimeZoneCapabilities.Builder builder2 = new TimeZoneCapabilities.Builder()
- .setConfiguration(configuration1)
- .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
- .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
- .setSuggestManualTimeZone(CAPABILITY_POSSESSED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertEquals(one, two);
- }
-
- builder2.setConfiguration(configuration2);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setConfiguration(configuration2);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertEquals(one, two);
- }
-
- builder2.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertEquals(one, two);
- }
-
- builder2.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertEquals(one, two);
- }
-
- builder2.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertNotEquals(one, two);
- }
-
- builder1.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED);
- {
- TimeZoneCapabilities one = builder1.build();
- TimeZoneCapabilities two = builder2.build();
- assertEquals(one, two);
- }
- }
-
- @Test
- public void testParcelable() {
- TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(true)
- .setGeoDetectionEnabled(true)
- .build();
- TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder()
- .setConfiguration(configuration)
- .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
- .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
- .setSuggestManualTimeZone(CAPABILITY_POSSESSED);
- assertRoundTripParcelable(builder.build());
-
- builder.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
- assertRoundTripParcelable(builder.build());
-
- builder.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
- assertRoundTripParcelable(builder.build());
-
- builder.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED);
- assertRoundTripParcelable(builder.build());
- }
-
- @Test
- public void testApplyUpdate_permitted() {
- TimeZoneConfiguration oldConfiguration =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(true)
- .setGeoDetectionEnabled(true)
- .build();
- TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder()
- .setConfiguration(oldConfiguration)
- .setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
- .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
- .setSuggestManualTimeZone(CAPABILITY_POSSESSED)
- .build();
- assertEquals(oldConfiguration, capabilities.getConfiguration());
-
- TimeZoneConfiguration configChange = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(false)
- .build();
-
- TimeZoneConfiguration expected = new TimeZoneConfiguration.Builder(oldConfiguration)
- .setAutoDetectionEnabled(false)
- .build();
- assertEquals(expected, capabilities.applyUpdate(configChange));
- }
-
- @Test
- public void testApplyUpdate_notPermitted() {
- TimeZoneConfiguration oldConfiguration =
- new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(true)
- .setGeoDetectionEnabled(true)
- .build();
- TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder()
- .setConfiguration(oldConfiguration)
- .setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED)
- .setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED)
- .setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED)
- .build();
- assertEquals(oldConfiguration, capabilities.getConfiguration());
-
- TimeZoneConfiguration configChange = new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionEnabled(false)
- .build();
-
- assertNull(capabilities.applyUpdate(configChange));
- }
-}
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index b68c54fc6365..9e76bc19360f 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -16,15 +16,16 @@
package com.android.server.timezonedetector;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_POSSESSED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
-import android.app.timezonedetector.TimeZoneCapabilities;
-import android.app.timezonedetector.TimeZoneConfiguration;
+import android.app.time.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
import android.os.UserHandle;
import java.util.Objects;
@@ -32,7 +33,7 @@ import java.util.Objects;
/**
* Holds all configuration values that affect time zone behavior and some associated logic, e.g.
* {@link #getAutoDetectionEnabledBehavior()}, {@link #getGeoDetectionEnabledBehavior()} and {@link
- * #createCapabilities()}.
+ * #createCapabilitiesAndConfig()}.
*/
public final class ConfigurationInternal {
@@ -106,10 +107,15 @@ public final class ConfigurationInternal {
return false;
}
- /** Creates a {@link TimeZoneCapabilities} object using the configuration values. */
- public TimeZoneCapabilities createCapabilities() {
- TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder()
- .setConfiguration(asConfiguration());
+ /** Creates a {@link TimeZoneCapabilitiesAndConfig} object using the configuration values. */
+ public TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig() {
+ return new TimeZoneCapabilitiesAndConfig(asCapabilities(), asConfiguration());
+ }
+
+ @NonNull
+ private TimeZoneCapabilities asCapabilities() {
+ UserHandle userHandle = UserHandle.of(mUserId);
+ TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder(userHandle);
boolean allowConfigDateTime = isUserConfigAllowed();
@@ -125,7 +131,7 @@ public final class ConfigurationInternal {
} else {
configureAutoDetectionEnabledCapability = CAPABILITY_POSSESSED;
}
- builder.setConfigureAutoDetectionEnabled(configureAutoDetectionEnabledCapability);
+ builder.setConfigureAutoDetectionEnabledCapability(configureAutoDetectionEnabledCapability);
final int configureGeolocationDetectionEnabledCapability;
if (!deviceHasTimeZoneDetection) {
@@ -137,7 +143,8 @@ public final class ConfigurationInternal {
} else {
configureGeolocationDetectionEnabledCapability = CAPABILITY_POSSESSED;
}
- builder.setConfigureGeoDetectionEnabled(configureGeolocationDetectionEnabledCapability);
+ builder.setConfigureGeoDetectionEnabledCapability(
+ configureGeolocationDetectionEnabledCapability);
// The ability to make manual time zone suggestions can also be restricted by policy. With
// the current logic above, this could lead to a situation where a device hardware does not
@@ -151,14 +158,14 @@ public final class ConfigurationInternal {
} else {
suggestManualTimeZoneCapability = CAPABILITY_POSSESSED;
}
- builder.setSuggestManualTimeZone(suggestManualTimeZoneCapability);
+ builder.setSuggestManualTimeZoneCapability(suggestManualTimeZoneCapability);
return builder.build();
}
/** Returns a {@link TimeZoneConfiguration} from the configuration values. */
- public TimeZoneConfiguration asConfiguration() {
- return new TimeZoneConfiguration.Builder(mUserId)
+ private TimeZoneConfiguration asConfiguration() {
+ return new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(getAutoDetectionEnabledSetting())
.setGeoDetectionEnabled(getGeoDetectionEnabledSetting())
.build();
@@ -171,10 +178,10 @@ public final class ConfigurationInternal {
*/
public ConfigurationInternal merge(TimeZoneConfiguration newConfiguration) {
Builder builder = new Builder(this);
- if (newConfiguration.hasSetting(TimeZoneConfiguration.SETTING_AUTO_DETECTION_ENABLED)) {
+ if (newConfiguration.hasIsAutoDetectionEnabled()) {
builder.setAutoDetectionEnabled(newConfiguration.isAutoDetectionEnabled());
}
- if (newConfiguration.hasSetting(TimeZoneConfiguration.SETTING_GEO_DETECTION_ENABLED)) {
+ if (newConfiguration.hasIsGeoDetectionEnabled()) {
builder.setGeoDetectionEnabled(newConfiguration.isGeoDetectionEnabled());
}
return builder.build();
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
index 0a4f5474e4b4..964dbecf705c 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
@@ -23,7 +23,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
-import android.app.timezonedetector.TimeZoneConfiguration;
+import android.app.time.TimeZoneConfiguration;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -159,7 +159,7 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
}
@Override
- public void storeConfiguration(TimeZoneConfiguration configuration) {
+ public void storeConfiguration(@UserIdInt int userId, TimeZoneConfiguration configuration) {
Objects.requireNonNull(configuration);
// Avoid writing the auto detection enabled setting for devices that do not support auto
@@ -171,7 +171,6 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
setAutoDetectionEnabled(autoDetectionEnabled);
if (mGeoDetectionFeatureEnabled) {
- final int userId = configuration.getUserId();
final boolean geoTzDetectionEnabled = configuration.isGeoDetectionEnabled();
setGeoDetectionEnabled(userId, geoTzDetectionEnabled);
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index b72cb546aae4..6e1f89b3919d 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -18,18 +18,19 @@ package com.android.server.timezonedetector;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.timezonedetector.ITimeZoneConfigurationListener;
+import android.app.time.ITimeZoneDetectorListener;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ITimeZoneDetectorService;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.app.timezonedetector.TimeZoneCapabilities;
-import android.app.timezonedetector.TimeZoneConfiguration;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -41,7 +42,6 @@ import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.Objects;
/**
@@ -109,10 +109,14 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
@NonNull
private final TimeZoneDetectorStrategy mTimeZoneDetectorStrategy;
- @GuardedBy("mConfigurationListeners")
+ /**
+ * Holds the listeners. The key is the {@link IBinder} associated with the listener, the value
+ * is the listener itself.
+ */
+ @GuardedBy("mListeners")
@NonNull
- private final ArrayList<ITimeZoneConfigurationListener> mConfigurationListeners =
- new ArrayList<>();
+ private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners =
+ new ArrayMap<>();
private static TimeZoneDetectorService create(
@NonNull Context context, @NonNull Handler handler,
@@ -133,20 +137,22 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
mCallerIdentityInjector = Objects.requireNonNull(callerIdentityInjector);
mTimeZoneDetectorStrategy = Objects.requireNonNull(timeZoneDetectorStrategy);
- // Wire up a change listener so that ITimeZoneConfigurationListeners can be notified when
+ // Wire up a change listener so that ITimeZoneDetectorListeners can be notified when
// the configuration changes for any reason.
mTimeZoneDetectorStrategy.addConfigChangeListener(this::handleConfigurationChanged);
}
@Override
@NonNull
- public TimeZoneCapabilities getCapabilities() {
- enforceManageTimeZoneDetectorConfigurationPermission();
+ public TimeZoneCapabilitiesAndConfig getCapabilitiesAndConfig() {
+ enforceManageTimeZoneDetectorPermission();
int userId = mCallerIdentityInjector.getCallingUserId();
long token = mCallerIdentityInjector.clearCallingIdentity();
try {
- return mTimeZoneDetectorStrategy.getConfigurationInternal(userId).createCapabilities();
+ ConfigurationInternal configurationInternal =
+ mTimeZoneDetectorStrategy.getConfigurationInternal(userId);
+ return configurationInternal.createCapabilitiesAndConfig();
} finally {
mCallerIdentityInjector.restoreCallingIdentity(token);
}
@@ -154,37 +160,34 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
@Override
public boolean updateConfiguration(@NonNull TimeZoneConfiguration configuration) {
- enforceManageTimeZoneDetectorConfigurationPermission();
+ enforceManageTimeZoneDetectorPermission();
Objects.requireNonNull(configuration);
int callingUserId = mCallerIdentityInjector.getCallingUserId();
- if (callingUserId != configuration.getUserId()) {
- return false;
- }
-
long token = mCallerIdentityInjector.clearCallingIdentity();
try {
- return mTimeZoneDetectorStrategy.updateConfiguration(configuration);
+ return mTimeZoneDetectorStrategy.updateConfiguration(callingUserId, configuration);
} finally {
mCallerIdentityInjector.restoreCallingIdentity(token);
}
}
@Override
- public void addConfigurationListener(@NonNull ITimeZoneConfigurationListener listener) {
- enforceManageTimeZoneDetectorConfigurationPermission();
+ public void addListener(@NonNull ITimeZoneDetectorListener listener) {
+ enforceManageTimeZoneDetectorPermission();
Objects.requireNonNull(listener);
- synchronized (mConfigurationListeners) {
- if (mConfigurationListeners.contains(listener)) {
+ synchronized (mListeners) {
+ IBinder listenerBinder = listener.asBinder();
+ if (mListeners.containsKey(listenerBinder)) {
return;
}
try {
// Ensure the reference to the listener will be removed if the client process dies.
- listener.asBinder().linkToDeath(this, 0 /* flags */);
+ listenerBinder.linkToDeath(this, 0 /* flags */);
// Only add the listener if we can linkToDeath().
- mConfigurationListeners.add(listener);
+ mListeners.put(listenerBinder, listener);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to linkToDeath() for listener=" + listener, e);
}
@@ -192,21 +195,22 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
}
@Override
- public void removeConfigurationListener(@NonNull ITimeZoneConfigurationListener listener) {
- enforceManageTimeZoneDetectorConfigurationPermission();
+ public void removeListener(@NonNull ITimeZoneDetectorListener listener) {
+ enforceManageTimeZoneDetectorPermission();
Objects.requireNonNull(listener);
- synchronized (mConfigurationListeners) {
+ synchronized (mListeners) {
+ IBinder listenerBinder = listener.asBinder();
boolean removedListener = false;
- if (mConfigurationListeners.remove(listener)) {
+ if (mListeners.remove(listenerBinder) != null) {
// Stop listening for the client process to die.
- listener.asBinder().unlinkToDeath(this, 0 /* flags */);
+ listenerBinder.unlinkToDeath(this, 0 /* flags */);
removedListener = true;
}
if (!removedListener) {
Slog.w(TAG, "Client asked to remove listener=" + listener
+ ", but no listeners were removed."
- + " mConfigurationListeners=" + mConfigurationListeners);
+ + " mListeners=" + mListeners);
}
}
}
@@ -218,19 +222,18 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
}
/**
- * Called when one of the ITimeZoneConfigurationListener processes dies before calling
- * {@link #removeConfigurationListener(ITimeZoneConfigurationListener)}.
+ * Called when one of the ITimeZoneDetectorListener processes dies before calling
+ * {@link #removeListener(ITimeZoneDetectorListener)}.
*/
@Override
public void binderDied(IBinder who) {
- synchronized (mConfigurationListeners) {
+ synchronized (mListeners) {
boolean removedListener = false;
- final int listenerCount = mConfigurationListeners.size();
+ final int listenerCount = mListeners.size();
for (int listenerIndex = listenerCount - 1; listenerIndex >= 0; listenerIndex--) {
- ITimeZoneConfigurationListener listener =
- mConfigurationListeners.get(listenerIndex);
- if (listener.asBinder().equals(who)) {
- mConfigurationListeners.remove(listenerIndex);
+ IBinder listenerBinder = mListeners.keyAt(listenerIndex);
+ if (listenerBinder.equals(who)) {
+ mListeners.removeAt(listenerIndex);
removedListener = true;
break;
}
@@ -238,7 +241,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
if (!removedListener) {
Slog.w(TAG, "Notified of binder death for who=" + who
+ ", but did not remove any listeners."
- + " mConfigurationListeners=" + mConfigurationListeners);
+ + " mConfigurationListeners=" + mListeners);
}
}
}
@@ -247,11 +250,10 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
// Configuration has changed, but each user may have a different view of the configuration.
// It's possible that this will cause unnecessary notifications but that shouldn't be a
// problem.
- synchronized (mConfigurationListeners) {
- final int listenerCount = mConfigurationListeners.size();
+ synchronized (mListeners) {
+ final int listenerCount = mListeners.size();
for (int listenerIndex = 0; listenerIndex < listenerCount; listenerIndex++) {
- ITimeZoneConfigurationListener listener =
- mConfigurationListeners.get(listenerIndex);
+ ITimeZoneDetectorListener listener = mListeners.valueAt(listenerIndex);
try {
listener.onChange();
} catch (RemoteException e) {
@@ -302,11 +304,10 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
ipw.flush();
}
- private void enforceManageTimeZoneDetectorConfigurationPermission() {
- // TODO Switch to a dedicated MANAGE_TIME_AND_ZONE_CONFIGURATION permission.
+ private void enforceManageTimeZoneDetectorPermission() {
mContext.enforceCallingPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS,
- "manage time and time zone configuration");
+ android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION,
+ "manage time and time zone detection");
}
private void enforceSuggestGeolocationTimeZonePermission() {
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index f944c5638fa9..0b1d6d71ea7b 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -17,9 +17,9 @@ package com.android.server.timezonedetector;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.app.timezonedetector.TimeZoneConfiguration;
import android.util.IndentingPrintWriter;
/**
@@ -96,7 +96,8 @@ public interface TimeZoneDetectorStrategy extends Dumpable, Dumpable.Container {
* <p>This method returns {@code true} if the configuration was changed,
* {@code false} otherwise.
*/
- boolean updateConfiguration(@NonNull TimeZoneConfiguration configuration);
+ boolean updateConfiguration(
+ @UserIdInt int userId, @NonNull TimeZoneConfiguration configuration);
/**
* Suggests zero, one or more time zones for the device, or withdraws a previous suggestion if
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index 743baedb00e1..781668bebbc9 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -15,20 +15,21 @@
*/
package com.android.server.timezonedetector;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.time.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.app.timezonedetector.TimeZoneCapabilities;
-import android.app.timezonedetector.TimeZoneConfiguration;
import android.content.Context;
import android.os.Handler;
import android.util.IndentingPrintWriter;
@@ -93,7 +94,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
* All checks about user capabilities must be done by the caller and
* {@link TimeZoneConfiguration#isComplete()} must be {@code true}.
*/
- void storeConfiguration(TimeZoneConfiguration newConfiguration);
+ void storeConfiguration(@UserIdInt int userId, TimeZoneConfiguration newConfiguration);
}
private static final String LOG_TAG = "TimeZoneDetectorStrategy";
@@ -240,27 +241,26 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
}
@Override
- public synchronized boolean updateConfiguration(
+ public synchronized boolean updateConfiguration(@UserIdInt int userId,
@NonNull TimeZoneConfiguration requestedConfiguration) {
Objects.requireNonNull(requestedConfiguration);
- int userId = requestedConfiguration.getUserId();
- TimeZoneCapabilities capabilities = getConfigurationInternal(userId).createCapabilities();
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ getConfigurationInternal(userId).createCapabilitiesAndConfig();
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ TimeZoneConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();
- // Create a new configuration builder, and copy across the mutable properties users are
- // able to modify. Other properties are therefore ignored.
final TimeZoneConfiguration newConfiguration =
- capabilities.applyUpdate(requestedConfiguration);
+ capabilities.tryApplyConfigChanges(oldConfiguration, requestedConfiguration);
if (newConfiguration == null) {
- // The changes could not be made due to
+ // The changes could not be made because the user's capabilities do not allow it.
return false;
}
// Store the configuration / notify as needed. This will cause the mCallback to invoke
// handleConfigChanged() asynchronously.
- mCallback.storeConfiguration(newConfiguration);
+ mCallback.storeConfiguration(userId, newConfiguration);
- TimeZoneConfiguration oldConfiguration = capabilities.getConfiguration();
String logMsg = "Configuration changed:"
+ " oldConfiguration=" + oldConfiguration
+ ", newConfiguration=" + newConfiguration;
@@ -313,8 +313,10 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
String timeZoneId = suggestion.getZoneId();
String cause = "Manual time suggestion received: suggestion=" + suggestion;
- TimeZoneCapabilities capabilities = getConfigurationInternal(userId).createCapabilities();
- if (capabilities.getSuggestManualTimeZone() != CAPABILITY_POSSESSED) {
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ getConfigurationInternal(userId).createCapabilitiesAndConfig();
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ if (capabilities.getSuggestManualTimeZoneCapability() != CAPABILITY_POSSESSED) {
Slog.i(LOG_TAG, "User does not have the capability needed to set the time zone manually"
+ ", capabilities=" + capabilities
+ ", timeZoneId=" + timeZoneId
@@ -605,7 +607,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
ipw.println("mCallback.getCurrentUserId()=" + currentUserId);
ConfigurationInternal configuration = mCallback.getConfigurationInternal(currentUserId);
ipw.println("mCallback.getConfiguration(currentUserId)=" + configuration);
- ipw.println("[Capabilities=" + configuration.createCapabilities() + "]");
+ ipw.println("[Capabilities=" + configuration.createCapabilitiesAndConfig() + "]");
ipw.println("mCallback.isDeviceTimeZoneInitialized()="
+ mCallback.isDeviceTimeZoneInitialized());
ipw.println("mCallback.getDeviceTimeZone()=" + mCallback.getDeviceTimeZone());
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
index d7ed96fd5833..54b5bee9a6ab 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
@@ -16,22 +16,23 @@
package com.android.server.timezonedetector;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
-import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_POSSESSED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_ALLOWED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_NOT_SUPPORTED;
+import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.app.timezonedetector.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
import org.junit.Test;
/**
- * Tests for {@link ConfigurationInternal} and the {@link TimeZoneCapabilities} and
- * {@link android.app.timezonedetector.TimeZoneConfiguration} that can be generated from it.
+ * Tests for {@link ConfigurationInternal} and the {@link TimeZoneCapabilitiesAndConfig}.
*/
public class ConfigurationInternalTest {
@@ -59,13 +60,20 @@ public class ConfigurationInternalTest {
assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
assertTrue(autoOnConfig.getGeoDetectionEnabledBehavior());
- TimeZoneCapabilities capabilities = autoOnConfig.createCapabilities();
- assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureAutoDetectionEnabled());
- assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureGeoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_APPLICABLE, capabilities.getSuggestManualTimeZone());
- assertEquals(autoOnConfig.asConfiguration(), capabilities.getConfiguration());
- assertTrue(capabilities.getConfiguration().isAutoDetectionEnabled());
- assertTrue(capabilities.getConfiguration().isGeoDetectionEnabled());
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ autoOnConfig.createCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getConfigureGeoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_APPLICABLE,
+ capabilities.getSuggestManualTimeZoneCapability());
+
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertTrue(configuration.isAutoDetectionEnabled());
+ assertTrue(configuration.isGeoDetectionEnabled());
}
{
@@ -77,13 +85,20 @@ public class ConfigurationInternalTest {
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
assertFalse(autoOffConfig.getGeoDetectionEnabledBehavior());
- TimeZoneCapabilities capabilities = autoOffConfig.createCapabilities();
- assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureAutoDetectionEnabled());
- assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureGeoDetectionEnabled());
- assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone());
- assertEquals(autoOffConfig.asConfiguration(), capabilities.getConfiguration());
- assertFalse(capabilities.getConfiguration().isAutoDetectionEnabled());
- assertTrue(capabilities.getConfiguration().isGeoDetectionEnabled());
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ autoOffConfig.createCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getConfigureGeoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED,
+ capabilities.getSuggestManualTimeZoneCapability());
+
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertFalse(configuration.isAutoDetectionEnabled());
+ assertTrue(configuration.isGeoDetectionEnabled());
}
}
@@ -106,13 +121,20 @@ public class ConfigurationInternalTest {
assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
assertTrue(autoOnConfig.getGeoDetectionEnabledBehavior());
- TimeZoneCapabilities capabilities = autoOnConfig.createCapabilities();
- assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureAutoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureGeoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeZone());
- assertEquals(autoOnConfig.asConfiguration(), capabilities.getConfiguration());
- assertTrue(capabilities.getConfiguration().isAutoDetectionEnabled());
- assertTrue(capabilities.getConfiguration().isGeoDetectionEnabled());
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ autoOnConfig.createCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getConfigureGeoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getSuggestManualTimeZoneCapability());
+
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertTrue(configuration.isAutoDetectionEnabled());
+ assertTrue(configuration.isGeoDetectionEnabled());
}
{
@@ -124,13 +146,20 @@ public class ConfigurationInternalTest {
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
assertFalse(autoOffConfig.getGeoDetectionEnabledBehavior());
- TimeZoneCapabilities capabilities = autoOffConfig.createCapabilities();
- assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureAutoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureGeoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeZone());
- assertEquals(autoOffConfig.asConfiguration(), capabilities.getConfiguration());
- assertFalse(capabilities.getConfiguration().isAutoDetectionEnabled());
- assertTrue(capabilities.getConfiguration().isGeoDetectionEnabled());
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ autoOffConfig.createCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getConfigureGeoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_ALLOWED,
+ capabilities.getSuggestManualTimeZoneCapability());
+
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertFalse(configuration.isAutoDetectionEnabled());
+ assertTrue(configuration.isGeoDetectionEnabled());
}
}
@@ -153,13 +182,19 @@ public class ConfigurationInternalTest {
assertFalse(autoOnConfig.getAutoDetectionEnabledBehavior());
assertFalse(autoOnConfig.getGeoDetectionEnabledBehavior());
- TimeZoneCapabilities capabilities = autoOnConfig.createCapabilities();
- assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureAutoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureGeoDetectionEnabled());
- assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone());
- assertEquals(autoOnConfig.asConfiguration(), capabilities.getConfiguration());
- assertTrue(capabilities.getConfiguration().isAutoDetectionEnabled());
- assertTrue(capabilities.getConfiguration().isGeoDetectionEnabled());
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ autoOnConfig.createCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_SUPPORTED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_SUPPORTED,
+ capabilities.getConfigureGeoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZoneCapability());
+
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertTrue(configuration.isAutoDetectionEnabled());
+ assertTrue(configuration.isGeoDetectionEnabled());
}
{
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
@@ -170,13 +205,19 @@ public class ConfigurationInternalTest {
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
assertFalse(autoOffConfig.getGeoDetectionEnabledBehavior());
- TimeZoneCapabilities capabilities = autoOffConfig.createCapabilities();
- assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureAutoDetectionEnabled());
- assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureGeoDetectionEnabled());
- assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone());
- assertEquals(autoOffConfig.asConfiguration(), capabilities.getConfiguration());
- assertFalse(capabilities.getConfiguration().isAutoDetectionEnabled());
- assertTrue(capabilities.getConfiguration().isGeoDetectionEnabled());
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ autoOffConfig.createCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ assertEquals(CAPABILITY_NOT_SUPPORTED,
+ capabilities.getConfigureAutoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_NOT_SUPPORTED,
+ capabilities.getConfigureGeoDetectionEnabledCapability());
+ assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZoneCapability());
+
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ assertFalse(configuration.isAutoDetectionEnabled());
+ assertTrue(configuration.isGeoDetectionEnabled());
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
index 4ef20829f2dc..bad380acf4b3 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
@@ -22,10 +22,11 @@ import static org.junit.Assert.fail;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
+import android.app.time.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.app.timezonedetector.TimeZoneCapabilities;
-import android.app.timezonedetector.TimeZoneConfiguration;
import android.util.IndentingPrintWriter;
import java.util.ArrayList;
@@ -67,20 +68,25 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
}
@Override
- public boolean updateConfiguration(@NonNull TimeZoneConfiguration requestedChanges) {
+ public boolean updateConfiguration(
+ @UserIdInt int userID, @NonNull TimeZoneConfiguration requestedChanges) {
assertNotNull(mConfigurationInternal);
assertNotNull(requestedChanges);
// Simulate the real strategy's behavior: the new configuration will be updated to be the
// old configuration merged with the new if the user has the capability to up the settings.
// Then, if the configuration changed, the change listener is invoked.
- TimeZoneCapabilities capabilities = mConfigurationInternal.createCapabilities();
- TimeZoneConfiguration newConfiguration = capabilities.applyUpdate(requestedChanges);
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ mConfigurationInternal.createCapabilitiesAndConfig();
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+ TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+ TimeZoneConfiguration newConfiguration =
+ capabilities.tryApplyConfigChanges(configuration, requestedChanges);
if (newConfiguration == null) {
return false;
}
- if (!newConfiguration.equals(capabilities.getConfiguration())) {
+ if (!newConfiguration.equals(capabilitiesAndConfig.getConfiguration())) {
mConfigurationInternal = mConfigurationInternal.merge(newConfiguration);
// Note: Unlike the real strategy, the listeners is invoked synchronously.
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index 27b04b6ab17d..cb27657f8364 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -31,10 +31,10 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import android.app.timezonedetector.ITimeZoneConfigurationListener;
+import android.app.time.ITimeZoneDetectorListener;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.app.timezonedetector.TimeZoneConfiguration;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.HandlerThread;
@@ -91,85 +91,85 @@ public class TimeZoneDetectorServiceTest {
}
@Test(expected = SecurityException.class)
- public void testGetCapabilities_withoutPermission() {
+ public void testGetCapabilitiesAndConfig_withoutPermission() {
doThrow(new SecurityException("Mock"))
.when(mMockContext).enforceCallingPermission(anyString(), any());
try {
- mTimeZoneDetectorService.getCapabilities();
+ mTimeZoneDetectorService.getCapabilitiesAndConfig();
fail();
} finally {
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
}
}
@Test
- public void testGetCapabilities() {
+ public void testGetCapabilitiesAndConfig() {
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
ConfigurationInternal configuration =
createConfigurationInternal(true /* autoDetectionEnabled*/);
mFakeTimeZoneDetectorStrategy.initializeConfiguration(configuration);
- assertEquals(configuration.createCapabilities(),
- mTimeZoneDetectorService.getCapabilities());
+ assertEquals(configuration.createCapabilitiesAndConfig(),
+ mTimeZoneDetectorService.getCapabilitiesAndConfig());
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
}
@Test(expected = SecurityException.class)
- public void testAddConfigurationListener_withoutPermission() {
+ public void testAddListener_withoutPermission() {
doThrow(new SecurityException("Mock"))
.when(mMockContext).enforceCallingPermission(anyString(), any());
- ITimeZoneConfigurationListener mockListener = mock(ITimeZoneConfigurationListener.class);
+ ITimeZoneDetectorListener mockListener = mock(ITimeZoneDetectorListener.class);
try {
- mTimeZoneDetectorService.addConfigurationListener(mockListener);
+ mTimeZoneDetectorService.addListener(mockListener);
fail();
} finally {
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
}
}
@Test(expected = SecurityException.class)
- public void testRemoveConfigurationListener_withoutPermission() {
+ public void testRemoveListener_withoutPermission() {
doThrow(new SecurityException("Mock"))
.when(mMockContext).enforceCallingPermission(anyString(), any());
- ITimeZoneConfigurationListener mockListener = mock(ITimeZoneConfigurationListener.class);
+ ITimeZoneDetectorListener mockListener = mock(ITimeZoneDetectorListener.class);
try {
- mTimeZoneDetectorService.removeConfigurationListener(mockListener);
+ mTimeZoneDetectorService.removeListener(mockListener);
fail("Expected a SecurityException");
} finally {
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
}
}
@Test
- public void testConfigurationChangeListenerRegistrationAndCallbacks() throws Exception {
+ public void testListenerRegistrationAndCallbacks() throws Exception {
ConfigurationInternal initialConfiguration =
createConfigurationInternal(false /* autoDetectionEnabled */);
mFakeTimeZoneDetectorStrategy.initializeConfiguration(initialConfiguration);
IBinder mockListenerBinder = mock(IBinder.class);
- ITimeZoneConfigurationListener mockListener = mock(ITimeZoneConfigurationListener.class);
+ ITimeZoneDetectorListener mockListener = mock(ITimeZoneDetectorListener.class);
{
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
when(mockListener.asBinder()).thenReturn(mockListenerBinder);
- mTimeZoneDetectorService.addConfigurationListener(mockListener);
+ mTimeZoneDetectorService.addListener(mockListener);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
verify(mockListener).asBinder();
verify(mockListenerBinder).linkToDeath(any(), anyInt());
@@ -186,7 +186,7 @@ public class TimeZoneDetectorServiceTest {
mTimeZoneDetectorService.updateConfiguration(autoDetectEnabledConfiguration);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
verify(mockListener).onChange();
verifyNoMoreInteractions(mockListenerBinder, mockListener, mMockContext);
@@ -200,10 +200,10 @@ public class TimeZoneDetectorServiceTest {
// Now remove the listener, change the config again, and verify the listener is not
// called.
- mTimeZoneDetectorService.removeConfigurationListener(mockListener);
+ mTimeZoneDetectorService.removeListener(mockListener);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
verify(mockListener).asBinder();
verify(mockListenerBinder).unlinkToDeath(any(), eq(0));
@@ -219,7 +219,7 @@ public class TimeZoneDetectorServiceTest {
mTimeZoneDetectorService.updateConfiguration(autoDetectDisabledConfiguration);
verify(mMockContext).enforceCallingPermission(
- eq(android.Manifest.permission.WRITE_SECURE_SETTINGS),
+ eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
anyString());
verify(mockListener, never()).onChange();
verifyNoMoreInteractions(mockListenerBinder, mockListener, mMockContext);
@@ -354,7 +354,7 @@ public class TimeZoneDetectorServiceTest {
}
private static TimeZoneConfiguration createTimeZoneConfiguration(boolean autoDetectionEnabled) {
- return new TimeZoneConfiguration.Builder(ARBITRARY_USER_ID)
+ return new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(autoDetectionEnabled)
.build();
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index 1cdf19319209..296aa73f9c45 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -39,11 +39,11 @@ import static org.junit.Assert.fail;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
-import android.app.timezonedetector.TimeZoneConfiguration;
import android.util.IndentingPrintWriter;
import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
@@ -186,26 +186,27 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
// Set the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, true /* expectedResult */);
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
// Nothing should have happened: it was initialized in this state.
script.verifyConfigurationNotChanged();
// Update the configuration with auto detection disabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_DISABLED, true /* expectedResult */);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */);
// The settings should have been changed and the StrategyListener onChange() called.
script.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED);
// Update the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, true /* expectedResult */);
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
// The settings should have been changed and the StrategyListener onChange() called.
script.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
// Update the configuration to enable geolocation time zone detection.
script.simulateUpdateConfiguration(
- CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */);
+ USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */);
// The settings should have been changed and the StrategyListener onChange() called.
script.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED);
@@ -216,20 +217,22 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script().initializeConfig(CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED);
// Try to update the configuration with auto detection disabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_DISABLED, false /* expectedResult */);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
// Update the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, false /* expectedResult */);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
// Try to update the configuration to enable geolocation time zone detection.
script.simulateUpdateConfiguration(
- CONFIG_GEO_DETECTION_ENABLED, false /* expectedResult */);
+ USER_ID, CONFIG_GEO_DETECTION_ENABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
@@ -240,13 +243,15 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script().initializeConfig(CONFIG_INT_AUTO_DETECT_NOT_SUPPORTED);
// Try to update the configuration with auto detection disabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_DISABLED, false /* expectedResult */);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
// Update the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, false /* expectedResult */);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
@@ -389,7 +394,8 @@ public class TimeZoneDetectorStrategyImplTest {
mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Toggling the time zone setting on should cause the device setting to be set.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, true /* expectedResult */);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
// When time zone detection is already enabled the suggestion (if it scores highly
// enough) should be set immediately.
@@ -406,7 +412,8 @@ public class TimeZoneDetectorStrategyImplTest {
mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Toggling the time zone setting should off should do nothing.
- script.simulateUpdateConfiguration(CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged();
// Assert internal service state.
@@ -588,18 +595,20 @@ public class TimeZoneDetectorStrategyImplTest {
// Toggling time zone detection should set the device time zone only if the current setting
// value is different from the most recent telephony suggestion.
- script.simulateUpdateConfiguration(CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged()
- .simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged();
// Simulate a user turning auto detection off, a new suggestion being made while auto
// detection is off, and the user turning it on again.
- script.simulateUpdateConfiguration(CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
.simulateTelephonyTimeZoneSuggestion(newYorkSuggestion)
.verifyTimeZoneNotChanged();
// Latest suggestion should be used.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(newYorkSuggestion);
}
@@ -784,7 +793,7 @@ public class TimeZoneDetectorStrategyImplTest {
assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
// Turn off geo detection and verify the latest suggestion is cleared.
- script.simulateUpdateConfiguration(CONFIG_GEO_DETECTION_DISABLED, true)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_GEO_DETECTION_DISABLED, true)
.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
// Assert internal service state.
@@ -824,19 +833,21 @@ public class TimeZoneDetectorStrategyImplTest {
// Toggling the time zone detection enabled setting on should cause the device setting to be
// set from the telephony signal, as we've started with geolocation time zone detection
// disabled.
- script.simulateUpdateConfiguration(CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(telephonySuggestion);
// Changing the detection to enable geo detection won't cause the device tz setting to
// change because the geo suggestion is empty.
- script.simulateUpdateConfiguration(CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged()
.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
.verifyTimeZoneChangedAndReset(geolocationSuggestion.getZoneIds().get(0));
// Changing the detection to disable geo detection should cause the device tz setting to
// change to the telephony suggestion.
- script.simulateUpdateConfiguration(CONFIG_GEO_DETECTION_DISABLED, true /* expectedResult */)
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_GEO_DETECTION_DISABLED, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(telephonySuggestion);
assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -898,7 +909,7 @@ public class TimeZoneDetectorStrategyImplTest {
private static TimeZoneConfiguration createConfig(
@Nullable Boolean autoDetection, @Nullable Boolean geoDetection) {
- TimeZoneConfiguration.Builder builder = new TimeZoneConfiguration.Builder(USER_ID);
+ TimeZoneConfiguration.Builder builder = new TimeZoneConfiguration.Builder();
if (autoDetection != null) {
builder.setAutoDetectionEnabled(autoDetection);
}
@@ -957,9 +968,10 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Override
- public void storeConfiguration(TimeZoneConfiguration newConfiguration) {
+ public void storeConfiguration(
+ @UserIdInt int userId, TimeZoneConfiguration newConfiguration) {
ConfigurationInternal oldConfiguration = mConfigurationInternal.getLatest();
- if (newConfiguration.getUserId() != oldConfiguration.getUserId()) {
+ if (userId != oldConfiguration.getUserId()) {
fail("FakeCallback does not support multiple users");
}
@@ -1014,9 +1026,9 @@ public class TimeZoneDetectorStrategyImplTest {
* the return value.
*/
Script simulateUpdateConfiguration(
- TimeZoneConfiguration configuration, boolean expectedResult) {
+ int userId, TimeZoneConfiguration configuration, boolean expectedResult) {
assertEquals(expectedResult,
- mTimeZoneDetectorStrategy.updateConfiguration(configuration));
+ mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration));
return this;
}