Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b7f7628 authored by Jeongik Cha's avatar Jeongik Cha Committed by Gerrit Code Review
Browse files

Merge "Add ParcelableHolder for NDK backend"

parents 3695285a 62240b96
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -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

/** @} */
+47 −0
Original line number Diff line number Diff line
@@ -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

/** @} */
+5 −0
Original line number Diff line number Diff line
@@ -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 {
+18 −0
Original line number Diff line number Diff line
@@ -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