summaryrefslogtreecommitdiff
path: root/libs/binder/include/binder/Parcel.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/binder/include/binder/Parcel.h')
-rw-r--r--libs/binder/include/binder/Parcel.h1139
1 files changed, 411 insertions, 728 deletions
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 5aaaa0c3d2..c1f64fb541 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef ANDROID_PARCEL_H
+#define ANDROID_PARCEL_H
#include <map> // for legacy reasons
#include <string>
@@ -33,31 +34,26 @@
#include <binder/Parcelable.h>
#ifdef BINDER_IPC_32BIT
-//NOLINTNEXTLINE(google-runtime-int) b/173188702
typedef unsigned int binder_size_t;
#else
-//NOLINTNEXTLINE(google-runtime-int) b/173188702
typedef unsigned long long binder_size_t;
#endif
-struct flat_binder_object;
// ---------------------------------------------------------------------------
namespace android {
template <typename T> class Flattenable;
template <typename T> class LightFlattenable;
+struct flat_binder_object;
class IBinder;
class IPCThreadState;
class ProcessState;
-class RpcSession;
class String8;
class TextOutput;
class Parcel {
friend class IPCThreadState;
- friend class RpcState;
-
public:
class ReadableBlob;
class WritableBlob;
@@ -88,30 +84,8 @@ public:
bool hasFileDescriptors() const;
- // Zeros data when reallocating. Other mitigations may be added
- // in the future.
- //
- // WARNING: some read methods may make additional copies of data.
- // In order to verify this, heap dumps should be used.
- void markSensitive() const;
-
- // For a 'data' Parcel, this should mark the Parcel as being prepared for a
- // transaction on this specific binder object. Based on this, the format of
- // the wire binder protocol may change (data is written differently when it
- // is for an RPC transaction).
- void markForBinder(const sp<IBinder>& binder);
-
- // Whenever possible, markForBinder should be preferred. This method is
- // called automatically on reply Parcels for RPC transactions.
- void markForRpc(const sp<RpcSession>& session);
-
- // Whether this Parcel is written for RPC transactions (after calls to
- // markForBinder or markForRpc).
- bool isForRpc() const;
-
- // Writes the IPC/RPC header.
+ // Writes the RPC header.
status_t writeInterfaceToken(const String16& interface);
- status_t writeInterfaceToken(const char16_t* str, size_t len);
// Parses the RPC header, returning true if the interface name
// in the header matches the expected interface from the caller.
@@ -147,8 +121,7 @@ public:
status_t writeString8(const String8& str);
status_t writeString8(const char* str, size_t len);
status_t writeString16(const String16& str);
- status_t writeString16(const std::optional<String16>& str);
- status_t writeString16(const std::unique_ptr<String16>& str) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeString16(const std::unique_ptr<String16>& str);
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
status_t writeInt32Array(size_t len, const int32_t *val);
@@ -159,95 +132,57 @@ public:
// Take a UTF8 encoded string, convert to UTF16, write it to the parcel.
status_t writeUtf8AsUtf16(const std::string& str);
- status_t writeUtf8AsUtf16(const std::optional<std::string>& str);
- status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str);
- status_t writeByteVector(const std::optional<std::vector<int8_t>>& val);
- status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val);
status_t writeByteVector(const std::vector<int8_t>& val);
- status_t writeByteVector(const std::optional<std::vector<uint8_t>>& val);
- status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val);
status_t writeByteVector(const std::vector<uint8_t>& val);
- status_t writeInt32Vector(const std::optional<std::vector<int32_t>>& val);
- status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val);
status_t writeInt32Vector(const std::vector<int32_t>& val);
- status_t writeInt64Vector(const std::optional<std::vector<int64_t>>& val);
- status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val);
status_t writeInt64Vector(const std::vector<int64_t>& val);
- status_t writeUint64Vector(const std::optional<std::vector<uint64_t>>& val);
- status_t writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val);
status_t writeUint64Vector(const std::vector<uint64_t>& val);
- status_t writeFloatVector(const std::optional<std::vector<float>>& val);
- status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val);
status_t writeFloatVector(const std::vector<float>& val);
- status_t writeDoubleVector(const std::optional<std::vector<double>>& val);
- status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val);
status_t writeDoubleVector(const std::vector<double>& val);
- status_t writeBoolVector(const std::optional<std::vector<bool>>& val);
- status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val);
status_t writeBoolVector(const std::vector<bool>& val);
- status_t writeCharVector(const std::optional<std::vector<char16_t>>& val);
- status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val);
status_t writeCharVector(const std::vector<char16_t>& val);
status_t writeString16Vector(
- const std::optional<std::vector<std::optional<String16>>>& val);
- status_t writeString16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) __attribute__((deprecated("use std::optional version instead")));
+ const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val);
status_t writeString16Vector(const std::vector<String16>& val);
status_t writeUtf8VectorAsUtf16Vector(
- const std::optional<std::vector<std::optional<std::string>>>& val);
- status_t writeUtf8VectorAsUtf16Vector(
- const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) __attribute__((deprecated("use std::optional version instead")));
+ const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val);
status_t writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
- status_t writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val);
- status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead")));
+ 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)
- { return writeData(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::optional<std::vector<T>>& val)
- { return writeData(val); }
+ 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) __attribute__((deprecated("use std::optional version instead")))
- { return writeData(val); }
+ 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)
- { return writeData(val); }
+ 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::optional<std::vector<T>>& val)
- { return writeData(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) __attribute__((deprecated("use std::optional version instead")))
- { return writeData(val); }
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
template<typename T>
- status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val)
- { return writeData(val); }
- template<typename T>
- status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
- { return writeData(val); }
- template<typename T>
- status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
- { return writeData(val); }
+ status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
- status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val)
- { return writeData(val); }
+ status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
- status_t writeParcelableVector(const std::vector<T>& val)
- { return writeData(val); }
+ status_t writeParcelableVector(const std::vector<T>& val);
template<typename T>
- status_t writeNullableParcelable(const std::optional<T>& parcelable)
- { return writeData(parcelable); }
- template<typename T>
- status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")))
- { return writeData(parcelable); }
+ status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable);
status_t writeParcelable(const Parcelable& parcelable);
@@ -260,9 +195,7 @@ public:
template<typename T>
status_t writeVectorSize(const std::vector<T>& val);
template<typename T>
- status_t writeVectorSize(const std::optional<std::vector<T>>& val);
- template<typename T>
- status_t writeVectorSize(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
+ status_t writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
// Place a native_handle into the parcel (the native_handle's file-
// descriptors are dup'ed, so it is safe to delete the native_handle
@@ -297,9 +230,7 @@ public:
// Place a vector of file desciptors into the parcel. Each descriptor is
// dup'd as in writeDupFileDescriptor
status_t writeUniqueFileDescriptorVector(
- const std::optional<std::vector<base::unique_fd>>& val);
- status_t writeUniqueFileDescriptorVector(
- const std::unique_ptr<std::vector<base::unique_fd>>& val) __attribute__((deprecated("use std::optional version instead")));
+ const std::unique_ptr<std::vector<base::unique_fd>>& val);
status_t writeUniqueFileDescriptorVector(
const std::vector<base::unique_fd>& val);
@@ -337,6 +268,8 @@ public:
status_t readFloat(float *pArg) const;
double readDouble() const;
status_t readDouble(double *pArg) const;
+ intptr_t readIntPtr() const;
+ status_t readIntPtr(intptr_t *pArg) const;
bool readBool() const;
status_t readBool(bool *pArg) const;
char16_t readChar() const;
@@ -346,8 +279,7 @@ public:
// Read a UTF16 encoded string, convert to UTF8
status_t readUtf8FromUtf16(std::string* str) const;
- status_t readUtf8FromUtf16(std::optional<std::string>* str) const;
- status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const;
const char* readCString() const;
String8 readString8() const;
@@ -355,104 +287,68 @@ public:
const char* readString8Inplace(size_t* outLen) const;
String16 readString16() const;
status_t readString16(String16* pArg) const;
- status_t readString16(std::optional<String16>* pArg) const;
- status_t readString16(std::unique_ptr<String16>* pArg) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readString16(std::unique_ptr<String16>* pArg) const;
const char16_t* readString16Inplace(size_t* outLen) const;
sp<IBinder> readStrongBinder() const;
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
- { return readData(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 readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
- { return readData(val); }
+ 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::optional<std::vector<T>>* val) const
- { return readData(val); }
+ 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
- { return readData(val); }
+ 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 __attribute__((deprecated("use std::optional version instead")))
- { return readData(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 readEnumVector(std::optional<std::vector<T>>* val) const
- { return readData(val); }
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
template<typename T>
status_t readParcelableVector(
- std::optional<std::vector<std::optional<T>>>* val) const
- { return readData(val); }
+ std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
template<typename T>
- status_t readParcelableVector(
- std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")))
- { return readData(val); }
- template<typename T>
- status_t readParcelableVector(std::vector<T>* val) const
- { return readData(val); }
+ status_t readParcelableVector(std::vector<T>* val) const;
status_t readParcelable(Parcelable* parcelable) const;
template<typename T>
- status_t readParcelable(std::optional<T>* parcelable) const
- { return readData(parcelable); }
- template<typename T>
- status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")))
- { return readData(parcelable); }
+ status_t readParcelable(std::unique_ptr<T>* parcelable) const;
- // If strong binder would be nullptr, readStrongBinder() returns an error.
- // TODO: T must be derived from IInterface, fix for clarity.
template<typename T>
status_t readStrongBinder(sp<T>* val) const;
template<typename T>
status_t readNullableStrongBinder(sp<T>* val) const;
- status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
- status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
- status_t readByteVector(std::optional<std::vector<int8_t>>* val) const;
- status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const;
status_t readByteVector(std::vector<int8_t>* val) const;
- status_t readByteVector(std::optional<std::vector<uint8_t>>* val) const;
- status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const;
status_t readByteVector(std::vector<uint8_t>* val) const;
- status_t readInt32Vector(std::optional<std::vector<int32_t>>* val) const;
- status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const;
status_t readInt32Vector(std::vector<int32_t>* val) const;
- status_t readInt64Vector(std::optional<std::vector<int64_t>>* val) const;
- status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const;
status_t readInt64Vector(std::vector<int64_t>* val) const;
- status_t readUint64Vector(std::optional<std::vector<uint64_t>>* val) const;
- status_t readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const;
status_t readUint64Vector(std::vector<uint64_t>* val) const;
- status_t readFloatVector(std::optional<std::vector<float>>* val) const;
- status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const;
status_t readFloatVector(std::vector<float>* val) const;
- status_t readDoubleVector(std::optional<std::vector<double>>* val) const;
- status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const;
status_t readDoubleVector(std::vector<double>* val) const;
- status_t readBoolVector(std::optional<std::vector<bool>>* val) const;
- status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const;
status_t readBoolVector(std::vector<bool>* val) const;
- status_t readCharVector(std::optional<std::vector<char16_t>>* val) const;
- status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const;
status_t readCharVector(std::vector<char16_t>* val) const;
status_t readString16Vector(
- std::optional<std::vector<std::optional<String16>>>* val) const;
- status_t readString16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const;
status_t readString16Vector(std::vector<String16>* val) const;
status_t readUtf8VectorFromUtf16Vector(
- std::optional<std::vector<std::optional<std::string>>>* val) const;
- status_t readUtf8VectorFromUtf16Vector(
- std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const;
status_t readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
template<typename T>
@@ -461,13 +357,15 @@ public:
template<typename T>
status_t read(LightFlattenable<T>& val) const;
- // resizeOutVector is used to resize AIDL out vector parameters.
template<typename T>
status_t resizeOutVector(std::vector<T>* val) const;
template<typename T>
- status_t resizeOutVector(std::optional<std::vector<T>>* val) const;
+ 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 resizeOutVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ 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
@@ -501,9 +399,7 @@ public:
// Retrieve a vector of smart file descriptors from the parcel.
status_t readUniqueFileDescriptorVector(
- std::optional<std::vector<base::unique_fd>>* val) const;
- status_t readUniqueFileDescriptorVector(
- std::unique_ptr<std::vector<base::unique_fd>>* val) const __attribute__((deprecated("use std::optional version instead")));
+ std::unique_ptr<std::vector<base::unique_fd>>* val) const;
status_t readUniqueFileDescriptorVector(
std::vector<base::unique_fd>* val) const;
@@ -525,21 +421,27 @@ public:
// uid.
uid_t readCallingWorkSourceUid() const;
- void print(TextOutput& to, uint32_t flags = 0) const;
-
private:
typedef void (*release_func)(Parcel* parcel,
const uint8_t* data, size_t dataSize,
- const binder_size_t* objects, size_t objectsSize);
-
+ const binder_size_t* objects, size_t objectsSize,
+ void* cookie);
+
uintptr_t ipcData() const;
size_t ipcDataSize() const;
uintptr_t ipcObjects() const;
size_t ipcObjectsCount() const;
void ipcSetDataReference(const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsCount,
- release_func relFunc);
+ release_func relFunc, void* relCookie);
+
+public:
+ void print(TextOutput& to, uint32_t flags = 0) const;
+private:
+ Parcel(const Parcel& o);
+ Parcel& operator=(const Parcel& o);
+
status_t finishWrite(size_t len);
void releaseObjects();
void acquireObjects();
@@ -553,10 +455,10 @@ private:
void initState();
void scanForFds() const;
status_t validateReadData(size_t len) const;
-
void updateWorkSourceRequestHeaderPosition() const;
- status_t finishFlattenBinder(const sp<IBinder>& binder);
+ status_t finishFlattenBinder(const sp<IBinder>& binder,
+ const flat_binder_object& flat);
status_t finishUnflattenBinder(const sp<IBinder>& binder, sp<IBinder>* out) const;
status_t flattenBinder(const sp<IBinder>& binder);
status_t unflattenBinder(sp<IBinder>* out) const;
@@ -572,544 +474,44 @@ private:
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
- //-----------------------------------------------------------------------------
- // Generic type read and write methods for Parcel:
- //
- // readData(T *value) will read a value from the Parcel.
- // writeData(const T& value) will write a value to the Parcel.
- //
- // Our approach to parceling is based on two overloaded functions
- // readData() and writeData() that generate parceling code for an
- // object automatically based on its type. The code from templates are generated at
- // compile time (if constexpr), and decomposes an object through a call graph matching
- // recursive descent of the template typename.
- //
- // This approach unifies handling of complex objects,
- // resulting in fewer lines of code, greater consistency,
- // extensibility to nested types, efficiency (decisions made at compile time),
- // and better code maintainability and optimization.
- //
- // Design decision: Incorporate the read and write code into Parcel rather than
- // as a non-intrusive serializer that emits a byte stream, as we have
- // active objects, alignment, legacy code, and historical idiosyncrasies.
- //
- // --- Overview
- //
- // Parceling is a way of serializing objects into a sequence of bytes for communication
- // between processes, as part of marshaling data for remote procedure calls.
- //
- // The Parcel instance contains objects serialized as bytes, such as the following:
- //
- // 1) Ordinary primitive data such as int, float.
- // 2) Established structured data such as String16, std::string.
- // 3) Parcelables, which are C++ objects that derive from Parcelable (and thus have a
- // readFromParcel and writeToParcel method). (Similar for Java)
- // 4) A std::vector<> of such data.
- // 5) Nullable objects contained in std::optional, std::unique_ptr, or std::shared_ptr.
- //
- // And active objects from the Android ecosystem such as:
- // 6) File descriptors, base::unique_fd (kernel object handles)
- // 7) Binder objects, sp<IBinder> (active Android RPC handles)
- //
- // Objects from (1) through (5) serialize into the mData buffer.
- // Active objects (6) and (7) serialize into both mData and mObjects buffers.
- //
- // --- Data layout details
- //
- // Data is read or written to the parcel by recursively decomposing the type of the parameter
- // type T through readData() and writeData() methods.
- //
- // We focus on writeData() here in our explanation of the data layout.
- //
- // 1) Alignment
- // Implementation detail: Regardless of the parameter type, writeData() calls are designed
- // to finish at a multiple of 4 bytes, the default alignment of the Parcel.
- //
- // Writes of single uint8_t, int8_t, enums based on types of size 1, char16_t, etc
- // will result in 4 bytes being written. The data is widened to int32 and then written;
- // hence the position of the nonzero bytes depend on the native endianness of the CPU.
- //
- // Writes of primitive values with 8 byte size, double, int64_t, uint64_t,
- // are stored with 4 byte alignment. The ARM and x86/x64 permit unaligned reads
- // and writes (albeit with potential latency/throughput penalty) which may or may
- // not be observable unless the process is IO bound.
- //
- // 2) Parcelables
- // Parcelables are detected by the type's base class, and implemented through calling
- // into the Parcelable type's readFromParcel() or writeToParcel() methods.
- // Historically, due to null object detection, a (int32_t) 1 is prepended to the data written.
- // Parcelables must have a default constructor (i.e. one that takes no arguments).
- //
- // 3) Arrays
- // Arrays of uint8_t and int8_t, and enums based on size 1 are written as
- // a contiguous packed byte stream. Hidden zero padding is applied at the end of the byte
- // stream to make a multiple of 4 bytes (and prevent info leakage when writing).
- //
- // All other array writes can be conceptually thought of as recursively calling
- // writeData on the individual elements (though may be implemented differently for speed).
- // As discussed in (1), alignment rules are therefore applied for each element
- // write (not as an aggregate whole), so the wire representation of data can be
- // substantially larger.
- //
- // Historical Note:
- // Because of element-wise alignment, CharVector and BoolVector are expanded
- // element-wise into integers even though they could have been optimized to be packed
- // just like uint8_t, int8_t (size 1 data).
- //
- // 3.1) Arrays accessed by the std::vector type. This is the default for AIDL.
- //
- // 4) Nullables
- // std::optional, std::unique_ptr, std::shared_ptr are all parceled identically
- // (i.e. result in identical byte layout).
- // The target of the std::optional, std::unique_ptr, or std::shared_ptr
- // can either be a std::vector, String16, std::string, or a Parcelable.
- //
- // Detection of null relies on peeking the first int32 data and checking if the
- // the peeked value is considered invalid for the object:
- // (-1 for vectors, String16, std::string) (0 for Parcelables). If the peeked value
- // is invalid, then a null is returned.
- //
- // Application Note: When to use each nullable type:
- //
- // std::optional: Embeds the object T by value rather than creating a new instance
- // by managed pointer as std::unique_ptr or std::shared_ptr. This will save a malloc
- // when creating an optional instance.
- //
- // Use of std::optionals by value can result in copies of the underlying value stored in it,
- // so a std::move may be used to move in and move out (for example) a vector value into
- // the std::optional or for the std::optional itself.
- //
- // std::unique_ptr, std::shared_ptr: These are preferred when the lifetime of the object is
- // already managed by the application. This reduces unnecessary copying of data
- // especially when the calls are local in-proc (rather than via binder rpc).
- //
- // 5) StrongBinder (sp<IBinder>)
- // StrongBinder objects are written regardless of null. When read, null StrongBinder values
- // will be interpreted as UNKNOWN_ERROR if the type is a single argument <sp<T>>
- // or in a vector argument <std::vector<sp<T>>. However, they will be read without an error
- // if present in a std::optional, std::unique_ptr, or std::shared_ptr vector, e.g.
- // <std::optional<std::vector<sp<T>>>.
- //
- // See AIDL annotation @Nullable, readStrongBinder(), and readNullableStrongBinder().
- //
- // Historical Note: writing a vector of StrongBinder objects <std::vector<sp<T>>
- // containing a null will not cause an error. However reading such a vector will cause
- // an error _and_ early termination of the read.
-
- // --- Examples
- //
- // Using recursive parceling, we can parcel complex data types so long
- // as they obey the rules described above.
- //
- // Example #1
- // Parceling of a 3D vector
- //
- // std::vector<std::vector<std::vector<int32_t>>> v1 {
- // { {1}, {2, 3}, {4} },
- // {},
- // { {10}, {20}, {30, 40} },
- // };
- // Parcel p1;
- // p1.writeData(v1);
- // decltype(v1) v2;
- // p1.setDataPosition(0);
- // p1.readData(&v2);
- // ASSERT_EQ(v1, v2);
- //
- // Example #2
- // Parceling of mixed shared pointers
- //
- // Parcel p1;
- // auto sp1 = std::make_shared<std::vector<std::shared_ptr<std::vector<int>>>>(3);
- // (*sp1)[2] = std::make_shared<std::vector<int>>(3);
- // (*(*sp1)[2])[2] = 2;
- // p1.writeData(sp1);
- // decltype(sp1) sp2;
- // p1.setDataPosition(0);
- // p1.readData(&sp2);
- // ASSERT_EQ((*sp1)[0], (*sp2)[0]); // nullptr
- // ASSERT_EQ((*sp1)[1], (*sp2)[1]); // nullptr
- // ASSERT_EQ(*(*sp1)[2], *(*sp2)[2]); // { 0, 0, 2}
-
- // --- Helper Methods
- // TODO: move this to a utils header.
- //
- // Determine if a type is a specialization of a templated type
- // Example: is_specialization_v<T, std::vector>
-
- template <typename Test, template <typename...> class Ref>
- struct is_specialization : std::false_type {};
-
- template <template <typename...> class Ref, typename... Args>
- struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
-
- template <typename Test, template <typename...> class Ref>
- static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value;
-
- // Get the first template type from a container, the T from MyClass<T, ...>.
- template<typename T> struct first_template_type;
-
- template <template <typename ...> class V, typename T, typename... Args>
- struct first_template_type<V<T, Args...>> {
- using type_t = T;
- };
-
- template <typename T>
- using first_template_type_t = typename first_template_type<T>::type_t;
-
- // For static assert(false) we need a template version to avoid early failure.
- template <typename T>
- static inline constexpr bool dependent_false_v = false;
-
- // primitive types that we consider packed and trivially copyable as an array
- template <typename T>
- static inline constexpr bool is_pointer_equivalent_array_v =
- std::is_same_v<T, int8_t>
- || std::is_same_v<T, uint8_t>
- // We could support int16_t and uint16_t, but those aren't currently AIDL types.
- || std::is_same_v<T, int32_t>
- || std::is_same_v<T, uint32_t>
- || std::is_same_v<T, float>
- // are unaligned reads and write support is assumed.
- || std::is_same_v<T, uint64_t>
- || std::is_same_v<T, int64_t>
- || std::is_same_v<T, double>
- || (std::is_enum_v<T> && (sizeof(T) == 1 || sizeof(T) == 4)); // size check not type
-
- // allowed "nullable" types
- // These are nonintrusive containers std::optional, std::unique_ptr, std::shared_ptr.
- template <typename T>
- static inline constexpr bool is_parcel_nullable_type_v =
- is_specialization_v<T, std::optional>
- || is_specialization_v<T, std::unique_ptr>
- || is_specialization_v<T, std::shared_ptr>;
-
- // special int32 value to indicate NonNull or Null parcelables
- // This is fixed to be only 0 or 1 by contract, do not change.
- static constexpr int32_t kNonNullParcelableFlag = 1;
- static constexpr int32_t kNullParcelableFlag = 0;
-
- // special int32 size representing a null vector, when applicable in Nullable data.
- // This fixed as -1 by contract, do not change.
- static constexpr int32_t kNullVectorSize = -1;
-
- // --- readData and writeData methods.
- // We choose a mixture of function and template overloads to improve code readability.
- // TODO: Consider C++20 concepts when they become available.
-
- // writeData function overloads.
- // Implementation detail: Function overloading improves code readability over
- // template overloading, but prevents writeData<T> from being used for those types.
-
- status_t writeData(bool t) {
- return writeBool(t); // this writes as int32_t
- }
-
- status_t writeData(int8_t t) {
- return writeByte(t); // this writes as int32_t
- }
-
- status_t writeData(uint8_t t) {
- return writeByte(static_cast<int8_t>(t)); // this writes as int32_t
- }
-
- status_t writeData(char16_t t) {
- return writeChar(t); // this writes as int32_t
- }
-
- status_t writeData(int32_t t) {
- return writeInt32(t);
- }
-
- status_t writeData(uint32_t t) {
- return writeUint32(t);
- }
-
- status_t writeData(int64_t t) {
- return writeInt64(t);
- }
-
- status_t writeData(uint64_t t) {
- return writeUint64(t);
- }
-
- status_t writeData(float t) {
- return writeFloat(t);
- }
-
- status_t writeData(double t) {
- return writeDouble(t);
- }
-
- status_t writeData(const String16& t) {
- return writeString16(t);
- }
-
- status_t writeData(const std::string& t) {
- return writeUtf8AsUtf16(t);
- }
-
- status_t writeData(const base::unique_fd& t) {
- return writeUniqueFileDescriptor(t);
- }
-
- status_t writeData(const Parcelable& t) { // std::is_base_of_v<Parcelable, T>
- // implemented here. writeParcelable() calls this.
- status_t status = writeData(static_cast<int32_t>(kNonNullParcelableFlag));
- if (status != OK) return status;
- return t.writeToParcel(this);
- }
-
- // writeData<T> template overloads.
- // Written such that the first template type parameter is the complete type
- // of the first function parameter.
- template <typename T,
- typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
- status_t writeData(const T& t) {
- // implemented here. writeEnum() calls this.
- using UT = std::underlying_type_t<T>;
- return writeData(static_cast<UT>(t)); // recurse
- }
-
- template <typename T,
- typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true>
- status_t writeData(const T& t) {
- return writeStrongBinder(t);
- }
-
- // std::optional, std::unique_ptr, std::shared_ptr special case.
- template <typename CT,
- typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true>
- status_t writeData(const CT& c) {
- using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
- if constexpr (is_specialization_v<T, std::vector>
- || std::is_same_v<T, String16>
- || std::is_same_v<T, std::string>) {
- if (!c) return writeData(static_cast<int32_t>(kNullVectorSize));
- } else if constexpr (std::is_base_of_v<Parcelable, T>) {
- if (!c) return writeData(static_cast<int32_t>(kNullParcelableFlag));
- } else /* constexpr */ { // could define this, but raise as error.
- static_assert(dependent_false_v<CT>);
- }
- return writeData(*c);
- }
-
- template <typename CT,
- typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
- status_t writeData(const CT& c) {
- using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
- if (c.size() > std::numeric_limits<int32_t>::max()) return BAD_VALUE;
- const auto size = static_cast<int32_t>(c.size());
- writeData(size);
- if constexpr (is_pointer_equivalent_array_v<T>) {
- constexpr size_t limit = std::numeric_limits<size_t>::max() / sizeof(T);
- if (c.size() > limit) return BAD_VALUE;
- // is_pointer_equivalent types do not have gaps which could leak info,
- // which is only a concern when writing through binder.
-
- // TODO: Padding of the write is suboptimal when the length of the
- // data is not a multiple of 4. Consider improving the write() method.
- return write(c.data(), c.size() * sizeof(T));
- } else if constexpr (std::is_same_v<T, bool>
- || std::is_same_v<T, char16_t>) {
- // reserve data space to write to
- auto data = reinterpret_cast<int32_t*>(writeInplace(c.size() * sizeof(int32_t)));
- if (data == nullptr) return BAD_VALUE;
- for (const auto t: c) {
- *data++ = static_cast<int32_t>(t);
- }
- } else /* constexpr */ {
- for (const auto &t : c) {
- const status_t status = writeData(t);
- if (status != OK) return status;
- }
- }
- return OK;
- }
-
- // readData function overloads.
- // Implementation detail: Function overloading improves code readability over
- // template overloading, but prevents readData<T> from being used for those types.
-
- status_t readData(bool* t) const {
- return readBool(t); // this reads as int32_t
- }
-
- status_t readData(int8_t* t) const {
- return readByte(t); // this reads as int32_t
- }
+ 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);
- status_t readData(uint8_t* t) const {
- return readByte(reinterpret_cast<int8_t*>(t)); // NOTE: this reads as int32_t
- }
-
- status_t readData(char16_t* t) const {
- return readChar(t); // this reads as int32_t
- }
-
- status_t readData(int32_t* t) const {
- return readInt32(t);
- }
-
- status_t readData(uint32_t* t) const {
- return readUint32(t);
- }
-
- status_t readData(int64_t* t) const {
- return readInt64(t);
- }
-
- status_t readData(uint64_t* t) const {
- return readUint64(t);
- }
-
- status_t readData(float* t) const {
- return readFloat(t);
- }
-
- status_t readData(double* t) const {
- return readDouble(t);
- }
-
- status_t readData(String16* t) const {
- return readString16(t);
- }
-
- status_t readData(std::string* t) const {
- return readUtf8FromUtf16(t);
- }
-
- status_t readData(base::unique_fd* t) const {
- return readUniqueFileDescriptor(t);
- }
+ 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 readData(Parcelable* t) const { // std::is_base_of_v<Parcelable, T>
- // implemented here. readParcelable() calls this.
- int32_t present;
- status_t status = readData(&present);
- if (status != OK) return status;
- if (present != kNonNullParcelableFlag) return UNEXPECTED_NULL;
- return t->readFromParcel(this);
- }
-
- // readData<T> template overloads.
- // Written such that the first template type parameter is the complete type
- // of the first function parameter.
-
- template <typename T,
- typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
- status_t readData(T* t) const {
- // implemented here. readEnum() calls this.
- using UT = std::underlying_type_t<T>;
- return readData(reinterpret_cast<UT*>(t));
- }
-
- template <typename T,
- typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true>
- status_t readData(T* t) const {
- return readStrongBinder(t); // Note: on null, returns failure
- }
-
-
- template <typename CT,
- typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true>
- status_t readData(CT* c) const {
- using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
- const size_t startPos = dataPosition();
- int32_t peek;
- status_t status = readData(&peek);
- if (status != OK) return status;
- if constexpr (is_specialization_v<T, std::vector>
- || std::is_same_v<T, String16>
- || std::is_same_v<T, std::string>) {
- if (peek == kNullVectorSize) {
- c->reset();
- return OK;
- }
- } else if constexpr (std::is_base_of_v<Parcelable, T>) {
- if (peek == kNullParcelableFlag) {
- c->reset();
- return OK;
- }
- } else /* constexpr */ { // could define this, but raise as error.
- static_assert(dependent_false_v<CT>);
- }
- // create a new object.
- if constexpr (is_specialization_v<CT, std::optional>) {
- c->emplace();
- } else /* constexpr */ {
- T* const t = new (std::nothrow) T; // contents read from Parcel below.
- if (t == nullptr) return NO_MEMORY;
- c->reset(t);
- }
- // rewind data ptr to reread (this is pretty quick), otherwise we could
- // pass an optional argument to readData to indicate a peeked value.
- setDataPosition(startPos);
- if constexpr (is_specialization_v<T, std::vector>) {
- return readData(&**c, READ_FLAG_SP_NULLABLE); // nullable sp<> allowed now
- } else {
- return readData(&**c);
- }
- }
-
- // std::vector special case, incorporating flags whether the vector
- // accepts nullable sp<> to be read.
- enum ReadFlags {
- READ_FLAG_NONE = 0,
- READ_FLAG_SP_NULLABLE = 1 << 0,
- };
-
- template <typename CT,
- typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
- status_t readData(CT* c, ReadFlags readFlags = READ_FLAG_NONE) const {
- using T = first_template_type_t<CT>; // The T in CT == C<T, ...>
- int32_t size;
- status_t status = readInt32(&size);
- if (status != OK) return status;
- if (size < 0) return UNEXPECTED_NULL;
- const size_t availableBytes = dataAvail(); // coarse bound on vector size.
- if (static_cast<size_t>(size) > availableBytes) return BAD_VALUE;
- c->clear(); // must clear before resizing/reserving otherwise move ctors may be called.
- if constexpr (is_pointer_equivalent_array_v<T>) {
- // could consider POD without gaps and alignment of 4.
- auto data = reinterpret_cast<const T*>(
- readInplace(static_cast<size_t>(size) * sizeof(T)));
- if (data == nullptr) return BAD_VALUE;
- c->insert(c->begin(), data, data + size); // insert should do a reserve().
- } else if constexpr (std::is_same_v<T, bool>
- || std::is_same_v<T, char16_t>) {
- c->reserve(size); // avoids default initialization
- auto data = reinterpret_cast<const int32_t*>(
- readInplace(static_cast<size_t>(size) * sizeof(int32_t)));
- if (data == nullptr) return BAD_VALUE;
- for (int32_t i = 0; i < size; ++i) {
- c->emplace_back(static_cast<T>(*data++));
- }
- } else if constexpr (is_specialization_v<T, sp>) {
- c->resize(size); // calls ctor
- if (readFlags & READ_FLAG_SP_NULLABLE) {
- for (auto &t : *c) {
- status = readNullableStrongBinder(&t); // allow nullable
- if (status != OK) return status;
- }
- } else {
- for (auto &t : *c) {
- status = readStrongBinder(&t);
- if (status != OK) return status;
- }
- }
- } else /* constexpr */ {
- c->resize(size); // calls ctor
- for (auto &t : *c) {
- status = readData(&t);
- if (status != OK) return status;
- }
- }
- return OK;
- }
+ status_t writeByteVectorInternal(const int8_t* data, size_t size);
+ template<typename T>
+ status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
- //-----------------------------------------------------------------------------
- private:
+ template<typename T, typename U>
+ status_t unsafeReadTypedVector(std::vector<T>* val,
+ status_t(Parcel::*read_func)(U*) const) const;
+ template<typename T>
+ status_t readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
+ status_t(Parcel::*read_func)(T*) const) const;
+ template<typename T>
+ status_t readTypedVector(std::vector<T>* val,
+ status_t(Parcel::*read_func)(T*) const) const;
+ template<typename T, typename U>
+ status_t unsafeWriteTypedVector(const std::vector<T>& val,
+ status_t(Parcel::*write_func)(U));
+ template<typename T>
+ status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+ status_t(Parcel::*write_func)(const T&));
+ template<typename T>
+ status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+ status_t(Parcel::*write_func)(T));
+ template<typename T>
+ status_t writeTypedVector(const std::vector<T>& val,
+ status_t(Parcel::*write_func)(const T&));
+ template<typename T>
+ status_t writeTypedVector(const std::vector<T>& val,
+ status_t(Parcel::*write_func)(T));
status_t mError;
uint8_t* mData;
@@ -1123,20 +525,14 @@ private:
mutable bool mObjectsSorted;
mutable bool mRequestHeaderPresent;
-
mutable size_t mWorkSourceRequestHeaderPosition;
mutable bool mFdsKnown;
mutable bool mHasFds;
bool mAllowFds;
- // if this parcelable is involved in a secure transaction, force the
- // data to be overridden with zero when deallocated
- mutable bool mDeallocZero;
-
release_func mOwner;
-
- sp<RpcSession> mSession;
+ void* mOwnerCookie;
class Blob {
public:
@@ -1295,15 +691,6 @@ status_t Parcel::writeVectorSize(const std::vector<T>& val) {
}
template<typename T>
-status_t Parcel::writeVectorSize(const std::optional<std::vector<T>>& val) {
- if (!val) {
- return writeInt32(-1);
- }
-
- return writeVectorSize(*val);
-}
-
-template<typename T>
status_t Parcel::writeVectorSize(const std::unique_ptr<std::vector<T>>& val) {
if (!val) {
return writeInt32(-1);
@@ -1328,7 +715,7 @@ status_t Parcel::resizeOutVector(std::vector<T>* val) const {
}
template<typename T>
-status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const {
+status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
int32_t size;
status_t err = readInt32(&size);
if (err != NO_ERROR) {
@@ -1337,23 +724,43 @@ status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const {
val->reset();
if (size >= 0) {
- val->emplace(size_t(size));
+ val->reset(new std::vector<T>(size_t(size)));
}
return OK;
}
template<typename T>
-status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
- int32_t size;
- status_t err = readInt32(&size);
+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;
}
- val->reset();
- if (size >= 0) {
- val->reset(new std::vector<T>(size_t(size)));
+ 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;
@@ -1391,6 +798,280 @@ status_t Parcel::readNullableStrongBinder(sp<T>* val) const {
return ret;
}
+template<typename T, typename U>
+status_t Parcel::unsafeReadTypedVector(
+ std::vector<T>* val,
+ status_t(Parcel::*read_func)(U*) const) const {
+ int32_t size;
+ status_t status = this->readInt32(&size);
+
+ if (status != OK) {
+ return status;
+ }
+
+ if (size < 0) {
+ return UNEXPECTED_NULL;
+ }
+
+ if (val->max_size() < static_cast<size_t>(size)) {
+ return NO_MEMORY;
+ }
+
+ val->resize(static_cast<size_t>(size));
+
+ if (val->size() < static_cast<size_t>(size)) {
+ return NO_MEMORY;
+ }
+
+ for (auto& v: *val) {
+ status = (this->*read_func)(&v);
+
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ return OK;
+}
+
+template<typename T>
+status_t Parcel::readTypedVector(std::vector<T>* val,
+ status_t(Parcel::*read_func)(T*) const) const {
+ return unsafeReadTypedVector(val, read_func);
+}
+
+template<typename T>
+status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
+ status_t(Parcel::*read_func)(T*) const) const {
+ const size_t start = dataPosition();
+ int32_t size;
+ status_t status = readInt32(&size);
+ val->reset();
+
+ if (status != OK || size < 0) {
+ return status;
+ }
+
+ setDataPosition(start);
+ val->reset(new std::vector<T>());
+
+ status = unsafeReadTypedVector(val->get(), read_func);
+
+ if (status != OK) {
+ val->reset();
+ }
+
+ return status;
+}
+
+template<typename T, typename U>
+status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val,
+ status_t(Parcel::*write_func)(U)) {
+ if (val.size() > std::numeric_limits<int32_t>::max()) {
+ return BAD_VALUE;
+ }
+
+ status_t status = this->writeInt32(static_cast<int32_t>(val.size()));
+
+ if (status != OK) {
+ return status;
+ }
+
+ for (const auto& item : val) {
+ status = (this->*write_func)(item);
+
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ return OK;
+}
+
+template<typename T>
+status_t Parcel::writeTypedVector(const std::vector<T>& val,
+ status_t(Parcel::*write_func)(const T&)) {
+ return unsafeWriteTypedVector(val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeTypedVector(const std::vector<T>& val,
+ status_t(Parcel::*write_func)(T)) {
+ return unsafeWriteTypedVector(val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+ status_t(Parcel::*write_func)(const T&)) {
+ if (val.get() == nullptr) {
+ return this->writeInt32(-1);
+ }
+
+ return unsafeWriteTypedVector(*val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+ status_t(Parcel::*write_func)(T)) {
+ if (val.get() == nullptr) {
+ return this->writeInt32(-1);
+ }
+
+ return unsafeWriteTypedVector(*val, write_func);
+}
+
+template<typename T>
+status_t Parcel::readParcelableVector(std::vector<T>* val) const {
+ return unsafeReadTypedVector<T, Parcelable>(val, &Parcel::readParcelable);
+}
+
+template<typename T>
+status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const {
+ const size_t start = dataPosition();
+ int32_t size;
+ status_t status = readInt32(&size);
+ val->reset();
+
+ if (status != OK || size < 0) {
+ return status;
+ }
+
+ setDataPosition(start);
+ val->reset(new std::vector<std::unique_ptr<T>>());
+
+ status = unsafeReadTypedVector(val->get(), &Parcel::readParcelable<T>);
+
+ if (status != OK) {
+ val->reset();
+ }
+
+ return status;
+}
+
+template<typename T>
+status_t Parcel::readParcelable(std::unique_ptr<T>* parcelable) const {
+ const size_t start = dataPosition();
+ int32_t present;
+ status_t status = readInt32(&present);
+ parcelable->reset();
+
+ if (status != OK || !present) {
+ return status;
+ }
+
+ setDataPosition(start);
+ parcelable->reset(new T());
+
+ status = readParcelable(parcelable->get());
+
+ if (status != OK) {
+ parcelable->reset();
+ }
+
+ return status;
+}
+
+template<typename T>
+status_t Parcel::writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
+ return writeRawNullableParcelable(parcelable.get());
+}
+
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::vector<T>& val) {
+ return unsafeWriteTypedVector<T,const Parcelable&>(val, &Parcel::writeParcelable);
+}
+
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) {
+ if (val.get() == nullptr) {
+ return this->writeInt32(-1);
+ }
+
+ return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
+}
+
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) {
+ if (val.get() == nullptr) {
+ return this->writeInt32(-1);
+ }
+
+ 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>
+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 {
+ 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 {
+ size_t size;
+ if (status_t status = reserveOutVector(val, &size); status != OK) return status;
+ if (val->get() == nullptr) {
+ // reserveOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null Enum vector.
+ return OK;
+ }
+ 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 {
+ 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)
@@ -1402,3 +1083,5 @@ inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
} // namespace android
// ---------------------------------------------------------------------------
+
+#endif // ANDROID_PARCEL_H