diff options
| -rw-r--r-- | libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h | 91 | ||||
| -rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_parcel.h | 47 | ||||
| -rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 5 | ||||
| -rw-r--r-- | libs/binder/ndk/parcel.cpp | 18 |
4 files changed, 161 insertions, 0 deletions
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h index 670151882f..5f2f3820a4 100644 --- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h @@ -25,6 +25,8 @@ */ #pragma once +#include <android/binder_parcel_utils.h> +#include <optional> namespace ndk { // Also see Parcelable.h in libbinder. @@ -33,6 +35,95 @@ enum { STABILITY_LOCAL, STABILITY_VINTF, // corresponds to @VintfStability }; +#define RETURN_ON_FAILURE(expr) \ + do { \ + binder_status_t _status = (expr); \ + if (_status != STATUS_OK) return _status; \ + } while (false) + +class AParcelableHolder { + public: + AParcelableHolder() = delete; + explicit AParcelableHolder(parcelable_stability_t stability) + : mParcel(AParcel_create()), mStability(stability) {} + + virtual ~AParcelableHolder() = default; + + binder_status_t writeToParcel(AParcel* parcel) const { + std::lock_guard<std::mutex> l(mMutex); + RETURN_ON_FAILURE(AParcel_writeInt32(parcel, static_cast<int32_t>(this->mStability))); + RETURN_ON_FAILURE(AParcel_writeInt32(parcel, AParcel_getDataSize(this->mParcel.get()))); + RETURN_ON_FAILURE(AParcel_appendFrom(this->mParcel.get(), parcel, 0, + AParcel_getDataSize(this->mParcel.get()))); + return STATUS_OK; + } + + binder_status_t readFromParcel(const AParcel* parcel) { + std::lock_guard<std::mutex> l(mMutex); + + AParcel_reset(mParcel.get()); + + RETURN_ON_FAILURE(AParcel_readInt32(parcel, &this->mStability)); + int32_t dataSize; + binder_status_t status = AParcel_readInt32(parcel, &dataSize); + + if (status != STATUS_OK || dataSize < 0) { + return status != STATUS_OK ? status : STATUS_BAD_VALUE; + } + + int32_t dataStartPos = AParcel_getDataPosition(parcel); + + if (dataStartPos > INT32_MAX - dataSize) { + return STATUS_BAD_VALUE; + } + + status = AParcel_appendFrom(parcel, mParcel.get(), dataStartPos, dataSize); + if (status != STATUS_OK) { + return status; + } + return AParcel_setDataPosition(parcel, dataStartPos + dataSize); + } + + template <typename T> + bool setParcelable(T* p) { + std::lock_guard<std::mutex> l(mMutex); + if (p && this->mStability > T::_aidl_stability) { + return false; + } + AParcel_reset(mParcel.get()); + AParcel_writeString(mParcel.get(), T::descriptor, strlen(T::descriptor)); + p->writeToParcel(mParcel.get()); + return true; + } + + template <typename T> + std::unique_ptr<T> getParcelable() const { + std::lock_guard<std::mutex> l(mMutex); + const std::string parcelableDesc(T::descriptor); + AParcel_setDataPosition(mParcel.get(), 0); + if (AParcel_getDataSize(mParcel.get()) == 0) { + return nullptr; + } + std::string parcelableDescInParcel; + binder_status_t status = AParcel_readString(mParcel.get(), &parcelableDescInParcel); + if (status != STATUS_OK || parcelableDesc != parcelableDescInParcel) { + return nullptr; + } + std::unique_ptr<T> ret = std::make_unique<T>(); + status = ret->readFromParcel(this->mParcel.get()); + if (status != STATUS_OK) { + return nullptr; + } + return std::move(ret); + } + + private: + mutable ndk::ScopedAParcel mParcel; + mutable std::mutex mMutex; + parcelable_stability_t mStability; +}; + +#undef RETURN_ON_FAILURE } // namespace ndk /** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h index a031e2973d..93c3f32100 100644 --- a/libs/binder/ndk/include_ndk/android/binder_parcel.h +++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h @@ -1120,6 +1120,53 @@ binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData, // @END-PRIMITIVE-READ-WRITE #endif //__ANDROID_API__ >= 29 +#if __ANDROID_API__ >= 31 +/** + * Reset the parcel to the initial status. + * + * Available since API level 31. + * + * \param parcel The parcel of which to be reset. + * + * \return STATUS_OK on success. + */ +binder_status_t AParcel_reset(AParcel* parcel) __INTRODUCED_IN(31); + +/** + * Gets the size of the parcel. + * + * Available since API level 31. + * + * \param parcel The parcel of which to get the size. + * + * \return The size of the parcel. + */ +int32_t AParcel_getDataSize(const AParcel* parcel) __INTRODUCED_IN(31); + +/** + * Copy the data of a parcel to other parcel. + * + * Available since API level 31. + * + * \param from The source + * \param to The detination + * \param start The position where the copied data starts. + * \param size The amount of data which will be copied. + * + * \return STATUS_OK on success. + */ +binder_status_t AParcel_appendFrom(const AParcel* from, AParcel* to, int32_t start, int32_t size) + __INTRODUCED_IN(31); + +/** + * Creates a parcel. + * + * Available since API level 31. + * + * \return A parcel which is not related to any IBinder objects. + */ +AParcel* AParcel_create() __INTRODUCED_IN(31); +#endif //__ANDROID_API__ >= 31 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 1701fb5705..947cc98d55 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -120,6 +120,11 @@ LIBBINDER_NDK31 { # introduced=31 AServiceManager_isDeclared; # apex llndk AServiceManager_registerLazyService; # llndk AServiceManager_waitForService; # apex llndk + + AParcel_reset; + AParcel_getDataSize; + AParcel_appendFrom; + AParcel_create; }; LIBBINDER_NDK_PLATFORM { diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp index 722ae232ed..2f95318874 100644 --- a/libs/binder/ndk/parcel.cpp +++ b/libs/binder/ndk/parcel.cpp @@ -647,4 +647,22 @@ bool AParcel_getAllowFds(const AParcel* parcel) { return parcel->get()->allowFds(); } +binder_status_t AParcel_reset(AParcel* parcel) { + parcel->get()->freeData(); + return STATUS_OK; +} + +int32_t AParcel_getDataSize(const AParcel* parcel) { + return parcel->get()->dataSize(); +} + +binder_status_t AParcel_appendFrom(const AParcel* from, AParcel* to, int32_t start, int32_t size) { + status_t status = to->get()->appendFrom(from->get(), start, size); + return PruneStatusT(status); +} + +AParcel* AParcel_create() { + return new AParcel(nullptr); +} + // @END |