Merge "libbinder_ndk: recombine allocators/getters"
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index d36b3c0..33c3f6c 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -50,98 +50,128 @@
  */
 void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
 
-/**
- * This is called to allocate an array with a given length. If allocation fails, null should be
- * returned.
- */
-typedef void* (*AParcel_arrayReallocator)(void* vectorData, size_t length);
-
 // @START-PRIMITIVE-VECTOR-GETTERS
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readInt32Array
  */
-typedef int32_t* (*AParcel_int32ArrayGetter)(void* arrayData);
+typedef int32_t* (*AParcel_int32Allocator)(void* arrayData, size_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readUint32Array
  */
-typedef uint32_t* (*AParcel_uint32ArrayGetter)(void* arrayData);
+typedef uint32_t* (*AParcel_uint32Allocator)(void* arrayData, size_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readInt64Array
  */
-typedef int64_t* (*AParcel_int64ArrayGetter)(void* arrayData);
+typedef int64_t* (*AParcel_int64Allocator)(void* arrayData, size_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readUint64Array
  */
-typedef uint64_t* (*AParcel_uint64ArrayGetter)(void* arrayData);
+typedef uint64_t* (*AParcel_uint64Allocator)(void* arrayData, size_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readFloatArray
  */
-typedef float* (*AParcel_floatArrayGetter)(void* arrayData);
+typedef float* (*AParcel_floatAllocator)(void* arrayData, size_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readDoubleArray
  */
-typedef double* (*AParcel_doubleArrayGetter)(void* arrayData);
+typedef double* (*AParcel_doubleAllocator)(void* arrayData, size_t length);
 
 /**
- * This is called to get the underlying data from an arrayData object.
+ * This allocates an array of length length inside of arrayData and returns whether or not there was
+ * a success.
  *
- * This will never be called for an empty array.
+ * See also AParcel_readBoolArray
+ */
+typedef bool (*AParcel_boolAllocator)(void* arrayData, size_t length);
+
+/**
+ * This is called to get the underlying data from an arrayData object at index.
+ *
+ * See also AParcel_writeBoolArray
  */
 typedef bool (*AParcel_boolArrayGetter)(const void* arrayData, size_t index);
 
 /**
  * This is called to set an underlying value in an arrayData object at index.
+ *
+ * See also AParcel_readBoolArray
  */
 typedef void (*AParcel_boolArraySetter)(void* arrayData, size_t index, bool value);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readCharArray
  */
-typedef char16_t* (*AParcel_charArrayGetter)(void* arrayData);
+typedef char16_t* (*AParcel_charAllocator)(void* arrayData, size_t length);
 
 /**
  * This is called to get the underlying data from an arrayData object.
  *
- * This will never be called for an empty array.
+ * The implementation of this function should allocate a contiguous array of length length and
+ * return that underlying buffer to be filled out. If there is an error or length is 0, null may be
+ * returned.
+ *
+ * See also AParcel_readByteArray
  */
-typedef int8_t* (*AParcel_byteArrayGetter)(void* arrayData);
+typedef int8_t* (*AParcel_byteAllocator)(void* arrayData, size_t length);
 
 // @END-PRIMITIVE-VECTOR-GETTERS
 
 /**
- * This is called to allocate a buffer
+ * This is called to allocate a buffer for a C-style string (null-terminated). The buffer should be
+ * of length length which includes space for the null-terminator.
  *
- * The length here includes the space required to insert a '\0' for a properly formed c-str. If the
- * buffer returned from this function is retStr, it will be filled by AParcel_readString with the
- * data from the remote process, and it will be filled such that retStr[length] == '\0'.
+ * See also AParcel_readString.
  *
  * If allocation fails, null should be returned.
  */
-typedef void* (*AParcel_stringReallocator)(void* stringData, size_t length);
-
-/**
- * This is called to get the buffer from a stringData object.
- */
-typedef char* (*AParcel_stringGetter)(void* stringData);
+typedef char* (*AParcel_stringAllocator)(void* stringData, size_t length);
 
 /**
  * Writes an AIBinder to the next location in a non-null parcel. Can be null.
@@ -190,17 +220,12 @@
 /**
  * Reads and allocates string value from the next location in a non-null parcel.
  *
- * Data is passed to the string allocator once the string size is known. This data should be used to
- * point to some kind of string data. For instance, it could be a char*, and the string allocator
- * could be realloc. Then the getter would simply be a cast to char*. In more complicated cases,
- * stringData could be a structure containing additional string data.
- *
- * If this function returns a success, the buffer returned by allocator when passed stringData will
- * contain a null-terminated c-str read from the binder.
+ * Data is passed to the string allocator once the string size is known. This size includes the
+ * space for the null-terminator of this string. This allocator returns a buffer which is used as
+ * the output buffer from this read.
  */
-binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringReallocator reallocator,
-                                   AParcel_stringGetter getter, void** stringData)
-        __INTRODUCED_IN(29);
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringAllocator allocator,
+                                   void* stringData) __INTRODUCED_IN(29);
 
 // @START-PRIMITIVE-READ-WRITE
 /**
@@ -331,6 +356,9 @@
 
 /**
  * Writes an array of bool to the next location in a non-null parcel.
+ *
+ * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying
+ * values to write to the parcel.
  */
 binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData,
                                        AParcel_boolArrayGetter getter, size_t length)
@@ -350,66 +378,93 @@
 
 /**
  * Reads an array of int32_t from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readInt32Array(const AParcel* parcel, void** arrayData,
-                                       AParcel_arrayReallocator reallocator,
-                                       AParcel_int32ArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
+                                       AParcel_int32Allocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of uint32_t from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readUint32Array(const AParcel* parcel, void** arrayData,
-                                        AParcel_arrayReallocator reallocator,
-                                        AParcel_uint32ArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
+                                        AParcel_uint32Allocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of int64_t from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readInt64Array(const AParcel* parcel, void** arrayData,
-                                       AParcel_arrayReallocator reallocator,
-                                       AParcel_int64ArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
+                                       AParcel_int64Allocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of uint64_t from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readUint64Array(const AParcel* parcel, void** arrayData,
-                                        AParcel_arrayReallocator reallocator,
-                                        AParcel_uint64ArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
+                                        AParcel_uint64Allocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of float from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readFloatArray(const AParcel* parcel, void** arrayData,
-                                       AParcel_arrayReallocator reallocator,
-                                       AParcel_floatArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
+                                       AParcel_floatAllocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of double from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void** arrayData,
-                                        AParcel_arrayReallocator reallocator,
-                                        AParcel_doubleArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
+                                        AParcel_doubleAllocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of bool from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. Then, for every i in [0, length),
+ * setter(arrayData, i, x) will be called where x is the value at the associated index.
  */
-binder_status_t AParcel_readBoolArray(const AParcel* parcel, void** arrayData,
-                                      AParcel_arrayReallocator reallocator,
+binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
+                                      AParcel_boolAllocator allocator,
                                       AParcel_boolArraySetter setter) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of char16_t from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readCharArray(const AParcel* parcel, void** arrayData,
-                                      AParcel_arrayReallocator reallocator,
-                                      AParcel_charArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
+                                      AParcel_charAllocator allocator) __INTRODUCED_IN(29);
 
 /**
  * Reads an array of int8_t from the next location in a non-null parcel.
+ *
+ * First, allocator will be called with the length of the array. If the allocation succeeds and the
+ * length is greater than zero, the buffer returned by the allocator will be filled with the
+ * corresponding data
  */
-binder_status_t AParcel_readByteArray(const AParcel* parcel, void** arrayData,
-                                      AParcel_arrayReallocator reallocator,
-                                      AParcel_byteArrayGetter getter) __INTRODUCED_IN(29);
+binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
+                                      AParcel_byteAllocator allocator) __INTRODUCED_IN(29);
 
 // @END-PRIMITIVE-READ-WRITE
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index bf0c956..6e41a7f 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -36,24 +36,26 @@
 namespace ndk {
 
 /**
- * This resizes a std::vector of some underlying type to the given length.
+ * This retrieves and allocates a vector to length length and returns the underlying buffer.
  */
 template <typename T>
-static inline void* AParcel_stdVectorReallocator(void* vectorData, size_t length) {
+static inline T* AParcel_stdVectorAllocator(void* vectorData, size_t length) {
     std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
     if (length > vec->max_size()) return nullptr;
 
     vec->resize(length);
-    return vec;
+    return vec->data();
 }
 
 /**
- * This retrieves the underlying contiguous vector from a corresponding vectorData.
+ * This allocates a vector to length length and returns whether the allocation is successful.
  */
-template <typename T>
-static inline T* AParcel_stdVectorGetter(void* vectorData) {
-    std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
-    return vec->data();
+static inline bool AParcel_stdVectorBoolAllocator(void* vectorData, size_t length) {
+    std::vector<bool>* vec = static_cast<std::vector<bool>*>(vectorData);
+    if (length > vec->max_size()) return false;
+
+    vec->resize(length);
+    return true;
 }
 
 /**
@@ -89,8 +91,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readInt32Array(parcel, &vectorData, &AParcel_stdVectorReallocator<int32_t>,
-                                  AParcel_stdVectorGetter<int32_t>);
+    return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
 }
 
 /**
@@ -105,8 +106,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readUint32Array(parcel, &vectorData, &AParcel_stdVectorReallocator<uint32_t>,
-                                   AParcel_stdVectorGetter<uint32_t>);
+    return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
 }
 
 /**
@@ -121,8 +121,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readInt64Array(parcel, &vectorData, &AParcel_stdVectorReallocator<int64_t>,
-                                  AParcel_stdVectorGetter<int64_t>);
+    return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
 }
 
 /**
@@ -137,8 +136,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readUint64Array(parcel, &vectorData, &AParcel_stdVectorReallocator<uint64_t>,
-                                   AParcel_stdVectorGetter<uint64_t>);
+    return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
 }
 
 /**
@@ -153,8 +151,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readFloatArray(parcel, &vectorData, &AParcel_stdVectorReallocator<float>,
-                                  AParcel_stdVectorGetter<float>);
+    return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
 }
 
 /**
@@ -169,8 +166,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readDoubleArray(parcel, &vectorData, &AParcel_stdVectorReallocator<double>,
-                                   AParcel_stdVectorGetter<double>);
+    return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
 }
 
 /**
@@ -186,7 +182,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readBoolArray(parcel, &vectorData, &AParcel_stdVectorReallocator<bool>,
+    return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorBoolAllocator,
                                  AParcel_stdVectorSetter<bool>);
 }
 
@@ -202,8 +198,7 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readCharArray(parcel, &vectorData, &AParcel_stdVectorReallocator<char16_t>,
-                                 AParcel_stdVectorGetter<char16_t>);
+    return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
 }
 
 /**
@@ -218,27 +213,18 @@
  */
 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int8_t>* vec) {
     void* vectorData = static_cast<void*>(vec);
-    return AParcel_readByteArray(parcel, &vectorData, &AParcel_stdVectorReallocator<int8_t>,
-                                 AParcel_stdVectorGetter<int8_t>);
+    return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
 }
 
 // @END
 
 /**
- * Takes a std::string and reallocates it to the specified length. For use with AParcel_readString.
- * See use below in AParcel_readString.
+ * Allocates a std::string to length and returns the underlying buffer. For use with
+ * AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*).
  */
-static inline void* AParcel_stdStringReallocator(void* stringData, size_t length) {
+static inline char* AParcel_stdStringAllocator(void* stringData, size_t length) {
     std::string* str = static_cast<std::string*>(stringData);
     str->resize(length - 1);
-    return stringData;
-}
-
-/**
- * Takes a std::string and returns the inner char*.
- */
-static inline char* AParcel_stdStringGetter(void* stringData) {
-    std::string* str = static_cast<std::string*>(stringData);
     return &(*str)[0];
 }
 
@@ -254,8 +240,7 @@
  */
 static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
     void* stringData = static_cast<void*>(str);
-    return AParcel_readString(parcel, AParcel_stdStringReallocator, AParcel_stdStringGetter,
-                              &stringData);
+    return AParcel_readString(parcel, AParcel_stdStringAllocator, stringData);
 }
 
 template <typename T>
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 29094db..cfe0f46 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -32,7 +32,10 @@
 using ::android::status_t;
 
 template <typename T>
-using ContiguousArrayGetter = T* (*)(void* arrayData);
+using ContiguousArrayAllocator = T* (*)(void* arrayData, size_t length);
+
+template <typename T>
+using ArrayAllocator = bool (*)(void* arrayData, size_t length);
 template <typename T>
 using ArrayGetter = T (*)(const void* arrayData, size_t index);
 template <typename T>
@@ -81,8 +84,8 @@
 }
 
 template <typename T>
-binder_status_t ReadArray(const AParcel* parcel, void** arrayData,
-                          AParcel_arrayReallocator reallocator, ContiguousArrayGetter<T> getter) {
+binder_status_t ReadArray(const AParcel* parcel, void* arrayData,
+                          ContiguousArrayAllocator<T> allocator) {
     const Parcel* rawParcel = parcel->get();
 
     int32_t length;
@@ -91,12 +94,8 @@
     if (status != STATUS_OK) return PruneStatusT(status);
     if (length < 0) return STATUS_UNEXPECTED_NULL;
 
-    *arrayData = reallocator(*arrayData, length);
-    if (*arrayData == nullptr) return STATUS_NO_MEMORY;
-
+    T* array = allocator(arrayData, length);
     if (length == 0) return STATUS_OK;
-
-    T* array = getter(*arrayData);
     if (array == nullptr) return STATUS_NO_MEMORY;
 
     int32_t size = 0;
@@ -112,9 +111,8 @@
 
 // Each element in a char16_t array is converted to an int32_t (not packed)
 template <>
-binder_status_t ReadArray<char16_t>(const AParcel* parcel, void** arrayData,
-                                    AParcel_arrayReallocator reallocator,
-                                    ContiguousArrayGetter<char16_t> getter) {
+binder_status_t ReadArray<char16_t>(const AParcel* parcel, void* arrayData,
+                                    ContiguousArrayAllocator<char16_t> allocator) {
     const Parcel* rawParcel = parcel->get();
 
     int32_t length;
@@ -123,12 +121,8 @@
     if (status != STATUS_OK) return PruneStatusT(status);
     if (length < 0) return STATUS_UNEXPECTED_NULL;
 
-    *arrayData = reallocator(*arrayData, length);
-    if (*arrayData == nullptr) return STATUS_NO_MEMORY;
-
+    char16_t* array = allocator(arrayData, length);
     if (length == 0) return STATUS_OK;
-
-    char16_t* array = getter(*arrayData);
     if (array == nullptr) return STATUS_NO_MEMORY;
 
     int32_t size = 0;
@@ -163,9 +157,8 @@
 }
 
 template <typename T>
-binder_status_t ReadArray(const AParcel* parcel, void** arrayData,
-                          AParcel_arrayReallocator reallocator, ArraySetter<T> setter,
-                          status_t (Parcel::*read)(T*) const) {
+binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator<T> allocator,
+                          ArraySetter<T> setter, status_t (Parcel::*read)(T*) const) {
     const Parcel* rawParcel = parcel->get();
 
     int32_t length;
@@ -174,15 +167,14 @@
     if (status != STATUS_OK) return PruneStatusT(status);
     if (length < 0) return STATUS_UNEXPECTED_NULL;
 
-    *arrayData = reallocator(*arrayData, length);
-    if (*arrayData == nullptr) return STATUS_NO_MEMORY;
+    if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
 
     for (size_t i = 0; i < length; i++) {
         T readTarget;
         status = (rawParcel->*read)(&readTarget);
         if (status != STATUS_OK) return PruneStatusT(status);
 
-        setter(*arrayData, i, readTarget);
+        setter(arrayData, i, readTarget);
     }
 
     return STATUS_OK;
@@ -255,8 +247,8 @@
     return STATUS_OK;
 }
 
-binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringReallocator reallocator,
-                                   AParcel_stringGetter getter, void** stringData) {
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_stringAllocator allocator,
+                                   void* stringData) {
     size_t len16;
     const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
 
@@ -278,16 +270,10 @@
         return STATUS_BAD_VALUE;
     }
 
-    *stringData = reallocator(*stringData, len8);
-
-    if (*stringData == nullptr) {
-        return STATUS_NO_MEMORY;
-    }
-
-    char* str8 = getter(*stringData);
+    char* str8 = allocator(stringData, len8);
 
     if (str8 == nullptr) {
-        LOG(WARNING) << __func__ << ": AParcel_stringReallocator failed to allocate.";
+        LOG(WARNING) << __func__ << ": AParcel_stringAllocator failed to allocate.";
         return STATUS_NO_MEMORY;
     }
 
@@ -426,58 +412,50 @@
     return WriteArray<int8_t>(parcel, value, length);
 }
 
-binder_status_t AParcel_readInt32Array(const AParcel* parcel, void** arrayData,
-                                       AParcel_arrayReallocator reallocator,
-                                       AParcel_int32ArrayGetter getter) {
-    return ReadArray<int32_t>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
+                                       AParcel_int32Allocator allocator) {
+    return ReadArray<int32_t>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readUint32Array(const AParcel* parcel, void** arrayData,
-                                        AParcel_arrayReallocator reallocator,
-                                        AParcel_uint32ArrayGetter getter) {
-    return ReadArray<uint32_t>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
+                                        AParcel_uint32Allocator allocator) {
+    return ReadArray<uint32_t>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readInt64Array(const AParcel* parcel, void** arrayData,
-                                       AParcel_arrayReallocator reallocator,
-                                       AParcel_int64ArrayGetter getter) {
-    return ReadArray<int64_t>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
+                                       AParcel_int64Allocator allocator) {
+    return ReadArray<int64_t>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readUint64Array(const AParcel* parcel, void** arrayData,
-                                        AParcel_arrayReallocator reallocator,
-                                        AParcel_uint64ArrayGetter getter) {
-    return ReadArray<uint64_t>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
+                                        AParcel_uint64Allocator allocator) {
+    return ReadArray<uint64_t>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readFloatArray(const AParcel* parcel, void** arrayData,
-                                       AParcel_arrayReallocator reallocator,
-                                       AParcel_floatArrayGetter getter) {
-    return ReadArray<float>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
+                                       AParcel_floatAllocator allocator) {
+    return ReadArray<float>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void** arrayData,
-                                        AParcel_arrayReallocator reallocator,
-                                        AParcel_doubleArrayGetter getter) {
-    return ReadArray<double>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
+                                        AParcel_doubleAllocator allocator) {
+    return ReadArray<double>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readBoolArray(const AParcel* parcel, void** arrayData,
-                                      AParcel_arrayReallocator reallocator,
+binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
+                                      AParcel_boolAllocator allocator,
                                       AParcel_boolArraySetter setter) {
-    return ReadArray<bool>(parcel, arrayData, reallocator, setter, &Parcel::readBool);
+    return ReadArray<bool>(parcel, arrayData, allocator, setter, &Parcel::readBool);
 }
 
-binder_status_t AParcel_readCharArray(const AParcel* parcel, void** arrayData,
-                                      AParcel_arrayReallocator reallocator,
-                                      AParcel_charArrayGetter getter) {
-    return ReadArray<char16_t>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
+                                      AParcel_charAllocator allocator) {
+    return ReadArray<char16_t>(parcel, arrayData, allocator);
 }
 
-binder_status_t AParcel_readByteArray(const AParcel* parcel, void** arrayData,
-                                      AParcel_arrayReallocator reallocator,
-                                      AParcel_byteArrayGetter getter) {
-    return ReadArray<int8_t>(parcel, arrayData, reallocator, getter);
+binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
+                                      AParcel_byteAllocator allocator) {
+    return ReadArray<int8_t>(parcel, arrayData, allocator);
 }
 
 // @END
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index 2cf10d3..86cc57e 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -96,6 +96,10 @@
 
         header += "/**\n"
         header += " * Writes an array of " + cpp + " to the next location in a non-null parcel.\n"
+        if nca:
+            header += " *\n"
+            header += " * getter(arrayData, i) will be called for each i in [0, length) in order to get the underlying values to write "
+            header += "to the parcel.\n"
         header += " */\n"
         header += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_type + ", size_t length) __INTRODUCED_IN(29);\n\n"
         source += "binder_status_t AParcel_write" + pretty + "Array(AParcel* parcel, " + arg_type + ", size_t length) {\n"
@@ -105,48 +109,69 @@
     for pretty, cpp in data_types:
         nca = pretty in non_contiguously_addressable
 
-        extra_getter_args = ""
-        if nca: extra_getter_args = ", size_t index"
-        getter_return = cpp + "*"
-        if nca: getter_return = cpp
-        getter_array_data = "void* arrayData"
-        if nca: getter_array_data = "const void* arrayData"
-
+        read_func = "AParcel_read" + pretty + "Array"
+        write_func = "AParcel_write" + pretty + "Array"
+        allocator_type = "AParcel_" + pretty.lower() + "Allocator"
         getter_type = "AParcel_" + pretty.lower() + "ArrayGetter"
         setter_type = "AParcel_" + pretty.lower() + "ArraySetter"
 
-        pre_header += "/**\n"
-        pre_header += " * This is called to get the underlying data from an arrayData object.\n"
-        pre_header += " *\n"
-        pre_header += " * This will never be called for an empty array.\n"
-        pre_header += " */\n"
-        pre_header += "typedef " + getter_return + " (*" + getter_type + ")(" + getter_array_data + extra_getter_args + ");\n\n"
-
         if nca:
             pre_header += "/**\n"
+            pre_header += " * This allocates an array of length length inside of arrayData and returns whether or not there was "
+            pre_header += "a success.\n"
+            pre_header += " *\n"
+            pre_header += " * See also " + read_func + "\n"
+            pre_header += " */\n"
+            pre_header += "typedef bool (*" + allocator_type + ")(void* arrayData, size_t length);\n\n"
+
+            pre_header += "/**\n"
+            pre_header += " * This is called to get the underlying data from an arrayData object at index.\n"
+            pre_header += " *\n"
+            pre_header += " * See also " + write_func + "\n"
+            pre_header += " */\n"
+            pre_header += "typedef " + cpp + " (*" + getter_type + ")(const void* arrayData, size_t index);\n\n"
+
+            pre_header += "/**\n"
             pre_header += " * This is called to set an underlying value in an arrayData object at index.\n"
+            pre_header += " *\n"
+            pre_header += " * See also " + read_func + "\n"
             pre_header += " */\n"
             pre_header += "typedef void (*" + setter_type + ")(void* arrayData, size_t index, " + cpp + " value);\n\n"
+        else:
+            pre_header += "/**\n"
+            pre_header += " * This is called to get the underlying data from an arrayData object.\n"
+            pre_header += " *\n"
+            pre_header += " * The implementation of this function should allocate a contiguous array of length length and "
+            pre_header += "return that underlying buffer to be filled out. If there is an error or length is 0, null may be "
+            pre_header += "returned.\n"
+            pre_header += " *\n"
+            pre_header += " * See also " + read_func + "\n"
+            pre_header += " */\n"
+            pre_header += "typedef " + cpp + "* (*" + allocator_type + ")(void* arrayData, size_t length);\n\n"
 
-        read_using = "getter"
-        if nca: read_using = "setter"
-        read_type = getter_type
-        if nca: read_type = setter_type
+        read_array_args = [("const AParcel*", "parcel")]
+        read_array_args += [("void*", "arrayData")]
+        read_array_args += [(allocator_type, "allocator")]
+        if nca: read_array_args += [(setter_type, "setter")]
 
-        arguments = ["const AParcel* parcel"]
-        arguments += ["void** arrayData"]
-        arguments += ["AParcel_arrayReallocator reallocator"]
-        arguments += [read_type + " " + read_using]
-        arguments = ", ".join(arguments)
+        read_type_args = ", ".join((varType + " " + name for varType, name in read_array_args))
+        read_call_args = ", ".join((name for varType, name in read_array_args))
 
         header += "/**\n"
         header += " * Reads an array of " + cpp + " from the next location in a non-null parcel.\n"
+        header += " *\n"
+        if nca:
+            header += " * First, allocator will be called with the length of the array. Then, for every i in [0, length), "
+            header += "setter(arrayData, i, x) will be called where x is the value at the associated index.\n"
+        else:
+            header += " * First, allocator will be called with the length of the array. If the allocation succeeds and the "
+            header += "length is greater than zero, the buffer returned by the allocator will be filled with the corresponding data\n"
         header += " */\n"
-        header += "binder_status_t AParcel_read" + pretty + "Array(" + arguments + ") __INTRODUCED_IN(29);\n\n"
-        source += "binder_status_t AParcel_read" + pretty + "Array(" + arguments + ") {\n"
+        header += "binder_status_t " + read_func + "(" + read_type_args + ") __INTRODUCED_IN(29);\n\n"
+        source += "binder_status_t " + read_func + "(" + read_type_args + ") {\n"
         additional_args = ""
         if nca: additional_args = ", &Parcel::read" + pretty
-        source += "    return ReadArray<" + cpp + ">(parcel, arrayData, reallocator, " + read_using + additional_args + ");\n";
+        source += "    return ReadArray<" + cpp + ">(" + read_call_args + additional_args + ");\n";
         source += "}\n\n"
 
         cpp_helper += "/**\n"
@@ -165,9 +190,12 @@
         cpp_helper += "    void* vectorData = static_cast<void*>(vec);\n"
         read_args = []
         read_args += ["parcel"]
-        read_args += ["&vectorData"]
-        read_args += ["&AParcel_stdVectorReallocator<" + cpp + ">"]
-        read_args += ["AParcel_stdVector" + read_using.capitalize() + "<" + cpp + ">"]
+        read_args += ["vectorData"]
+        if nca:
+            read_args += ["AParcel_stdVectorBoolAllocator"]
+            read_args += ["AParcel_stdVectorSetter<" + cpp + ">"]
+        else:
+            read_args += ["AParcel_stdVectorAllocator<" + cpp + ">"]
         cpp_helper += "    return AParcel_read" + pretty + "Array(" + ", ".join(read_args) + ");\n"
         cpp_helper += "}\n\n"