1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.time;
18 
19 import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.app.time.Capabilities.CapabilityState;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.os.UserHandle;
28 
29 import java.util.Objects;
30 
31 /**
32  * Time-relate capabilities for a user.
33  *
34  * <p>For configuration settings capabilities, the associated settings value can be found via
35  * {@link TimeManager#getTimeCapabilitiesAndConfig()} and may be changed using {@link
36  * TimeManager#updateTimeConfiguration(TimeConfiguration)} (if the user's capabilities
37  * allow).
38  *
39  * @hide
40  */
41 @SystemApi
42 public final class TimeCapabilities implements Parcelable {
43 
44     public static final @NonNull Creator<TimeCapabilities> CREATOR = new Creator<>() {
45         public TimeCapabilities createFromParcel(Parcel in) {
46             return TimeCapabilities.createFromParcel(in);
47         }
48 
49         public TimeCapabilities[] newArray(int size) {
50             return new TimeCapabilities[size];
51         }
52     };
53 
54 
55     /**
56      * The user the capabilities are for. This is used for object equality and debugging but there
57      * is no accessor.
58      */
59     @NonNull
60     private final UserHandle mUserHandle;
61     private final @CapabilityState int mConfigureAutoDetectionEnabledCapability;
62     private final @CapabilityState int mSetManualTimeCapability;
63 
TimeCapabilities(@onNull Builder builder)64     private TimeCapabilities(@NonNull Builder builder) {
65         this.mUserHandle = Objects.requireNonNull(builder.mUserHandle);
66         this.mConfigureAutoDetectionEnabledCapability =
67                 builder.mConfigureAutoDetectionEnabledCapability;
68         this.mSetManualTimeCapability = builder.mSetManualTimeCapability;
69     }
70 
71     @NonNull
createFromParcel(@onNull Parcel in)72     private static TimeCapabilities createFromParcel(@NonNull Parcel in) {
73         UserHandle userHandle = UserHandle.readFromParcel(in);
74         return new TimeCapabilities.Builder(userHandle)
75                 .setConfigureAutoDetectionEnabledCapability(in.readInt())
76                 .setSetManualTimeCapability(in.readInt())
77                 .build();
78     }
79 
80     @Override
writeToParcel(@onNull Parcel dest, int flags)81     public void writeToParcel(@NonNull Parcel dest, int flags) {
82         UserHandle.writeToParcel(mUserHandle, dest);
83         dest.writeInt(mConfigureAutoDetectionEnabledCapability);
84         dest.writeInt(mSetManualTimeCapability);
85     }
86 
87     /**
88      * Returns the capability state associated with the user's ability to modify the automatic time
89      * detection setting. The setting can be updated via {@link
90      * TimeManager#updateTimeConfiguration(TimeConfiguration)}.
91      */
92     @CapabilityState
getConfigureAutoDetectionEnabledCapability()93     public int getConfigureAutoDetectionEnabledCapability() {
94         return mConfigureAutoDetectionEnabledCapability;
95     }
96 
97     /**
98      * Returns the capability state associated with the user's ability to manually set time on a
99      * device. The setting can be updated via {@link
100      * TimeManager#updateTimeConfiguration(TimeConfiguration)}.
101      */
102     @CapabilityState
getSetManualTimeCapability()103     public int getSetManualTimeCapability() {
104         return mSetManualTimeCapability;
105     }
106 
107     /**
108      * Tries to create a new {@link TimeConfiguration} from the {@code config} and the set of
109      * {@code requestedChanges}, if {@code this} capabilities allow. The new configuration is
110      * returned. If the capabilities do not permit one or more of the requested changes then {@code
111      * null} is returned.
112      *
113      * @hide
114      */
115     @Nullable
tryApplyConfigChanges( @onNull TimeConfiguration config, @NonNull TimeConfiguration requestedChanges)116     public TimeConfiguration tryApplyConfigChanges(
117             @NonNull TimeConfiguration config,
118             @NonNull TimeConfiguration requestedChanges) {
119         TimeConfiguration.Builder newConfigBuilder = new TimeConfiguration.Builder(config);
120         if (requestedChanges.hasIsAutoDetectionEnabled()) {
121             if (this.getConfigureAutoDetectionEnabledCapability() < CAPABILITY_NOT_APPLICABLE) {
122                 return null;
123             }
124             newConfigBuilder.setAutoDetectionEnabled(requestedChanges.isAutoDetectionEnabled());
125         }
126 
127         return newConfigBuilder.build();
128     }
129 
130     @Override
describeContents()131     public int describeContents() {
132         return 0;
133     }
134 
135     @Override
equals(Object o)136     public boolean equals(Object o) {
137         if (this == o) return true;
138         if (o == null || getClass() != o.getClass()) return false;
139         TimeCapabilities that = (TimeCapabilities) o;
140         return mConfigureAutoDetectionEnabledCapability
141                 == that.mConfigureAutoDetectionEnabledCapability
142                 && mSetManualTimeCapability == that.mSetManualTimeCapability
143                 && mUserHandle.equals(that.mUserHandle);
144     }
145 
146     @Override
hashCode()147     public int hashCode() {
148         return Objects.hash(mUserHandle, mConfigureAutoDetectionEnabledCapability,
149                 mSetManualTimeCapability);
150     }
151 
152     @Override
toString()153     public String toString() {
154         return "TimeCapabilities{"
155                 + "mUserHandle=" + mUserHandle
156                 + ", mConfigureAutoDetectionEnabledCapability="
157                 + mConfigureAutoDetectionEnabledCapability
158                 + ", mSetManualTimeCapability=" + mSetManualTimeCapability
159                 + '}';
160     }
161 
162     /**
163      * A builder of {@link TimeCapabilities} objects.
164      *
165      * @hide
166      */
167     public static class Builder {
168 
169         @NonNull private final UserHandle mUserHandle;
170         private @CapabilityState int mConfigureAutoDetectionEnabledCapability;
171         private @CapabilityState int mSetManualTimeCapability;
172 
Builder(@onNull UserHandle userHandle)173         public Builder(@NonNull UserHandle userHandle) {
174             this.mUserHandle = Objects.requireNonNull(userHandle);
175         }
176 
Builder(@onNull TimeCapabilities timeCapabilities)177         public Builder(@NonNull TimeCapabilities timeCapabilities) {
178             Objects.requireNonNull(timeCapabilities);
179             this.mUserHandle = timeCapabilities.mUserHandle;
180             this.mConfigureAutoDetectionEnabledCapability =
181                     timeCapabilities.mConfigureAutoDetectionEnabledCapability;
182             this.mSetManualTimeCapability = timeCapabilities.mSetManualTimeCapability;
183         }
184 
185         /** Sets the value for the "configure automatic time detection" capability. */
setConfigureAutoDetectionEnabledCapability(@apabilityState int value)186         public Builder setConfigureAutoDetectionEnabledCapability(@CapabilityState int value) {
187             this.mConfigureAutoDetectionEnabledCapability = value;
188             return this;
189         }
190 
191         /** Sets the value for the "set manual time" capability. */
setSetManualTimeCapability(@apabilityState int value)192         public Builder setSetManualTimeCapability(@CapabilityState int value) {
193             this.mSetManualTimeCapability = value;
194             return this;
195         }
196 
197         /** Returns the {@link TimeCapabilities}. */
build()198         public TimeCapabilities build() {
199             verifyCapabilitySet(mConfigureAutoDetectionEnabledCapability,
200                     "configureAutoDetectionEnabledCapability");
201             verifyCapabilitySet(mSetManualTimeCapability, "mSetManualTimeCapability");
202             return new TimeCapabilities(this);
203         }
204 
verifyCapabilitySet(int value, String name)205         private void verifyCapabilitySet(int value, String name) {
206             if (value == 0) {
207                 throw new IllegalStateException(name + " was not set");
208             }
209         }
210     }
211 }
212