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.CurrentTimeMillisLong;
20 import android.annotation.ElapsedRealtimeLong;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.os.ShellCommand;
27 import android.os.SystemClock;
28 
29 import java.io.PrintWriter;
30 import java.util.Objects;
31 
32 /**
33  * A Unix epoch time value with an associated reading from the elapsed realtime clock.
34  * When representing a device's system clock time, the Unix epoch time can be obtained using {@link
35  * System#currentTimeMillis()}. The Unix epoch time might also come from an external source
36  * depending on usage.
37  *
38  * <p>The elapsed realtime clock can be obtained using methods like {@link
39  * SystemClock#elapsedRealtime()} or {@link SystemClock#elapsedRealtimeClock()}.
40  *
41  * @hide
42  */
43 @SystemApi
44 public final class UnixEpochTime implements Parcelable {
45     @ElapsedRealtimeLong private final long mElapsedRealtimeMillis;
46     @CurrentTimeMillisLong private final long mUnixEpochTimeMillis;
47 
UnixEpochTime(@lapsedRealtimeLong long elapsedRealtimeMillis, long unixEpochTimeMillis)48     public UnixEpochTime(@ElapsedRealtimeLong long elapsedRealtimeMillis,
49             long unixEpochTimeMillis) {
50         mElapsedRealtimeMillis = elapsedRealtimeMillis;
51         mUnixEpochTimeMillis = unixEpochTimeMillis;
52     }
53 
54     /** @hide */
55     @NonNull
parseCommandLineArgs(ShellCommand cmd)56     public static UnixEpochTime parseCommandLineArgs(ShellCommand cmd) {
57         Long elapsedRealtimeMillis = null;
58         Long unixEpochTimeMillis = null;
59         String opt;
60         while ((opt = cmd.getNextArg()) != null) {
61             switch (opt) {
62                 case "--elapsed_realtime": {
63                     elapsedRealtimeMillis = Long.parseLong(cmd.getNextArgRequired());
64                     break;
65                 }
66                 case "--unix_epoch_time": {
67                     unixEpochTimeMillis = Long.parseLong(cmd.getNextArgRequired());
68                     break;
69                 }
70                 default: {
71                     throw new IllegalArgumentException("Unknown option: " + opt);
72                 }
73             }
74         }
75 
76         if (elapsedRealtimeMillis == null) {
77             throw new IllegalArgumentException("No elapsedRealtimeMillis specified.");
78         }
79         if (unixEpochTimeMillis == null) {
80             throw new IllegalArgumentException("No unixEpochTimeMillis specified.");
81         }
82         return new UnixEpochTime(elapsedRealtimeMillis, unixEpochTimeMillis);
83     }
84 
85     /** @hide */
printCommandLineOpts(PrintWriter pw)86     public static void printCommandLineOpts(PrintWriter pw) {
87         pw.println("UnixEpochTime options:\n");
88         pw.println("  --elapsed_realtime <elapsed realtime millis>");
89         pw.println("  --unix_epoch_time <Unix epoch time millis>");
90         pw.println();
91         pw.println("See " + UnixEpochTime.class.getName() + " for more information");
92     }
93 
94     /** Returns the elapsed realtime clock value. See {@link UnixEpochTime} for more information. */
95     @ElapsedRealtimeLong
getElapsedRealtimeMillis()96     public long getElapsedRealtimeMillis() {
97         return mElapsedRealtimeMillis;
98     }
99 
100     /** Returns the unix epoch time value. See {@link UnixEpochTime} for more information. */
101     @CurrentTimeMillisLong
getUnixEpochTimeMillis()102     public long getUnixEpochTimeMillis() {
103         return mUnixEpochTimeMillis;
104     }
105 
106     @Override
equals(@ullable Object o)107     public boolean equals(@Nullable Object o) {
108         if (this == o) {
109             return true;
110         }
111         if (o == null || getClass() != o.getClass()) {
112             return false;
113         }
114         UnixEpochTime that = (UnixEpochTime) o;
115         return mElapsedRealtimeMillis == that.mElapsedRealtimeMillis
116                 && mUnixEpochTimeMillis == that.mUnixEpochTimeMillis;
117     }
118 
119     @Override
hashCode()120     public int hashCode() {
121         return Objects.hash(mElapsedRealtimeMillis, mUnixEpochTimeMillis);
122     }
123 
124     @Override
toString()125     public String toString() {
126         return "UnixEpochTime{"
127                 + "mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
128                 + ", mUnixEpochTimeMillis=" + mUnixEpochTimeMillis
129                 + '}';
130     }
131 
132     public static final @NonNull Creator<UnixEpochTime> CREATOR = new Creator<>() {
133         @Override
134         public UnixEpochTime createFromParcel(@NonNull Parcel source) {
135             long elapsedRealtimeMillis = source.readLong();
136             long unixEpochTimeMillis = source.readLong();
137             return new UnixEpochTime(elapsedRealtimeMillis, unixEpochTimeMillis);
138         }
139 
140         @Override
141         public UnixEpochTime[] newArray(int size) {
142             return new UnixEpochTime[size];
143         }
144     };
145 
146     @Override
writeToParcel(@onNull Parcel dest, int flags)147     public void writeToParcel(@NonNull Parcel dest, int flags) {
148         dest.writeLong(mElapsedRealtimeMillis);
149         dest.writeLong(mUnixEpochTimeMillis);
150     }
151 
152     @Override
describeContents()153     public int describeContents() {
154         return 0;
155     }
156 
157     /**
158      * Creates a new Unix epoch time value at {@code elapsedRealtimeTimeMillis} by adjusting this
159      * Unix epoch time by the difference between the elapsed realtime value supplied and the one
160      * associated with this instance.
161      */
162     @NonNull
at(@lapsedRealtimeLong long elapsedRealtimeTimeMillis)163     public UnixEpochTime at(@ElapsedRealtimeLong long elapsedRealtimeTimeMillis) {
164         long adjustedUnixEpochTimeMillis =
165                 (elapsedRealtimeTimeMillis - mElapsedRealtimeMillis) + mUnixEpochTimeMillis;
166         return new UnixEpochTime(elapsedRealtimeTimeMillis, adjustedUnixEpochTimeMillis);
167     }
168 
169     /**
170      * Returns the difference in milliseconds between two instance's elapsed realtimes.
171      *
172      * @hide
173      */
elapsedRealtimeDifference( @onNull UnixEpochTime one, @NonNull UnixEpochTime two)174     public static long elapsedRealtimeDifference(
175             @NonNull UnixEpochTime one, @NonNull UnixEpochTime two) {
176         return one.mElapsedRealtimeMillis - two.mElapsedRealtimeMillis;
177     }
178 }
179