diff options
| -rw-r--r-- | libs/binder/Parcel.cpp | 130 | ||||
| -rw-r--r-- | libs/binder/include/binder/Parcel.h | 99 | 
2 files changed, 132 insertions, 97 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index ee26997912..82ea5a3cd0 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -750,61 +750,37 @@ status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {    return writeUtf8AsUtf16(*str);  } -namespace { - -template<typename T> -status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val) -{ -    status_t status; -    if (val.size() > std::numeric_limits<int32_t>::max()) { -        status = BAD_VALUE; -        return status; +status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) { +    if (size > std::numeric_limits<int32_t>::max()) { +        return BAD_VALUE;      } -    status = parcel->writeInt32(val.size()); +    status_t status = writeInt32(size);      if (status != OK) {          return status;      } -    void* data = parcel->writeInplace(val.size()); -    if (!data) { -        status = BAD_VALUE; -        return status; -    } - -    memcpy(data, val.data(), val.size()); -    return status; -} - -template<typename T> -status_t writeByteVectorInternalPtr(Parcel* parcel, -                                    const std::unique_ptr<std::vector<T>>& val) -{ -    if (!val) { -        return parcel->writeInt32(-1); -    } - -    return writeByteVectorInternal(parcel, *val); +    return write(data, size);  } -}  // namespace -  status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { -    return writeByteVectorInternal(this, val); +    return writeByteVectorInternal(val.data(), val.size());  }  status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)  { -    return writeByteVectorInternalPtr(this, val); +    if (!val) return writeInt32(-1); +    return writeByteVectorInternal(val->data(), val->size());  }  status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { -    return writeByteVectorInternal(this, val); +    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());  }  status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)  { -    return writeByteVectorInternalPtr(this, val); +    if (!val) return writeInt32(-1); +    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());  }  status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) @@ -1477,81 +1453,41 @@ restart_write:      return err;  } -namespace { - -template<typename T> -status_t readByteVectorInternal(const Parcel* parcel, -                                std::vector<T>* val) { -    val->clear(); - -    int32_t size; -    status_t status = parcel->readInt32(&size); - -    if (status != OK) { -        return status; -    } - -    if (size < 0) { -        status = UNEXPECTED_NULL; -        return status; +status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const { +    if (size_t(size) > dataAvail()) { +      return BAD_VALUE;      } -    if (size_t(size) > parcel->dataAvail()) { -        status = BAD_VALUE; -        return status; -    } - -    T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size))); -    if (!data) { -        status = BAD_VALUE; -        return status; -    } -    val->reserve(size); -    val->insert(val->end(), data, data + size); - -    return status; +    return read(data, size);  } -template<typename T> -status_t readByteVectorInternalPtr( -        const Parcel* parcel, -        std::unique_ptr<std::vector<T>>* val) { -    const int32_t start = parcel->dataPosition(); -    int32_t size; -    status_t status = parcel->readInt32(&size); -    val->reset(); - -    if (status != OK || size < 0) { -        return status; -    } - -    parcel->setDataPosition(start); -    val->reset(new (std::nothrow) std::vector<T>()); - -    status = readByteVectorInternal(parcel, val->get()); - -    if (status != OK) { -        val->reset(); -    } - -    return status; -} - -}  // namespace -  status_t Parcel::readByteVector(std::vector<int8_t>* val) const { -    return readByteVectorInternal(this, val); +    if (status_t status = resizeOutVector(val); status != OK) return status; +    return readByteVectorInternal(val->data(), val->size());  }  status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { -    return readByteVectorInternal(this, val); +    if (status_t status = resizeOutVector(val); status != OK) return status; +    return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());  }  status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { -    return readByteVectorInternalPtr(this, val); +    if (status_t status = resizeOutVector(val); status != OK) return status; +    if (val->get() == nullptr) { +        // resizeOutVector does not create the out vector if size is < 0. +        // This occurs when writing a null byte vector. +        return OK; +    } +    return readByteVectorInternal((*val)->data(), (*val)->size());  }  status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { -    return readByteVectorInternalPtr(this, val); +    if (status_t status = resizeOutVector(val); status != OK) return status; +    if (val->get() == nullptr) { +        // resizeOutVector does not create the out vector if size is < 0. +        // This occurs when writing a null byte vector. +        return OK; +    } +    return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());  }  status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 3471e1356d..7c34071270 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -19,6 +19,7 @@  #include <map> // for legacy reasons  #include <string> +#include <type_traits>  #include <vector>  #include <android-base/unique_fd.h> @@ -157,6 +158,18 @@ public:      status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);      status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val); +    // Write an Enum vector with underlying type int8_t. +    // Does not use padding; each byte is contiguous. +    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            writeEnumVector(const std::vector<T>& val); +    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val); +    // Write an Enum vector with underlying type != int8_t. +    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            writeEnumVector(const std::vector<T>& val); +    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val); +      template<typename T>      status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);      template<typename T> @@ -275,6 +288,19 @@ public:      status_t            readStrongBinder(sp<IBinder>* val) const;      status_t            readNullableStrongBinder(sp<IBinder>* val) const; + +    // Read an Enum vector with underlying type int8_t. +    // Does not use padding; each byte is contiguous. +    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            readEnumVector(std::vector<T>* val) const; +    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const; +    // Read an Enum vector with underlying type != int8_t. +    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            readEnumVector(std::vector<T>* val) const; +    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> +    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const; +      template<typename T>      status_t            readParcelableVector(                              std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const; @@ -438,6 +464,19 @@ private:      status_t            writeRawNullableParcelable(const Parcelable*                                                     parcelable); +    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0> +    status_t            writeEnum(const T& val); +    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0> +    status_t            writeEnum(const T& val); + +    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0> +    status_t            readEnum(T* pArg) const; +    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0> +    status_t            readEnum(T* pArg) const; + +    status_t writeByteVectorInternal(const int8_t* data, size_t size); +    status_t readByteVectorInternal(int8_t* data, size_t size) const; +      template<typename T, typename U>      status_t            unsafeReadTypedVector(std::vector<T>* val,                                                status_t(Parcel::*read_func)(U*) const) const; @@ -913,6 +952,66 @@ status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::un      return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);  } +template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>> +status_t Parcel::writeEnum(const T& val) { +    return writeInt32(static_cast<int32_t>(val)); +} +template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>> +status_t Parcel::writeEnum(const T& val) { +    return writeInt64(static_cast<int64_t>(val)); +} + +template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::writeEnumVector(const std::vector<T>& val) { +    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size()); +} +template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) { +    if (!val) return writeInt32(-1); +    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size()); +} +template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::writeEnumVector(const std::vector<T>& val) { +    return writeTypedVector(val, &Parcel::writeEnum); +} +template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) { +    return writeNullableTypedVector(val, &Parcel::writeEnum); +} + +template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>> +status_t Parcel::readEnum(T* pArg) const { +    return readInt32(reinterpret_cast<int32_t *>(pArg)); +} +template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>> +status_t Parcel::readEnum(T* pArg) const { +    return readInt64(reinterpret_cast<int64_t *>(pArg)); +} + +template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::readEnumVector(std::vector<T>* val) const { +    if (status_t status = resizeOutVector(val); status != OK) return status; +    return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size()); +} +template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const { +    if (status_t status = resizeOutVector(val); status != OK) return status; +    if (val->get() == nullptr) { +        // resizeOutVector does not create the out vector if size is < 0. +        // This occurs when writing a null Enum vector. +        return OK; +    } +    return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size()); +} +template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::readEnumVector(std::vector<T>* val) const { +    return readTypedVector(val, &Parcel::readEnum); +} +template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> +status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const { +    return readNullableTypedVector(val, &Parcel::readEnum); +} +  // ---------------------------------------------------------------------------  inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)  |