Loading libs/binder/Binder.cpp +73 −16 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <binder/Binder.h> #include <atomic> #include <set> #include <android-base/unique_fd.h> #include <binder/BpBinder.h> Loading Loading @@ -150,7 +151,8 @@ status_t IBinder::getDebugPid(pid_t* out) { return OK; } status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd) { status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd, const sp<IBinder>& keepAliveBinder) { if constexpr (!kEnableRpcDevServers) { ALOGW("setRpcClientDebug disallowed because RPC is not enabled"); return INVALID_OPERATION; Loading @@ -158,7 +160,7 @@ status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd) { BBinder* local = this->localBinder(); if (local != nullptr) { return local->BBinder::setRpcClientDebug(std::move(socketFd)); return local->BBinder::setRpcClientDebug(std::move(socketFd), keepAliveBinder); } BpBinder* proxy = this->remoteBinder(); Loading @@ -173,11 +175,44 @@ status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd) { status = data.writeFileDescriptor(socketFd.release(), true /* own */); if (status != OK) return status; } if (status = data.writeStrongBinder(keepAliveBinder); status != OK) return status; return transact(SET_RPC_CLIENT_TRANSACTION, data, &reply); } // --------------------------------------------------------------------------- class BBinder::RpcServerLink : public IBinder::DeathRecipient { public: // On binder died, calls RpcServer::shutdown on @a rpcServer, and removes itself from @a binder. RpcServerLink(const sp<RpcServer>& rpcServer, const sp<IBinder>& keepAliveBinder, const wp<BBinder>& binder) : mRpcServer(rpcServer), mKeepAliveBinder(keepAliveBinder), mBinder(binder) {} void binderDied(const wp<IBinder>&) override { LOG_RPC_DETAIL("RpcServerLink: binder died, shutting down RpcServer"); if (mRpcServer == nullptr) { ALOGW("RpcServerLink: Unable to shut down RpcServer because it does not exist."); } else { ALOGW_IF(!mRpcServer->shutdown(), "RpcServerLink: RpcServer did not shut down properly. Not started?"); } mRpcServer.clear(); auto promoted = mBinder.promote(); if (promoted == nullptr) { ALOGW("RpcServerLink: Unable to remove link from parent binder object because parent " "binder object is gone."); } else { promoted->removeRpcServerLink(sp<RpcServerLink>::fromExisting(this)); } mBinder.clear(); } private: sp<RpcServer> mRpcServer; sp<IBinder> mKeepAliveBinder; // hold to avoid automatically unlinking wp<BBinder> mBinder; }; class BBinder::Extras { public: Loading @@ -190,7 +225,7 @@ public: // for below objects Mutex mLock; sp<RpcServer> mRpcServer; std::set<sp<RpcServerLink>> mRpcServerLinks; BpBinder::ObjectManager mObjects; }; Loading Loading @@ -453,11 +488,14 @@ status_t BBinder::setRpcClientDebug(const Parcel& data) { if (hasSocketFd) { if (status = data.readUniqueFileDescriptor(&clientFd); status != OK) return status; } sp<IBinder> keepAliveBinder; if (status = data.readNullableStrongBinder(&keepAliveBinder); status != OK) return status; return setRpcClientDebug(std::move(clientFd)); return setRpcClientDebug(std::move(clientFd), keepAliveBinder); } status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd) { status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd, const sp<IBinder>& keepAliveBinder) { if constexpr (!kEnableRpcDevServers) { ALOGW("%s: disallowed because RPC is not enabled", __PRETTY_FUNCTION__); return INVALID_OPERATION; Loading @@ -471,6 +509,11 @@ status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd) { return BAD_VALUE; } if (keepAliveBinder == nullptr) { ALOGE("%s: No keepAliveBinder provided.", __PRETTY_FUNCTION__); return UNEXPECTED_NULL; } size_t binderThreadPoolMaxCount = ProcessState::self()->getThreadPoolMaxThreadCount(); if (binderThreadPoolMaxCount <= 1) { ALOGE("%s: ProcessState thread pool max count is %zu. RPC is disabled for this service " Loading @@ -479,24 +522,38 @@ status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd) { return INVALID_OPERATION; } // Weak ref to avoid circular dependency: // BBinder -> RpcServerLink ----> RpcServer -X-> BBinder // `-X-> BBinder auto weakThis = wp<BBinder>::fromExisting(this); Extras* e = getOrCreateExtras(); AutoMutex _l(e->mLock); if (e->mRpcServer != nullptr) { ALOGE("%s: Already have RPC client", __PRETTY_FUNCTION__); return ALREADY_EXISTS; } e->mRpcServer = RpcServer::make(); LOG_ALWAYS_FATAL_IF(e->mRpcServer == nullptr, "RpcServer::make returns null"); e->mRpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); // Weak ref to avoid circular dependency: BBinder -> RpcServer -X-> BBinder e->mRpcServer->setRootObjectWeak(wp<BBinder>::fromExisting(this)); e->mRpcServer->setupExternalServer(std::move(socketFd)); e->mRpcServer->setMaxThreads(binderThreadPoolMaxCount); e->mRpcServer->start(); auto rpcServer = RpcServer::make(); LOG_ALWAYS_FATAL_IF(rpcServer == nullptr, "RpcServer::make returns null"); rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); auto link = sp<RpcServerLink>::make(rpcServer, keepAliveBinder, weakThis); if (auto status = keepAliveBinder->linkToDeath(link, nullptr, 0); status != OK) { ALOGE("%s: keepAliveBinder->linkToDeath returns %s", __PRETTY_FUNCTION__, statusToString(status).c_str()); return status; } rpcServer->setRootObjectWeak(weakThis); rpcServer->setupExternalServer(std::move(socketFd)); rpcServer->setMaxThreads(binderThreadPoolMaxCount); rpcServer->start(); e->mRpcServerLinks.emplace(link); LOG_RPC_DETAIL("%s(fd=%d) successful", __PRETTY_FUNCTION__, socketFdForPrint); return OK; } void BBinder::removeRpcServerLink(const sp<RpcServerLink>& link) { Extras* e = mExtras.load(std::memory_order_acquire); if (!e) return; AutoMutex _l(e->mLock); (void)e->mRpcServerLinks.erase(link); } BBinder::~BBinder() { Extras* e = mExtras.load(std::memory_order_relaxed); Loading libs/binder/include/binder/Binder.h +4 −1 Original line number Diff line number Diff line Loading @@ -101,7 +101,8 @@ public: // to another process. void setParceled(); [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd); [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd, const sp<IBinder>& keepAliveBinder); protected: virtual ~BBinder(); Loading @@ -116,11 +117,13 @@ private: BBinder(const BBinder& o); BBinder& operator=(const BBinder& o); class RpcServerLink; class Extras; Extras* getOrCreateExtras(); [[nodiscard]] status_t setRpcClientDebug(const Parcel& data); void removeRpcServerLink(const sp<RpcServerLink>& link); std::atomic<Extras*> mExtras; Loading libs/binder/include/binder/IBinder.h +6 −3 Original line number Diff line number Diff line Loading @@ -162,14 +162,17 @@ public: * 2. spawns 1 new thread that calls RpcServer::join() * - join() spawns some number of threads that accept() connections; see RpcServer * * setRpcClientDebug() may only be called once. * TODO(b/182914638): If allow to shut down the client, addRpcClient can be called repeatedly. * setRpcClientDebug() may be called multiple times. Each call will add a new RpcServer * and opens up a TCP port. * * Note: A thread is spawned for each accept()'ed fd, which may call into functions of the * interface freely. See RpcServer::join(). To avoid such race conditions, implement the service * functions with multithreading support. * * On death of @a keepAliveBinder, the RpcServer shuts down. */ [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd socketFd); [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd socketFd, const sp<IBinder>& keepAliveBinder); // NOLINTNEXTLINE(google-default-arguments) virtual status_t transact( uint32_t code, Loading libs/binder/servicedispatcher.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -26,9 +26,11 @@ #include <binder/IServiceManager.h> #include <binder/RpcServer.h> using android::BBinder; using android::defaultServiceManager; using android::OK; using android::RpcServer; using android::sp; using android::statusToString; using android::String16; using android::base::Basename; Loading Loading @@ -74,7 +76,8 @@ int Dispatch(const char* name) { return EX_SOFTWARE; } auto socket = rpcServer->releaseServer(); auto status = binder->setRpcClientDebug(std::move(socket)); auto keepAliveBinder = sp<BBinder>::make(); auto status = binder->setRpcClientDebug(std::move(socket), keepAliveBinder); if (status != OK) { LOG(ERROR) << "setRpcClientDebug failed with " << statusToString(status); return EX_SOFTWARE; Loading libs/binder/tests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ cc_test { shared_libs: [ "libbase", "libbinder", "liblog", "libutils", ], static_libs: [ Loading Loading @@ -104,6 +105,7 @@ cc_test { shared_libs: [ "libbase", "libbinder", "liblog", "libutils", ], static_libs: [ Loading Loading
libs/binder/Binder.cpp +73 −16 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <binder/Binder.h> #include <atomic> #include <set> #include <android-base/unique_fd.h> #include <binder/BpBinder.h> Loading Loading @@ -150,7 +151,8 @@ status_t IBinder::getDebugPid(pid_t* out) { return OK; } status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd) { status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd, const sp<IBinder>& keepAliveBinder) { if constexpr (!kEnableRpcDevServers) { ALOGW("setRpcClientDebug disallowed because RPC is not enabled"); return INVALID_OPERATION; Loading @@ -158,7 +160,7 @@ status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd) { BBinder* local = this->localBinder(); if (local != nullptr) { return local->BBinder::setRpcClientDebug(std::move(socketFd)); return local->BBinder::setRpcClientDebug(std::move(socketFd), keepAliveBinder); } BpBinder* proxy = this->remoteBinder(); Loading @@ -173,11 +175,44 @@ status_t IBinder::setRpcClientDebug(android::base::unique_fd socketFd) { status = data.writeFileDescriptor(socketFd.release(), true /* own */); if (status != OK) return status; } if (status = data.writeStrongBinder(keepAliveBinder); status != OK) return status; return transact(SET_RPC_CLIENT_TRANSACTION, data, &reply); } // --------------------------------------------------------------------------- class BBinder::RpcServerLink : public IBinder::DeathRecipient { public: // On binder died, calls RpcServer::shutdown on @a rpcServer, and removes itself from @a binder. RpcServerLink(const sp<RpcServer>& rpcServer, const sp<IBinder>& keepAliveBinder, const wp<BBinder>& binder) : mRpcServer(rpcServer), mKeepAliveBinder(keepAliveBinder), mBinder(binder) {} void binderDied(const wp<IBinder>&) override { LOG_RPC_DETAIL("RpcServerLink: binder died, shutting down RpcServer"); if (mRpcServer == nullptr) { ALOGW("RpcServerLink: Unable to shut down RpcServer because it does not exist."); } else { ALOGW_IF(!mRpcServer->shutdown(), "RpcServerLink: RpcServer did not shut down properly. Not started?"); } mRpcServer.clear(); auto promoted = mBinder.promote(); if (promoted == nullptr) { ALOGW("RpcServerLink: Unable to remove link from parent binder object because parent " "binder object is gone."); } else { promoted->removeRpcServerLink(sp<RpcServerLink>::fromExisting(this)); } mBinder.clear(); } private: sp<RpcServer> mRpcServer; sp<IBinder> mKeepAliveBinder; // hold to avoid automatically unlinking wp<BBinder> mBinder; }; class BBinder::Extras { public: Loading @@ -190,7 +225,7 @@ public: // for below objects Mutex mLock; sp<RpcServer> mRpcServer; std::set<sp<RpcServerLink>> mRpcServerLinks; BpBinder::ObjectManager mObjects; }; Loading Loading @@ -453,11 +488,14 @@ status_t BBinder::setRpcClientDebug(const Parcel& data) { if (hasSocketFd) { if (status = data.readUniqueFileDescriptor(&clientFd); status != OK) return status; } sp<IBinder> keepAliveBinder; if (status = data.readNullableStrongBinder(&keepAliveBinder); status != OK) return status; return setRpcClientDebug(std::move(clientFd)); return setRpcClientDebug(std::move(clientFd), keepAliveBinder); } status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd) { status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd, const sp<IBinder>& keepAliveBinder) { if constexpr (!kEnableRpcDevServers) { ALOGW("%s: disallowed because RPC is not enabled", __PRETTY_FUNCTION__); return INVALID_OPERATION; Loading @@ -471,6 +509,11 @@ status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd) { return BAD_VALUE; } if (keepAliveBinder == nullptr) { ALOGE("%s: No keepAliveBinder provided.", __PRETTY_FUNCTION__); return UNEXPECTED_NULL; } size_t binderThreadPoolMaxCount = ProcessState::self()->getThreadPoolMaxThreadCount(); if (binderThreadPoolMaxCount <= 1) { ALOGE("%s: ProcessState thread pool max count is %zu. RPC is disabled for this service " Loading @@ -479,24 +522,38 @@ status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd) { return INVALID_OPERATION; } // Weak ref to avoid circular dependency: // BBinder -> RpcServerLink ----> RpcServer -X-> BBinder // `-X-> BBinder auto weakThis = wp<BBinder>::fromExisting(this); Extras* e = getOrCreateExtras(); AutoMutex _l(e->mLock); if (e->mRpcServer != nullptr) { ALOGE("%s: Already have RPC client", __PRETTY_FUNCTION__); return ALREADY_EXISTS; } e->mRpcServer = RpcServer::make(); LOG_ALWAYS_FATAL_IF(e->mRpcServer == nullptr, "RpcServer::make returns null"); e->mRpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); // Weak ref to avoid circular dependency: BBinder -> RpcServer -X-> BBinder e->mRpcServer->setRootObjectWeak(wp<BBinder>::fromExisting(this)); e->mRpcServer->setupExternalServer(std::move(socketFd)); e->mRpcServer->setMaxThreads(binderThreadPoolMaxCount); e->mRpcServer->start(); auto rpcServer = RpcServer::make(); LOG_ALWAYS_FATAL_IF(rpcServer == nullptr, "RpcServer::make returns null"); rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); auto link = sp<RpcServerLink>::make(rpcServer, keepAliveBinder, weakThis); if (auto status = keepAliveBinder->linkToDeath(link, nullptr, 0); status != OK) { ALOGE("%s: keepAliveBinder->linkToDeath returns %s", __PRETTY_FUNCTION__, statusToString(status).c_str()); return status; } rpcServer->setRootObjectWeak(weakThis); rpcServer->setupExternalServer(std::move(socketFd)); rpcServer->setMaxThreads(binderThreadPoolMaxCount); rpcServer->start(); e->mRpcServerLinks.emplace(link); LOG_RPC_DETAIL("%s(fd=%d) successful", __PRETTY_FUNCTION__, socketFdForPrint); return OK; } void BBinder::removeRpcServerLink(const sp<RpcServerLink>& link) { Extras* e = mExtras.load(std::memory_order_acquire); if (!e) return; AutoMutex _l(e->mLock); (void)e->mRpcServerLinks.erase(link); } BBinder::~BBinder() { Extras* e = mExtras.load(std::memory_order_relaxed); Loading
libs/binder/include/binder/Binder.h +4 −1 Original line number Diff line number Diff line Loading @@ -101,7 +101,8 @@ public: // to another process. void setParceled(); [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd); [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd, const sp<IBinder>& keepAliveBinder); protected: virtual ~BBinder(); Loading @@ -116,11 +117,13 @@ private: BBinder(const BBinder& o); BBinder& operator=(const BBinder& o); class RpcServerLink; class Extras; Extras* getOrCreateExtras(); [[nodiscard]] status_t setRpcClientDebug(const Parcel& data); void removeRpcServerLink(const sp<RpcServerLink>& link); std::atomic<Extras*> mExtras; Loading
libs/binder/include/binder/IBinder.h +6 −3 Original line number Diff line number Diff line Loading @@ -162,14 +162,17 @@ public: * 2. spawns 1 new thread that calls RpcServer::join() * - join() spawns some number of threads that accept() connections; see RpcServer * * setRpcClientDebug() may only be called once. * TODO(b/182914638): If allow to shut down the client, addRpcClient can be called repeatedly. * setRpcClientDebug() may be called multiple times. Each call will add a new RpcServer * and opens up a TCP port. * * Note: A thread is spawned for each accept()'ed fd, which may call into functions of the * interface freely. See RpcServer::join(). To avoid such race conditions, implement the service * functions with multithreading support. * * On death of @a keepAliveBinder, the RpcServer shuts down. */ [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd socketFd); [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd socketFd, const sp<IBinder>& keepAliveBinder); // NOLINTNEXTLINE(google-default-arguments) virtual status_t transact( uint32_t code, Loading
libs/binder/servicedispatcher.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -26,9 +26,11 @@ #include <binder/IServiceManager.h> #include <binder/RpcServer.h> using android::BBinder; using android::defaultServiceManager; using android::OK; using android::RpcServer; using android::sp; using android::statusToString; using android::String16; using android::base::Basename; Loading Loading @@ -74,7 +76,8 @@ int Dispatch(const char* name) { return EX_SOFTWARE; } auto socket = rpcServer->releaseServer(); auto status = binder->setRpcClientDebug(std::move(socket)); auto keepAliveBinder = sp<BBinder>::make(); auto status = binder->setRpcClientDebug(std::move(socket), keepAliveBinder); if (status != OK) { LOG(ERROR) << "setRpcClientDebug failed with " << statusToString(status); return EX_SOFTWARE; Loading
libs/binder/tests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ cc_test { shared_libs: [ "libbase", "libbinder", "liblog", "libutils", ], static_libs: [ Loading Loading @@ -104,6 +105,7 @@ cc_test { shared_libs: [ "libbase", "libbinder", "liblog", "libutils", ], static_libs: [ Loading