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 time state.
31  *
32  * <p>{@code unixEpochTime} contains a snapshot of the system clock time and elapsed realtime clock
33  * time.
34  *
35  * <p>{@code userShouldConfirmTime} is {@code true} if the system automatic time detection logic
36  * suggests that the user be asked to confirm the {@code unixEpochTime} value is correct via {@link
37  * TimeManager#confirmTime}. If it is not correct, the value can usually be changed via {@link
38  * TimeManager#setManualTime}.
39  *
40  * @hide
41  */
42 @SystemApi
43 public final class TimeState implements Parcelable {
44 
45     public static final @NonNull Creator<TimeState> CREATOR = new Creator<>() {
46         public TimeState createFromParcel(Parcel in) {
47             return TimeState.createFromParcel(in);
48         }
49 
50         public TimeState[] newArray(int size) {
51             return new TimeState[size];
52         }
53     };
54 
55     @NonNull private final UnixEpochTime mUnixEpochTime;
56     private final boolean mUserShouldConfirmTime;
57 
58     /** @hide */
TimeState(@onNull UnixEpochTime unixEpochTime, boolean userShouldConfirmTime)59     public TimeState(@NonNull UnixEpochTime unixEpochTime, boolean userShouldConfirmTime) {
60         mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
61         mUserShouldConfirmTime = userShouldConfirmTime;
62     }
63 
createFromParcel(Parcel in)64     private static TimeState createFromParcel(Parcel in) {
65         UnixEpochTime unixEpochTime = in.readParcelable(null, UnixEpochTime.class);
66         boolean userShouldConfirmId = in.readBoolean();
67         return new TimeState(unixEpochTime, userShouldConfirmId);
68     }
69 
70     @Override
writeToParcel(@onNull Parcel dest, int flags)71     public void writeToParcel(@NonNull Parcel dest, int flags) {
72         dest.writeParcelable(mUnixEpochTime, 0);
73         dest.writeBoolean(mUserShouldConfirmTime);
74     }
75 
76     /** @hide */
77     @Nullable
parseCommandLineArgs(@onNull ShellCommand cmd)78     public static TimeState parseCommandLineArgs(@NonNull ShellCommand cmd) {
79         Long elapsedRealtimeMillis = null;
80         Long unixEpochTimeMillis = null;
81         Boolean userShouldConfirmTime = null;
82         String opt;
83         while ((opt = cmd.getNextArg()) != null) {
84             switch (opt) {
85                 case "--elapsed_realtime": {
86                     elapsedRealtimeMillis = Long.parseLong(cmd.getNextArgRequired());
87                     break;
88                 }
89                 case "--unix_epoch_time": {
90                     unixEpochTimeMillis = Long.parseLong(cmd.getNextArgRequired());
91                     break;
92                 }
93                 case "--user_should_confirm_time": {
94                     userShouldConfirmTime  = Boolean.parseBoolean(cmd.getNextArgRequired());
95                     break;
96                 }
97                 default: {
98                     throw new IllegalArgumentException("Unknown option: " + opt);
99                 }
100             }
101         }
102 
103         if (elapsedRealtimeMillis == null) {
104             throw new IllegalArgumentException("No elapsedRealtimeMillis specified.");
105         }
106         if (unixEpochTimeMillis == null) {
107             throw new IllegalArgumentException("No unixEpochTimeMillis specified.");
108         }
109         if (userShouldConfirmTime == null) {
110             throw new IllegalArgumentException("No userShouldConfirmTime specified.");
111         }
112 
113         UnixEpochTime unixEpochTime = new UnixEpochTime(elapsedRealtimeMillis, unixEpochTimeMillis);
114         return new TimeState(unixEpochTime, userShouldConfirmTime);
115     }
116 
117     /** @hide */
printCommandLineOpts(@onNull PrintWriter pw)118     public static void printCommandLineOpts(@NonNull PrintWriter pw) {
119         pw.println("TimeState options:");
120         pw.println("  --elapsed_realtime <elapsed realtime millis>");
121         pw.println("  --unix_epoch_time <Unix epoch time millis>");
122         pw.println("  --user_should_confirm_time {true|false}");
123         pw.println();
124         pw.println("See " + TimeState.class.getName() + " for more information");
125     }
126 
127     @Override
describeContents()128     public int describeContents() {
129         return 0;
130     }
131 
132     @NonNull
getUnixEpochTime()133     public UnixEpochTime getUnixEpochTime() {
134         return mUnixEpochTime;
135     }
136 
getUserShouldConfirmTime()137     public boolean getUserShouldConfirmTime() {
138         return mUserShouldConfirmTime;
139     }
140 
141     @Override
equals(@ullable Object o)142     public boolean equals(@Nullable Object o) {
143         if (this == o) {
144             return true;
145         }
146         if (o == null || getClass() != o.getClass()) {
147             return false;
148         }
149         TimeState that = (TimeState) o;
150         return Objects.equals(mUnixEpochTime, that.mUnixEpochTime)
151                 && mUserShouldConfirmTime == that.mUserShouldConfirmTime;
152     }
153 
154     @Override
hashCode()155     public int hashCode() {
156         return Objects.hash(mUnixEpochTime, mUserShouldConfirmTime);
157     }
158 
159     @Override
toString()160     public String toString() {
161         return "TimeState{"
162                 + "mUnixEpochTime=" + mUnixEpochTime
163                 + ", mUserShouldConfirmTime=" + mUserShouldConfirmTime
164                 + '}';
165     }
166 }
167