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:
Almaz Mingaleev
2021-03-03 11:24:07 +00:00
parent d3035fe485
commit fda49aa575
26 changed files with 1092 additions and 70 deletions

View File

@@ -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;
}

View 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() {}
}

View 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;

View 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");
}
}
}
}

View 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;

View 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
+ '}';
}
}

View 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;

View 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);
}
}
}

View File

@@ -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

View File

@@ -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
*/

View File

@@ -113,7 +113,7 @@ public final class TimeZoneCapabilitiesAndConfig implements Parcelable {
@Override
public String toString() {
return "TimeZoneDetectorCapabilitiesAndConfig{"
return "TimeZoneCapabilitiesAndConfig{"
+ "mCapabilities=" + mCapabilities
+ ", mConfiguration=" + mConfiguration
+ '}';

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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");
}
}

View File

@@ -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.

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -327,6 +327,11 @@ public class TimeDetectorServiceTest {
mLastExternalSuggestion = timeSuggestion;
}
@Override
public ConfigurationInternal getConfigurationInternal(int userId) {
throw new UnsupportedOperationException();
}
@Override
public void handleAutoTimeConfigChanged() {
mHandleAutoTimeDetectionChangedCalled = true;

View File

@@ -1157,6 +1157,11 @@ public class TimeDetectorStrategyImplTest {
return mAutoOriginPriorities;
}
@Override
public ConfigurationInternal configurationInternal(int userId) {
throw new UnsupportedOperationException();
}
@Override
public void acquireWakeLock() {
if (mWakeLockAcquired) {

View File

@@ -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;