Merge "Fuzz java parcel surfaces" am: 8a09c9a244 am: bd98943f2c
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2321414 Change-Id: I2546058994536bb8026e966b94d969ef8c5a4661 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -432,6 +432,7 @@ filegroup {
|
||||
"android/os/IInterface.java",
|
||||
"android/os/Binder.java",
|
||||
"android/os/IBinder.java",
|
||||
"android/os/Parcelable.java",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ public class FuzzBinder {
|
||||
fuzzServiceInternal(binder, data);
|
||||
}
|
||||
|
||||
// This API creates random parcel object
|
||||
public static void createRandomParcel(Parcel parcel, byte[] data) {
|
||||
getRandomParcel(parcel, data);
|
||||
// This API fills parcel object
|
||||
public static void fillRandomParcel(Parcel parcel, byte[] data) {
|
||||
fillParcelInternal(parcel, data);
|
||||
}
|
||||
|
||||
private static native void fuzzServiceInternal(IBinder binder, byte[] data);
|
||||
private static native void getRandomParcel(Parcel parcel, byte[] data);
|
||||
private static native void fillParcelInternal(Parcel parcel, byte[] data);
|
||||
private static native int registerNatives();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ JNIEXPORT jint JNICALL Java_randomparcel_FuzzBinder_registerNatives(JNIEnv* env)
|
||||
return registerFrameworkNatives(env);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_getRandomParcel(JNIEnv *env, jobject thiz, jobject jparcel, jbyteArray fuzzData) {
|
||||
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_fillParcelInternal(JNIEnv *env, jobject thiz, jobject jparcel, jbyteArray fuzzData) {
|
||||
size_t len = static_cast<size_t>(env->GetArrayLength(fuzzData));
|
||||
uint8_t data[len];
|
||||
env->GetByteArrayRegion(fuzzData, 0, len, reinterpret_cast<jbyte*>(data));
|
||||
|
||||
@@ -24,5 +24,5 @@ extern "C" {
|
||||
// Function from AndroidRuntime
|
||||
jint registerFrameworkNatives(JNIEnv* env);
|
||||
|
||||
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_getRandomParcel(JNIEnv *env, jobject thiz, jobject parcel, jbyteArray fuzzData);
|
||||
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_fillParcelInternal(JNIEnv *env, jobject thiz, jobject parcel, jbyteArray fuzzData);
|
||||
}
|
||||
|
||||
40
core/tests/fuzzers/ParcelFuzzer/Android.bp
Normal file
40
core/tests/fuzzers/ParcelFuzzer/Android.bp
Normal file
@@ -0,0 +1,40 @@
|
||||
package {
|
||||
default_applicable_licenses: ["frameworks_base_license"],
|
||||
}
|
||||
|
||||
java_fuzz {
|
||||
name: "java_binder_parcel_fuzzer",
|
||||
srcs: [
|
||||
"ParcelFuzzer.java",
|
||||
"ReadUtils.java",
|
||||
"FuzzUtils.java",
|
||||
"FuzzOperation.java",
|
||||
"ReadOperation.java",
|
||||
":framework-core-sources-for-fuzzers",
|
||||
],
|
||||
static_libs: [
|
||||
"jazzer",
|
||||
"random_parcel_lib",
|
||||
"binderReadParcelIface-java",
|
||||
],
|
||||
jni_libs: [
|
||||
"librandom_parcel_jni",
|
||||
"libc++",
|
||||
"libandroid_runtime",
|
||||
],
|
||||
libs: [
|
||||
"framework",
|
||||
"unsupportedappusage",
|
||||
"ext",
|
||||
"framework-res",
|
||||
],
|
||||
native_bridge_supported: true,
|
||||
fuzz_config: {
|
||||
cc: [
|
||||
"smoreland@google.com",
|
||||
"waghpawan@google.com",
|
||||
],
|
||||
// Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
|
||||
hotlists: ["4637097"],
|
||||
},
|
||||
}
|
||||
22
core/tests/fuzzers/ParcelFuzzer/FuzzOperation.java
Normal file
22
core/tests/fuzzers/ParcelFuzzer/FuzzOperation.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 parcelfuzzer;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
|
||||
public interface FuzzOperation {
|
||||
void doFuzz(FuzzedDataProvider data);
|
||||
}
|
||||
87
core/tests/fuzzers/ParcelFuzzer/FuzzUtils.java
Normal file
87
core/tests/fuzzers/ParcelFuzzer/FuzzUtils.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 parcelfuzzer;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
|
||||
import randomparcel.FuzzBinder;
|
||||
|
||||
public class FuzzUtils {
|
||||
public static FuzzOperation[] FUZZ_OPERATIONS =
|
||||
new FuzzOperation[] {
|
||||
new FuzzOperation() {
|
||||
@java.lang.Override
|
||||
public void doFuzz(FuzzedDataProvider provider) {
|
||||
// Fuzz Append
|
||||
int start = provider.consumeInt();
|
||||
int len = provider.consumeInt();
|
||||
Parcel p1 = null;
|
||||
Parcel p2 = null;
|
||||
|
||||
try {
|
||||
p1 = Parcel.obtain();
|
||||
p2 = Parcel.obtain();
|
||||
|
||||
byte[] data =
|
||||
provider.consumeBytes(
|
||||
provider.consumeInt(0, provider.remainingBytes()));
|
||||
FuzzBinder.fillRandomParcel(p1, data);
|
||||
FuzzBinder.fillRandomParcel(p2, provider.consumeRemainingAsBytes());
|
||||
|
||||
p1.appendFrom(p2, start, len);
|
||||
|
||||
} catch (Exception e) {
|
||||
// Rethrow exception as runtime exceptions are catched
|
||||
// at highest level.
|
||||
throw e;
|
||||
} finally {
|
||||
p1.recycle();
|
||||
p2.recycle();
|
||||
}
|
||||
}
|
||||
},
|
||||
new FuzzOperation() {
|
||||
@java.lang.Override
|
||||
public void doFuzz(FuzzedDataProvider provider) {
|
||||
// Fuzz Read
|
||||
// Use maximum bytes to generate read instructions and remaining for parcel
|
||||
// creation
|
||||
int maxParcelBytes = provider.remainingBytes() / 3;
|
||||
byte[] data = provider.consumeBytes(maxParcelBytes);
|
||||
Parcel randomParcel = null;
|
||||
|
||||
try {
|
||||
randomParcel = Parcel.obtain();
|
||||
FuzzBinder.fillRandomParcel(randomParcel, data);
|
||||
|
||||
while (provider.remainingBytes() > 0) {
|
||||
provider.pickValue(ReadUtils.READ_OPERATIONS)
|
||||
.readParcel(randomParcel, provider);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// Rethrow exception as runtime exceptions are catched
|
||||
// at highest level.
|
||||
throw e;
|
||||
} finally {
|
||||
randomParcel.recycle();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
42
core/tests/fuzzers/ParcelFuzzer/ParcelFuzzer.java
Normal file
42
core/tests/fuzzers/ParcelFuzzer/ParcelFuzzer.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 parcelfuzzer;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
|
||||
import randomparcel.FuzzBinder;
|
||||
|
||||
public class ParcelFuzzer {
|
||||
|
||||
static {
|
||||
// Initialize JNI dependencies
|
||||
FuzzBinder.init();
|
||||
}
|
||||
|
||||
public static void fuzzerTestOneInput(FuzzedDataProvider provider) {
|
||||
// Default behavior for Java APIs is to throw RuntimeException.
|
||||
// We need to fuzz to detect other problems which are not handled explicitly.
|
||||
// TODO(b/150808347): Change known API exceptions to subclass of
|
||||
// RuntimeExceptions and catch those only.
|
||||
try {
|
||||
provider.pickValue(FuzzUtils.FUZZ_OPERATIONS).doFuzz(provider);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e("ParcelFuzzer", "Exception occurred while fuzzing ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
core/tests/fuzzers/ParcelFuzzer/ReadOperation.java
Normal file
24
core/tests/fuzzers/ParcelFuzzer/ReadOperation.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 parcelfuzzer;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||
|
||||
public interface ReadOperation {
|
||||
void readParcel(Parcel parcel, FuzzedDataProvider provider);
|
||||
}
|
||||
435
core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
Normal file
435
core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
Normal file
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 parcelfuzzer;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import parcelables.EmptyParcelable;
|
||||
import parcelables.GenericDataParcelable;
|
||||
import parcelables.SingleDataParcelable;
|
||||
|
||||
public class ReadUtils {
|
||||
public static int MAX_LEN = 1000000;
|
||||
public static int MIN_LEN = 0;
|
||||
|
||||
private static class SomeParcelable implements Parcelable {
|
||||
private final int mValue;
|
||||
|
||||
private SomeParcelable(Parcel in) {
|
||||
this.mValue = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeInt(mValue);
|
||||
}
|
||||
|
||||
public static Parcelable.Creator<SomeParcelable> CREATOR =
|
||||
new Parcelable.Creator<SomeParcelable>() {
|
||||
|
||||
@Override
|
||||
public SomeParcelable createFromParcel(Parcel source) {
|
||||
return new SomeParcelable(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SomeParcelable[] newArray(int size) {
|
||||
return new SomeParcelable[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class TestClassLoader extends ClassLoader {
|
||||
TestClassLoader() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestInterface implements IInterface {
|
||||
public Binder binder;
|
||||
private static final String DESCRIPTOR = "TestInterface";
|
||||
|
||||
TestInterface() {
|
||||
binder = new Binder();
|
||||
binder.attachInterface(this, DESCRIPTOR);
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public static TestInterface asInterface(IBinder binder) {
|
||||
if (binder != null) {
|
||||
IInterface iface = binder.queryLocalInterface(DESCRIPTOR);
|
||||
if (iface != null && iface instanceof TestInterface) {
|
||||
return (TestInterface) iface;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ReadOperation[] READ_OPERATIONS =
|
||||
new ReadOperation[] {
|
||||
(parcel, provider) -> {
|
||||
parcel.setDataPosition(provider.consumeInt());
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.setDataCapacity(provider.consumeInt());
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.setDataSize(provider.consumeInt());
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.dataSize();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.dataPosition();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.dataCapacity();
|
||||
},
|
||||
|
||||
// read basic types
|
||||
(parcel, provider) -> {
|
||||
parcel.readByte();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readBoolean();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readInt();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readLong();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readFloat();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readDouble();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readString();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readString8();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readString16();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readBlob();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readStrongBinder();
|
||||
},
|
||||
|
||||
// read arrays of random length
|
||||
(parcel, provider) -> {
|
||||
byte[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new byte[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new byte[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readByteArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
char[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new char[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new char[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readCharArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
int[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new int[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new int[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readIntArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
double[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new double[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new double[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readDoubleArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
float[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new float[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new float[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readFloatArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
boolean[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new boolean[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new boolean[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readBooleanArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
long[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new long[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new long[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readLongArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
IBinder[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new IBinder[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new IBinder[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readBinderArray(array);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
ArrayList<IBinder> arrayList = new ArrayList<IBinder>();
|
||||
parcel.readBinderList(arrayList);
|
||||
},
|
||||
|
||||
// unmarshall from random parcel data and random bytes
|
||||
(parcel, provider) -> {
|
||||
byte[] data = parcel.marshall();
|
||||
Parcel p = Parcel.obtain();
|
||||
p.unmarshall(data, provider.consumeInt(), provider.consumeInt());
|
||||
p.recycle();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
byte[] data = provider.consumeRemainingAsBytes();
|
||||
Parcel p = Parcel.obtain();
|
||||
p.unmarshall(data, provider.consumeInt(), provider.consumeInt());
|
||||
p.recycle();
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.hasFileDescriptors(provider.consumeInt(), provider.consumeInt());
|
||||
},
|
||||
|
||||
// read AIDL generated parcelables
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelable(loader, SingleDataParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelableArray(loader, SingleDataParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
SingleDataParcelable[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new SingleDataParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new SingleDataParcelable[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readTypedArray(array, SingleDataParcelable.CREATOR);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelable(loader, EmptyParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelableArray(loader, EmptyParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
EmptyParcelable[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new EmptyParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new EmptyParcelable[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readTypedArray(array, EmptyParcelable.CREATOR);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelable(loader, GenericDataParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelableArray(loader, GenericDataParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
GenericDataParcelable[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new GenericDataParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
int len = provider.consumeInt(MIN_LEN, MAX_LEN);
|
||||
array = new GenericDataParcelable[len];
|
||||
}
|
||||
parcel.readTypedArray(array, GenericDataParcelable.CREATOR);
|
||||
},
|
||||
|
||||
// read parcelables
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelable(loader, SomeParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelableArray(loader, SomeParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
SomeParcelable[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new SomeParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new SomeParcelable[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readTypedArray(array, SomeParcelable.CREATOR);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelableArray(loader);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.hasFileDescriptors(provider.consumeInt(), provider.consumeInt());
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readParcelableArray(loader);
|
||||
},
|
||||
|
||||
// read lists
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readArrayList(loader);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readArrayList(loader, Object.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readArrayList(loader, SomeParcelable.class);
|
||||
},
|
||||
|
||||
// read sparse arrays
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readSparseArray(loader);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readSparseArray(loader, Object.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readSparseArray(loader, SomeParcelable.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readSerializable(loader, Object.class);
|
||||
},
|
||||
|
||||
// read interface
|
||||
(parcel, provider) -> {
|
||||
TestInterface[] array;
|
||||
if (provider.consumeBoolean()) {
|
||||
int pos = parcel.dataPosition();
|
||||
array = new TestInterface[Math.min(MAX_LEN, parcel.readInt())];
|
||||
parcel.setDataPosition(pos);
|
||||
} else {
|
||||
array = new TestInterface[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||
}
|
||||
parcel.readInterfaceArray(array, TestInterface::asInterface);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
int w = provider.consumeInt(MIN_LEN, MAX_LEN);
|
||||
int h = provider.consumeInt(MIN_LEN, MAX_LEN);
|
||||
TestInterface[][] array = new TestInterface[w][h];
|
||||
parcel.readFixedArray(array, TestInterface::asInterface);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
ArrayList<TestInterface> array = new ArrayList<TestInterface>();
|
||||
parcel.readInterfaceList(array, TestInterface::asInterface);
|
||||
},
|
||||
|
||||
// read bundle
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readBundle(loader);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
parcel.readBundle();
|
||||
},
|
||||
|
||||
// read HashMap
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readHashMap(loader);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readHashMap(loader, String.class, String.class);
|
||||
},
|
||||
(parcel, provider) -> {
|
||||
HashMap<String, String> hashMap = new HashMap<>();
|
||||
TestClassLoader loader = new TestClassLoader();
|
||||
parcel.readMap(hashMap, loader, String.class, String.class);
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user