Loading libs/binder/ndk/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ cc_library { "include_apex", ], cflags: ["-Wall", "-Wextra", "-Werror"], srcs: [ "ibinder.cpp", "ibinder_jni.cpp", Loading libs/binder/ndk/include_ndk/android/binder_parcel.h +77 −1 Original line number Diff line number Diff line Loading @@ -149,7 +149,49 @@ typedef bool (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t inde * 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); int32_t* outLength); /** * 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_readParcelableArray * * \param arrayData some external representation of an array * \param length the length to allocate this array to * * \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_parcelableArrayAllocator)(void* arrayData, int32_t length); /** * This is called to parcel the underlying data from an arrayData object at index. * * See also AParcel_writeParcelableArray * * \param parcel parcel to write the parcelable to * \param arrayData some external representation of an array of parcelables (a user-defined type). * \param index the index of the value to be retrieved. * * \return status (usually returned from other parceling functions). STATUS_OK for success. */ typedef binder_status_t (*AParcel_writeParcelableElement)(AParcel* parcel, const void* arrayData, size_t index); /** * This is called to set an underlying value in an arrayData object at index. * * See also AParcel_readParcelableArray * * \param parcel parcel to read the parcelable from * \param arrayData some external representation of an array of parcelables (a user-defined type). * \param index the index of the value to be set. * * \return status (usually returned from other parceling functions). STATUS_OK for success. */ typedef binder_status_t (*AParcel_readParcelableElement)(const AParcel* parcel, void* arrayData, size_t index); // @START-PRIMITIVE-VECTOR-GETTERS /** Loading Loading @@ -497,6 +539,40 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, AParcel_stringArrayElementAllocator elementAllocator) __INTRODUCED_IN(29); /** * Writes an array of parcelables (user-defined types) to the next location in a non-null parcel. * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. * \param elementWriter function to be called for every array index to write the user-defined type * at that location. * * \return STATUS_OK on successful write. */ binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length, AParcel_writeParcelableElement elementWriter) __INTRODUCED_IN(29); /** * Reads an array of parcelables (user-defined types) 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, elementReader will be called for every index to read the * corresponding parcelable. * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. * \param elementReader the callback that will be called to fill out individual elements. * * \return STATUS_OK on successful read. */ binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData, AParcel_parcelableArrayAllocator allocator, AParcel_readParcelableElement elementReader) __INTRODUCED_IN(29); // @START-PRIMITIVE-READ-WRITE /** * Writes int32_t value to the next location in a non-null parcel. Loading libs/binder/ndk/include_ndk/android/binder_parcel_utils.h +42 −2 Original line number Diff line number Diff line Loading @@ -299,7 +299,7 @@ static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, siz * index. */ static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index, size_t* outLength) { int32_t* outLength) { const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData); const std::string& element = vec->at(index); Loading Loading @@ -327,7 +327,7 @@ static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorD */ static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData, size_t index, size_t* outLength) { int32_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); Loading Loading @@ -420,6 +420,46 @@ static inline binder_status_t AParcel_readVector( AParcel_nullableStdVectorStringElementAllocator); } /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. */ template <typename P> binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData, size_t index) { const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData); return vector->at(index).writeToParcel(parcel); } /** * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'. */ template <typename P> binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData, size_t index) { std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData); return vector->at(index).readFromParcel(parcel); } /** * Convenience API for writing a std::vector<P> */ template <typename P> static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) { const void* vectorData = static_cast<const void*>(&vec); return AParcel_writeParcelableArray(parcel, vectorData, vec.size(), AParcel_writeStdVectorParcelableElement<P>); } /** * Convenience API for reading a std::vector<P> */ template <typename P> static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) { void* vectorData = static_cast<void*>(vec); return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>, AParcel_readStdVectorParcelableElement<P>); } // @START /** * Writes a vector of int32_t to the next location in a non-null parcel. Loading libs/binder/ndk/libbinder_ndk.map.txt +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ LIBBINDER_NDK { # introduced=29 AParcel_readInt32Array; AParcel_readInt64; AParcel_readInt64Array; AParcel_readParcelableArray; AParcel_readParcelFileDescriptor; AParcel_readStatusHeader; AParcel_readString; Loading @@ -64,6 +65,7 @@ LIBBINDER_NDK { # introduced=29 AParcel_writeInt32Array; AParcel_writeInt64; AParcel_writeInt64Array; AParcel_writeParcelableArray; AParcel_writeParcelFileDescriptor; AParcel_writeStatusHeader; AParcel_writeString; Loading libs/binder/ndk/parcel.cpp +47 −8 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ binder_status_t WriteArray(AParcel* parcel, const void* arrayData, int32_t lengt Parcel* rawParcel = parcel->get(); for (size_t i = 0; i < length; i++) { for (int32_t i = 0; i < length; i++) { status = (rawParcel->*write)(getter(arrayData, i)); if (status != STATUS_OK) return PruneStatusT(status); Loading @@ -197,7 +197,7 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator if (length <= 0) return STATUS_OK; for (size_t i = 0; i < length; i++) { for (int32_t i = 0; i < length; i++) { T readTarget; status = (rawParcel->*read)(&readTarget); if (status != STATUS_OK) return PruneStatusT(status); Loading Loading @@ -376,12 +376,12 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, if (status != STATUS_OK) return status; if (length <= 0) return STATUS_OK; for (size_t i = 0; i < length; i++) { size_t length = 0; const char* str = getter(arrayData, i, &length); if (str == nullptr && length != -1) return STATUS_BAD_VALUE; for (int32_t i = 0; i < length; i++) { int32_t elementLength = 0; const char* str = getter(arrayData, i, &elementLength); if (str == nullptr && elementLength != -1) return STATUS_BAD_VALUE; binder_status_t status = AParcel_writeString(parcel, str, length); binder_status_t status = AParcel_writeString(parcel, str, elementLength); if (status != STATUS_OK) return status; } Loading @@ -392,7 +392,7 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, // allocator. struct StringArrayElementAllocationAdapter { void* arrayData; // stringData from the NDK size_t index; // index into the string array int32_t index; // index into the string array AParcel_stringArrayElementAllocator elementAllocator; static bool Allocator(void* stringData, int32_t length, char** buffer) { Loading Loading @@ -433,6 +433,45 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, return STATUS_OK; } binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length, AParcel_writeParcelableElement elementWriter) { // we have no clue if arrayData represents a null object or not, we can only infer from length bool arrayIsNull = length < 0; binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length); if (status != STATUS_OK) return status; if (length <= 0) return STATUS_OK; for (int32_t i = 0; i < length; i++) { binder_status_t status = elementWriter(parcel, arrayData, i); if (status != STATUS_OK) return status; } return STATUS_OK; } binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData, AParcel_parcelableArrayAllocator allocator, AParcel_readParcelableElement elementReader) { const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; if (length == -1) return STATUS_OK; // null array for (int32_t i = 0; i < length; i++) { binder_status_t status = elementReader(parcel, arrayData, i); if (status != STATUS_OK) return status; } return STATUS_OK; } // See gen_parcel_helper.py. These auto-generated read/write methods use the same types for // libbinder and this library. // @START Loading Loading
libs/binder/ndk/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ cc_library { "include_apex", ], cflags: ["-Wall", "-Wextra", "-Werror"], srcs: [ "ibinder.cpp", "ibinder_jni.cpp", Loading
libs/binder/ndk/include_ndk/android/binder_parcel.h +77 −1 Original line number Diff line number Diff line Loading @@ -149,7 +149,49 @@ typedef bool (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t inde * 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); int32_t* outLength); /** * 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_readParcelableArray * * \param arrayData some external representation of an array * \param length the length to allocate this array to * * \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_parcelableArrayAllocator)(void* arrayData, int32_t length); /** * This is called to parcel the underlying data from an arrayData object at index. * * See also AParcel_writeParcelableArray * * \param parcel parcel to write the parcelable to * \param arrayData some external representation of an array of parcelables (a user-defined type). * \param index the index of the value to be retrieved. * * \return status (usually returned from other parceling functions). STATUS_OK for success. */ typedef binder_status_t (*AParcel_writeParcelableElement)(AParcel* parcel, const void* arrayData, size_t index); /** * This is called to set an underlying value in an arrayData object at index. * * See also AParcel_readParcelableArray * * \param parcel parcel to read the parcelable from * \param arrayData some external representation of an array of parcelables (a user-defined type). * \param index the index of the value to be set. * * \return status (usually returned from other parceling functions). STATUS_OK for success. */ typedef binder_status_t (*AParcel_readParcelableElement)(const AParcel* parcel, void* arrayData, size_t index); // @START-PRIMITIVE-VECTOR-GETTERS /** Loading Loading @@ -497,6 +539,40 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, AParcel_stringArrayElementAllocator elementAllocator) __INTRODUCED_IN(29); /** * Writes an array of parcelables (user-defined types) to the next location in a non-null parcel. * * \param parcel the parcel to write to. * \param arrayData an array of size 'length' (or null if length is -1, may be null if length is 0). * \param length the length of arrayData or -1 if this represents a null array. * \param elementWriter function to be called for every array index to write the user-defined type * at that location. * * \return STATUS_OK on successful write. */ binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length, AParcel_writeParcelableElement elementWriter) __INTRODUCED_IN(29); /** * Reads an array of parcelables (user-defined types) 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, elementReader will be called for every index to read the * corresponding parcelable. * * \param parcel the parcel to read from. * \param arrayData some external representation of an array. * \param allocator the callback that will be called to allocate the array. * \param elementReader the callback that will be called to fill out individual elements. * * \return STATUS_OK on successful read. */ binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData, AParcel_parcelableArrayAllocator allocator, AParcel_readParcelableElement elementReader) __INTRODUCED_IN(29); // @START-PRIMITIVE-READ-WRITE /** * Writes int32_t value to the next location in a non-null parcel. Loading
libs/binder/ndk/include_ndk/android/binder_parcel_utils.h +42 −2 Original line number Diff line number Diff line Loading @@ -299,7 +299,7 @@ static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, siz * index. */ static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index, size_t* outLength) { int32_t* outLength) { const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData); const std::string& element = vec->at(index); Loading Loading @@ -327,7 +327,7 @@ static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorD */ static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData, size_t index, size_t* outLength) { int32_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); Loading Loading @@ -420,6 +420,46 @@ static inline binder_status_t AParcel_readVector( AParcel_nullableStdVectorStringElementAllocator); } /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. */ template <typename P> binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData, size_t index) { const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData); return vector->at(index).writeToParcel(parcel); } /** * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'. */ template <typename P> binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData, size_t index) { std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData); return vector->at(index).readFromParcel(parcel); } /** * Convenience API for writing a std::vector<P> */ template <typename P> static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) { const void* vectorData = static_cast<const void*>(&vec); return AParcel_writeParcelableArray(parcel, vectorData, vec.size(), AParcel_writeStdVectorParcelableElement<P>); } /** * Convenience API for reading a std::vector<P> */ template <typename P> static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) { void* vectorData = static_cast<void*>(vec); return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>, AParcel_readStdVectorParcelableElement<P>); } // @START /** * Writes a vector of int32_t to the next location in a non-null parcel. Loading
libs/binder/ndk/libbinder_ndk.map.txt +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ LIBBINDER_NDK { # introduced=29 AParcel_readInt32Array; AParcel_readInt64; AParcel_readInt64Array; AParcel_readParcelableArray; AParcel_readParcelFileDescriptor; AParcel_readStatusHeader; AParcel_readString; Loading @@ -64,6 +65,7 @@ LIBBINDER_NDK { # introduced=29 AParcel_writeInt32Array; AParcel_writeInt64; AParcel_writeInt64Array; AParcel_writeParcelableArray; AParcel_writeParcelFileDescriptor; AParcel_writeStatusHeader; AParcel_writeString; Loading
libs/binder/ndk/parcel.cpp +47 −8 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ binder_status_t WriteArray(AParcel* parcel, const void* arrayData, int32_t lengt Parcel* rawParcel = parcel->get(); for (size_t i = 0; i < length; i++) { for (int32_t i = 0; i < length; i++) { status = (rawParcel->*write)(getter(arrayData, i)); if (status != STATUS_OK) return PruneStatusT(status); Loading @@ -197,7 +197,7 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator if (length <= 0) return STATUS_OK; for (size_t i = 0; i < length; i++) { for (int32_t i = 0; i < length; i++) { T readTarget; status = (rawParcel->*read)(&readTarget); if (status != STATUS_OK) return PruneStatusT(status); Loading Loading @@ -376,12 +376,12 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, if (status != STATUS_OK) return status; if (length <= 0) return STATUS_OK; for (size_t i = 0; i < length; i++) { size_t length = 0; const char* str = getter(arrayData, i, &length); if (str == nullptr && length != -1) return STATUS_BAD_VALUE; for (int32_t i = 0; i < length; i++) { int32_t elementLength = 0; const char* str = getter(arrayData, i, &elementLength); if (str == nullptr && elementLength != -1) return STATUS_BAD_VALUE; binder_status_t status = AParcel_writeString(parcel, str, length); binder_status_t status = AParcel_writeString(parcel, str, elementLength); if (status != STATUS_OK) return status; } Loading @@ -392,7 +392,7 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, // allocator. struct StringArrayElementAllocationAdapter { void* arrayData; // stringData from the NDK size_t index; // index into the string array int32_t index; // index into the string array AParcel_stringArrayElementAllocator elementAllocator; static bool Allocator(void* stringData, int32_t length, char** buffer) { Loading Loading @@ -433,6 +433,45 @@ binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, return STATUS_OK; } binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length, AParcel_writeParcelableElement elementWriter) { // we have no clue if arrayData represents a null object or not, we can only infer from length bool arrayIsNull = length < 0; binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length); if (status != STATUS_OK) return status; if (length <= 0) return STATUS_OK; for (int32_t i = 0; i < length; i++) { binder_status_t status = elementWriter(parcel, arrayData, i); if (status != STATUS_OK) return status; } return STATUS_OK; } binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData, AParcel_parcelableArrayAllocator allocator, AParcel_readParcelableElement elementReader) { const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; if (length == -1) return STATUS_OK; // null array for (int32_t i = 0; i < length; i++) { binder_status_t status = elementReader(parcel, arrayData, i); if (status != STATUS_OK) return status; } return STATUS_OK; } // See gen_parcel_helper.py. These auto-generated read/write methods use the same types for // libbinder and this library. // @START Loading