summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Moreland <smoreland@google.com>2018-11-14 17:25:45 -0800
committerSteven Moreland <smoreland@google.com>2018-11-14 18:00:16 -0800
commitb4e1461cb31bbd40a1cddf4c80bb020b36c6493f (patch)
tree805733a44cb8e657f65de287d0ae2ae7f2217b8d
parent0b8a3c363da75c86bfbe631b8632bd2ff67238f3 (diff)
downloadnative-b4e1461cb31bbd40a1cddf4c80bb020b36c6493f.tar.gz
libbinder_ndk: reading strings is optional.
This is converting the most complicated type in the NDK layer to be optional. This is for feature parity with Java. In AIDL itself, like in the C++ backend, @nullable will be used to determine whether the C++ layer above the NDK actually accepts the nullable types. Bug: 112664205 Test: atest android.binder.cts Change-Id: Ia020706318956a008de5e715730725e9a5a1308d
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_parcel.h53
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_parcel_utils.h209
-rw-r--r--libs/binder/ndk/parcel.cpp58
3 files changed, 276 insertions, 44 deletions
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index c6178984bc..ed18deeed8 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -55,9 +55,9 @@ void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
/**
* This is called to allocate a buffer for a C-style string (null-terminated). The returned buffer
- * should be at least length bytes. This includes space for a null terminator. length will always be
- * strictly less than or equal to the maximum size that can be held in a size_t and will always be
- * greater than 0.
+ * should be at least length bytes. This includes space for a null terminator. For a string, length
+ * will always be strictly less than or equal to the maximum size that can be held in a size_t and
+ * will always be greater than 0. However, if a 'null' string is being read, length will be -1.
*
* See also AParcel_readString.
*
@@ -65,31 +65,35 @@ void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
*
* \param stringData some external representation of a string
* \param length the length of the buffer needed to fill (including the null-terminator)
+ * \param buffer a buffer of size 'length' or null if allocation failed.
*
- * \return a buffer of size 'length' or null if allocation failed.
+ * \return true if the allocation succeeded, false otherwise. If length is -1, a true return here
+ * means that a 'null' value (or equivalent) was successfully stored.
*/
-typedef char* (*AParcel_stringAllocator)(void* stringData, size_t length);
+typedef bool (*AParcel_stringAllocator)(void* stringData, int32_t length, char** buffer);
/**
- * This is called to allocate an array of size 'length'.
+ * This is called to allocate an array of size 'length'. If length is -1, then a 'null' array (or
+ * equivalent) should be created.
*
* See also AParcel_readStringArray
*
* \param arrayData some external representation of an array
* \param length the length to allocate this array to
*
- * \return true if allocation succeeded
+ * \return true if allocation succeeded. If length is -1, a true return here means that a 'null'
+ * value (or equivalent) was successfully stored.
*/
-typedef bool (*AParcel_stringArrayAllocator)(void* arrayData, size_t length);
+typedef bool (*AParcel_stringArrayAllocator)(void* arrayData, int32_t length);
/**
* This is called to allocate a string inside of an array that was allocated by an
* AParcel_stringArrayAllocator.
*
* The index returned will always be within the range [0, length of arrayData). The returned buffer
- * should be at least length bytes. This includes space for a null-terminator. length will always be
- * strictly less than or equal to the maximum size that can be held in a size_t and will always be
- * greater than 0.
+ * should be at least length bytes. This includes space for a null-terminator. For a string, length
+ * will always be strictly less than or equal to the maximum size that can be held in a size_t and
+ * will always be greater than 0. However, if a 'null' string is being read, length will be -1.
*
* See also AParcel_readStringArray
*
@@ -97,10 +101,13 @@ typedef bool (*AParcel_stringArrayAllocator)(void* arrayData, size_t length);
* \param index the index at which a string should be allocated.
* \param length the length of the string to be allocated at this index. See also
* AParcel_stringAllocator. This includes the length required for a null-terminator.
+ * \param buffer a buffer of size 'length' or null if allocation failed.
*
- * \return a buffer of size 'length' or null if allocation failed.
+ * \return true if the allocation succeeded, false otherwise. If length is -1, a true return here
+ * means that a 'null' value (or equivalent) was successfully stored.
*/
-typedef char* (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t index, size_t length);
+typedef bool (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t index, int32_t length,
+ char** buffer);
/**
* This returns the length and buffer of an array at a specific index in an arrayData object.
@@ -110,10 +117,11 @@ typedef char* (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t ind
* \param arrayData some external representation of an array.
* \param index the index at which a string should be allocated.
* \param outLength an out parameter for the length of the string at the specified index. This
- * should not include the length for a null-terminator if there is one.
+ * should not include the length for a null-terminator if there is one. If the object at this index
+ * is 'null', then this should be set to -1.
*
* \param a buffer of size outLength or more representing the string at the provided index. This is
- * not required to be null-terminated.
+ * not required to be null-terminated. If the object at index is null, then this should be null.
*/
typedef const char* (*AParcel_stringArrayElementGetter)(const void* arrayData, size_t index,
size_t* outLength);
@@ -367,13 +375,15 @@ binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status
/**
* Writes utf-8 string value to the next location in a non-null parcel.
*
+ * If length is -1, and string is nullptr, this will write a 'null' string to the parcel.
+ *
* \param parcel the parcel to write to.
* \param string the null-terminated string to write to the parcel, at least of size 'length'.
* \param length the length of the string to be written.
*
* \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length)
__INTRODUCED_IN(29);
/**
@@ -381,7 +391,8 @@ binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t
*
* 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.
+ * the output buffer from this read. If there is a 'null' string on the binder buffer, the allocator
+ * will be called with length -1.
*
* \param parcel the parcel to read from.
* \param stringData some external representation of a string.
@@ -397,7 +408,8 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
*
* length is the length of the array. AParcel_stringArrayElementGetter will be called for all
* indices in range [0, length) with the arrayData provided here. The string length and buffer
- * returned from this function will be used to fill out the data from the parcel.
+ * returned from this function will be used to fill out the data from the parcel. If length is -1,
+ * this will write a 'null' string array to the binder buffer.
*
* \param parcel the parcel to write to.
* \param arrayData some external representation of an array.
@@ -407,7 +419,7 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
*
* \return STATUS_OK on successful write.
*/
-binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
AParcel_stringArrayElementGetter getter)
__INTRODUCED_IN(29);
@@ -418,7 +430,8 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData,
* length is the length of the array to be read from the parcel. Then, for each index i in [0,
* length), AParcel_stringArrayElementAllocator will be called with the length of the string to be
* read from the parcel. The resultant buffer from each of these calls will be filled according to
- * the contents of the string that is read.
+ * the contents of the string that is read. If the string array being read is 'null', this will
+ * instead just pass -1 to AParcel_stringArrayAllocator.
*
* \param parcel the parcel to read from.
* \param arrayData some external representation of an array.
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 657577ecbd..25cc6835fc 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -28,6 +28,7 @@
#include <android/binder_parcel.h>
+#include <optional>
#include <string>
#include <vector>
@@ -46,6 +47,8 @@ static inline T* AParcel_stdVectorAllocator(void* vectorData, size_t length) {
}
/**
+ * TODO(b/111445392): delete this function
+ *
* This allocates a vector to size 'length' and returns whether the allocation is successful.
*
* See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
@@ -53,7 +56,6 @@ static inline T* AParcel_stdVectorAllocator(void* vectorData, size_t length) {
* Instead, it is used in cases where callbacks are used.
*
* See AParcel_readVector(const AParcel* parcel, std::vector<bool>)
- * See AParcel_readVector(const AParcel* parcel, std::vector<std::string>)
*/
template <typename T>
static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, size_t length) {
@@ -65,6 +67,55 @@ static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, size_t l
}
/**
+ * This allocates a vector to size 'length' and returns whether the allocation is successful.
+ *
+ * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
+ * externally with respect to the NDK, and that size information is not passed into the NDK.
+ * Instead, it is used in cases where callbacks are used. Note that when this allocator is used,
+ * null arrays are not supported.
+ *
+ * See AParcel_readVector(const AParcel* parcel, std::vector<std::string>)
+ */
+template <typename T>
+static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, int32_t length) {
+ if (length < 0) return false;
+
+ std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
+ if (length > vec->max_size()) return false;
+
+ vec->resize(length);
+ return true;
+}
+
+/**
+ * This allocates a vector to size 'length' and returns whether the allocation is successful.
+ *
+ * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
+ * externally with respect to the NDK, and that size information is not passed into the NDK.
+ * Instead, it is used in cases where callbacks are used. Note, when this allocator is used,
+ * the vector itself can be nullable.
+ *
+ * See AParcel_readVector(const AParcel* parcel,
+ * std::optional<std::vector<std::optional<std::string>>>)
+ */
+template <typename T>
+static inline bool AParcel_nullableStdVectorExternalAllocator(void* vectorData, int32_t length) {
+ std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
+
+ if (length < 0) {
+ *vec = std::nullopt;
+ return true;
+ }
+
+ *vec = std::optional<std::vector<T>>(std::vector<T>{});
+
+ if (length > (*vec)->max_size()) return false;
+ (*vec)->resize(length);
+
+ return true;
+}
+
+/**
* This retrieves the underlying value in a vector which may not be contiguous at index from a
* corresponding vectorData.
*/
@@ -110,22 +161,45 @@ static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* pa
* 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 char* AParcel_stdStringAllocator(void* stringData, size_t length) {
+static inline bool AParcel_stdStringAllocator(void* stringData, int32_t length, char** buffer) {
+ if (length <= 0) return false;
+
std::string* str = static_cast<std::string*>(stringData);
str->resize(length - 1);
- return &(*str)[0];
+ *buffer = &(*str)[0];
+ return true;
}
/**
- * Allocates a std::string inside of a std::vector<std::string> at index index to size 'length'.
+ * Allocates a string in a std::optional<std::string> to size 'length' (or to std::nullopt when
+ * length is -1) and returns the underlying buffer. For use with AParcel_readString. See use below
+ * in AParcel_readString(const AParcel*, std::optional<std::string>*).
*/
-static inline char* AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
- size_t length) {
- std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
+static inline bool AParcel_nullableStdStringAllocator(void* stringData, int32_t length,
+ char** buffer) {
+ if (length == 0) return false;
+
+ std::optional<std::string>* str = static_cast<std::optional<std::string>*>(stringData);
+
+ if (length < 0) {
+ *str = std::nullopt;
+ return true;
+ }
+
+ *str = std::optional<std::string>(std::string{});
+ (*str)->resize(length - 1);
+ *buffer = &(**str)[0];
+ return true;
+}
+/**
+ * Allocates a std::string inside of a std::vector<std::string> at index 'index' to size 'length'.
+ */
+static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
+ int32_t length, char** buffer) {
+ std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
std::string& element = vec->at(index);
- element.resize(length - 1);
- return &element[0];
+ return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
}
/**
@@ -135,7 +209,6 @@ static inline char* AParcel_stdVectorStringElementAllocator(void* vectorData, si
static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index,
size_t* outLength) {
const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData);
-
const std::string& element = vec->at(index);
*outLength = element.size();
@@ -143,6 +216,40 @@ static inline const char* AParcel_stdVectorStringElementGetter(const void* vecto
}
/**
+ * Allocates a string in a std::optional<std::string> inside of a
+ * std::optional<std::vector<std::optional<std::string>>> at index 'index' to size 'length' (or to
+ * std::nullopt when length is -1).
+ */
+static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorData, size_t index,
+ int32_t length, char** buffer) {
+ std::optional<std::vector<std::optional<std::string>>>* vec =
+ static_cast<std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
+ std::optional<std::string>& element = vec->value().at(index);
+ return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::optional<std::string> inside of a
+ * std::vector<std::string> at index index. If the string is null, then it returns null and a length
+ * of -1.
+ */
+static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData,
+ size_t index,
+ size_t* outLength) {
+ const std::optional<std::vector<std::optional<std::string>>>* vec =
+ static_cast<const std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
+ const std::optional<std::string>& element = vec->value().at(index);
+
+ if (!element) {
+ *outLength = -1;
+ return nullptr;
+ }
+
+ *outLength = element->size();
+ return element->c_str();
+}
+
+/**
* Convenience API for writing a std::string.
*/
static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
@@ -158,6 +265,27 @@ static inline binder_status_t AParcel_readString(const AParcel* parcel, std::str
}
/**
+ * Convenience API for writing a std::optional<std::string>.
+ */
+static inline binder_status_t AParcel_writeString(AParcel* parcel,
+ const std::optional<std::string>& str) {
+ if (!str) {
+ return AParcel_writeString(parcel, nullptr, -1);
+ }
+
+ return AParcel_writeString(parcel, str->c_str(), str->size());
+}
+
+/**
+ * Convenience API for reading a std::optional<std::string>.
+ */
+static inline binder_status_t AParcel_readString(const AParcel* parcel,
+ std::optional<std::string>* str) {
+ void* stringData = static_cast<void*>(str);
+ return AParcel_readString(parcel, stringData, AParcel_nullableStdStringAllocator);
+}
+
+/**
* Convenience API for writing a std::vector<std::string>
*/
static inline binder_status_t AParcel_writeVector(AParcel* parcel,
@@ -178,6 +306,28 @@ static inline binder_status_t AParcel_readVector(const AParcel* parcel,
AParcel_stdVectorStringElementAllocator);
}
+/**
+ * Convenience API for writing a std::optional<std::vector<std::optional<std::string>>>
+ */
+static inline binder_status_t AParcel_writeVector(
+ AParcel* parcel, const std::optional<std::vector<std::optional<std::string>>>& vec) {
+ const void* vectorData = static_cast<const void*>(&vec);
+ return AParcel_writeStringArray(parcel, vectorData, (vec ? vec->size() : -1),
+ AParcel_nullableStdVectorStringElementGetter);
+}
+
+/**
+ * Convenience API for reading a std::optional<std::vector<std::optional<std::string>>>
+ */
+static inline binder_status_t AParcel_readVector(
+ const AParcel* parcel, std::optional<std::vector<std::optional<std::string>>>* vec) {
+ void* vectorData = static_cast<void*>(vec);
+ return AParcel_readStringArray(
+ parcel, vectorData,
+ AParcel_nullableStdVectorExternalAllocator<std::optional<std::string>>,
+ AParcel_nullableStdVectorStringElementAllocator);
+}
+
// @START
/**
* Writes a vector of int32_t to the next location in a non-null parcel.
@@ -331,6 +481,23 @@ static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std
}
/**
+ * Convenience API for writing the size of a vector.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel,
+ const std::optional<std::vector<T>>& vec) {
+ if (!vec) {
+ return AParcel_writeInt32(parcel, -1);
+ }
+
+ if (vec->size() > INT32_MAX) {
+ return STATUS_BAD_VALUE;
+ }
+
+ return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size()));
+}
+
+/**
* Convenience API for resizing a vector.
*/
template <typename T>
@@ -345,6 +512,28 @@ static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::v
return STATUS_OK;
}
+/**
+ * Convenience API for resizing a vector.
+ */
+template <typename T>
+static inline binder_status_t AParcel_resizeVector(const AParcel* parcel,
+ std::optional<std::vector<T>>* vec) {
+ int32_t size;
+ binder_status_t err = AParcel_readInt32(parcel, &size);
+
+ if (err != STATUS_OK) return err;
+ if (size < -1) return STATUS_UNEXPECTED_NULL;
+
+ if (size == -1) {
+ *vec = std::nullopt;
+ return STATUS_OK;
+ }
+
+ *vec = std::optional<std::vector<T>>(std::vector<T>{});
+ (*vec)->resize(static_cast<size_t>(size));
+ return STATUS_OK;
+}
+
} // namespace ndk
/** @} */
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 53e50100a3..4136698abe 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -237,9 +237,23 @@ binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status
return PruneStatusT(ret);
}
-binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
- const uint8_t* str8 = (uint8_t*)string;
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length) {
+ if (string == nullptr) {
+ if (length != -1) {
+ LOG(WARNING) << __func__ << ": null string must be used with length == -1.";
+ return STATUS_BAD_VALUE;
+ }
+
+ status_t err = parcel->get()->writeInt32(-1);
+ return PruneStatusT(err);
+ }
+ if (length < 0) {
+ LOG(WARNING) << __func__ << ": Negative string length: " << length;
+ return STATUS_BAD_VALUE;
+ }
+
+ const uint8_t* str8 = (uint8_t*)string;
const ssize_t len16 = utf8_to_utf16_length(str8, length);
if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
@@ -268,7 +282,10 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
if (str16 == nullptr) {
- LOG(WARNING) << __func__ << ": Failed to read string in place.";
+ if (allocator(stringData, -1, nullptr)) {
+ return STATUS_OK;
+ }
+
return STATUS_UNEXPECTED_NULL;
}
@@ -285,9 +302,10 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
return STATUS_BAD_VALUE;
}
- char* str8 = allocator(stringData, len8);
+ char* str8;
+ bool success = allocator(stringData, len8, &str8);
- if (str8 == nullptr) {
+ if (!success || str8 == nullptr) {
LOG(WARNING) << __func__ << ": AParcel_stringAllocator failed to allocate.";
return STATUS_NO_MEMORY;
}
@@ -297,19 +315,27 @@ binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
return STATUS_OK;
}
-binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, size_t length,
+binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
AParcel_stringArrayElementGetter getter) {
- if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
-
Parcel* rawParcel = parcel->get();
+ if (length < 0) {
+ if (length != -1) {
+ LOG(WARNING) << __func__ << ": null array must be used with length == -1.";
+ return STATUS_BAD_VALUE;
+ }
+
+ status_t status = rawParcel->writeInt32(-1);
+ return PruneStatusT(status);
+ }
+
status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
if (status != STATUS_OK) return PruneStatusT(status);
for (size_t i = 0; i < length; i++) {
size_t length = 0;
const char* str = getter(arrayData, i, &length);
- if (str == nullptr) return STATUS_BAD_VALUE;
+ if (str == nullptr && length != -1) return STATUS_BAD_VALUE;
binder_status_t status = AParcel_writeString(parcel, str, length);
if (status != STATUS_OK) return status;
@@ -325,10 +351,10 @@ struct StringArrayElementAllocationAdapter {
size_t index; // index into the string array
AParcel_stringArrayElementAllocator elementAllocator;
- static char* Allocator(void* stringData, size_t length) {
+ static bool Allocator(void* stringData, int32_t length, char** buffer) {
StringArrayElementAllocationAdapter* adapter =
static_cast<StringArrayElementAllocationAdapter*>(stringData);
- return adapter->elementAllocator(adapter->arrayData, adapter->index, length);
+ return adapter->elementAllocator(adapter->arrayData, adapter->index, length, buffer);
}
};
@@ -341,10 +367,12 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
status_t status = rawParcel->readInt32(&length);
if (status != STATUS_OK) return PruneStatusT(status);
- if (length < 0) return STATUS_UNEXPECTED_NULL;
+ if (length < -1) return STATUS_BAD_VALUE;
if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
+ if (length == -1) return STATUS_OK; // null string array
+
StringArrayElementAllocationAdapter adapter{
.arrayData = arrayData,
.index = 0,
@@ -352,8 +380,10 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
};
for (; adapter.index < length; adapter.index++) {
- AParcel_readString(parcel, static_cast<void*>(&adapter),
- StringArrayElementAllocationAdapter::Allocator);
+ binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
+ StringArrayElementAllocationAdapter::Allocator);
+
+ if (status != STATUS_OK) return status;
}
return STATUS_OK;