Changes readByteVector methods to use more efficient reads.
Bug: 143592429
Test: system/tools/aidl/runtests.sh
Test: ran the regressed performance test from b/143592429
Change-Id: Ie22bb8f9016c3dd5b3b9531a1b0ee0cc8a8e59e1
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9b47f80..9be06cd 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1449,41 +1449,38 @@
return err;
}
-status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const {
- if (size_t(size) > dataAvail()) {
- return BAD_VALUE;
- }
- return read(data, size);
-}
-
status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
- if (status_t status = resizeOutVector(val); status != OK) return status;
- return readByteVectorInternal(val->data(), val->size());
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+ return readByteVectorInternal(val, size);
}
status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
- if (status_t status = resizeOutVector(val); status != OK) return status;
- return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+ return readByteVectorInternal(val, size);
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
- if (status_t status = resizeOutVector(val); status != OK) return status;
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
if (val->get() == nullptr) {
- // resizeOutVector does not create the out vector if size is < 0.
+ // reserveOutVector 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());
+ return readByteVectorInternal(val->get(), size);
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
- if (status_t status = resizeOutVector(val); status != OK) return status;
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
if (val->get() == nullptr) {
- // resizeOutVector does not create the out vector if size is < 0.
+ // reserveOutVector 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());
+ return readByteVectorInternal(val->get(), 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 0f8abab..d4bb85b 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -356,6 +356,11 @@
status_t resizeOutVector(std::vector<T>* val) const;
template<typename T>
status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
+ template<typename T>
+ status_t reserveOutVector(std::vector<T>* val, size_t* size) const;
+ template<typename T>
+ status_t reserveOutVector(std::unique_ptr<std::vector<T>>* val,
+ size_t* size) const;
// Like Parcel.java's readExceptionCode(). Reads the first int32
// off of a Parcel's header, returning 0 or the negative error
@@ -475,7 +480,8 @@
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>
+ status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
template<typename T, typename U>
status_t unsafeReadTypedVector(std::vector<T>* val,
@@ -720,6 +726,42 @@
}
template<typename T>
+status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
+ int32_t read_size;
+ status_t err = readInt32(&read_size);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ if (read_size < 0) {
+ return UNEXPECTED_NULL;
+ }
+ *size = static_cast<size_t>(read_size);
+ val->reserve(*size);
+ return OK;
+}
+
+template<typename T>
+status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
+ size_t* size) const {
+ int32_t read_size;
+ status_t err = readInt32(&read_size);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ if (read_size >= 0) {
+ *size = static_cast<size_t>(read_size);
+ val->reset(new std::vector<T>());
+ (*val)->reserve(*size);
+ } else {
+ val->reset();
+ }
+
+ return OK;
+}
+
+template<typename T>
status_t Parcel::readStrongBinder(sp<T>* val) const {
sp<IBinder> tmp;
status_t ret = readStrongBinder(&tmp);
@@ -988,20 +1030,33 @@
return readInt64(reinterpret_cast<int64_t *>(pArg));
}
+template<typename T>
+inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const {
+ // readByteVectorInternal expects a vector that has been reserved (but not
+ // resized) to have the provided size.
+ const T* data = reinterpret_cast<const T*>(readInplace(size));
+ if (!data) return BAD_VALUE;
+ val->clear();
+ val->insert(val->begin(), data, data+size);
+ return NO_ERROR;
+}
+
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());
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+ return readByteVectorInternal(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;
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
if (val->get() == nullptr) {
- // resizeOutVector does not create the out vector if size is < 0.
+ // reserveOutVector 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());
+ return readByteVectorInternal(val->get(), 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 {