diff options
| author | 2019-10-15 11:05:40 -0700 | |
|---|---|---|
| committer | 2019-10-15 11:05:40 -0700 | |
| commit | b071702bee63d231843af3a24a3a196ced7276f1 (patch) | |
| tree | 9832094bd68ee442e8cb8bc9a0fdcf9254082bf3 | |
| parent | ad82179d5bd61fb266e342bc1f229b2003c7d116 (diff) | |
| parent | 2a5ad5dbf0bc6d3a1158ddda6b4ea4f2daa80989 (diff) | |
Merge "Adds read and write methods for Enum vectors." am: 126c6b7452 am: 294a32f470
am: 2a5ad5dbf0
Change-Id: I5c4047ebd6a1968dc515a7e341c39df3ce239602
| -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 32e06cd94d..7b5a03d6e6 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 87266819e6..0f8ababd6b 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) |