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

Commit bfe51f8b authored by Neil Fuller's avatar Neil Fuller Committed by android-build-merger
Browse files

Merge "Make TimestampedValue Parcelable" am: 81a70569 am: 209c74f8

am: 4055cdd9

Change-Id: I2e507f9cef730c1032767500d36dc0397499c310
parents 434b36ec 4055cdd9
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();