blob: 1289e4db0743603e57cfb5e80734c9b1612331cd [file] [log] [blame]
Neil Fuller4773b9d2018-06-08 18:44:49 +01001/*
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
17package android.util;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.os.Parcel;
22import android.os.SystemClock;
23
24import 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 */
40public final class TimestampedValue<T> {
41 private final long mReferenceTimeMillis;
42 private final T mValue;
43
44 public TimestampedValue(long referenceTimeMillis, T value) {
45 mReferenceTimeMillis = referenceTimeMillis;
46 mValue = value;
47 }
48
49 public long getReferenceTimeMillis() {
50 return mReferenceTimeMillis;
51 }
52
53 public T getValue() {
54 return mValue;
55 }
56
57 @Override
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
71 public int hashCode() {
72 return Objects.hash(mReferenceTimeMillis, mValue);
73 }
74
Neil Fullerca97b342018-06-13 15:23:32 +010075 @Override
76 public String toString() {
77 return "TimestampedValue{"
78 + "mReferenceTimeMillis=" + mReferenceTimeMillis
79 + ", mValue=" + mValue
80 + '}';
81 }
82
Neil Fuller4773b9d2018-06-08 18:44:49 +010083 /**
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
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 */
124 public static void writeToParcel(
125 @NonNull Parcel dest, @NonNull TimestampedValue<?> timestampedValue) {
126 dest.writeLong(timestampedValue.mReferenceTimeMillis);
127 dest.writeValue(timestampedValue.mValue);
128 }
Neil Fuller4980bbc2018-06-12 21:06:20 +0100129
130 /**
131 * Returns the difference in milliseconds between two instance's reference times.
132 */
133 public static long referenceTimeDifference(
134 @NonNull TimestampedValue<?> one, @NonNull TimestampedValue<?> two) {
135 return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
136 }
Neil Fuller4773b9d2018-06-08 18:44:49 +0100137}