Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81a70569 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Make TimestampedValue Parcelable"

parents 8b178a66 def77b5c
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -56,8 +56,7 @@ public final class TimeSignal implements Parcelable {

    private static TimeSignal createFromParcel(Parcel in) {
        String sourceId = in.readString();
        TimestampedValue<Long> utcTime =
                TimestampedValue.readFromParcel(in, null /* classLoader */, Long.class);
        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
        return new TimeSignal(sourceId, utcTime);
    }

@@ -69,7 +68,7 @@ public final class TimeSignal implements Parcelable {
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeString(mSourceId);
        TimestampedValue.writeToParcel(dest, mUtcTime);
        dest.writeParcelable(mUtcTime, 0);
    }

    @NonNull
+38 −51
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;

import java.util.Objects;
@@ -30,14 +31,14 @@ import java.util.Objects;
 * 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)}.
 * <p>This class implements {@link Parcelable} for convenience but instances will only actually be
 * parcelable if the value type held is {@code null}, {@link Parcelable}, or one of the other types
 * supported by {@link Parcel#writeValue(Object)} / {@link Parcel#readValue(ClassLoader)}.
 *
 * @param <T> the type of the value with an associated timestamp
 * @hide
 */
public final class TimestampedValue<T> {
public final class TimestampedValue<T> implements Parcelable {
    private final long mReferenceTimeMillis;
    private final T mValue;

@@ -81,57 +82,43 @@ public final class TimestampedValue<T> {
    }

    /**
     * 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
     * Returns the difference in milliseconds between two instance's reference times.
     */
    @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);
    public static long referenceTimeDifference(
            @NonNull TimestampedValue<?> one, @NonNull TimestampedValue<?> two) {
        return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
    }

    public static final @NonNull Parcelable.Creator<TimestampedValue<?>> CREATOR =
            new Parcelable.ClassLoaderCreator<TimestampedValue<?>>() {

                @Override
                public TimestampedValue<?> createFromParcel(@NonNull Parcel source) {
                    return createFromParcel(source, null);
                }

                @Override
                public TimestampedValue<?> createFromParcel(
                        @NonNull Parcel source, @Nullable ClassLoader classLoader) {
                    long referenceTimeMillis = source.readLong();
                    Object value = source.readValue(classLoader);
                    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);
                @Override
                public TimestampedValue[] newArray(int size) {
                    return new TimestampedValue[size];
                }
            };

    /**
     * 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;
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeLong(mReferenceTimeMillis);
        dest.writeValue(mValue);
    }
}
+14 −15
Original line number Diff line number Diff line
@@ -55,12 +55,12 @@ public class TimestampedValueTest {
        TimestampedValue<String> stringValue = new TimestampedValue<>(1000, "Hello");
        Parcel parcel = Parcel.obtain();
        try {
            TimestampedValue.writeToParcel(parcel, stringValue);
            parcel.writeParcelable(stringValue, 0);

            parcel.setDataPosition(0);

            TimestampedValue<String> stringValueCopy =
                    TimestampedValue.readFromParcel(parcel, null /* classLoader */, String.class);
                    parcel.readParcelable(null /* classLoader */);
            assertEquals(stringValue, stringValueCopy);
        } finally {
            parcel.recycle();
@@ -72,12 +72,12 @@ public class TimestampedValueTest {
        TimestampedValue<String> stringValue = new TimestampedValue<>(1000, "Hello");
        Parcel parcel = Parcel.obtain();
        try {
            TimestampedValue.writeToParcel(parcel, stringValue);
            parcel.writeParcelable(stringValue, 0);

            parcel.setDataPosition(0);

            TimestampedValue<Object> stringValueCopy =
                    TimestampedValue.readFromParcel(parcel, null /* classLoader */, Object.class);
            TimestampedValue<String> stringValueCopy =
                    parcel.readParcelable(null /* classLoader */);
            assertEquals(stringValue, stringValueCopy);
        } finally {
            parcel.recycle();
@@ -85,15 +85,15 @@ public class TimestampedValueTest {
    }

    @Test
    public void testParceling_valueClassIncompatible() {
        TimestampedValue<String> stringValue = new TimestampedValue<>(1000, "Hello");
    public void testParceling_valueClassNotParcelable() {
        // This class is not one supported by Parcel.writeValue().
        class NotParcelable {}

        TimestampedValue<NotParcelable> notParcelableValue =
                new TimestampedValue<>(1000, new NotParcelable());
        Parcel parcel = Parcel.obtain();
        try {
            TimestampedValue.writeToParcel(parcel, stringValue);

            parcel.setDataPosition(0);

            TimestampedValue.readFromParcel(parcel, null /* classLoader */, Double.class);
            parcel.writeParcelable(notParcelableValue, 0);
            fail();
        } catch (RuntimeException expected) {
        } finally {
@@ -106,12 +106,11 @@ public class TimestampedValueTest {
        TimestampedValue<String> nullValue = new TimestampedValue<>(1000, null);
        Parcel parcel = Parcel.obtain();
        try {
            TimestampedValue.writeToParcel(parcel, nullValue);
            parcel.writeParcelable(nullValue, 0);

            parcel.setDataPosition(0);

            TimestampedValue<Object> nullValueCopy =
                    TimestampedValue.readFromParcel(parcel, null /* classLoader */, String.class);
            TimestampedValue<String> nullValueCopy = parcel.readParcelable(null /* classLoader */);
            assertEquals(nullValue, nullValueCopy);
        } finally {
            parcel.recycle();