Loading libs/binder/ndk/include_ndk/android/binder_parcel.h +33 −20 Original line number Diff line number Diff line Loading @@ -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. * Loading @@ -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 * Loading @@ -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. Loading @@ -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); Loading Loading @@ -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); /** Loading @@ -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. Loading @@ -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. Loading @@ -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); Loading @@ -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. Loading libs/binder/ndk/include_ndk/android/binder_parcel_utils.h +199 −10 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <android/binder_parcel.h> #include <optional> #include <string> #include <vector> Loading @@ -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 Loading @@ -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) { Loading @@ -64,6 +66,55 @@ static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, size_t l 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 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. Loading Loading @@ -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); } /** Loading @@ -135,13 +209,46 @@ 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(); return element.c_str(); } /** * 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. */ Loading @@ -157,6 +264,27 @@ static inline binder_status_t AParcel_readString(const AParcel* parcel, std::str return AParcel_readString(parcel, stringData, AParcel_stdStringAllocator); } /** * 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> */ Loading @@ -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. Loading Loading @@ -330,6 +480,23 @@ static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size())); } /** * 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. */ Loading @@ -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 /** @} */ libs/binder/ndk/parcel.cpp +44 −14 Original line number Diff line number Diff line Loading @@ -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()) { Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading @@ -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); } }; Loading @@ -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, Loading @@ -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), binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter), StringArrayElementAllocationAdapter::Allocator); if (status != STATUS_OK) return status; } return STATUS_OK; Loading Loading
libs/binder/ndk/include_ndk/android/binder_parcel.h +33 −20 Original line number Diff line number Diff line Loading @@ -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. * Loading @@ -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 * Loading @@ -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. Loading @@ -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); Loading Loading @@ -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); /** Loading @@ -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. Loading @@ -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. Loading @@ -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); Loading @@ -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. Loading
libs/binder/ndk/include_ndk/android/binder_parcel_utils.h +199 −10 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <android/binder_parcel.h> #include <optional> #include <string> #include <vector> Loading @@ -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 Loading @@ -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) { Loading @@ -64,6 +66,55 @@ static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, size_t l 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 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. Loading Loading @@ -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); } /** Loading @@ -135,13 +209,46 @@ 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(); return element.c_str(); } /** * 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. */ Loading @@ -157,6 +264,27 @@ static inline binder_status_t AParcel_readString(const AParcel* parcel, std::str return AParcel_readString(parcel, stringData, AParcel_stdStringAllocator); } /** * 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> */ Loading @@ -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. Loading Loading @@ -330,6 +480,23 @@ static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size())); } /** * 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. */ Loading @@ -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 /** @} */
libs/binder/ndk/parcel.cpp +44 −14 Original line number Diff line number Diff line Loading @@ -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()) { Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading @@ -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); } }; Loading @@ -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, Loading @@ -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), binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter), StringArrayElementAllocationAdapter::Allocator); if (status != STATUS_OK) return status; } return STATUS_OK; Loading