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

Commit 98a4a1b8 authored by Bernardo Rufino's avatar Bernardo Rufino Committed by Gerrit Code Review
Browse files

Merge "Add range-based Parcel.compareData()"

parents c9b6889e 7e4edf5b
Loading
Loading
Loading
Loading
+9 −14
Original line number Diff line number Diff line
@@ -381,6 +381,8 @@ public final class Parcel {
    private static native void nativeUnmarshall(
            long nativePtr, byte[] data, int offset, int length);
    private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
    private static native boolean nativeCompareDataInRange(
            long ptrA, int offsetA, long ptrB, int offsetB, int length);
    private static native void nativeAppendFrom(
            long thisNativePtr, long otherNativePtr, int offset, int length);
    @CriticalNative
@@ -678,10 +680,15 @@ public final class Parcel {
    }

    /** @hide */
    public final int compareData(Parcel other) {
    public int compareData(Parcel other) {
        return nativeCompareData(mNativePtr, other.mNativePtr);
    }

    /** @hide */
    public static boolean compareData(Parcel a, int offsetA, Parcel b, int offsetB, int length) {
        return nativeCompareDataInRange(a.mNativePtr, offsetA, b.mNativePtr, offsetB, length);
    }

    /** @hide */
    public final void setClassCookie(Class clz, Object cookie) {
        if (mClassCookies == null) {
@@ -3609,7 +3616,6 @@ public final class Parcel {
        private final int mType;
        @Nullable private final ClassLoader mLoader;
        @Nullable private Object mObject;
        @Nullable private volatile Parcel mValueParcel;

        /**
         * This goes from non-null to null once. Always check the nullability of this object before
@@ -3707,7 +3713,7 @@ public final class Parcel {
                return false;
            }
            // Finally we compare the payload.
            return getValueParcel(source).compareData(value.getValueParcel(otherSource)) == 0;
            return Parcel.compareData(source, mPosition, otherSource, value.mPosition, mLength);
        }

        @Override
@@ -3715,17 +3721,6 @@ public final class Parcel {
            // Accessing mSource first to provide memory barrier for mObject
            return Objects.hash(mSource == null, mObject, mLoader, mType, mLength);
        }

        /** This extracts the parcel section responsible for the object and returns it. */
        private Parcel getValueParcel(Parcel source) {
            Parcel parcel = mValueParcel;
            if (parcel == null) {
                parcel = Parcel.obtain();
                parcel.appendFrom(source, mPosition, mLength);
                mValueParcel = parcel;
            }
            return parcel;
        }
    }

    /**
+20 −0
Original line number Diff line number Diff line
@@ -604,6 +604,25 @@ static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisN
    return thisParcel->compareData(*otherParcel);
}

static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
                                                     jint thisOffset, jlong otherNativePtr,
                                                     jint otherOffset, jint length) {
    Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
    LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");

    Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
    LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");

    int result;
    status_t err =
            thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
    if (err != NO_ERROR) {
        signalExceptionForError(env, clazz, err);
        return JNI_FALSE;
    }
    return (result == 0) ? JNI_TRUE : JNI_FALSE;
}

static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
                                          jlong otherNativePtr, jint offset, jint length)
{
@@ -841,6 +860,7 @@ static const JNINativeMethod gParcelMethods[] = {
    {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
    {"nativeUnmarshall",          "(J[BII)V", (void*)android_os_Parcel_unmarshall},
    {"nativeCompareData",         "(JJ)I", (void*)android_os_Parcel_compareData},
    {"nativeCompareDataInRange",  "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
    {"nativeAppendFrom",          "(JJII)V", (void*)android_os_Parcel_appendFrom},
    // @CriticalNative
    {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
+8 −3
Original line number Diff line number Diff line
@@ -273,16 +273,21 @@ public class BundleTest {
        Parcelable p1 = new CustomParcelable(13, "Tiramisu");
        Parcelable p2 = new CustomParcelable(13, "Tiramisu");
        Bundle a = new Bundle();
        a.putParcelable("key", p1);
        a.putParcelable("key1", p1);
        a.readFromParcel(getParcelledBundle(a));
        a.setClassLoader(getClass().getClassLoader());
        Bundle b = new Bundle();
        b.putParcelable("key", p2);
        // Adding extra element so that the position of the elements of interest in their respective
        // source parcels are different so we can cover that case of Parcel.compareData(). We'll
        // remove the element later so the map is equal.
        b.putString("key0", "string");
        b.putParcelable("key1", p2);
        b.readFromParcel(getParcelledBundle(b));
        b.setClassLoader(getClass().getClassLoader());
        // 2 lazy values with identical parcels inside
        a.isEmpty();
        b.isEmpty();
        b.remove("key0");
        // 2 lazy values with identical parcels inside

        assertTrue(Bundle.kindofEquals(a, b));
    }
+129 −0
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
package android.os;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import android.platform.test.annotations.Presubmit;

@@ -110,4 +113,130 @@ public class ParcelTest {
            assertEquals(string, p.readString16());
        }
    }

    @Test
    public void testCompareDataInRange_whenSameData() {
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(13);
        pA.writeString("Tiramisu");
        int length = pA.dataPosition() - iA;
        Parcel pB = Parcel.obtain();
        pB.writeString("Prefix");
        int iB = pB.dataPosition();
        pB.writeInt(13);
        pB.writeString("Tiramisu");

        assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
    }

    @Test
    public void testCompareDataInRange_whenSameDataWithBinder() {
        Binder binder = new Binder();
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(13);
        pA.writeStrongBinder(binder);
        pA.writeString("Tiramisu");
        int length = pA.dataPosition() - iA;
        Parcel pB = Parcel.obtain();
        pB.writeString("Prefix");
        int iB = pB.dataPosition();
        pB.writeInt(13);
        pB.writeStrongBinder(binder);
        pB.writeString("Tiramisu");

        assertTrue(Parcel.compareData(pA, iA, pB, iB, length));
    }

    @Test
    public void testCompareDataInRange_whenDifferentData() {
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(13);
        pA.writeString("Tiramisu");
        int length = pA.dataPosition() - iA;
        Parcel pB = Parcel.obtain();
        int iB = pB.dataPosition();
        pB.writeString("Prefix");
        pB.writeInt(13);
        pB.writeString("Tiramisu");

        assertFalse(Parcel.compareData(pA, iA, pB, iB, length));
    }

    @Test
    public void testCompareDataInRange_whenLimitOutOfBounds_throws() {
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(12);
        pA.writeString("Tiramisu");
        int length = pA.dataPosition() - iA;
        Parcel pB = Parcel.obtain();
        pB.writeString("Prefix");
        int iB = pB.dataPosition();
        pB.writeInt(13);
        pB.writeString("Tiramisu");
        pB.writeInt(-1);

        assertThrows(IllegalArgumentException.class,
                () -> Parcel.compareData(pA, iA + length, pB, iB, 1));
        assertThrows(IllegalArgumentException.class,
                () -> Parcel.compareData(pA, iA, pB, pB.dataSize(), 1));
        assertThrows(IllegalArgumentException.class,
                () -> Parcel.compareData(pA, iA, pB, iB, length + 1));
        assertThrows(IllegalArgumentException.class,
                () -> Parcel.compareData(pA, iA + length + 1, pB, iB, 0));
        assertThrows(IllegalArgumentException.class,
                () -> Parcel.compareData(pA, iA, pB, iB + pB.dataSize() + 1, 0));
    }

    @Test
    public void testCompareDataInRange_whenLengthZero() {
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(12);
        pA.writeString("Tiramisu");
        int length = pA.dataPosition() - iA;
        Parcel pB = Parcel.obtain();
        pB.writeString("Prefix");
        int iB = pB.dataPosition();
        pB.writeInt(13);
        pB.writeString("Tiramisu");

        assertTrue(Parcel.compareData(pA, 0, pB, iB, 0));
        assertTrue(Parcel.compareData(pA, iA + length, pB, iB, 0));
        assertTrue(Parcel.compareData(pA, iA, pB, pB.dataSize(), 0));
    }

    @Test
    public void testCompareDataInRange_whenNegativeLength_throws() {
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(12);
        pA.writeString("Tiramisu");
        Parcel pB = Parcel.obtain();
        pB.writeString("Prefix");
        int iB = pB.dataPosition();
        pB.writeInt(13);
        pB.writeString("Tiramisu");

        assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, iA, pB, iB, -1));
    }

    @Test
    public void testCompareDataInRange_whenNegativeOffset_throws() {
        Parcel pA = Parcel.obtain();
        int iA = pA.dataPosition();
        pA.writeInt(12);
        pA.writeString("Tiramisu");
        Parcel pB = Parcel.obtain();
        pB.writeString("Prefix");
        int iB = pB.dataPosition();
        pB.writeInt(13);
        pB.writeString("Tiramisu");

        assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0));
        assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0));
    }
}