Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b341b33f authored by Steven Moreland's avatar Steven Moreland Committed by android-build-merger
Browse files

libbinder_ndk: read/write parcelable array

am: e22a9949

Change-Id: I2124e247ba360013a9e8b1cb1933aa25dde96ee4
parents 6c1acd09 e22a9949
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -151,6 +151,48 @@ typedef bool (*AParcel_stringArrayElementAllocator)(void* arrayData, size_t inde
typedef const char* (*AParcel_stringArrayElementGetter)(const void* arrayData, size_t index,
                                                        size_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
/**
 * This is called to get the underlying data from an arrayData object.
@@ -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.
+40 −0
Original line number Diff line number Diff line
@@ -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.
+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ LIBBINDER_NDK { # introduced=29
    AParcel_readInt32Array;
    AParcel_readInt64;
    AParcel_readInt64Array;
    AParcel_readParcelableArray;
    AParcel_readParcelFileDescriptor;
    AParcel_readStatusHeader;
    AParcel_readString;
@@ -64,6 +65,7 @@ LIBBINDER_NDK { # introduced=29
    AParcel_writeInt32Array;
    AParcel_writeInt64;
    AParcel_writeInt64Array;
    AParcel_writeParcelableArray;
    AParcel_writeParcelFileDescriptor;
    AParcel_writeStatusHeader;
    AParcel_writeString;
+43 −4
Original line number Diff line number Diff line
@@ -377,11 +377,11 @@ binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData,
    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;
        size_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;
    }

@@ -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 (size_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 (size_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