Loading libs/binder/Status.cpp +21 −1 Original line number Diff line number Diff line Loading @@ -63,6 +63,26 @@ Status Status::fromStatusT(status_t status) { return ret; } std::string Status::exceptionToString(int32_t exceptionCode) { switch (exceptionCode) { #define EXCEPTION_TO_CASE(EXCEPTION) case EXCEPTION: return #EXCEPTION; EXCEPTION_TO_CASE(EX_NONE) EXCEPTION_TO_CASE(EX_SECURITY) EXCEPTION_TO_CASE(EX_BAD_PARCELABLE) EXCEPTION_TO_CASE(EX_ILLEGAL_ARGUMENT) EXCEPTION_TO_CASE(EX_NULL_POINTER) EXCEPTION_TO_CASE(EX_ILLEGAL_STATE) EXCEPTION_TO_CASE(EX_NETWORK_MAIN_THREAD) EXCEPTION_TO_CASE(EX_UNSUPPORTED_OPERATION) EXCEPTION_TO_CASE(EX_SERVICE_SPECIFIC) EXCEPTION_TO_CASE(EX_PARCELABLE) EXCEPTION_TO_CASE(EX_HAS_REPLY_HEADER) EXCEPTION_TO_CASE(EX_TRANSACTION_FAILED) #undef EXCEPTION_TO_CASE default: return std::to_string(exceptionCode); } } Status::Status(int32_t exceptionCode, int32_t errorCode) : mException(exceptionCode), mErrorCode(errorCode) {} Loading Loading @@ -184,7 +204,7 @@ String8 Status::toString8() const { if (mException == EX_NONE) { ret.append("No error"); } else { ret.appendFormat("Status(%d): '", mException); ret.appendFormat("Status(%d, %s): '", mException, exceptionToString(mException).c_str()); if (mException == EX_SERVICE_SPECIFIC || mException == EX_TRANSACTION_FAILED) { ret.appendFormat("%d: ", mErrorCode); Loading libs/binder/include/binder/IBinder.h +3 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,9 @@ public: * dies. The @a cookie is optional. If non-NULL, you can * supply a NULL @a recipient, and the recipient previously * added with that cookie will be unlinked. * * If the binder is dead, this will return DEAD_OBJECT. Deleting * the object will also unlink all death recipients. */ // NOLINTNEXTLINE(google-default-arguments) virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient, Loading libs/binder/include/binder/Status.h +3 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <binder/Parcel.h> #include <utils/String8.h> #include <string> namespace android { namespace binder { Loading Loading @@ -97,6 +98,8 @@ public: static Status fromStatusT(status_t status); static std::string exceptionToString(status_t exceptionCode); Status() = default; ~Status() = default; Loading libs/binder/ndk/ibinder.cpp +38 −10 Original line number Diff line number Diff line Loading @@ -269,6 +269,18 @@ void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinde CHECK(who == mWho); mOnDied(mCookie); sp<AIBinder_DeathRecipient> recipient = mParentRecipient.promote(); sp<IBinder> strongWho = who.promote(); // otherwise this will be cleaned up later with pruneDeadTransferEntriesLocked if (recipient != nullptr && strongWho != nullptr) { status_t result = recipient->unlinkToDeath(strongWho, mCookie); if (result != ::android::DEAD_OBJECT) { LOG(WARNING) << "Unlinking to dead binder resulted in: " << result; } } mWho = nullptr; } Loading @@ -277,24 +289,34 @@ AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinde CHECK(onDied != nullptr); } binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) { void AIBinder_DeathRecipient::pruneDeadTransferEntriesLocked() { mDeathRecipients.erase(std::remove_if(mDeathRecipients.begin(), mDeathRecipients.end(), [](const sp<TransferDeathRecipient>& tdr) { return tdr->getWho() == nullptr; }), mDeathRecipients.end()); } binder_status_t AIBinder_DeathRecipient::linkToDeath(sp<IBinder> binder, void* cookie) { CHECK(binder != nullptr); std::lock_guard<std::mutex> l(mDeathRecipientsMutex); sp<TransferDeathRecipient> recipient = new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied); new TransferDeathRecipient(binder, cookie, this, mOnDied); status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/); status_t status = binder->linkToDeath(recipient, cookie, 0 /*flags*/); if (status != STATUS_OK) { return PruneStatusT(status); } mDeathRecipients.push_back(recipient); pruneDeadTransferEntriesLocked(); return STATUS_OK; } binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) { binder_status_t AIBinder_DeathRecipient::unlinkToDeath(sp<IBinder> binder, void* cookie) { CHECK(binder != nullptr); std::lock_guard<std::mutex> l(mDeathRecipientsMutex); Loading @@ -302,10 +324,10 @@ binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* c for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) { sp<TransferDeathRecipient> recipient = *it; if (recipient->getCookie() == cookie && recipient->getWho() == binder->getBinder()) { if (recipient->getCookie() == cookie && recipient->getWho() == binder) { mDeathRecipients.erase(it.base() - 1); status_t status = binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/); status_t status = binder->unlinkToDeath(recipient, cookie, 0 /*flags*/); if (status != ::android::OK) { LOG(ERROR) << __func__ << ": removed reference to death recipient but unlink failed."; Loading Loading @@ -390,7 +412,7 @@ binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* } // returns binder_status_t return recipient->linkToDeath(binder, cookie); return recipient->linkToDeath(binder->getBinder(), cookie); } binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, Loading @@ -401,7 +423,7 @@ binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient } // returns binder_status_t return recipient->unlinkToDeath(binder, cookie); return recipient->unlinkToDeath(binder->getBinder(), cookie); } uid_t AIBinder_getCallingUid() { Loading Loading @@ -555,9 +577,15 @@ AIBinder_DeathRecipient* AIBinder_DeathRecipient_new( LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter."; return nullptr; } return new AIBinder_DeathRecipient(onBinderDied); auto ret = new AIBinder_DeathRecipient(onBinderDied); ret->incStrong(nullptr); return ret; } void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) { delete recipient; if (recipient == nullptr) { return; } recipient->decStrong(nullptr); } libs/binder/ndk/ibinder_internal.h +15 −4 Original line number Diff line number Diff line Loading @@ -128,13 +128,14 @@ struct AIBinder_Class { // // 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 { struct AIBinder_DeathRecipient : ::android::RefBase { // 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 ::android::wp<AIBinder_DeathRecipient>& parentRecipient, const AIBinder_DeathRecipient_onBinderDied onDied) : mWho(who), mCookie(cookie), mOnDied(onDied) {} : mWho(who), mCookie(cookie), mParentRecipient(parentRecipient), mOnDied(onDied) {} void binderDied(const ::android::wp<::android::IBinder>& who) override; Loading @@ -144,14 +145,24 @@ struct AIBinder_DeathRecipient { private: ::android::wp<::android::IBinder> mWho; void* mCookie; ::android::wp<AIBinder_DeathRecipient> mParentRecipient; // This is kept separately from AIBinder_DeathRecipient in case the death recipient is // deleted while the death notification is fired const AIBinder_DeathRecipient_onBinderDied mOnDied; }; explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied); binder_status_t linkToDeath(AIBinder* binder, void* cookie); binder_status_t unlinkToDeath(AIBinder* binder, void* cookie); binder_status_t linkToDeath(::android::sp<::android::IBinder>, void* cookie); binder_status_t unlinkToDeath(::android::sp<::android::IBinder> binder, void* cookie); private: // When the user of this API deletes a Bp object but not the death recipient, the // TransferDeathRecipient object can't be cleaned up. This is called whenever a new // TransferDeathRecipient is linked, and it ensures that mDeathRecipients can't grow unbounded. void pruneDeadTransferEntriesLocked(); std::mutex mDeathRecipientsMutex; std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients; AIBinder_DeathRecipient_onBinderDied mOnDied; Loading Loading
libs/binder/Status.cpp +21 −1 Original line number Diff line number Diff line Loading @@ -63,6 +63,26 @@ Status Status::fromStatusT(status_t status) { return ret; } std::string Status::exceptionToString(int32_t exceptionCode) { switch (exceptionCode) { #define EXCEPTION_TO_CASE(EXCEPTION) case EXCEPTION: return #EXCEPTION; EXCEPTION_TO_CASE(EX_NONE) EXCEPTION_TO_CASE(EX_SECURITY) EXCEPTION_TO_CASE(EX_BAD_PARCELABLE) EXCEPTION_TO_CASE(EX_ILLEGAL_ARGUMENT) EXCEPTION_TO_CASE(EX_NULL_POINTER) EXCEPTION_TO_CASE(EX_ILLEGAL_STATE) EXCEPTION_TO_CASE(EX_NETWORK_MAIN_THREAD) EXCEPTION_TO_CASE(EX_UNSUPPORTED_OPERATION) EXCEPTION_TO_CASE(EX_SERVICE_SPECIFIC) EXCEPTION_TO_CASE(EX_PARCELABLE) EXCEPTION_TO_CASE(EX_HAS_REPLY_HEADER) EXCEPTION_TO_CASE(EX_TRANSACTION_FAILED) #undef EXCEPTION_TO_CASE default: return std::to_string(exceptionCode); } } Status::Status(int32_t exceptionCode, int32_t errorCode) : mException(exceptionCode), mErrorCode(errorCode) {} Loading Loading @@ -184,7 +204,7 @@ String8 Status::toString8() const { if (mException == EX_NONE) { ret.append("No error"); } else { ret.appendFormat("Status(%d): '", mException); ret.appendFormat("Status(%d, %s): '", mException, exceptionToString(mException).c_str()); if (mException == EX_SERVICE_SPECIFIC || mException == EX_TRANSACTION_FAILED) { ret.appendFormat("%d: ", mErrorCode); Loading
libs/binder/include/binder/IBinder.h +3 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,9 @@ public: * dies. The @a cookie is optional. If non-NULL, you can * supply a NULL @a recipient, and the recipient previously * added with that cookie will be unlinked. * * If the binder is dead, this will return DEAD_OBJECT. Deleting * the object will also unlink all death recipients. */ // NOLINTNEXTLINE(google-default-arguments) virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient, Loading
libs/binder/include/binder/Status.h +3 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <binder/Parcel.h> #include <utils/String8.h> #include <string> namespace android { namespace binder { Loading Loading @@ -97,6 +98,8 @@ public: static Status fromStatusT(status_t status); static std::string exceptionToString(status_t exceptionCode); Status() = default; ~Status() = default; Loading
libs/binder/ndk/ibinder.cpp +38 −10 Original line number Diff line number Diff line Loading @@ -269,6 +269,18 @@ void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinde CHECK(who == mWho); mOnDied(mCookie); sp<AIBinder_DeathRecipient> recipient = mParentRecipient.promote(); sp<IBinder> strongWho = who.promote(); // otherwise this will be cleaned up later with pruneDeadTransferEntriesLocked if (recipient != nullptr && strongWho != nullptr) { status_t result = recipient->unlinkToDeath(strongWho, mCookie); if (result != ::android::DEAD_OBJECT) { LOG(WARNING) << "Unlinking to dead binder resulted in: " << result; } } mWho = nullptr; } Loading @@ -277,24 +289,34 @@ AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinde CHECK(onDied != nullptr); } binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) { void AIBinder_DeathRecipient::pruneDeadTransferEntriesLocked() { mDeathRecipients.erase(std::remove_if(mDeathRecipients.begin(), mDeathRecipients.end(), [](const sp<TransferDeathRecipient>& tdr) { return tdr->getWho() == nullptr; }), mDeathRecipients.end()); } binder_status_t AIBinder_DeathRecipient::linkToDeath(sp<IBinder> binder, void* cookie) { CHECK(binder != nullptr); std::lock_guard<std::mutex> l(mDeathRecipientsMutex); sp<TransferDeathRecipient> recipient = new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied); new TransferDeathRecipient(binder, cookie, this, mOnDied); status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/); status_t status = binder->linkToDeath(recipient, cookie, 0 /*flags*/); if (status != STATUS_OK) { return PruneStatusT(status); } mDeathRecipients.push_back(recipient); pruneDeadTransferEntriesLocked(); return STATUS_OK; } binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) { binder_status_t AIBinder_DeathRecipient::unlinkToDeath(sp<IBinder> binder, void* cookie) { CHECK(binder != nullptr); std::lock_guard<std::mutex> l(mDeathRecipientsMutex); Loading @@ -302,10 +324,10 @@ binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* c for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) { sp<TransferDeathRecipient> recipient = *it; if (recipient->getCookie() == cookie && recipient->getWho() == binder->getBinder()) { if (recipient->getCookie() == cookie && recipient->getWho() == binder) { mDeathRecipients.erase(it.base() - 1); status_t status = binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/); status_t status = binder->unlinkToDeath(recipient, cookie, 0 /*flags*/); if (status != ::android::OK) { LOG(ERROR) << __func__ << ": removed reference to death recipient but unlink failed."; Loading Loading @@ -390,7 +412,7 @@ binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* } // returns binder_status_t return recipient->linkToDeath(binder, cookie); return recipient->linkToDeath(binder->getBinder(), cookie); } binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, Loading @@ -401,7 +423,7 @@ binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient } // returns binder_status_t return recipient->unlinkToDeath(binder, cookie); return recipient->unlinkToDeath(binder->getBinder(), cookie); } uid_t AIBinder_getCallingUid() { Loading Loading @@ -555,9 +577,15 @@ AIBinder_DeathRecipient* AIBinder_DeathRecipient_new( LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter."; return nullptr; } return new AIBinder_DeathRecipient(onBinderDied); auto ret = new AIBinder_DeathRecipient(onBinderDied); ret->incStrong(nullptr); return ret; } void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) { delete recipient; if (recipient == nullptr) { return; } recipient->decStrong(nullptr); }
libs/binder/ndk/ibinder_internal.h +15 −4 Original line number Diff line number Diff line Loading @@ -128,13 +128,14 @@ struct AIBinder_Class { // // 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 { struct AIBinder_DeathRecipient : ::android::RefBase { // 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 ::android::wp<AIBinder_DeathRecipient>& parentRecipient, const AIBinder_DeathRecipient_onBinderDied onDied) : mWho(who), mCookie(cookie), mOnDied(onDied) {} : mWho(who), mCookie(cookie), mParentRecipient(parentRecipient), mOnDied(onDied) {} void binderDied(const ::android::wp<::android::IBinder>& who) override; Loading @@ -144,14 +145,24 @@ struct AIBinder_DeathRecipient { private: ::android::wp<::android::IBinder> mWho; void* mCookie; ::android::wp<AIBinder_DeathRecipient> mParentRecipient; // This is kept separately from AIBinder_DeathRecipient in case the death recipient is // deleted while the death notification is fired const AIBinder_DeathRecipient_onBinderDied mOnDied; }; explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied); binder_status_t linkToDeath(AIBinder* binder, void* cookie); binder_status_t unlinkToDeath(AIBinder* binder, void* cookie); binder_status_t linkToDeath(::android::sp<::android::IBinder>, void* cookie); binder_status_t unlinkToDeath(::android::sp<::android::IBinder> binder, void* cookie); private: // When the user of this API deletes a Bp object but not the death recipient, the // TransferDeathRecipient object can't be cleaned up. This is called whenever a new // TransferDeathRecipient is linked, and it ensures that mDeathRecipients can't grow unbounded. void pruneDeadTransferEntriesLocked(); std::mutex mDeathRecipientsMutex; std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients; AIBinder_DeathRecipient_onBinderDied mOnDied; Loading