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

Commit 5ac75988 authored by Steven Moreland's avatar Steven Moreland Committed by android-build-merger
Browse files

Merge changes I9d3a049f,I0d52ed5e,I556435ca am: fea8cb29

am: f62c470a

Change-Id: I5e0a497ff3411446a56672982d79d6548f88331c
parents 8fc56b7b f62c470a
Loading
Loading
Loading
Loading
+153 −4
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@

#include <android-base/logging.h>

using DeathRecipient = ::android::IBinder::DeathRecipient;

using ::android::IBinder;
using ::android::Parcel;
using ::android::sp;
@@ -32,10 +34,10 @@ namespace ABBinderTag {

static const void* kId = "ABBinder";
static void* kValue = static_cast<void*>(new bool{true});
void cleanId(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
void clean(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};

static void attach(const sp<IBinder>& binder) {
    binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
    binder->attachObject(kId, kValue, nullptr /*cookie*/, clean);
}
static bool has(const sp<IBinder>& binder) {
    return binder != nullptr && binder->findObject(kId) == kValue;
@@ -43,6 +45,21 @@ static bool has(const sp<IBinder>& binder) {

} // namespace ABBinderTag

namespace ABpBinderTag {

static std::mutex gLock;
static const void* kId = "ABpBinder";
struct Value {
    wp<ABpBinder> binder;
};
void clean(const void* id, void* obj, void* cookie) {
    CHECK(id == kId) << id << " " << obj << " " << cookie;

    delete static_cast<Value*>(obj);
};

} // namespace ABpBinderTag

AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}

@@ -121,14 +138,51 @@ ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
}
ABpBinder::~ABpBinder() {}

sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
void ABpBinder::onLastStrongRef(const void* id) {
    {
        std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
        // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for
        // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no
        // longer be able to exist at the time of this method call, there is no longer a need to
        // recover it.

        ABpBinderTag::Value* value =
                static_cast<ABpBinderTag::Value*>(remote()->findObject(ABpBinderTag::kId));
        if (value != nullptr) {
            value->binder = nullptr;
        }
    }

    BpRefBase::onLastStrongRef(id);
}

sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(const ::android::sp<::android::IBinder>& binder) {
    if (binder == nullptr) {
        return nullptr;
    }
    if (ABBinderTag::has(binder)) {
        return static_cast<ABBinder*>(binder.get());
    }
    return new ABpBinder(binder);

    // The following code ensures that for a given binder object (remote or local), if it is not an
    // ABBinder then at most one ABpBinder object exists in a given process representing it.
    std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);

    ABpBinderTag::Value* value =
            static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
    if (value == nullptr) {
        value = new ABpBinderTag::Value;
        binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/,
                             ABpBinderTag::clean);
    }

    sp<ABpBinder> ret = value->binder.promote();
    if (ret == nullptr) {
        ret = new ABpBinder(binder);
        value->binder = ret;
    }

    return ret;
}

struct AIBinder_Weak {
@@ -179,6 +233,63 @@ AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
    return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
}

void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
    CHECK(who == mWho);

    mOnDied(mCookie);
    mWho = nullptr;
}

AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied)
      : mOnDied(onDied) {
    CHECK(onDied != nullptr);
}

binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) {
    CHECK(binder != nullptr);

    std::lock_guard<std::mutex> l(mDeathRecipientsMutex);

    sp<TransferDeathRecipient> recipient =
            new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied);

    binder_status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/);
    if (status != EX_NONE) {
        return status;
    }

    mDeathRecipients.push_back(recipient);
    return EX_NONE;
}

binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) {
    CHECK(binder != nullptr);

    std::lock_guard<std::mutex> l(mDeathRecipientsMutex);

    for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) {
        sp<TransferDeathRecipient> recipient = *it;

        if (recipient->getCookie() == cookie &&

            recipient->getWho() == binder->getBinder()) {
            mDeathRecipients.erase(it.base() - 1);

            binder_status_t status =
                    binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/);
            if (status != EX_NONE) {
                LOG(ERROR) << __func__
                           << ": removed reference to death recipient but unlink failed.";
            }
            return status;
        }
    }

    return -ENOENT;
}

