Merge "Add range-based Parcel.compareData()"
This commit is contained in:
commit
98a4a1b8b9
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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},
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user