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

Commit fb3c17bc authored by Steven Moreland's avatar Steven Moreland Committed by Gerrit Code Review
Browse files

Merge changes from topic "stable-aidl-nullability"

* changes:
  libbinder_ndk: reading strings is optional.
  libbinder_ndk: use c++17
  libbinder_ndk: remove NullableStrongBinder
  libbinder_ndk: align parcel_utils and parcel order
parents cde4890d b4e1461c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ cc_library {
        "libutils",
    ],

    cpp_std: "c++17",

    version_script: "libbinder_ndk.map.txt",
}

+36 −37
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);
@@ -297,31 +305,17 @@ typedef int8_t* (*AParcel_byteArrayAllocator)(void* arrayData, size_t length);
binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) __INTRODUCED_IN(29);

/**
 * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
 * non-null. One strong ref-count of ownership is passed to the caller of this function.
 * Reads an AIBinder from the next location in a non-null parcel. One strong ref-count of ownership
 * is passed to the caller of this function.
 *
 * \param parcel the parcel to read from.
 * \param binder the out parameter for what is read from the parcel. This will not be null on
 * success.
 * \param binder the out parameter for what is read from the parcel. This may be null.
 *
 * \return STATUS_OK on successful write.
 */
binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder)
        __INTRODUCED_IN(29);

/**
 * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
 * ref-count of ownership is passed to the caller of this function.
 *
 * \param parcel the parcel to read from.
 * \param binder the out parameter for what is read from the parcel. This may be null even on
 * success.
 *
 * \return STATUS_OK on successful write.
 */
binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
        __INTRODUCED_IN(29);

/**
 * Writes a file descriptor to the next location in a non-null parcel. This does not take ownership
 * of fd.
@@ -381,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);

/**
@@ -395,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.
@@ -411,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.
@@ -421,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);

@@ -432,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.
+282 −71
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.
@@ -84,6 +135,199 @@ static inline void AParcel_stdVectorSetter(void* vectorData, size_t index, T val
    (*vec)[index] = value;
}

/**
 * Convenience method to write a strong binder but return an error if it is null.
 */
static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel, AIBinder* binder) {
    if (binder == nullptr) {
        return STATUS_UNEXPECTED_NULL;
    }
    return AParcel_writeStrongBinder(parcel, binder);
}

/**
 * Convenience method to read a strong binder but return an error if it is null.
 */
static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel,
                                                               AIBinder** binder) {
    binder_status_t ret = AParcel_readStrongBinder(parcel, binder);
    if (ret == STATUS_OK && *binder == nullptr) {
        return STATUS_UNEXPECTED_NULL;
    }
    return ret;
}

/**
 * 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 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);
    *buffer = &(*str)[0];
    return true;
}

/**
 * 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 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);
    return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
}

/**
 * This gets the length and buffer of a std::string inside of a std::vector<std::string> at index
 * index.
 */
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.
 */
static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
    return AParcel_writeString(parcel, str.c_str(), str.size());
}

/**
 * Convenience API for reading a std::string.
 */
static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
    void* stringData = static_cast<void*>(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>
 */
static inline binder_status_t AParcel_writeVector(AParcel* parcel,
                                                  const std::vector<std::string>& vec) {
    const void* vectorData = static_cast<const void*>(&vec);
    return AParcel_writeStringArray(parcel, vectorData, vec.size(),
                                    AParcel_stdVectorStringElementGetter);
}

/**
 * Convenience API for reading a std::vector<std::string>
 */
static inline binder_status_t AParcel_readVector(const AParcel* parcel,
                                                 std::vector<std::string>* vec) {
    void* vectorData = static_cast<void*>(vec);
    return AParcel_readStringArray(parcel, vectorData,
                                   AParcel_stdVectorExternalAllocator<std::string>,
                                   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.
@@ -225,101 +469,68 @@ inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int
// @END

/**
 * 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) {
    std::string* str = static_cast<std::string*>(stringData);
    str->resize(length - 1);
    return &(*str)[0];
}

/**
 * Allocates a std::string inside of a std::vector<std::string> at index index to size 'length'.
 */
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);

    std::string& element = vec->at(index);
    element.resize(length - 1);
    return &element[0];
}

/**
 * This gets the length and buffer of a std::string inside of a std::vector<std::string> at index
 * index.
 * Convenience API for writing the size of a vector.
 */
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();
template <typename T>
static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) {
    if (vec.size() > INT32_MAX) {
        return STATUS_BAD_VALUE;
    }

/**
 * Convenience API for writing a std::string.
 */
static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
    return AParcel_writeString(parcel, str.c_str(), str.size());
    return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size()));
}

/**
 * Convenience API for reading a std::string.
 * Convenience API for writing the size of a vector.
 */
static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
    void* stringData = static_cast<void*>(str);
    return AParcel_readString(parcel, stringData, AParcel_stdStringAllocator);
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);
    }

/**
 * Convenience API for writing a std::vector<std::string>
 */
static inline binder_status_t AParcel_writeVector(AParcel* parcel,
                                                  const std::vector<std::string>& vec) {
    const void* vectorData = static_cast<const void*>(&vec);
    return AParcel_writeStringArray(parcel, vectorData, vec.size(),
                                    AParcel_stdVectorStringElementGetter);
    if (vec->size() > INT32_MAX) {
        return STATUS_BAD_VALUE;
    }

/**
 * Convenience API for reading a std::vector<std::string>
 */
static inline binder_status_t AParcel_readVector(const AParcel* parcel,
                                                 std::vector<std::string>* vec) {
    void* vectorData = static_cast<void*>(vec);
    return AParcel_readStringArray(parcel, vectorData,
                                   AParcel_stdVectorExternalAllocator<std::string>,
                                   AParcel_stdVectorStringElementAllocator);
    return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size()));
}

/**
 * Convenience API for writing the size of a vector.
 * Convenience API for resizing a vector.
 */
template <typename T>
static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) {
    if (vec.size() > INT32_MAX) {
        return STATUS_BAD_VALUE;
    }
static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) {
    int32_t size;
    binder_status_t err = AParcel_readInt32(parcel, &size);

    return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size()));
    if (err != STATUS_OK) return err;
    if (size < 0) return STATUS_UNEXPECTED_NULL;

    vec->resize(static_cast<size_t>(size));
    return STATUS_OK;
}

/**
 * Convenience API for resizing a vector.
 */
template <typename T>
static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) {
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 < 0) return STATUS_UNEXPECTED_NULL;
    if (size < -1) return STATUS_UNEXPECTED_NULL;

    vec->resize(static_cast<size_t>(size));
    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;
}

+0 −1
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ LIBBINDER_NDK { # introduced=29
    AParcel_readInt32Array;
    AParcel_readInt64;
    AParcel_readInt64Array;
    AParcel_readNullableStrongBinder;
    AParcel_readParcelFileDescriptor;
    AParcel_readStatusHeader;
    AParcel_readString;
+44 −25

File changed.

Preview size limit exceeded, changes collapsed.

Loading