1 /*
2  * Copyright (C) 2022 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.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.ShellCommand;
25 
26 import java.io.PrintWriter;
27 import java.util.Objects;
28 
29 /**
30  * A snapshot of the system's time zone state.
31  *
32  * <p>{@code id} contains the system's time zone ID setting, e.g. "America/Los_Angeles". This
33  * will usually agree with {@code TimeZone.getDefault().getID()} but it can be empty in rare cases.
34  *
35  * <p>{@code userShouldConfirmId} is {@code true} if the system automatic time zone detection logic
36  * suggests that the user be asked to confirm the {@code id} value is correct via {@link
37  * TimeManager#confirmTimeZone}. If it is not correct, the value can usually be changed via {@link
38  * TimeManager#setManualTimeZone}.
39  *
40  * @hide
41  */
42 @SystemApi
43 public final class TimeZoneState implements Parcelable {
44 
45     public static final @NonNull Creator<TimeZoneState> CREATOR = new Creator<>() {
46         public TimeZoneState createFromParcel(Parcel in) {
47             return TimeZoneState.createFromParcel(in);
48         }
49 
50         public TimeZoneState[] newArray(int size) {
51             return new TimeZoneState[size];
52         }
53     };
54 
55     @NonNull private final String mId;
56     private final boolean mUserShouldConfirmId;
57 
58     /** @hide */
TimeZoneState(@onNull String id, boolean userShouldConfirmId)59     public TimeZoneState(@NonNull String id, boolean userShouldConfirmId) {
60         mId = Objects.requireNonNull(id);
61         mUserShouldConfirmId = userShouldConfirmId;
62     }
63 
createFromParcel(Parcel in)64     private static TimeZoneState createFromParcel(Parcel in) {
65         String zoneId = in.readString8();
66         boolean userShouldConfirmId = in.readBoolean();
67         return new TimeZoneState(zoneId, userShouldConfirmId);
68     }
69 
70     @Override
writeToParcel(@onNull Parcel dest, int flags)71     public void writeToParcel(@NonNull Parcel dest, int flags) {
72         dest.writeString8(mId);
73         dest.writeBoolean(mUserShouldConfirmId);
74     }
75 
76     /** @hide */
77     @Nullable
parseCommandLineArgs(@onNull ShellCommand cmd)78     public static TimeZoneState parseCommandLineArgs(@NonNull ShellCommand cmd) {
79         String zoneIdString = null;
80         Boolean userShouldConfirmId = null;
81         String opt;
82         while ((opt = cmd.getNextArg()) != null) {
83             switch (opt) {
84                 case "--zone_id": {
85                     zoneIdString  = cmd.getNextArgRequired();
86                     break;
87                 }
88                 case "--user_should_confirm_id": {
89                     userShouldConfirmId  = Boolean.parseBoolean(cmd.getNextArgRequired());
90                     break;
91                 }
92                 default: {
93                     throw new IllegalArgumentException("Unknown option: " + opt);
94                 }
95             }
96         }
97         if (zoneIdString == null) {
98             throw new IllegalArgumentException("No zoneId specified.");
99         }
100         if (userShouldConfirmId == null) {
101             throw new IllegalArgumentException("No userShouldConfirmId specified.");
102         }
103         return new TimeZoneState(zoneIdString, userShouldConfirmId);
104     }
105 
106     /** @hide */
printCommandLineOpts(@onNull PrintWriter pw)107     public static void printCommandLineOpts(@NonNull PrintWriter pw) {
108         pw.println("TimeZoneState options:");
109         pw.println("  --zone_id {<Olson ID>}");
110         pw.println("  --user_should_confirm_id {true|false}");
111         pw.println();
112         pw.println("See " + TimeZoneState.class.getName() + " for more information");
113     }
114 
115     @Override
describeContents()116     public int describeContents() {
117         return 0;
118     }
119 
120     @NonNull
getId()121     public String getId() {
122         return mId;
123     }
124 
getUserShouldConfirmId()125     public boolean getUserShouldConfirmId() {
126         return mUserShouldConfirmId;
127     }
128 
129     @Override
equals(@ullable Object o)130     public boolean equals(@Nullable Object o) {
131         if (this == o) {
132             return true;
133         }
134         if (o == null || getClass() != o.getClass()) {
135             return false;
136         }
137         TimeZoneState that = (TimeZoneState) o;
138         return Objects.equals(mId, that.mId)
139                 && mUserShouldConfirmId == that.mUserShouldConfirmId;
140     }
141 
142     @Override
hashCode()143     public int hashCode() {
144         return Objects.hash(mId, mUserShouldConfirmId);
145     }
146 
147     @Override
toString()148     public String toString() {
149         return "TimeZoneState{"
150                 + "mZoneId=" + mId
151                 + ", mUserShouldConfirmId=" + mUserShouldConfirmId
152                 + '}';
153     }
154 }
155