summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2020-09-30 14:46:11 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-09-30 14:46:11 +0000
commite23fca65cd63c96fe31bd84a06d3095fcef5b412 (patch)
tree9ab463517a6a2fb0f1969dd4b0380042aec715e8 /core/java/android
parentb3e2b63d91c20345c279f9cbd257167efba23383 (diff)
parent02d943f44d4ed11a7cde1fa33a4c0c07b9cb7e3c (diff)
Merge "Get ready to add System APIs for use by SUW"
Diffstat (limited to 'core/java/android')
-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
14 files changed, 550 insertions, 318 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
*/