1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.SystemClock;
import java.util.Objects;
/**
* A value with an associated reference time. The reference time will typically be provided by the
* elapsed realtime clock. The elapsed realtime clock can be obtained using methods like
* {@link SystemClock#elapsedRealtime()} or {@link SystemClock#elapsedRealtimeClock()}.
* If a suitable clock is used the reference time can be used to identify the age of a value or
* ordering between values.
*
* <p>To read and write a timestamped value from / to a Parcel see
* {@link #readFromParcel(Parcel, ClassLoader, Class)} and
* {@link #writeToParcel(Parcel, TimestampedValue)}.
*
* @param <T> the type of the value with an associated timestamp
* @hide
*/
public final class TimestampedValue<T> {
private final long mReferenceTimeMillis;
private final T mValue;
public TimestampedValue(long referenceTimeMillis, T value) {
mReferenceTimeMillis = referenceTimeMillis;
mValue = value;
}
public long getReferenceTimeMillis() {
return mReferenceTimeMillis;
}
public T getValue() {
return mValue;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TimestampedValue<?> that = (TimestampedValue<?>) o;
return mReferenceTimeMillis == that.mReferenceTimeMillis
&& Objects.equals(mValue, that.mValue);
}
@Override
public int hashCode() {
return Objects.hash(mReferenceTimeMillis, mValue);
}
@Override
public String toString() {
return "TimestampedValue{"
+ "mReferenceTimeMillis=" + mReferenceTimeMillis
+ ", mValue=" + mValue
+ '}';
}
/**
* Read a {@link TimestampedValue} from a parcel that was stored using
* {@link #writeToParcel(Parcel, TimestampedValue)}.
*
* <p>The marshalling/unmarshalling of the value relies upon {@link Parcel#writeValue(Object)}
* and {@link Parcel#readValue(ClassLoader)} and so this method can only be used with types
* supported by those methods.
*
* @param in the Parcel to read from
* @param classLoader the ClassLoader to pass to {@link Parcel#readValue(ClassLoader)}
* @param valueClass the expected type of the value, typically the same as {@code <T>} but can
* also be a subclass
* @throws RuntimeException if the value read is not compatible with {@code valueClass} or the
* object could not be read
*/
@SuppressWarnings("unchecked")
@NonNull
public static <T> TimestampedValue<T> readFromParcel(
@NonNull Parcel in, @Nullable ClassLoader classLoader, Class<? extends T> valueClass) {
long referenceTimeMillis = in.readLong();
T value = (T) in.readValue(classLoader);
// Equivalent to static code: if (!(value.getClass() instanceof {valueClass})) {
if (value != null && !valueClass.isAssignableFrom(value.getClass())) {
throw new RuntimeException("Value was of type " + value.getClass()
+ " is not assignable to " + valueClass);
}
return new TimestampedValue<>(referenceTimeMillis, value);
}
/**
* Write a {@link TimestampedValue} to a parcel so that it can be read using
* {@link #readFromParcel(Parcel, ClassLoader, Class)}.
*
* <p>The marshalling/unmarshalling of the value relies upon {@link Parcel#writeValue(Object)}
* and {@link Parcel#readValue(ClassLoader)} and so this method can only be used with types
* supported by those methods.
*
* @param dest the Parcel
* @param timestampedValue the value
* @throws RuntimeException if the value could not be written to the Parcel
*/
public static void writeToParcel(
@NonNull Parcel dest, @NonNull TimestampedValue<?> timestampedValue) {
dest.writeLong(timestampedValue.mReferenceTimeMillis);
dest.writeValue(timestampedValue.mValue);
}
/**
* Returns the difference in milliseconds between two instance's reference times.
*/
public static long referenceTimeDifference(
@NonNull TimestampedValue<?> one, @NonNull TimestampedValue<?> two) {
return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
}
}
|