From bbacfde150f750212279413f035716a28633c0eb Mon Sep 17 00:00:00 2001
From: Jooyung Han
Date: Fri, 5 Nov 2021 17:03:35 +0900
Subject: Parcel: add new methods for interface list/array
New methods are to write a list/array of interface objects and to read
them again.
Basically these methods are quite similar to those for IBinder objects.
But when reading IInterface objects, we need to create an array of the
exact type and need a way of converting IBinder into IInterface value.
Two functional interfaces (newArray and asInterface) are just like
while Parcelable.Creator does. We could pass "Stub" class which is
generated by the AIDL compiler and use reflection to create a typed
array instance and call `asInterface` method. But rather than relying on
reflection, passing `IMyInterface[]::new` and
`IMyInterface.Stub::asInterface` would be simple enough to use.
Bug: 205195901
Test: atest -d android.os.cts.ParcelTest
Change-Id: I275db9ebf52d3b9713fa105d81da3a1d289d96a8
---
core/java/android/os/Parcel.java | 146 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 145 insertions(+), 1 deletion(-)
(limited to 'core/java/android')
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index d1e671691897..5a2f27d83893 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -62,6 +62,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.function.Function;
+import java.util.function.IntFunction;
import java.util.function.Supplier;
/**
@@ -178,8 +180,12 @@ import java.util.function.Supplier;
* {@link #writeStrongInterface(IInterface)}, {@link #readStrongBinder()},
* {@link #writeBinderArray(IBinder[])}, {@link #readBinderArray(IBinder[])},
* {@link #createBinderArray()},
+ * {@link #writeInterfaceArray(T[])}, {@link #readInterfaceArray(T[], Function)},
+ * {@link #createInterfaceArray(IntFunction, Function)},
* {@link #writeBinderList(List)}, {@link #readBinderList(List)},
- * {@link #createBinderArrayList()}.
+ * {@link #createBinderArrayList()},
+ * {@link #writeInterfaceList(List)}, {@link #readInterfaceList(List, Function)},
+ * {@link #createInterfaceArrayList(Function)}.
*
* FileDescriptor objects, representing raw Linux file descriptor identifiers,
* can be written and {@link ParcelFileDescriptor} objects returned to operate
@@ -1729,6 +1735,30 @@ public final class Parcel {
}
}
+ /**
+ * Flatten a homogeneous array containing an IInterface type into the parcel,
+ * at the current dataPosition() and growing dataCapacity() if needed. The
+ * type of the objects in the array must be one that implements IInterface.
+ *
+ * @param val The array of objects to be written.
+ *
+ * @see #createInterfaceArray
+ * @see #readInterfaceArray
+ * @see IInterface
+ */
+ public final void writeInterfaceArray(
+ @SuppressLint("ArrayReturn") @Nullable T[] val) {
+ if (val != null) {
+ int N = val.length;
+ writeInt(N);
+ for (int i=0; i T[] createInterfaceArray(
+ @NonNull IntFunction newArray, @NonNull Function asInterface) {
+ int N = readInt();
+ if (N >= 0) {
+ T[] val = newArray.apply(N);
+ for (int i=0; i void readInterfaceArray(
+ @SuppressLint("ArrayReturn") @NonNull T[] val,
+ @NonNull Function asInterface) {
+ int N = readInt();
+ if (N == val.length) {
+ for (int i=0; i void writeInterfaceList(@Nullable List val) {
+ if (val == null) {
+ writeInt(-1);
+ return;
+ }
+ int N = val.size();
+ int i=0;
+ writeInt(N);
+ while (i < N) {
+ writeStrongInterface(val.get(i));
+ i++;
+ }
+ }
+
/**
* Flatten a {@code List} containing arbitrary {@code Parcelable} objects into this parcel
* at the current position. They can later be retrieved using
@@ -3379,6 +3475,32 @@ public final class Parcel {
return l;
}
+ /**
+ * Read and return a new ArrayList containing T (IInterface) objects from
+ * the parcel that was written with {@link #writeInterfaceList} at the
+ * current dataPosition(). Returns null if the
+ * previously written list object was null.
+ *
+ * @return A newly created ArrayList containing T (IInterface)
+ *
+ * @see #writeInterfaceList
+ */
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ @Nullable
+ public final ArrayList createInterfaceArrayList(
+ @NonNull Function asInterface) {
+ int N = readInt();
+ if (N < 0) {
+ return null;
+ }
+ ArrayList l = new ArrayList(N);
+ while (N > 0) {
+ l.add(asInterface.apply(readStrongBinder()));
+ N--;
+ }
+ return l;
+ }
+
/**
* Read into the given List items String objects that were written with
* {@link #writeStringList} at the current dataPosition().
@@ -3421,6 +3543,28 @@ public final class Parcel {
}
}
+ /**
+ * Read into the given List items IInterface objects that were written with
+ * {@link #writeInterfaceList} at the current dataPosition().
+ *
+ * @see #writeInterfaceList
+ */
+ public final void readInterfaceList(@NonNull List list,
+ @NonNull Function asInterface) {
+ int M = list.size();
+ int N = readInt();
+ int i = 0;
+ for (; i < M && i < N; i++) {
+ list.set(i, asInterface.apply(readStrongBinder()));
+ }
+ for (; i