Add time related API to TimeManager.
It copies time zone API to keep in consistent. Bug: 172891783 Test: atest services/tests/servicestests/src/com/android/server/timedetector/* Change-Id: Id32745540483eafe8292a0de2221e6a7ff22cc84
This commit is contained in:
@@ -1695,6 +1695,13 @@ package android.app.smartspace {
|
||||
|
||||
package android.app.time {
|
||||
|
||||
public final class Capabilities {
|
||||
field public static final int CAPABILITY_NOT_ALLOWED = 20; // 0x14
|
||||
field public static final int CAPABILITY_NOT_APPLICABLE = 30; // 0x1e
|
||||
field public static final int CAPABILITY_NOT_SUPPORTED = 10; // 0xa
|
||||
field public static final int CAPABILITY_POSSESSED = 40; // 0x28
|
||||
}
|
||||
|
||||
public final class TimeManager {
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void addTimeZoneDetectorListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public android.app.time.TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig();
|
||||
@@ -1711,10 +1718,6 @@ package android.app.time {
|
||||
method public int getConfigureAutoDetectionEnabledCapability();
|
||||
method public int getConfigureGeoDetectionEnabledCapability();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field public static final int CAPABILITY_NOT_ALLOWED = 20; // 0x14
|
||||
field public static final int CAPABILITY_NOT_APPLICABLE = 30; // 0x1e
|
||||
field public static final int CAPABILITY_NOT_SUPPORTED = 10; // 0xa
|
||||
field public static final int CAPABILITY_POSSESSED = 40; // 0x28
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneCapabilities> CREATOR;
|
||||
}
|
||||
|
||||
|
||||
78
core/java/android/app/time/Capabilities.java
Normal file
78
core/java/android/app/time/Capabilities.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.IntDef;
|
||||
import android.annotation.SystemApi;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* A capability is the ability for the user to configure something or perform an action. This
|
||||
* information is exposed so that system apps like SettingsUI can be dynamic, rather than
|
||||
* hard-coding knowledge of when configuration or actions are applicable / available to the user.
|
||||
*
|
||||
* <p>Capabilities have states that users cannot change directly. They may influence some
|
||||
* capabilities indirectly by agreeing to certain device-wide behaviors such as location sharing, or
|
||||
* by changing the configuration. See the {@code CAPABILITY_} constants for details.
|
||||
*
|
||||
* <p>Actions have associated methods, see the documentation for each action for details.
|
||||
*
|
||||
* <p>Note: Capabilities are independent of app permissions required to call the associated APIs.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class Capabilities {
|
||||
|
||||
/** @hide */
|
||||
@IntDef({ CAPABILITY_NOT_SUPPORTED, CAPABILITY_NOT_ALLOWED, CAPABILITY_NOT_APPLICABLE,
|
||||
CAPABILITY_POSSESSED })
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CapabilityState {}
|
||||
|
||||
/**
|
||||
* Indicates that a capability is not supported on this device, e.g. because of form factor or
|
||||
* hardware. The associated UI should usually not be shown to the user.
|
||||
*/
|
||||
public static final int CAPABILITY_NOT_SUPPORTED = 10;
|
||||
|
||||
/**
|
||||
* Indicates that a capability is supported on this device, but not allowed for the user, e.g.
|
||||
* if the capability relates to the ability to modify settings the user is not able to.
|
||||
* This could be because of the user's type (e.g. maybe it applies to the primary user only) or
|
||||
* device policy. Depending on the capability, this could mean the associated UI
|
||||
* should be hidden, or displayed but disabled.
|
||||
*/
|
||||
public static final int CAPABILITY_NOT_ALLOWED = 20;
|
||||
|
||||
/**
|
||||
* Indicates that a capability is possessed but not currently applicable, e.g. if the
|
||||
* capability relates to the ability to modify settings, the user has the ability to modify
|
||||
* it, but it is currently rendered irrelevant by other settings or other device state (flags,
|
||||
* resource config, etc.). The associated UI may be hidden, disabled, or left visible (but
|
||||
* ineffective) depending on requirements.
|
||||
*/
|
||||
public static final int CAPABILITY_NOT_APPLICABLE = 30;
|
||||
|
||||
/** Indicates that a capability is possessed by the user. */
|
||||
public static final int CAPABILITY_POSSESSED = 40;
|
||||
|
||||
private Capabilities() {}
|
||||
|
||||
}
|
||||
19
core/java/android/app/time/TimeCapabilities.aidl
Normal file
19
core/java/android/app/time/TimeCapabilities.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 TimeCapabilities;
|
||||
186
core/java/android/app/time/TimeCapabilities.java
Normal file
186
core/java/android/app/time/TimeCapabilities.java
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.app.time.Capabilities.CapabilityState;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Time-relate capabilities for a user.
|
||||
*
|
||||
* <p>For configuration settings capabilities, the associated settings value can be found via
|
||||
* {@link TimeManager#getTimeCapabilitiesAndConfig()} and may be changed using {@link
|
||||
* TimeManager#updateTimeConfiguration(TimeConfiguration)} (if the user's capabilities
|
||||
* allow).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class TimeCapabilities implements Parcelable {
|
||||
|
||||
public static final @NonNull Creator<TimeCapabilities> CREATOR =
|
||||
new Creator<TimeCapabilities>() {
|
||||
public TimeCapabilities createFromParcel(Parcel in) {
|
||||
return TimeCapabilities.createFromParcel(in);
|
||||
}
|
||||
|
||||
public TimeCapabilities[] newArray(int size) {
|
||||
return new TimeCapabilities[size];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 mConfigureAutoTimeDetectionEnabledCapability;
|
||||
private final @CapabilityState int mSuggestTimeManuallyCapability;
|
||||
|
||||
private TimeCapabilities(@NonNull Builder builder) {
|
||||
this.mUserHandle = Objects.requireNonNull(builder.mUserHandle);
|
||||
this.mConfigureAutoTimeDetectionEnabledCapability =
|
||||
builder.mConfigureAutoDetectionEnabledCapability;
|
||||
this.mSuggestTimeManuallyCapability =
|
||||
builder.mSuggestTimeManuallyCapability;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static TimeCapabilities createFromParcel(Parcel in) {
|
||||
UserHandle userHandle = UserHandle.readFromParcel(in);
|
||||
return new TimeCapabilities.Builder(userHandle)
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(in.readInt())
|
||||
.setSuggestTimeManuallyCapability(in.readInt())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
UserHandle.writeToParcel(mUserHandle, dest);
|
||||
dest.writeInt(mConfigureAutoTimeDetectionEnabledCapability);
|
||||
dest.writeInt(mSuggestTimeManuallyCapability);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the capability state associated with the user's ability to modify the automatic time
|
||||
* detection setting.
|
||||
*/
|
||||
@CapabilityState
|
||||
public int getConfigureAutoTimeDetectionEnabledCapability() {
|
||||
return mConfigureAutoTimeDetectionEnabledCapability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the capability state associated with the user's ability to manually set time on a
|
||||
* device.
|
||||
*/
|
||||
@CapabilityState
|
||||
public int getSuggestTimeManuallyCapability() {
|
||||
return mSuggestTimeManuallyCapability;
|
||||
}
|
||||
|
||||
@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;
|
||||
TimeCapabilities that = (TimeCapabilities) o;
|
||||
return mConfigureAutoTimeDetectionEnabledCapability
|
||||
== that.mConfigureAutoTimeDetectionEnabledCapability
|
||||
&& mSuggestTimeManuallyCapability == that.mSuggestTimeManuallyCapability
|
||||
&& mUserHandle.equals(that.mUserHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUserHandle, mConfigureAutoTimeDetectionEnabledCapability,
|
||||
mSuggestTimeManuallyCapability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeCapabilities{"
|
||||
+ "mUserHandle=" + mUserHandle
|
||||
+ ", mConfigureAutoTimeDetectionEnabledCapability="
|
||||
+ mConfigureAutoTimeDetectionEnabledCapability
|
||||
+ ", mSuggestTimeManuallyCapability=" + mSuggestTimeManuallyCapability
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder of {@link TimeCapabilities} objects.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static class Builder {
|
||||
@NonNull private final UserHandle mUserHandle;
|
||||
private @CapabilityState int mConfigureAutoDetectionEnabledCapability;
|
||||
private @CapabilityState int mSuggestTimeManuallyCapability;
|
||||
|
||||
public Builder(@NonNull TimeCapabilities timeCapabilities) {
|
||||
Objects.requireNonNull(timeCapabilities);
|
||||
this.mUserHandle = timeCapabilities.mUserHandle;
|
||||
this.mConfigureAutoDetectionEnabledCapability =
|
||||
timeCapabilities.mConfigureAutoTimeDetectionEnabledCapability;
|
||||
this.mSuggestTimeManuallyCapability =
|
||||
timeCapabilities.mSuggestTimeManuallyCapability;
|
||||
}
|
||||
|
||||
public Builder(@NonNull UserHandle userHandle) {
|
||||
this.mUserHandle = Objects.requireNonNull(userHandle);
|
||||
}
|
||||
|
||||
/** Sets the state for automatic time detection config. */
|
||||
public Builder setConfigureAutoTimeDetectionEnabledCapability(
|
||||
@CapabilityState int setConfigureAutoTimeDetectionEnabledCapability) {
|
||||
this.mConfigureAutoDetectionEnabledCapability =
|
||||
setConfigureAutoTimeDetectionEnabledCapability;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the state for manual time change. */
|
||||
public Builder setSuggestTimeManuallyCapability(
|
||||
@CapabilityState int suggestTimeManuallyCapability) {
|
||||
this.mSuggestTimeManuallyCapability = suggestTimeManuallyCapability;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns the {@link TimeCapabilities}. */
|
||||
public TimeCapabilities build() {
|
||||
verifyCapabilitySet(mConfigureAutoDetectionEnabledCapability,
|
||||
"configureAutoDetectionEnabledCapability");
|
||||
verifyCapabilitySet(mSuggestTimeManuallyCapability, "suggestTimeManuallyCapability");
|
||||
return new TimeCapabilities(this);
|
||||
}
|
||||
|
||||
private void verifyCapabilitySet(int value, String name) {
|
||||
if (value == 0) {
|
||||
throw new IllegalStateException(name + " was not set");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
core/java/android/app/time/TimeCapabilitiesAndConfig.aidl
Normal file
19
core/java/android/app/time/TimeCapabilitiesAndConfig.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 TimeCapabilitiesAndConfig;
|
||||
119
core/java/android/app/time/TimeCapabilitiesAndConfig.java
Normal file
119
core/java/android/app/time/TimeCapabilitiesAndConfig.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 TimeCapabilities} and {@link TimeConfiguration}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class TimeCapabilitiesAndConfig implements Parcelable {
|
||||
|
||||
public static final @NonNull Creator<TimeCapabilitiesAndConfig> CREATOR =
|
||||
new Creator<TimeCapabilitiesAndConfig>() {
|
||||
@Override
|
||||
public TimeCapabilitiesAndConfig createFromParcel(Parcel source) {
|
||||
return TimeCapabilitiesAndConfig.readFromParcel(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeCapabilitiesAndConfig[] newArray(int size) {
|
||||
return new TimeCapabilitiesAndConfig[size];
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private final TimeCapabilities mTimeCapabilities;
|
||||
|
||||
@NonNull
|
||||
private final TimeConfiguration mTimeConfiguration;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public TimeCapabilitiesAndConfig(@NonNull TimeCapabilities timeCapabilities,
|
||||
@NonNull TimeConfiguration timeConfiguration) {
|
||||
mTimeCapabilities = Objects.requireNonNull(timeCapabilities);
|
||||
mTimeConfiguration = Objects.requireNonNull(timeConfiguration);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static TimeCapabilitiesAndConfig readFromParcel(Parcel in) {
|
||||
TimeCapabilities capabilities = in.readParcelable(null);
|
||||
TimeConfiguration configuration = in.readParcelable(null);
|
||||
return new TimeCapabilitiesAndConfig(capabilities, configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's time behaviour capabilities.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public TimeCapabilities getTimeCapabilities() {
|
||||
return mTimeCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's time behaviour configuration.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public TimeConfiguration getTimeConfiguration() {
|
||||
return mTimeConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeParcelable(mTimeCapabilities, flags);
|
||||
dest.writeParcelable(mTimeConfiguration, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TimeCapabilitiesAndConfig that = (TimeCapabilitiesAndConfig) o;
|
||||
return mTimeCapabilities.equals(that.mTimeCapabilities)
|
||||
&& mTimeConfiguration.equals(that.mTimeConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mTimeCapabilities, mTimeConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeCapabilitiesAndConfig{"
|
||||
+ "mTimeCapabilities=" + mTimeCapabilities
|
||||
+ ", mTimeConfiguration=" + mTimeConfiguration
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
19
core/java/android/app/time/TimeConfiguration.aidl
Normal file
19
core/java/android/app/time/TimeConfiguration.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 TimeConfiguration;
|
||||
141
core/java/android/app/time/TimeConfiguration.java
Normal file
141
core/java/android/app/time/TimeConfiguration.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.StringDef;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* User visible settings that control the behavior of the time zone detector / manual time zone
|
||||
* entry.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class TimeConfiguration implements Parcelable {
|
||||
|
||||
public static final @NonNull Creator<TimeConfiguration> CREATOR =
|
||||
new Creator<TimeConfiguration>() {
|
||||
@Override
|
||||
public TimeConfiguration createFromParcel(Parcel source) {
|
||||
return TimeConfiguration.readFromParcel(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeConfiguration[] newArray(int size) {
|
||||
return new TimeConfiguration[size];
|
||||
}
|
||||
};
|
||||
|
||||
@StringDef(SETTING_AUTO_DETECTION_ENABLED)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface Setting {}
|
||||
|
||||
@Setting
|
||||
private static final String SETTING_AUTO_DETECTION_ENABLED = "autoDetectionEnabled";
|
||||
|
||||
@NonNull
|
||||
private final Bundle mBundle;
|
||||
|
||||
private TimeConfiguration(Builder builder) {
|
||||
this.mBundle = builder.mBundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting. This
|
||||
* controls whether a device will attempt to determine the time automatically using
|
||||
* contextual information if the device supports auto detection.
|
||||
*/
|
||||
public boolean isAutoDetectionEnabled() {
|
||||
return mBundle.getBoolean(SETTING_AUTO_DETECTION_ENABLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeBundle(mBundle);
|
||||
}
|
||||
|
||||
private static TimeConfiguration readFromParcel(Parcel in) {
|
||||
return new TimeConfiguration.Builder()
|
||||
.merge(in.readBundle())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TimeConfiguration that = (TimeConfiguration) o;
|
||||
return mBundle.kindofEquals(that.mBundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mBundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeConfiguration{"
|
||||
+ "mBundle=" + mBundle
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link TimeConfiguration} objects.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final class Builder {
|
||||
private final Bundle mBundle = new Bundle();
|
||||
|
||||
public Builder() {}
|
||||
|
||||
public Builder(@NonNull TimeConfiguration configuration) {
|
||||
mBundle.putAll(configuration.mBundle);
|
||||
}
|
||||
|
||||
/** Sets whether auto detection is enabled or not. */
|
||||
@NonNull
|
||||
public Builder setAutoDetectionEnabled(boolean enabled) {
|
||||
mBundle.putBoolean(SETTING_AUTO_DETECTION_ENABLED, enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder merge(@NonNull Bundle bundle) {
|
||||
mBundle.putAll(bundle);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns {@link TimeConfiguration} object. */
|
||||
@NonNull
|
||||
public TimeConfiguration build() {
|
||||
return new TimeConfiguration(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public final class TimeManager {
|
||||
@NonNull
|
||||
public TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "getTimeZoneCapabilities called");
|
||||
Log.d(TAG, "getTimeZoneCapabilitiesAndConfig called");
|
||||
}
|
||||
try {
|
||||
return mITimeZoneDetectorService.getCapabilitiesAndConfig();
|
||||
@@ -84,6 +84,44 @@ public final class TimeManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the calling user's time capabilities and configuration.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
|
||||
@NonNull
|
||||
public TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "getTimeCapabilitiesAndConfig called");
|
||||
}
|
||||
try {
|
||||
return mITimeDetectorService.getCapabilitiesAndConfig();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the time detection configuration.
|
||||
*
|
||||
* @return {@code true} if all the configuration settings specified have been set to the
|
||||
* new values, {@code false} if none have
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
|
||||
public boolean updateTimeConfiguration(@NonNull TimeConfiguration configuration) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "updateTimeConfiguration called: " + configuration);
|
||||
}
|
||||
try {
|
||||
return mITimeDetectorService.updateConfiguration(configuration);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the time zone detection configuration.
|
||||
*
|
||||
@@ -97,11 +135,11 @@ public final class TimeManager {
|
||||
* 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}
|
||||
* Capabilities#CAPABILITY_NOT_SUPPORTED} or {@link
|
||||
* Capabilities#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
|
||||
* Capabilities#CAPABILITY_NOT_APPLICABLE} or {@link
|
||||
* Capabilities#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
|
||||
|
||||
@@ -16,77 +16,33 @@
|
||||
|
||||
package android.app.time;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.app.time.Capabilities.CapabilityState;
|
||||
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;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Time zone-related capabilities for a user. A capability is the ability for the user to configure
|
||||
* something or perform an action. This information is exposed so that system apps like SettingsUI
|
||||
* can be dynamic, rather than hard-coding knowledge of when configuration or actions are applicable
|
||||
* / available to the user.
|
||||
*
|
||||
* <p>Capabilities have states that users cannot change directly. They may influence some
|
||||
* capabilities indirectly by agreeing to certain device-wide behaviors such as location sharing, or
|
||||
* by changing the configuration. See the {@code CAPABILITY_} constants for details.
|
||||
*
|
||||
* <p>Actions have associated methods, see the documentation for each action for details.
|
||||
* Time zone-related capabilities for a user.
|
||||
*
|
||||
* <p>For configuration settings capabilities, the associated settings value can be found via
|
||||
* {@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)
|
||||
public @interface CapabilityState {}
|
||||
|
||||
/**
|
||||
* Indicates that a capability is not supported on this device, e.g. because of form factor or
|
||||
* hardware. The associated UI should usually not be shown to the user.
|
||||
*/
|
||||
public static final int CAPABILITY_NOT_SUPPORTED = 10;
|
||||
|
||||
/**
|
||||
* Indicates that a capability is supported on this device, but not allowed for the user, e.g.
|
||||
* if the capability relates to the ability to modify settings the user is not able to.
|
||||
* This could be because of the user's type (e.g. maybe it applies to the primary user only) or
|
||||
* device policy. Depending on the capability, this could mean the associated UI
|
||||
* should be hidden, or displayed but disabled.
|
||||
*/
|
||||
public static final int CAPABILITY_NOT_ALLOWED = 20;
|
||||
|
||||
/**
|
||||
* Indicates that a capability is possessed but not currently applicable, e.g. if the
|
||||
* capability relates to the ability to modify settings, the user has the ability to modify
|
||||
* it, but it is currently rendered irrelevant by other settings or other device state (flags,
|
||||
* resource config, etc.). The associated UI may be hidden, disabled, or left visible (but
|
||||
* ineffective) depending on requirements.
|
||||
*/
|
||||
public static final int CAPABILITY_NOT_APPLICABLE = 30;
|
||||
|
||||
/** Indicates that a capability is possessed by the user. */
|
||||
public static final int CAPABILITY_POSSESSED = 40;
|
||||
|
||||
public static final @NonNull Creator<TimeZoneCapabilities> CREATOR =
|
||||
new Creator<TimeZoneCapabilities>() {
|
||||
public TimeZoneCapabilities createFromParcel(Parcel in) {
|
||||
@@ -159,7 +115,8 @@ public final class TimeZoneCapabilities implements Parcelable {
|
||||
* on a device via {@link TimeZoneDetector#suggestManualTimeZone(ManualTimeZoneSuggestion)}.
|
||||
*
|
||||
* <p>The suggestion will be ignored in all cases unless the value is {@link
|
||||
* #CAPABILITY_POSSESSED}. See also {@link TimeZoneConfiguration#isAutoDetectionEnabled()}.
|
||||
* Capabilities#CAPABILITY_POSSESSED}. See also
|
||||
* {@link TimeZoneConfiguration#isAutoDetectionEnabled()}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -113,7 +113,7 @@ public final class TimeZoneCapabilitiesAndConfig implements Parcelable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeZoneDetectorCapabilitiesAndConfig{"
|
||||
return "TimeZoneCapabilitiesAndConfig{"
|
||||
+ "mCapabilities=" + mCapabilities
|
||||
+ ", mConfiguration=" + mConfiguration
|
||||
+ '}';
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package android.app.timedetector;
|
||||
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.app.timedetector.GnssTimeSuggestion;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.app.timedetector.NetworkTimeSuggestion;
|
||||
@@ -36,6 +38,9 @@ import android.app.timedetector.TelephonyTimeSuggestion;
|
||||
* {@hide}
|
||||
*/
|
||||
interface ITimeDetectorService {
|
||||
TimeCapabilitiesAndConfig getCapabilitiesAndConfig();
|
||||
boolean updateConfiguration(in TimeConfiguration timeConfiguration);
|
||||
|
||||
void suggestExternalTime( in ExternalTimeSuggestion timeSuggestion);
|
||||
void suggestGnssTime(in GnssTimeSuggestion timeSuggestion);
|
||||
boolean suggestManualTime(in ManualTimeSuggestion timeSuggestion);
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.Capabilities.CAPABILITY_NOT_APPLICABLE;
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
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 TimeCapabilitiesTest {
|
||||
|
||||
private static final UserHandle USER_HANDLE = UserHandle.of(332211);
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
TimeCapabilities capabilities = new TimeCapabilities.Builder(USER_HANDLE)
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_NOT_APPLICABLE)
|
||||
.setSuggestTimeManuallyCapability(CAPABILITY_NOT_SUPPORTED)
|
||||
.build();
|
||||
|
||||
assertThat(capabilities.getConfigureAutoTimeDetectionEnabledCapability())
|
||||
.isEqualTo(CAPABILITY_NOT_APPLICABLE);
|
||||
assertThat(capabilities.getSuggestTimeManuallyCapability())
|
||||
.isEqualTo(CAPABILITY_NOT_SUPPORTED);
|
||||
|
||||
try {
|
||||
new TimeCapabilities.Builder(USER_HANDLE)
|
||||
.build();
|
||||
fail("Should throw IllegalStateException");
|
||||
} catch (IllegalStateException ignored) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
new TimeCapabilities.Builder(USER_HANDLE)
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_NOT_APPLICABLE)
|
||||
.build();
|
||||
fail("Should throw IllegalStateException");
|
||||
} catch (IllegalStateException ignored) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
new TimeCapabilities.Builder(USER_HANDLE)
|
||||
.setSuggestTimeManuallyCapability(CAPABILITY_NOT_APPLICABLE)
|
||||
.build();
|
||||
fail("Should throw IllegalStateException");
|
||||
} catch (IllegalStateException ignored) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userHandle_notIgnoredInEquals() {
|
||||
TimeCapabilities firstUserCapabilities = new TimeCapabilities.Builder(UserHandle.of(1))
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_POSSESSED)
|
||||
.setSuggestTimeManuallyCapability(CAPABILITY_POSSESSED)
|
||||
.build();
|
||||
|
||||
TimeCapabilities secondUserCapabilities = new TimeCapabilities.Builder(UserHandle.of(2))
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_POSSESSED)
|
||||
.setSuggestTimeManuallyCapability(CAPABILITY_POSSESSED)
|
||||
.build();
|
||||
|
||||
assertThat(firstUserCapabilities).isNotEqualTo(secondUserCapabilities);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelable() {
|
||||
TimeCapabilities.Builder builder = new TimeCapabilities.Builder(USER_HANDLE)
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_NOT_SUPPORTED)
|
||||
.setSuggestTimeManuallyCapability(CAPABILITY_NOT_SUPPORTED);
|
||||
|
||||
assertRoundTripParcelable(builder.build());
|
||||
|
||||
builder.setSuggestTimeManuallyCapability(CAPABILITY_POSSESSED);
|
||||
assertRoundTripParcelable(builder.build());
|
||||
|
||||
builder.setConfigureAutoTimeDetectionEnabledCapability(CAPABILITY_POSSESSED);
|
||||
assertRoundTripParcelable(builder.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
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 TimeConfigurationTest {
|
||||
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
TimeConfiguration first = new TimeConfiguration.Builder()
|
||||
.setAutoDetectionEnabled(true)
|
||||
.build();
|
||||
|
||||
assertThat(first.isAutoDetectionEnabled()).isTrue();
|
||||
|
||||
TimeConfiguration copyFromBuilderConfiguration = new TimeConfiguration.Builder(first)
|
||||
.build();
|
||||
|
||||
assertThat(first).isEqualTo(copyFromBuilderConfiguration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelable() {
|
||||
TimeConfiguration.Builder builder = new TimeConfiguration.Builder();
|
||||
|
||||
assertRoundTripParcelable(builder.setAutoDetectionEnabled(true).build());
|
||||
|
||||
assertRoundTripParcelable(builder.setAutoDetectionEnabled(false).build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
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.time.Capabilities.CAPABILITY_NOT_ALLOWED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
|
||||
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.Capabilities.CapabilityState;
|
||||
import android.app.time.TimeCapabilities;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Holds configuration values that affect time behaviour.
|
||||
*/
|
||||
public final class ConfigurationInternal {
|
||||
|
||||
private final @UserIdInt int mUserId;
|
||||
private final boolean mUserConfigAllowed;
|
||||
private final boolean mAutoDetectionEnabled;
|
||||
|
||||
private ConfigurationInternal(Builder builder) {
|
||||
mUserId = builder.mUserId;
|
||||
mUserConfigAllowed = builder.mUserConfigAllowed;
|
||||
mAutoDetectionEnabled = builder.mAutoDetectionEnabled;
|
||||
}
|
||||
|
||||
/** Returns a {@link TimeCapabilitiesAndConfig} objects based on configuration values. */
|
||||
public TimeCapabilitiesAndConfig capabilitiesAndConfig() {
|
||||
return new TimeCapabilitiesAndConfig(timeCapabilities(), timeConfiguration());
|
||||
}
|
||||
|
||||
private TimeConfiguration timeConfiguration() {
|
||||
return new TimeConfiguration.Builder()
|
||||
.setAutoDetectionEnabled(mAutoDetectionEnabled)
|
||||
.build();
|
||||
}
|
||||
|
||||
private TimeCapabilities timeCapabilities() {
|
||||
@CapabilityState int configureAutoTimeDetectionEnabledCapability =
|
||||
mUserConfigAllowed
|
||||
? CAPABILITY_POSSESSED
|
||||
: CAPABILITY_NOT_ALLOWED;
|
||||
|
||||
@CapabilityState int suggestTimeManuallyCapability =
|
||||
mUserConfigAllowed
|
||||
? CAPABILITY_POSSESSED
|
||||
: CAPABILITY_NOT_ALLOWED;
|
||||
|
||||
return new TimeCapabilities.Builder(UserHandle.of(mUserId))
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(
|
||||
configureAutoTimeDetectionEnabledCapability)
|
||||
.setSuggestTimeManuallyCapability(suggestTimeManuallyCapability)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ConfigurationInternal that = (ConfigurationInternal) o;
|
||||
return mUserId == that.mUserId
|
||||
&& mUserConfigAllowed == that.mUserConfigAllowed
|
||||
&& mAutoDetectionEnabled == that.mAutoDetectionEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mUserId, mUserConfigAllowed, mAutoDetectionEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfigurationInternal{"
|
||||
+ "mUserId=" + mUserId
|
||||
+ ", mUserConfigAllowed=" + mUserConfigAllowed
|
||||
+ ", mAutoDetectionEnabled=" + mAutoDetectionEnabled
|
||||
+ '}';
|
||||
}
|
||||
|
||||
static final class Builder {
|
||||
private final @UserIdInt int mUserId;
|
||||
private boolean mUserConfigAllowed;
|
||||
private boolean mAutoDetectionEnabled;
|
||||
|
||||
Builder(@UserIdInt int userId) {
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
Builder setUserConfigAllowed(boolean userConfigAllowed) {
|
||||
mUserConfigAllowed = userConfigAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setAutoDetectionEnabled(boolean autoDetectionEnabled) {
|
||||
mAutoDetectionEnabled = autoDetectionEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
ConfigurationInternal build() {
|
||||
return new ConfigurationInternal(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPH
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AlarmManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -28,6 +29,8 @@ import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -71,6 +74,7 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
@NonNull private final ContentResolver mContentResolver;
|
||||
@NonNull private final PowerManager.WakeLock mWakeLock;
|
||||
@NonNull private final AlarmManager mAlarmManager;
|
||||
@NonNull private final UserManager mUserManager;
|
||||
@NonNull private final int[] mOriginPriorities;
|
||||
|
||||
public EnvironmentImpl(@NonNull Context context) {
|
||||
@@ -83,6 +87,8 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
|
||||
mAlarmManager = Objects.requireNonNull(context.getSystemService(AlarmManager.class));
|
||||
|
||||
mUserManager = Objects.requireNonNull(context.getSystemService(UserManager.class));
|
||||
|
||||
mSystemClockUpdateThresholdMillis =
|
||||
SystemProperties.getInt("ro.sys.time_detector_update_diff",
|
||||
SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
|
||||
@@ -114,6 +120,14 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
return mOriginPriorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationInternal configurationInternal(@UserIdInt int userId) {
|
||||
return new ConfigurationInternal.Builder(userId)
|
||||
.setUserConfigAllowed(isUserConfigAllowed(userId))
|
||||
.setAutoDetectionEnabled(isAutoTimeDetectionEnabled())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquireWakeLock() {
|
||||
if (mWakeLock.isHeld()) {
|
||||
@@ -150,6 +164,11 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUserConfigAllowed(@UserIdInt int userId) {
|
||||
UserHandle userHandle = UserHandle.of(userId);
|
||||
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
|
||||
}
|
||||
|
||||
private static int[] getOriginPriorities(@NonNull Context context) {
|
||||
String[] originStrings =
|
||||
context.getResources().getStringArray(R.array.config_autoTimeSourcesPriority);
|
||||
|
||||
@@ -18,7 +18,10 @@ package com.android.server.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.app.timedetector.GnssTimeSuggestion;
|
||||
import android.app.timedetector.ITimeDetectorService;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
@@ -36,6 +39,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.server.FgThread;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.timezonedetector.CallerIdentityInjector;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -71,6 +75,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
|
||||
@NonNull private final CallerIdentityInjector mCallerIdentityInjector;
|
||||
|
||||
private static TimeDetectorService create(@NonNull Context context) {
|
||||
TimeDetectorStrategyImpl.Environment environment = new EnvironmentImpl(context);
|
||||
@@ -97,9 +102,42 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
||||
@VisibleForTesting
|
||||
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull TimeDetectorStrategy timeDetectorStrategy) {
|
||||
this(context, handler, timeDetectorStrategy, CallerIdentityInjector.REAL);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull TimeDetectorStrategy timeDetectorStrategy,
|
||||
@NonNull CallerIdentityInjector callerIdentityInjector) {
|
||||
mContext = Objects.requireNonNull(context);
|
||||
mHandler = Objects.requireNonNull(handler);
|
||||
mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
|
||||
mCallerIdentityInjector = Objects.requireNonNull(callerIdentityInjector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeCapabilitiesAndConfig getCapabilitiesAndConfig() {
|
||||
int userId = mCallerIdentityInjector.getCallingUserId();
|
||||
return getTimeCapabilitiesAndConfig(userId);
|
||||
}
|
||||
|
||||
private TimeCapabilitiesAndConfig getTimeCapabilitiesAndConfig(@UserIdInt int userId) {
|
||||
enforceManageTimeDetectorPermission();
|
||||
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
try {
|
||||
ConfigurationInternal configurationInternal =
|
||||
mTimeDetectorStrategy.getConfigurationInternal(userId);
|
||||
return configurationInternal.capabilitiesAndConfig();
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateConfiguration(TimeConfiguration timeConfiguration) {
|
||||
// TODO(b/172891783) Add actual logic
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,4 +231,11 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
||||
android.Manifest.permission.SET_TIME,
|
||||
"suggest time from external source");
|
||||
}
|
||||
|
||||
private void enforceManageTimeDetectorPermission() {
|
||||
mContext.enforceCallingPermission(
|
||||
android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION,
|
||||
"manage time and time zone detection");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.timedetector;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.timedetector.GnssTimeSuggestion;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
@@ -88,6 +89,9 @@ public interface TimeDetectorStrategy extends Dumpable {
|
||||
/** Processes the suggested time from external sources. */
|
||||
void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion);
|
||||
|
||||
/** Returns the configuration that controls time detector behaviour for specified user. */
|
||||
ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
|
||||
|
||||
/**
|
||||
* Handles the auto-time configuration changing For example, when the auto-time setting is
|
||||
* toggled on or off.
|
||||
|
||||
@@ -22,6 +22,7 @@ import static java.util.stream.Collectors.joining;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.timedetector.GnssTimeSuggestion;
|
||||
@@ -155,6 +156,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
*/
|
||||
@Origin int[] autoOriginPriorities();
|
||||
|
||||
/**
|
||||
* Returns {@link ConfigurationInternal} for specified user.
|
||||
*/
|
||||
@NonNull
|
||||
ConfigurationInternal configurationInternal(@UserIdInt int userId);
|
||||
|
||||
/** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
|
||||
void acquireWakeLock();
|
||||
|
||||
@@ -266,6 +273,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
doAutoTimeDetection(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
|
||||
return mEnvironment.configurationInternal(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void handleAutoTimeConfigChanged() {
|
||||
boolean enabled = mEnvironment.isAutoTimeDetectionEnabled();
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
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 android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
import static android.app.time.TimeZoneCapabilities.CAPABILITY_POSSESSED;
|
||||
import static android.app.time.Capabilities.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;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.time.Capabilities;
|
||||
import android.app.time.TimeCapabilities;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ConfigurationInternalTest {
|
||||
|
||||
@Test
|
||||
public void capabilitiesAndConfig() {
|
||||
int userId = 112233;
|
||||
ConfigurationInternal configurationInternal = new ConfigurationInternal.Builder(userId)
|
||||
.setAutoDetectionEnabled(true)
|
||||
.setUserConfigAllowed(true)
|
||||
.build();
|
||||
|
||||
TimeCapabilities timeCapabilities = new TimeCapabilities.Builder(UserHandle.of(userId))
|
||||
.setConfigureAutoTimeDetectionEnabledCapability(Capabilities.CAPABILITY_POSSESSED)
|
||||
.setSuggestTimeManuallyCapability(Capabilities.CAPABILITY_POSSESSED)
|
||||
.build();
|
||||
TimeConfiguration timeConfiguration = new TimeConfiguration.Builder()
|
||||
.setAutoDetectionEnabled(true)
|
||||
.build();
|
||||
TimeCapabilitiesAndConfig expected =
|
||||
new TimeCapabilitiesAndConfig(timeCapabilities, timeConfiguration);
|
||||
|
||||
assertThat(configurationInternal.capabilitiesAndConfig()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -327,6 +327,11 @@ public class TimeDetectorServiceTest {
|
||||
mLastExternalSuggestion = timeSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationInternal getConfigurationInternal(int userId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleAutoTimeConfigChanged() {
|
||||
mHandleAutoTimeDetectionChangedCalled = true;
|
||||
|
||||
@@ -1157,6 +1157,11 @@ public class TimeDetectorStrategyImplTest {
|
||||
return mAutoOriginPriorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationInternal configurationInternal(int userId) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquireWakeLock() {
|
||||
if (mWakeLockAcquired) {
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
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 android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
|
||||
import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
|
||||
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
Reference in New Issue
Block a user