/* * 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. * *

To read and write a timestamped value from / to a Parcel see * {@link #readFromParcel(Parcel, ClassLoader, Class)} and * {@link #writeToParcel(Parcel, TimestampedValue)}. * * @param the type of the value with an associated timestamp * @hide */ public final class TimestampedValue { 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)}. * *

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 } 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 TimestampedValue readFromParcel( @NonNull Parcel in, @Nullable ClassLoader classLoader, Class 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)}. * *

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; } }