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

Commit 6ecd1b6e authored by Jeongik Cha's avatar Jeongik Cha Committed by Automerger Merge Worker
Browse files

Merge "Add ParcelableHolder for NDK backend" am: 1b7f7628

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1458147

Change-Id: I9d9e27733f88199295c486a1680903ad8b11ed58
parents c455ec4f 1b7f7628
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