• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.timedetector;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.TimestampedValue;
24 
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Objects;
29 
30 /**
31  * A time suggestion from an identified telephony source. e.g. from NITZ information from a specific
32  * radio.
33  *
34  * <p>{@code slotIndex} identifies the suggestion source. This enables detection logic to identify
35  * suggestions from the same source when there are several in use.
36  *
37  * <p>{@code unixEpochTime}. When not {@code null}, the {@code unixEpochTime.value} is the number of
38  * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code unixEpochTime.referenceTimeMillis}
39  * is the value of the elapsed realtime clock when the {@code unixEpochTime.value} was established.
40  * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
41  * suggestions cannot be persisted across device resets. {@code unixEpochTime} can be {@code null}
42  * to indicate that the telephony source has entered an "un-opinionated" state and any previous
43  * suggestion from the source is being withdrawn.
44  *
45  * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
46  * record why the suggestion exists, e.g. what triggered it to be made and what heuristic was used
47  * to determine the time or its absence. This information exists only to aid in debugging and
48  * therefore is used by {@link #toString()}, but it is not for use in detection logic and is not
49  * considered in {@link #hashCode()} or {@link #equals(Object)}.
50  *
51  * @hide
52  */
53 public final class TelephonyTimeSuggestion implements Parcelable {
54 
55     /** @hide */
56     public static final @NonNull Parcelable.Creator<TelephonyTimeSuggestion> CREATOR =
57             new Parcelable.Creator<TelephonyTimeSuggestion>() {
58                 public TelephonyTimeSuggestion createFromParcel(Parcel in) {
59                     return TelephonyTimeSuggestion.createFromParcel(in);
60                 }
61 
62                 public TelephonyTimeSuggestion[] newArray(int size) {
63                     return new TelephonyTimeSuggestion[size];
64                 }
65             };
66 
67     private final int mSlotIndex;
68     @Nullable private final TimestampedValue<Long> mUnixEpochTime;
69     @Nullable private ArrayList<String> mDebugInfo;
70 
TelephonyTimeSuggestion(Builder builder)71     private TelephonyTimeSuggestion(Builder builder) {
72         mSlotIndex = builder.mSlotIndex;
73         mUnixEpochTime = builder.mUnixEpochTime;
74         mDebugInfo = builder.mDebugInfo != null ? new ArrayList<>(builder.mDebugInfo) : null;
75     }
76 
createFromParcel(Parcel in)77     private static TelephonyTimeSuggestion createFromParcel(Parcel in) {
78         int slotIndex = in.readInt();
79         TimestampedValue<Long> unixEpochTime =
80                 in.readParcelable(null /* classLoader */, android.os.TimestampedValue.class);
81         TelephonyTimeSuggestion suggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
82                 .setUnixEpochTime(unixEpochTime)
83                 .build();
84         @SuppressWarnings("unchecked")
85         ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(
86                 null /* classLoader */, java.lang.String.class);
87         if (debugInfo != null) {
88             suggestion.addDebugInfo(debugInfo);
89         }
90         return suggestion;
91     }
92 
93     @Override
describeContents()94     public int describeContents() {
95         return 0;
96     }
97 
98     @Override
writeToParcel(@onNull Parcel dest, int flags)99     public void writeToParcel(@NonNull Parcel dest, int flags) {
100         dest.writeInt(mSlotIndex);
101         dest.writeParcelable(mUnixEpochTime, 0);
102         dest.writeList(mDebugInfo);
103     }
104 
105     /**
106      * Returns an identifier for the source of this suggestion.
107      *
108      * <p>See {@link TelephonyTimeSuggestion} for more information about {@code slotIndex}.
109      */
getSlotIndex()110     public int getSlotIndex() {
111         return mSlotIndex;
112     }
113 
114     /**
115      * Returns the suggested time or {@code null} if there isn't one.
116      *
117      * <p>See {@link TelephonyTimeSuggestion} for more information about {@code unixEpochTime}.
118      */
119     @Nullable
getUnixEpochTime()120     public TimestampedValue<Long> getUnixEpochTime() {
121         return mUnixEpochTime;
122     }
123 
124     /**
125      * Returns debug metadata for the suggestion.
126      *
127      * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
128      */
129     @NonNull
getDebugInfo()130     public List<String> getDebugInfo() {
131         return mDebugInfo == null
132                 ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
133     }
134 
135     /**
136      * Associates information with the instance that can be useful for debugging / logging.
137      *
138      * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
139      */
addDebugInfo(@onNull String debugInfo)140     public void addDebugInfo(@NonNull String debugInfo) {
141         if (mDebugInfo == null) {
142             mDebugInfo = new ArrayList<>();
143         }
144         mDebugInfo.add(debugInfo);
145     }
146 
147     /**
148      * Associates information with the instance that can be useful for debugging / logging.
149      *
150      * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
151      */
addDebugInfo(@onNull List<String> debugInfo)152     public void addDebugInfo(@NonNull List<String> debugInfo) {
153         if (mDebugInfo == null) {
154             mDebugInfo = new ArrayList<>(debugInfo.size());
155         }
156         mDebugInfo.addAll(debugInfo);
157     }
158 
159     @Override
equals(@ullable Object o)160     public boolean equals(@Nullable Object o) {
161         if (this == o) {
162             return true;
163         }
164         if (o == null || getClass() != o.getClass()) {
165             return false;
166         }
167         TelephonyTimeSuggestion that = (TelephonyTimeSuggestion) o;
168         return mSlotIndex == that.mSlotIndex
169                 && Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
170     }
171 
172     @Override
hashCode()173     public int hashCode() {
174         return Objects.hash(mSlotIndex, mUnixEpochTime);
175     }
176 
177     @Override
toString()178     public String toString() {
179         return "TelephonyTimeSuggestion{"
180                 + "mSlotIndex='" + mSlotIndex + '\''
181                 + ", mUnixEpochTime=" + mUnixEpochTime
182                 + ", mDebugInfo=" + mDebugInfo
183                 + '}';
184     }
185 
186     /**
187      * Builds {@link TelephonyTimeSuggestion} instances.
188      *
189      * @hide
190      */
191     public static final class Builder {
192         private final int mSlotIndex;
193         @Nullable private TimestampedValue<Long> mUnixEpochTime;
194         @Nullable private List<String> mDebugInfo;
195 
196         /**
197          * Creates a builder with the specified {@code slotIndex}.
198          *
199          * <p>See {@link TelephonyTimeSuggestion} for more information about {@code slotIndex}.
200          */
Builder(int slotIndex)201         public Builder(int slotIndex) {
202             mSlotIndex = slotIndex;
203         }
204 
205         /**
206          * Returns the builder for call chaining.
207          *
208          * <p>See {@link TelephonyTimeSuggestion} for more information about {@code unixEpochTime}.
209          */
210         @NonNull
setUnixEpochTime(@ullable TimestampedValue<Long> unixEpochTime)211         public Builder setUnixEpochTime(@Nullable TimestampedValue<Long> unixEpochTime) {
212             if (unixEpochTime != null) {
213                 // unixEpochTime can be null, but the value it holds cannot.
214                 Objects.requireNonNull(unixEpochTime.getValue());
215             }
216 
217             mUnixEpochTime = unixEpochTime;
218             return this;
219         }
220 
221         /**
222          * Returns the builder for call chaining.
223          *
224          * <p>See {@link TelephonyTimeSuggestion} for more information about {@code debugInfo}.
225          */
226         @NonNull
addDebugInfo(@onNull String debugInfo)227         public Builder addDebugInfo(@NonNull String debugInfo) {
228             if (mDebugInfo == null) {
229                 mDebugInfo = new ArrayList<>();
230             }
231             mDebugInfo.add(debugInfo);
232             return this;
233         }
234 
235         /** Returns the {@link TelephonyTimeSuggestion}. */
236         @NonNull
build()237         public TelephonyTimeSuggestion build() {
238             return new TelephonyTimeSuggestion(this);
239         }
240     }
241 }
242