• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.util;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.SystemClock;
23 
24 import java.util.Objects;
25 
26 /**
27  * A value with an associated reference time. The reference time will typically be provided by the
28  * elapsed realtime clock. The elapsed realtime clock can be obtained using methods like
29  * {@link SystemClock#elapsedRealtime()} or {@link SystemClock#elapsedRealtimeClock()}.
30  * If a suitable clock is used the reference time can be used to identify the age of a value or
31  * ordering between values.
32  *
33  * <p>To read and write a timestamped value from / to a Parcel see
34  * {@link #readFromParcel(Parcel, ClassLoader, Class)} and
35  * {@link #writeToParcel(Parcel, TimestampedValue)}.
36  *
37  * @param <T> the type of the value with an associated timestamp
38  * @hide
39  */
40 public final class TimestampedValue<T> {
41     private final long mReferenceTimeMillis;
42     private final T mValue;
43 
TimestampedValue(long referenceTimeMillis, T value)44     public TimestampedValue(long referenceTimeMillis, T value) {
45         mReferenceTimeMillis = referenceTimeMillis;
46         mValue = value;
47     }
48 
getReferenceTimeMillis()49     public long getReferenceTimeMillis() {
50         return mReferenceTimeMillis;
51     }
52 
getValue()53     public T getValue() {
54         return mValue;
55     }
56 
57     @Override
equals(Object o)58     public boolean equals(Object o) {
59         if (this == o) {
60             return true;
61         }
62         if (o == null || getClass() != o.getClass()) {
63             return false;
64         }
65         TimestampedValue<?> that = (TimestampedValue<?>) o;
66         return mReferenceTimeMillis == that.mReferenceTimeMillis
67                 && Objects.equals(mValue, that.mValue);
68     }
69 
70     @Override
hashCode()71     public int hashCode() {
72         return Objects.hash(mReferenceTimeMillis, mValue);
73     }
74 
75     @Override
toString()76     public String toString() {
77         return "TimestampedValue{"
78                 + "mReferenceTimeMillis=" + mReferenceTimeMillis
79                 + ", mValue=" + mValue
80                 + '}';
81     }
82 
83     /**
84      * Read a {@link TimestampedValue} from a parcel that was stored using
85      * {@link #writeToParcel(Parcel, TimestampedValue)}.
86      *
87      * <p>The marshalling/unmarshalling of the value relies upon {@link Parcel#writeValue(Object)}
88      * and {@link Parcel#readValue(ClassLoader)} and so this method can only be used with types
89      * supported by those methods.
90      *
91      * @param in the Parcel to read from
92      * @param classLoader the ClassLoader to pass to {@link Parcel#readValue(ClassLoader)}
93      * @param valueClass the expected type of the value, typically the same as {@code <T>} but can
94      *     also be a subclass
95      * @throws RuntimeException if the value read is not compatible with {@code valueClass} or the
96      *     object could not be read
97      */
98     @SuppressWarnings("unchecked")
99     @NonNull
readFromParcel( @onNull Parcel in, @Nullable ClassLoader classLoader, Class<? extends T> valueClass)100     public static <T> TimestampedValue<T> readFromParcel(
101             @NonNull Parcel in, @Nullable ClassLoader classLoader, Class<? extends T> valueClass) {
102         long referenceTimeMillis = in.readLong();
103         T value = (T) in.readValue(classLoader);
104         // Equivalent to static code: if (!(value.getClass() instanceof {valueClass})) {
105         if (value != null && !valueClass.isAssignableFrom(value.getClass())) {
106             throw new RuntimeException("Value was of type " + value.getClass()
107                     + " is not assignable to " + valueClass);
108         }
109         return new TimestampedValue<>(referenceTimeMillis, value);
110     }
111 
112     /**
113      * Write a {@link TimestampedValue} to a parcel so that it can be read using
114      * {@link #readFromParcel(Parcel, ClassLoader, Class)}.
115      *
116      * <p>The marshalling/unmarshalling of the value relies upon {@link Parcel#writeValue(Object)}
117      * and {@link Parcel#readValue(ClassLoader)} and so this method can only be used with types
118      * supported by those methods.
119      *
120      * @param dest the Parcel
121      * @param timestampedValue the value
122      * @throws RuntimeException if the value could not be written to the Parcel
123      */
writeToParcel( @onNull Parcel dest, @NonNull TimestampedValue<?> timestampedValue)124     public static void writeToParcel(
125             @NonNull Parcel dest, @NonNull TimestampedValue<?> timestampedValue) {
126         dest.writeLong(timestampedValue.mReferenceTimeMillis);
127         dest.writeValue(timestampedValue.mValue);
128     }
129 
130     /**
131      * Returns the difference in milliseconds between two instance's reference times.
132      */
referenceTimeDifference( @onNull TimestampedValue<?> one, @NonNull TimestampedValue<?> two)133     public static long referenceTimeDifference(
134             @NonNull TimestampedValue<?> one, @NonNull TimestampedValue<?> two) {
135         return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
136     }
137 }
138