// start of C-API methods

AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
    if (clazz == nullptr) {
        LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
@@ -218,6 +329,26 @@ binder_status_t AIBinder_ping(AIBinder* binder) {
    return binder->getBinder()->pingBinder();
}

binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
                                     void* cookie) {
    if (binder == nullptr || recipient == nullptr) {
        LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
        return EX_NULL_POINTER;
    }

    return recipient->linkToDeath(binder, cookie);
}

binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
                                       void* cookie) {
    if (binder == nullptr || recipient == nullptr) {
        LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
        return EX_NULL_POINTER;
    }

    return recipient->unlinkToDeath(binder, cookie);
}

void AIBinder_incStrong(AIBinder* binder) {
    if (binder == nullptr) {
        LOG(ERROR) << __func__ << ": on null binder";
@@ -347,3 +478,21 @@ binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, APa

    return parcelStatus;
}

AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
        AIBinder_DeathRecipient_onBinderDied onBinderDied) {
    if (onBinderDied == nullptr) {
        LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter.";
        return nullptr;
    }
    return new AIBinder_DeathRecipient(onBinderDied);
}

void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient) {
    if (recipient == nullptr) {
        return;
    }

    delete *recipient;
    *recipient = nullptr;
}
+45 −3
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include "AIBinder_internal.h"

#include <atomic>
#include <mutex>
#include <vector>

#include <binder/Binder.h>
#include <binder/IBinder.h>
@@ -79,13 +81,18 @@ private:
    void* mUserData;
};

// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
// a class.
// This binder object may be remote or local (even though it is 'Bp'). The implication if it is
// local is that it is an IBinder object created outside of the domain of libbinder_ndk.
struct ABpBinder : public AIBinder, public ::android::BpRefBase {
    static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);
    // Looks up to see if this object has or is an existing ABBinder or ABpBinder object, otherwise
    // it creates an ABpBinder object.
    static ::android::sp<AIBinder> lookupOrCreateFromBinder(
            const ::android::sp<::android::IBinder>& binder);

    virtual ~ABpBinder();

    void onLastStrongRef(const void* id) override;

    ::android::sp<::android::IBinder> getBinder() override { return remote(); }
    ABpBinder* asABpBinder() override { return this; }

@@ -108,3 +115,38 @@ private:
    // one.
    const ::android::String16 mInterfaceDescriptor;
};

// Ownership is like this (when linked to death):
//
//   AIBinder_DeathRecipient -sp-> TransferDeathRecipient <-wp-> IBinder
//
// When the AIBinder_DeathRecipient is dropped, so are the actual underlying death recipients. When
// the IBinder dies, only a wp to it is kept.
struct AIBinder_DeathRecipient {
    // One of these is created for every linkToDeath. This is to be able to recover data when a
    // binderDied receipt only gives us information about the IBinder.
    struct TransferDeathRecipient : ::android::IBinder::DeathRecipient {
        TransferDeathRecipient(const ::android::wp<::android::IBinder>& who, void* cookie,
                               const AIBinder_DeathRecipient_onBinderDied& onDied)
              : mWho(who), mCookie(cookie), mOnDied(onDied) {}

        void binderDied(const ::android::wp<::android::IBinder>& who) override;

        const ::android::wp<::android::IBinder>& getWho() { return mWho; }
        void* getCookie() { return mCookie; }

    private:
        ::android::wp<::android::IBinder> mWho;
        void* mCookie;
        const AIBinder_DeathRecipient_onBinderDied& mOnDied;
    };

    AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
    binder_status_t linkToDeath(AIBinder* binder, void* cookie);
    binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);

private:
    std::mutex mDeathRecipientsMutex;
    std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients;
    AIBinder_DeathRecipient_onBinderDied mOnDied;
};
+4 −3
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ void AParcel_delete(AParcel** parcel) {
}

binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
    return (*parcel)->writeStrongBinder(binder->getBinder());
    sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
    return (*parcel)->writeStrongBinder(writeBinder);
}
binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
    sp<IBinder> readBinder = nullptr;
