Loading libs/binder/ndk/AIBinder.cpp +51 −46 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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) Loading Loading @@ -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; }; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading libs/binder/ndk/AIBinder_internal.h +12 −14 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; } Loading @@ -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. Loading @@ -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 { Loading libs/binder/ndk/AParcel.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; } Loading libs/binder/ndk/AServiceManager.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -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(); } libs/binder/ndk/include_ndk/android/binder_ibinder.h +3 −4 Original line number Diff line number Diff line Loading @@ -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 Loading
libs/binder/ndk/AIBinder.cpp +51 −46 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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) Loading Loading @@ -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; }; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading
libs/binder/ndk/AIBinder_internal.h +12 −14 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; } Loading @@ -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. Loading @@ -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 { Loading
libs/binder/ndk/AParcel.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; } Loading
libs/binder/ndk/AServiceManager.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -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(); }
libs/binder/ndk/include_ndk/android/binder_ibinder.h +3 −4 Original line number Diff line number Diff line Loading @@ -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