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 android.annotation.NonNull;
20 import android.annotation.StringDef;
21 import android.annotation.SystemApi;
22 import android.os.Bundle;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.Objects;
29 
30 /**
31  * User visible settings that control the behavior of the time detector / manual time entry.
32  *
33  * <p>When reading the configuration, values for all settings will be provided. In some cases, such
34  * as when the device behavior relies on optional hardware / OEM configuration, or the value of
35  * several settings, the device behavior may not be directly affected by the setting value.
36  *
37  * <p>Settings can be left absent when updating configuration via {@link
38  * TimeManager#updateTimeConfiguration(TimeConfiguration)} and those settings will not be
39  * changed. Not all configuration settings can be modified by all users: see {@link
40  * TimeManager#getTimeCapabilitiesAndConfig()} and {@link TimeCapabilities} for details.
41  *
42  * @hide
43  */
44 @SystemApi
45 public final class TimeConfiguration implements Parcelable {
46 
47     public static final @NonNull Creator<TimeConfiguration> CREATOR =
48             new Creator<TimeConfiguration>() {
49                 @Override
50                 public TimeConfiguration createFromParcel(Parcel source) {
51                     return TimeConfiguration.readFromParcel(source);
52                 }
53 
54                 @Override
55                 public TimeConfiguration[] newArray(int size) {
56                     return new TimeConfiguration[size];
57                 }
58             };
59 
60     /**
61      * All configuration properties
62      *
63      * @hide
64      */
65     @StringDef(SETTING_AUTO_DETECTION_ENABLED)
66     @Retention(RetentionPolicy.SOURCE)
67     @interface Setting {}
68 
69     /** See {@link TimeConfiguration#isAutoDetectionEnabled()} for details. */
70     @Setting
71     private static final String SETTING_AUTO_DETECTION_ENABLED = "autoDetectionEnabled";
72 
73     @NonNull
74     private final Bundle mBundle;
75 
TimeConfiguration(Builder builder)76     private TimeConfiguration(Builder builder) {
77         this.mBundle = builder.mBundle;
78     }
79 
readFromParcel(Parcel in)80     private static TimeConfiguration readFromParcel(Parcel in) {
81         return new TimeConfiguration.Builder()
82                 .setPropertyBundleInternal(in.readBundle())
83                 .build();
84     }
85 
86     @Override
writeToParcel(@onNull Parcel dest, int flags)87     public void writeToParcel(@NonNull Parcel dest, int flags) {
88         dest.writeBundle(mBundle);
89     }
90 
91     /**
92      * Returns {@code true} if all known settings are present.
93      *
94      * @hide
95      */
isComplete()96     public boolean isComplete() {
97         return hasIsAutoDetectionEnabled();
98     }
99 
100     /**
101      * Returns the value of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting. This
102      * controls whether a device will attempt to determine the time automatically using
103      * contextual information if the device supports auto detection.
104      *
105      * <p>See {@link TimeCapabilities#getConfigureAutoDetectionEnabledCapability()} for how to
106      * tell if the setting is meaningful for the current user at this time.
107      *
108      * @throws IllegalStateException if the setting is not present
109      */
isAutoDetectionEnabled()110     public boolean isAutoDetectionEnabled() {
111         enforceSettingPresent(SETTING_AUTO_DETECTION_ENABLED);
112         return mBundle.getBoolean(SETTING_AUTO_DETECTION_ENABLED);
113     }
114 
115     /**
116      * Returns {@code true} if the {@link #isAutoDetectionEnabled()} setting is present.
117      *
118      * @hide
119      */
hasIsAutoDetectionEnabled()120     public boolean hasIsAutoDetectionEnabled() {
121         return mBundle.containsKey(SETTING_AUTO_DETECTION_ENABLED);
122     }
123 
124     @Override
describeContents()125     public int describeContents() {
126         return 0;
127     }
128 
129     @Override
equals(Object o)130     public boolean equals(Object o) {
131         if (this == o) return true;
132         if (o == null || getClass() != o.getClass()) return false;
133         TimeConfiguration that = (TimeConfiguration) o;
134         return mBundle.kindofEquals(that.mBundle);
135     }
136 
137     @Override
hashCode()138     public int hashCode() {
139         return Objects.hash(mBundle);
140     }
141 
142     @Override
toString()143     public String toString() {
144         return "TimeConfiguration{"
145                 + "mBundle=" + mBundle
146                 + '}';
147     }
148 
enforceSettingPresent(@imeZoneConfiguration.Setting String setting)149     private void enforceSettingPresent(@TimeZoneConfiguration.Setting String setting) {
150         if (!mBundle.containsKey(setting)) {
151             throw new IllegalStateException(setting + " is not set");
152         }
153     }
154 
155     /**
156      * A builder for {@link TimeConfiguration} objects.
157      *
158      * @hide
159      */
160     @SystemApi
161     public static final class Builder {
162 
163         private final Bundle mBundle = new Bundle();
164 
165         /**
166          * Creates a new Builder with no settings held.
167          */
Builder()168         public Builder() {}
169 
170         /**
171          * Creates a new Builder by copying the settings from an existing instance.
172          */
Builder(@onNull TimeConfiguration toCopy)173         public Builder(@NonNull TimeConfiguration toCopy) {
174             mergeProperties(toCopy);
175         }
176 
177         /**
178          * Merges {@code other} settings into this instances, replacing existing values in this
179          * where the settings appear in both.
180          *
181          * @hide
182          */
183         @NonNull
mergeProperties(@onNull TimeConfiguration toCopy)184         public Builder mergeProperties(@NonNull TimeConfiguration toCopy) {
185             mBundle.putAll(toCopy.mBundle);
186             return this;
187         }
188 
189         @NonNull
setPropertyBundleInternal(@onNull Bundle bundle)190         Builder setPropertyBundleInternal(@NonNull Bundle bundle) {
191             this.mBundle.putAll(bundle);
192             return this;
193         }
194 
195         /** Sets whether auto detection is enabled or not. */
196         @NonNull
setAutoDetectionEnabled(boolean enabled)197         public Builder setAutoDetectionEnabled(boolean enabled) {
198             mBundle.putBoolean(SETTING_AUTO_DETECTION_ENABLED, enabled);
199             return this;
200         }
201 
202         /** Returns the {@link TimeConfiguration}. */
203         @NonNull
build()204         public TimeConfiguration build() {
205             return new TimeConfiguration(this);
206         }
207     }
208 }
209