@@ -43,7 +44,7 @@ binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binde
    if (status != EX_NONE) {
        return status;
    }
    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
    AIBinder_incStrong(ret.get());
    *binder = ret.get();
    return status;
@@ -54,7 +55,7 @@ binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder
    if (status != EX_NONE) {
        return status;
    }
    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
    AIBinder_incStrong(ret.get());
    *binder = ret.get();
    return status;
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ AIBinder* AServiceManager_getService(const char* instance) {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16(instance));

    sp<AIBinder> ret = ABpBinder::fromBinder(binder);
    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
    AIBinder_incStrong(ret.get());
    return ret.get();
}
+61 −0
Original line number Diff line number Diff line
@@ -94,6 +94,16 @@ typedef struct AIBinder_Class AIBinder_Class;
 * implementation (usually a callback) to transfer all ownership to a remote process and
 * automatically be deleted when the remote process is done with it or dies. Other memory models are
 * possible, but this is the standard one.
 *
 * If the process containing an AIBinder dies, it is possible to be holding a strong reference to
 * an object which does not exist. In this case, transactions to this binder will return
 * EX_DEAD_OBJECT. See also AIBinder_linkToDeath, AIBinder_unlinkToDeath, and AIBinder_isAlive.
 *
 * Once an AIBinder is created, anywhere it is passed (remotely or locally), there is a 1-1
 * correspondence between the address of an AIBinder and the object it represents. This means that
 * when two AIBinder pointers point to the same address, they represent the same object (whether
 * that object is local or remote). This correspondance can be broken accidentally if AIBinder_new
 * is erronesouly called to create the same object multiple times.
 */
struct AIBinder;
typedef struct AIBinder AIBinder;
@@ -106,6 +116,12 @@ typedef struct AIBinder AIBinder;
struct AIBinder_Weak;
typedef struct AIBinder_Weak AIBinder_Weak;

/**
 * Represents a handle on a death notification. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
 */
struct AIBinder_DeathRecipient;
typedef struct AIBinder_DeathRecipient AIBinder_DeathRecipient;

/**
 * This is called whenever a new AIBinder object is needed of a specific class.
 *
@@ -148,6 +164,14 @@ __attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
 *
 * When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
 * required to delete this object.
 *
 * Once an AIBinder object is created using this API, re-creating that AIBinder for the same
 * instance of the same class will break pointer equality for that specific AIBinder object. For
 * instance, if someone erroneously created two AIBinder instances representing the same callback
 * object and passed one to a hypothetical addCallback function and then later another one to a
 * hypothetical removeCallback function, the remote process would have no way to determine that
 * these two objects are actually equal using the AIBinder pointer alone (which they should be able
 * to do). Also see the suggested memory ownership model suggested above.
 */
__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);

@@ -172,6 +196,26 @@ bool AIBinder_isAlive(const AIBinder* binder);
 */
binder_status_t AIBinder_ping(AIBinder* binder);

/**
 * Registers for notifications that the associated binder is dead. The same death recipient may be
 * associated with multiple different binders. If the binder is local, then no death recipient will
 * be given (since if the local process dies, then no recipient will exist to recieve a
 * transaction). The cookie is passed to recipient in the case that this binder dies and can be
 * null. The exact cookie must also be used to unlink this transaction (see AIBinder_linkToDeath).
 * This function may return a binder transaction failure. The cookie can be used both for
 * identification and holding user data.
 */
binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
                                     void* cookie);

/**
 * Stops registration for the associated binder dying. Does not delete the recipient. This function
 * may return a binder transaction failure and in case the death recipient cannot be found, it
 * returns -ENOENT.
 */
binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
                                       void* cookie);

/**
 * This can only be called if a strong reference to this object already exists in process.
 */
@@ -264,6 +308,23 @@ void AIBinder_Weak_delete(AIBinder_Weak** weakBinder);
 */
__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);

/**
 * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
 */
typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie);

/**
 * Creates a new binder death recipient. This can be attached to multiple different binder objects.
 */
__attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
        AIBinder_DeathRecipient_onBinderDied onBinderDied);

/**
 * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
 * calling this as these will all be automatically unlinked.
 */
void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient);

__END_DECLS

/** @} */
Loading