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

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

Merge "libbinder_ndk: ABBinder objects are tagged." am: 9a582b08 am: dc7ac61f

am: 7f0bb8b3

Change-Id: I36d2effef745924c60cf0d01a7b1985307a7e868
parents 4a1f8f3d 7f0bb8b3
Loading
Loading
Loading
Loading
+51 −46
Original line number Diff line number Diff line
@@ -28,14 +28,29 @@ using ::android::sp;
using ::android::String16;
using ::android::wp;

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 */};

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

} // namespace ABBinderTag

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

sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
bool AIBinder::associateClass(const AIBinder_Class* clazz) {
    using ::android::String8;

    if (clazz == nullptr) return nullptr;
    if (mClazz == clazz) return this;
    if (clazz == nullptr) return false;
    if (mClazz == clazz) return true;

    String8 newDescriptor(clazz->getInterfaceDescriptor());

@@ -45,42 +60,31 @@ sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
            LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
                       << "' match during associateClass, but they are different class objects. "
                          "Class descriptor collision?";
            return nullptr;
        } else {
            LOG(ERROR) << __func__
                       << ": Class cannot be associated on object which already has a class. "
                          "Trying to associate to '"
                       << newDescriptor.c_str() << "' but already set to '"
                       << currentDescriptor.c_str() << "'.";
        }

        LOG(ERROR) << __func__
                   << ": Class cannot be associated on object which already has a class. Trying to "
                      "associate to '"
                   << newDescriptor.c_str() << "' but already set to '" << currentDescriptor.c_str()
                   << "'.";
        return nullptr;
        // always a failure because we know mClazz != clazz
        return false;
    }

    CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor

    String8 descriptor(getBinder()->getInterfaceDescriptor());
    if (descriptor != newDescriptor) {
        LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
                   << "' but descriptor is actually '" << descriptor.c_str() << "'.";
        return nullptr;
    }

    // The descriptor matches, so if it is local, this is guaranteed to be the libbinder_ndk class.
    // An error here can occur if there is a conflict between descriptors (two unrelated classes
    // define the same descriptor), but this should never happen.

    // if this is a local ABBinder, mClazz should be non-null
    CHECK(asABBinder() == nullptr);
    CHECK(asABpBinder() != nullptr);

    if (!isRemote()) {
        // ABpBinder but proxy to a local object. Therefore that local object must be an ABBinder.
        ABBinder* binder = static_cast<ABBinder*>(getBinder().get());
        return binder;
        return false;
    }

    // This is a remote object
    // if this is a local object, it's not one known to libbinder_ndk
    mClazz = clazz;

    return this;
    return true;
}

ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
@@ -111,12 +115,22 @@ binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data
    }
}

ABpBinder::ABpBinder(::android::sp<::android::IBinder> binder)
ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
      : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
    CHECK(binder != nullptr);
}
ABpBinder::~ABpBinder() {}

sp<AIBinder> ABpBinder::fromBinder(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);
}

struct AIBinder_Weak {
    wp<AIBinder> binder;
};
@@ -162,9 +176,11 @@ AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {

    void* userData = clazz->onCreate(args);

    AIBinder* ret = new ABBinder(clazz, userData);
    AIBinder_incStrong(ret);
    return ret;
    sp<AIBinder> ret = new ABBinder(clazz, userData);
    ABBinderTag::attach(ret->getBinder());

    AIBinder_incStrong(ret.get());
    return ret.get();
}

bool AIBinder_isRemote(AIBinder* binder) {
@@ -200,23 +216,12 @@ int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
    return binder->getStrongCount();
}

