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

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

Merge changes from topic "stable-aidl-nullability"

am: fb3c17bc

Change-Id: Ia41abb1b2b8ae2ad790a80ea0bde1930f5841daa
parents 3fd04a9b fb3c17bc
Loading
Loading
Loading
Loading
+33 −20
Original line number Diff line number Diff line
@@ -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.
+199 −10
Original line number Diff line number Diff line
@@ -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) {
@@ -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.
@@ -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,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.
 */
@@ -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>
 */
@@ -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.
@@ -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.
 */
@@ -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

/** @} */
+44 −14
Original line number Diff line number Diff line
@@ -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),
        binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
                                                    StringArrayElementAllocationAdapter::Allocator);

        if (status != STATUS_OK) return status;
    }

    return STATUS_OK;