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

Commit 063f2366 authored by Steven Moreland's avatar Steven Moreland
Browse files

libbinder_ndk: read/write ParcelFileDescriptor

Bug: 115607973
Test: atest android.binder.cts
Change-Id: Ic9ef70cba95a12f3765573d24d87fd15021ab7a9
parent eddf8dd3
Loading
Loading
Loading
Loading
+28 −12
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <android/binder_status.h>

#include <assert.h>
#include <unistd.h>

#ifdef __cplusplus

@@ -113,23 +114,23 @@ private:
/**
 * This baseclass owns a single object, used to make various classes RAII.
 */
template <typename T, void (*Destroy)(T*)>
template <typename T, typename R, R (*Destroy)(T), T DEFAULT>
class ScopedAResource {
public:
    /**
     * Takes ownership of t.
     */
    explicit ScopedAResource(T* t = nullptr) : mT(t) {}
    explicit ScopedAResource(T t = DEFAULT) : mT(t) {}

    /**
     * This deletes the underlying object if it exists. See set.
     */
    ~ScopedAResource() { set(nullptr); }
    ~ScopedAResource() { set(DEFAULT); }

    /**
     * Takes ownership of t.
     */
    void set(T* t) {
    void set(T t) {
        Destroy(mT);
        mT = t;
    }
@@ -137,12 +138,12 @@ public:
    /**
     * This returns the underlying object to be modified but does not affect ownership.
     */
    T* get() { return mT; }
    T get() { return mT; }

    /**
     * This returns the const underlying object but does not affect ownership.
     */
    const T* get() const { return mT; }
    const T get() const { return mT; }

    /**
     * This allows the value in this class to be set from beneath it. If you call this method and
@@ -156,7 +157,7 @@ public:
     * Other usecases are discouraged.
     *
     */
    T** getR() { return &mT; }
    T* getR() { return &mT; }

    // copy-constructing, or move/copy assignment is disallowed
    ScopedAResource(const ScopedAResource&) = delete;
@@ -167,13 +168,13 @@ public:
    ScopedAResource(ScopedAResource&&) = default;

private:
    T* mT;
    T mT;
};

/**
 * Convenience wrapper. See AParcel.
 */
class ScopedAParcel : public ScopedAResource<AParcel, AParcel_delete> {
class ScopedAParcel : public ScopedAResource<AParcel*, void, AParcel_delete, nullptr> {
public:
    /**
     * Takes ownership of a.
@@ -186,7 +187,7 @@ public:
/**
 * Convenience wrapper. See AStatus.
 */
class ScopedAStatus : public ScopedAResource<AStatus, AStatus_delete> {
class ScopedAStatus : public ScopedAResource<AStatus*, void, AStatus_delete, nullptr> {
public:
    /**
     * Takes ownership of a.
@@ -205,7 +206,8 @@ public:
 * Convenience wrapper. See AIBinder_DeathRecipient.
 */
class ScopedAIBinder_DeathRecipient
      : public ScopedAResource<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
      : public ScopedAResource<AIBinder_DeathRecipient*, void, AIBinder_DeathRecipient_delete,
                               nullptr> {
public:
    /**
     * Takes ownership of a.
@@ -219,7 +221,8 @@ public:
/**
 * Convenience wrapper. See AIBinder_Weak.
 */
class ScopedAIBinder_Weak : public ScopedAResource<AIBinder_Weak, AIBinder_Weak_delete> {
class ScopedAIBinder_Weak
      : public ScopedAResource<AIBinder_Weak*, void, AIBinder_Weak_delete, nullptr> {
public:
    /**
     * Takes ownership of a.
@@ -234,6 +237,19 @@ public:
    SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
};

/**
 * Convenience wrapper for a file descriptor.
 */
class ScopedFileDescriptor : public ScopedAResource<int, int, close, -1> {
public:
    /**
     * Takes ownership of a.
     */
    explicit ScopedFileDescriptor(int a = -1) : ScopedAResource(a) {}
    ~ScopedFileDescriptor() {}
    ScopedFileDescriptor(ScopedFileDescriptor&&) = default;
};

} // namespace ndk

#endif // __cplusplus
+17 −0
Original line number Diff line number Diff line
@@ -162,6 +162,23 @@ binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binde
binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
        __INTRODUCED_IN(29);

/**
 * Writes a file descriptor to the next location in a non-null parcel. This does not take ownership
 * of fd.
 *
 * This corresponds to the SDK's android.os.ParcelFileDescriptor.
 */
binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd);

/**
 * Reads an int from the next location in a non-null parcel.
 *
 * The returned fd must be closed.
 *
 * This corresponds to the SDK's android.os.ParcelFileDescriptor.
 */
binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd);

/**
 * Writes an AStatus object to the next location in a non-null parcel.
 *
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ LIBBINDER_NDK { # introduced=29
    AParcel_readInt64;
    AParcel_readInt64Array;
    AParcel_readNullableStrongBinder;
    AParcel_readParcelFileDescriptor;
    AParcel_readStatusHeader;
    AParcel_readString;
    AParcel_readStrongBinder;
@@ -59,6 +60,7 @@ LIBBINDER_NDK { # introduced=29
    AParcel_writeInt32Array;
    AParcel_writeInt64;
    AParcel_writeInt64Array;
    AParcel_writeParcelFileDescriptor;
    AParcel_writeStatusHeader;
    AParcel_writeString;
    AParcel_writeStrongBinder;
+26 −0
Original line number Diff line number Diff line
@@ -23,13 +23,17 @@
#include <limits>

#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <binder/Parcel.h>
#include <binder/ParcelFileDescriptor.h>
#include <utils/Unicode.h>

using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;
using ::android::status_t;
using ::android::base::unique_fd;
using ::android::os::ParcelFileDescriptor;

template <typename T>
using ContiguousArrayGetter = T* (*)(void* arrayData);
@@ -218,6 +222,28 @@ binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder
    *binder = ret.get();
    return PruneStatusT(status);
}

binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
    ParcelFileDescriptor parcelFd((unique_fd(fd)));

    status_t status = parcel->get()->writeParcelable(parcelFd);

    // ownership is retained by caller
    (void)parcelFd.release().release();

    return PruneStatusT(status);
}

binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
    ParcelFileDescriptor parcelFd;
    // status_t status = parcelFd.readFromParcel(parcel->get());
    status_t status = parcel->get()->readParcelable(&parcelFd);
    if (status != STATUS_OK) return PruneStatusT(status);

    *fd = parcelFd.release().release();
    return STATUS_OK;
}

binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
    return PruneStatusT(status->get()->writeToParcel(parcel->get()));
}