Loading libs/binder/include/binder/Parcel.h +27 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,23 @@ public: status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead"))); status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val); // Write an IInterface or a vector of IInterface's template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinder(const sp<T>& val) { return writeStrongBinder(T::asBinder(val)); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::vector<sp<T>>& val) { return writeData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::optional<std::vector<sp<T>>>& val) { return writeData(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> Loading Loading @@ -421,6 +438,16 @@ public: 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::vector<sp<IBinder>>* val) const; template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::vector<sp<T>>* val) const { return readData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::optional<std::vector<sp<T>>>* val) const { return readData(val); } 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"))); Loading libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +123 −67 Original line number Diff line number Diff line Loading @@ -27,15 +27,67 @@ #pragma once #include <android/binder_auto_utils.h> #include <android/binder_interface_utils.h> #include <android/binder_internal_logging.h> #include <android/binder_parcel.h> #include <optional> #include <string> #include <type_traits> #include <vector> namespace ndk { namespace { 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 { using type = void; }; template <template <typename...> class V, typename T, typename... Args> struct first_template_type<V<T, Args...>> { using type = T; }; template <typename T> using first_template_type_t = typename first_template_type<T>::type; // Tells if T represents NDK interface (shared_ptr<ICInterface-derived>) template <typename T> static inline constexpr bool is_interface_v = is_specialization_v<T, std::shared_ptr>&& std::is_base_of_v<::ndk::ICInterface, first_template_type_t<T>>; // Tells if T represents NDK parcelable with readFromParcel/writeToParcel methods defined template <typename T, typename = void> struct is_parcelable : std::false_type {}; template <typename T> struct is_parcelable< T, std::void_t<decltype(std::declval<T>().readFromParcel(std::declval<const AParcel*>())), decltype(std::declval<T>().writeToParcel(std::declval<AParcel*>()))>> : std::true_type {}; template <typename T> static inline constexpr bool is_parcelable_v = is_parcelable<T>::value; // Tells if T represents nullable NDK parcelable (optional<parcelable> or unique_ptr<parcelable>) template <typename T> static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_template_type_t<T>> && (is_specialization_v<T, std::optional> || is_specialization_v<T, std::unique_ptr>); } // namespace /** * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. */ Loading Loading @@ -429,18 +481,36 @@ static inline binder_status_t AParcel_readVector( */ template <typename P> static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { if constexpr (is_interface_v<P>) { if (!p) { return STATUS_UNEXPECTED_NULL; } return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_parcelable_v<P>); binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p.writeToParcel(parcel); } } /** * Convenience API for reading a non-null parcelable. */ template <typename P> static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { if constexpr (is_interface_v<P>) { binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p); if (status == STATUS_OK) { if (!*p) { return STATUS_UNEXPECTED_NULL; } } return status; } else { static_assert(is_parcelable_v<P>); int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { Loading @@ -451,29 +521,17 @@ static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p } return p->readFromParcel(parcel); } /** * Convenience API for writing a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const std::optional<P>& p) { if (p == std::nullopt) { return AParcel_writeInt32(parcel, 0); // null } binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p->writeToParcel(parcel); } /** * Convenience API for writing a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const std::unique_ptr<P>& p) { static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const P& p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_nullable_parcelable_v<P>); if (!p) { return AParcel_writeInt32(parcel, 0); // null } Loading @@ -483,13 +541,16 @@ static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, } return p->writeToParcel(parcel); } } /** * Convenience API for reading a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, std::optional<P>* p) { static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, P* p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::readFromParcel(parcel, p); } else if constexpr (is_specialization_v<P, std::optional>) { int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { Loading @@ -499,16 +560,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc *p = std::nullopt; return STATUS_OK; } *p = std::optional<P>(P{}); *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{}); return (*p)->readFromParcel(parcel); } /** * Convenience API for reading a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, std::unique_ptr<P>* p) { } else { static_assert(is_specialization_v<P, std::unique_ptr>); int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { Loading @@ -518,9 +573,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc p->reset(); return STATUS_OK; } *p = std::make_unique<P>(); *p = std::make_unique<first_template_type_t<P>>(); return (*p)->readFromParcel(parcel); } } /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. Loading libs/binder/rust/src/parcel/parcelable.rs +4 −0 Original line number Diff line number Diff line Loading @@ -702,6 +702,8 @@ impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { } } impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {} impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; Loading @@ -716,6 +718,8 @@ impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { } } impl<T: FromIBinder + ?Sized> DeserializeArray for Strong<T> {} // We need these to support Option<&T> for all T impl<T: Serialize + ?Sized> Serialize for &T { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Loading libs/binder/tests/parcel_fuzzer/binder.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { // only reading one binder type for now PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::os::IServiceManager>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::sp<android::os::IServiceManager>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), Loading libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ // TODO(b/142061461): parent class class SomeParcelable { public: binder_status_t writeToParcel(AParcel* /*parcel*/) { return STATUS_OK; } binder_status_t readFromParcel(const AParcel* parcel) { return AParcel_readInt32(parcel, &mValue); } Loading @@ -33,6 +34,41 @@ private: int32_t mValue = 0; }; class ISomeInterface : public ::ndk::ICInterface { public: ISomeInterface() = default; virtual ~ISomeInterface() = default; static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ISomeInterface>* instance); }; static binder_status_t onTransact(AIBinder*, transaction_code_t, const AParcel*, AParcel*) { return STATUS_UNKNOWN_TRANSACTION; } static AIBinder_Class* g_class = ::ndk::ICInterface::defineClass("ISomeInterface", onTransact); class BpSomeInterface : public ::ndk::BpCInterface<ISomeInterface> { public: explicit BpSomeInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {} virtual ~BpSomeInterface() = default; }; binder_status_t ISomeInterface::readFromParcel(const AParcel* parcel, std::shared_ptr<ISomeInterface>* instance) { ::ndk::SpAIBinder binder; binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR()); if (status == STATUS_OK) { if (AIBinder_associateClass(binder.get(), g_class)) { *instance = std::static_pointer_cast<ISomeInterface>( ::ndk::ICInterface::asInterface(binder.get())); } else { *instance = ::ndk::SharedRefBase::make<BpSomeInterface>(binder); } } return status; } #define PARCEL_READ(T, FUN) \ [](const NdkParcelAdapter& p, uint8_t /*data*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ Loading Loading @@ -100,6 +136,8 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ PARCEL_READ(std::optional<std::vector<ndk::SpAIBinder>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<ndk::ScopedFileDescriptor>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<ndk::ScopedFileDescriptor>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<std::shared_ptr<ISomeInterface>>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<std::shared_ptr<ISomeInterface>>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), Loading Loading
libs/binder/include/binder/Parcel.h +27 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,23 @@ public: status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead"))); status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val); // Write an IInterface or a vector of IInterface's template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinder(const sp<T>& val) { return writeStrongBinder(T::asBinder(val)); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::vector<sp<T>>& val) { return writeData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::optional<std::vector<sp<T>>>& val) { return writeData(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> Loading Loading @@ -421,6 +438,16 @@ public: 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::vector<sp<IBinder>>* val) const; template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::vector<sp<T>>* val) const { return readData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::optional<std::vector<sp<T>>>* val) const { return readData(val); } 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"))); Loading
libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +123 −67 Original line number Diff line number Diff line Loading @@ -27,15 +27,67 @@ #pragma once #include <android/binder_auto_utils.h> #include <android/binder_interface_utils.h> #include <android/binder_internal_logging.h> #include <android/binder_parcel.h> #include <optional> #include <string> #include <type_traits> #include <vector> namespace ndk { namespace { 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 { using type = void; }; template <template <typename...> class V, typename T, typename... Args> struct first_template_type<V<T, Args...>> { using type = T; }; template <typename T> using first_template_type_t = typename first_template_type<T>::type; // Tells if T represents NDK interface (shared_ptr<ICInterface-derived>) template <typename T> static inline constexpr bool is_interface_v = is_specialization_v<T, std::shared_ptr>&& std::is_base_of_v<::ndk::ICInterface, first_template_type_t<T>>; // Tells if T represents NDK parcelable with readFromParcel/writeToParcel methods defined template <typename T, typename = void> struct is_parcelable : std::false_type {}; template <typename T> struct is_parcelable< T, std::void_t<decltype(std::declval<T>().readFromParcel(std::declval<const AParcel*>())), decltype(std::declval<T>().writeToParcel(std::declval<AParcel*>()))>> : std::true_type {}; template <typename T> static inline constexpr bool is_parcelable_v = is_parcelable<T>::value; // Tells if T represents nullable NDK parcelable (optional<parcelable> or unique_ptr<parcelable>) template <typename T> static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_template_type_t<T>> && (is_specialization_v<T, std::optional> || is_specialization_v<T, std::unique_ptr>); } // namespace /** * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. */ Loading Loading @@ -429,18 +481,36 @@ static inline binder_status_t AParcel_readVector( */ template <typename P> static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { if constexpr (is_interface_v<P>) { if (!p) { return STATUS_UNEXPECTED_NULL; } return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_parcelable_v<P>); binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p.writeToParcel(parcel); } } /** * Convenience API for reading a non-null parcelable. */ template <typename P> static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { if constexpr (is_interface_v<P>) { binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p); if (status == STATUS_OK) { if (!*p) { return STATUS_UNEXPECTED_NULL; } } return status; } else { static_assert(is_parcelable_v<P>); int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { Loading @@ -451,29 +521,17 @@ static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p } return p->readFromParcel(parcel); } /** * Convenience API for writing a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const std::optional<P>& p) { if (p == std::nullopt) { return AParcel_writeInt32(parcel, 0); // null } binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p->writeToParcel(parcel); } /** * Convenience API for writing a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const std::unique_ptr<P>& p) { static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const P& p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_nullable_parcelable_v<P>); if (!p) { return AParcel_writeInt32(parcel, 0); // null } Loading @@ -483,13 +541,16 @@ static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, } return p->writeToParcel(parcel); } } /** * Convenience API for reading a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, std::optional<P>* p) { static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, P* p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::readFromParcel(parcel, p); } else if constexpr (is_specialization_v<P, std::optional>) { int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { Loading @@ -499,16 +560,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc *p = std::nullopt; return STATUS_OK; } *p = std::optional<P>(P{}); *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{}); return (*p)->readFromParcel(parcel); } /** * Convenience API for reading a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, std::unique_ptr<P>* p) { } else { static_assert(is_specialization_v<P, std::unique_ptr>); int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { Loading @@ -518,9 +573,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc p->reset(); return STATUS_OK; } *p = std::make_unique<P>(); *p = std::make_unique<first_template_type_t<P>>(); return (*p)->readFromParcel(parcel); } } /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. Loading
libs/binder/rust/src/parcel/parcelable.rs +4 −0 Original line number Diff line number Diff line Loading @@ -702,6 +702,8 @@ impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { } } impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {} impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; Loading @@ -716,6 +718,8 @@ impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { } } impl<T: FromIBinder + ?Sized> DeserializeArray for Strong<T> {} // We need these to support Option<&T> for all T impl<T: Serialize + ?Sized> Serialize for &T { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { // only reading one binder type for now PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::os::IServiceManager>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::sp<android::os::IServiceManager>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), Loading
libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ // TODO(b/142061461): parent class class SomeParcelable { public: binder_status_t writeToParcel(AParcel* /*parcel*/) { return STATUS_OK; } binder_status_t readFromParcel(const AParcel* parcel) { return AParcel_readInt32(parcel, &mValue); } Loading @@ -33,6 +34,41 @@ private: int32_t mValue = 0; }; class ISomeInterface : public ::ndk::ICInterface { public: ISomeInterface() = default; virtual ~ISomeInterface() = default; static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ISomeInterface>* instance); }; static binder_status_t onTransact(AIBinder*, transaction_code_t, const AParcel*, AParcel*) { return STATUS_UNKNOWN_TRANSACTION; } static AIBinder_Class* g_class = ::ndk::ICInterface::defineClass("ISomeInterface", onTransact); class BpSomeInterface : public ::ndk::BpCInterface<ISomeInterface> { public: explicit BpSomeInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {} virtual ~BpSomeInterface() = default; }; binder_status_t ISomeInterface::readFromParcel(const AParcel* parcel, std::shared_ptr<ISomeInterface>* instance) { ::ndk::SpAIBinder binder; binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR()); if (status == STATUS_OK) { if (AIBinder_associateClass(binder.get(), g_class)) { *instance = std::static_pointer_cast<ISomeInterface>( ::ndk::ICInterface::asInterface(binder.get())); } else { *instance = ::ndk::SharedRefBase::make<BpSomeInterface>(binder); } } return status; } #define PARCEL_READ(T, FUN) \ [](const NdkParcelAdapter& p, uint8_t /*data*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ Loading Loading @@ -100,6 +136,8 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ PARCEL_READ(std::optional<std::vector<ndk::SpAIBinder>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<ndk::ScopedFileDescriptor>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<ndk::ScopedFileDescriptor>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<std::shared_ptr<ISomeInterface>>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<std::shared_ptr<ISomeInterface>>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), Loading