void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz) {
    if (binder == nullptr || *binder == nullptr) {
        return;
    }

    sp<AIBinder> result = (*binder)->associateClass(clazz);

    // This function takes one refcount of 'binder' and delivers one refcount of 'result' to the
    // callee. First we give the callee their refcount and then take it away from binder. This is
    // done in this order in order to handle the case that the result and the binder are the same
    // object.
    if (result != nullptr) {
        AIBinder_incStrong(result.get());
bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
    if (binder == nullptr) {
        return false;
    }
    AIBinder_decStrong(*binder);

    *binder = result.get(); // Maybe no-op
    return binder->associateClass(clazz);
}

const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
+12 −14
Original line number Diff line number Diff line
@@ -35,24 +35,14 @@ struct AIBinder : public virtual ::android::RefBase {
    AIBinder(const AIBinder_Class* clazz);
    virtual ~AIBinder();

    // This returns an AIBinder object with this class associated. If the class is already
    // associated, 'this' will be returned. If there is a local AIBinder implementation, that will
    // be returned. If this is a remote object, the class will be associated and this will be ready
    // to be used for transactions.
    ::android::sp<AIBinder> associateClass(const AIBinder_Class* clazz);
    bool associateClass(const AIBinder_Class* clazz);
    const AIBinder_Class* getClass() const { return mClazz; }

    // This does not create the binder if it does not exist in the process.
    virtual ::android::sp<::android::IBinder> getBinder() = 0;
    virtual ABBinder* asABBinder() { return nullptr; }
    virtual ABpBinder* asABpBinder() { return nullptr; }

    bool isRemote() {
        auto binder = getBinder();
        // if the binder is nullptr, then it is a local object which hasn't been sent out of process
        // yet.
        return binder != nullptr && binder->remoteBinder() != nullptr;
    }
    bool isRemote() { return getBinder()->remoteBinder() != nullptr; }

private:
    // AIBinder instance is instance of this class for a local object. In order to transact on a
@@ -63,7 +53,6 @@ private:

// This is a local AIBinder object with a known class.
struct ABBinder : public AIBinder, public ::android::BBinder {
    ABBinder(const AIBinder_Class* clazz, void* userData);
    virtual ~ABBinder();

    void* getUserData() { return mUserData; }
@@ -76,6 +65,11 @@ struct ABBinder : public AIBinder, public ::android::BBinder {
                               ::android::Parcel* reply, binder_flags_t flags) override;

private:
    ABBinder(const AIBinder_Class* clazz, void* userData);

    // only thing that should create an ABBinder
    friend AIBinder* AIBinder_new(const AIBinder_Class*, void*);

    // Can contain implementation if this is a local binder. This can still be nullptr for a local
    // binder. If it is nullptr, the implication is the implementation state is entirely external to
    // this object and the functionality provided in the AIBinder_Class is sufficient.
@@ -85,11 +79,15 @@ private:
// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
// a class.
struct ABpBinder : public AIBinder, public ::android::BpRefBase {
    ABpBinder(::android::sp<::android::IBinder> binder);
    static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);

    virtual ~ABpBinder();

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

private:
    ABpBinder(const ::android::sp<::android::IBinder>& binder);
};

struct AIBinder_Class {
+6 −4
Original line number Diff line number Diff line
@@ -34,8 +34,9 @@ binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binde
    if (status != EX_NONE) {
        return status;
    }
    *binder = new ABpBinder(readBinder);
    AIBinder_incStrong(*binder);
    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
    AIBinder_incStrong(ret.get());
    *binder = ret.get();
    return status;
}
binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
@@ -44,8 +45,9 @@ binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder
    if (status != EX_NONE) {
        return status;
    }
    *binder = new ABpBinder(readBinder);
    AIBinder_incStrong(*binder);
    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
    AIBinder_incStrong(ret.get());
    *binder = ret.get();
    return status;
}

+3 −3
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));

    AIBinder* ret = new ABpBinder(binder);
    AIBinder_incStrong(ret);
    return ret;
    sp<AIBinder> ret = ABpBinder::fromBinder(binder);
    AIBinder_incStrong(ret.get());
    return ret.get();
}
+3 −4
Original line number Diff line number Diff line
@@ -167,11 +167,10 @@ int32_t AIBinder_debugGetRefCount(AIBinder* binder);
 * However, if an object is just intended to be passed through to another process or used as a
 * handle this need not be called.
 *
 * The binder parameter may or may not be updated. If it is updated, the ownership of the original
 * object is transferred to the new object. If the class association fails, ownership of the binder
 * is lost, and it is set to nullptr.
 * This returns true if the class association succeeds. If it fails, no change is made to the
 * binder object.
 */
void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz);
bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz);

/*
 * Returns the class that this binder was constructed with or associated with.
Loading