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

Commit d3c595ab authored by Frederick Mayle's avatar Frederick Mayle
Browse files

binder: Use variant for backend specific Parcel fields

This frees up some space to add RPC binder specific bookkeeping to
Parcel. `variant` has a size overhead of one pointer, but since there is
at least one pointer worth of fields in each case, it works out as an
overall win. We could probably do it cheaper by using a union and hiding
a bit field somewhere to indicate the active case, but that isn't
necessary yet.

Bug: 185909244
Test: TH
Change-Id: Id53ea0cbfe51b3246e6f9f1f3d9df7c8c193808e
parent 5caafddc
Loading
Loading
Loading
Loading
+330 −204

File changed.

Preview size limit exceeded, changes collapsed.

+3 −7
Original line number Diff line number Diff line
@@ -601,10 +601,8 @@ status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection,
    if (rpcReply->status != OK) return rpcReply->status;

    data.release();
    reply->ipcSetDataReference(rpcReply->data, command.bodySize - offsetof(RpcWireReply, data),
                               nullptr, 0, cleanup_reply_data);

    reply->markForRpc(session);
    reply->rpcSetDataReference(session, rpcReply->data,
                               command.bodySize - offsetof(RpcWireReply, data), cleanup_reply_data);

    return OK;
}
@@ -824,11 +822,9 @@ processTransactInternalTailCall:
        // transaction->data is owned by this function. Parcel borrows this data and
        // only holds onto it for the duration of this function call. Parcel will be
        // deleted before the 'transactionData' object.
        data.ipcSetDataReference(transaction->data,
        data.rpcSetDataReference(session, transaction->data,
                                 transactionData.size() - offsetof(RpcWireTransaction, data),
                                 nullptr /*object*/, 0 /*objectCount*/,
                                 do_nothing_to_transact_data);
        data.markForRpc(session);

        if (target) {
            bool origAllowNested = connection->allowNested;
+39 −14
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <map> // for legacy reasons
#include <string>
#include <type_traits>
#include <variant>
#include <vector>

#include <android-base/unique_fd.h>
@@ -605,15 +606,19 @@ private:
    size_t              ipcDataSize() const;
    uintptr_t           ipcObjects() const;
    size_t              ipcObjectsCount() const;
    void                ipcSetDataReference(const uint8_t* data, size_t dataSize,
                                            const binder_size_t* objects, size_t objectsCount,
    void ipcSetDataReference(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
                             size_t objectsCount, release_func relFunc);
    void rpcSetDataReference(const sp<RpcSession>& session, const uint8_t* data, size_t dataSize,
                             release_func relFunc);

    status_t            finishWrite(size_t len);
    void                releaseObjects();
    void                acquireObjects();
    status_t            growData(size_t len);
    // Clear the Parcel and set the capacity to `desired`.
    // Doesn't reset the RPC session association.
    status_t            restartWrite(size_t desired);
    // Set the capacity to `desired`, truncating the Parcel if necessary.
    status_t            continueWrite(size_t desired);
    status_t            writePointer(uintptr_t val);
    status_t            readPointer(uintptr_t *pArg) const;
@@ -1253,18 +1258,39 @@ private:
    size_t              mDataSize;
    size_t              mDataCapacity;
    mutable size_t mDataPos;
    binder_size_t*      mObjects;
    size_t              mObjectsSize;
    size_t              mObjectsCapacity;
    mutable size_t      mNextObjectHint;
    mutable bool        mObjectsSorted;

    mutable bool        mRequestHeaderPresent;
    // Fields only needed when parcelling for "kernel Binder".
    struct KernelFields {
        binder_size_t* mObjects = nullptr;
        size_t mObjectsSize = 0;
        size_t mObjectsCapacity = 0;
        mutable size_t mNextObjectHint = 0;

    mutable size_t      mWorkSourceRequestHeaderPosition;
        mutable size_t mWorkSourceRequestHeaderPosition = 0;
        mutable bool mRequestHeaderPresent = false;

        mutable bool mObjectsSorted = false;
        mutable bool mFdsKnown = true;
        mutable bool mHasFds = false;
    };
    // Fields only needed when parcelling for RPC Binder.
    struct RpcFields {
        RpcFields(const sp<RpcSession>& session);

        // Should always be non-null.
        const sp<RpcSession> mSession;
    };
    std::variant<KernelFields, RpcFields> mVariantFields;

    // Pointer to KernelFields in mVariantFields if present.
    KernelFields* maybeKernelFields() { return std::get_if<KernelFields>(&mVariantFields); }
    const KernelFields* maybeKernelFields() const {
        return std::get_if<KernelFields>(&mVariantFields);
    }
    // Pointer to RpcFields in mVariantFields if present.
    RpcFields* maybeRpcFields() { return std::get_if<RpcFields>(&mVariantFields); }
    const RpcFields* maybeRpcFields() const { return std::get_if<RpcFields>(&mVariantFields); }

    mutable bool        mFdsKnown;
    mutable bool        mHasFds;
    bool                mAllowFds;

    // if this parcelable is involved in a secure transaction, force the
@@ -1273,7 +1299,6 @@ private:

    release_func        mOwner;

    sp<RpcSession> mSession;
    size_t mReserved;

    class Blob {