Loading libs/binder/Binder.cpp +56 −1 Original line number Diff line number Diff line Loading @@ -238,6 +238,22 @@ sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func m return proxy->lookupOrCreateWeak(objectID, make, makeArgs); } void IBinder::setMinRpcThreads(uint16_t min) { if (BBinder* local = this->localBinder(); local != nullptr) { local->setMinRpcThreads(min); } else { LOG_ALWAYS_FATAL("setMinRpcThreads only works for local BBinders."); } } uint16_t IBinder::getMinRpcThreads() { if (BBinder* local = this->localBinder(); local != nullptr) { return local->getMinRpcThreads(); } else { LOG_ALWAYS_FATAL("getMinRpcThreads only works for local BBinders."); } } // --------------------------------------------------------------------------- class BBinder::RpcServerLink : public IBinder::DeathRecipient { Loading Loading @@ -273,6 +289,8 @@ private: }; BBinder::RpcServerLink::~RpcServerLink() {} static constexpr uint16_t kDefaultMinThreads = 1; class BBinder::Extras { public: Loading @@ -289,6 +307,7 @@ public: RpcMutex mLock; std::set<sp<RpcServerLink>> mRpcServerLinks; BpBinder::ObjectManager mObjectMgr; uint16_t mMinThreads = kDefaultMinThreads; unique_fd mRecordingFd; }; Loading Loading @@ -366,8 +385,24 @@ status_t BBinder::stopRecordingTransactions() { const String16& BBinder::getInterfaceDescriptor() const { // Throttle logging because getInterfaceDescriptor can be invoked a lot. static std::atomic<std::chrono::steady_clock::time_point> sLastLogTime = { std::chrono::steady_clock::time_point::min()}; auto lastLogTime = sLastLogTime.load(std::memory_order_acquire); auto currentTime = std::chrono::steady_clock::now(); // Don't log more than once per second. The check is not strict, since it may happen that // multiple theads read lastLogTime at the same time but we don't want it to be strict // for performance reasons. // Note: Do not subtract time_point::min(), that would cause an arithmetic overflow. if (lastLogTime == std::chrono::steady_clock::time_point::min() || to_ms(currentTime - lastLogTime) >= 1000) { ALOGW("BBinder::getInterfaceDescriptor (this=%p). Override?", this); sLastLogTime.store(currentTime, std::memory_order_release); } [[clang::no_destroy]] static StaticString16 sBBinder(u"BBinder"); ALOGW("Reached BBinder::getInterfaceDescriptor (this=%p). Override?", this); return sBBinder; } Loading Loading @@ -630,6 +665,26 @@ void BBinder::setInheritRt(bool inheritRt) { e->mInheritRt = inheritRt; } void BBinder::setMinRpcThreads(uint16_t min) { LOG_ALWAYS_FATAL_IF(mParceled, "setMinRpcThreads() should not be called after a binder object " "is parceled/sent to another process"); Extras* e = mExtras.load(std::memory_order_acquire); if (!e) { e = getOrCreateExtras(); if (!e) return; // out of memory } e->mMinThreads = min; } uint16_t BBinder::getMinRpcThreads() const { Extras* e = mExtras.load(std::memory_order_acquire); if (!e) { return kDefaultMinThreads; } return e->mMinThreads; } std::atomic<bool> BBinder::sGlobalInheritRt(false); void BBinder::setGlobalInheritRt(bool enabled) { Loading libs/binder/IPCThreadState.cpp +16 −4 Original line number Diff line number Diff line Loading @@ -635,14 +635,15 @@ void IPCThreadState::clearCaller() mCallingUid = getuid(); } void IPCThreadState::flushCommands() { status_t IPCThreadState::flushCommands() { if (mProcess->mDriverFD < 0) return; return -EBADF; if (status_t res = talkWithDriver(false); res != OK) { // TODO: we may want to abort for some of these cases ALOGW("1st call to talkWithDriver returned error in flushCommands: %s", statusToString(res).c_str()); return res; } // The flush could have caused post-write refcount decrements to have Loading @@ -653,11 +654,14 @@ void IPCThreadState::flushCommands() { // TODO: we may want to abort for some of these cases ALOGW("2nd call to talkWithDriver returned error in flushCommands: %s", statusToString(res).c_str()); return res; } } if (mOut.dataSize() > 0) { ALOGW("mOut.dataSize() > 0 after flushCommands()"); } return NO_ERROR; } bool IPCThreadState::flushIfNeeded() Loading Loading @@ -1030,7 +1034,11 @@ status_t IPCThreadState::addFrozenStateChangeCallback(int32_t handle, BpBinder* mOut.writeInt32(BC_REQUEST_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); if (status_t res = flushCommands(); res != OK) { LOG_ALWAYS_FATAL("%s(%d): %s", __func__, handle, statusToString(res).c_str()); } return NO_ERROR; } Loading @@ -1043,7 +1051,11 @@ status_t IPCThreadState::removeFrozenStateChangeCallback(int32_t handle, BpBinde mOut.writeInt32(BC_CLEAR_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); if (status_t res = flushCommands(); res != OK) { LOG_ALWAYS_FATAL("%s(%d): %s", __func__, handle, statusToString(res).c_str()); } return NO_ERROR; } Loading libs/binder/RpcServer.cpp +29 −1 Original line number Diff line number Diff line Loading @@ -135,6 +135,13 @@ void RpcServer::setMaxThreads(size_t threads) { #endif // BINDER_RPC_SINGLE_THREADED LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads"); LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running"); if (sp<IBinder> root = getRootObject(); root != nullptr) { LOG_ALWAYS_FATAL_IF(threads < root->getMinRpcThreads(), "RpcServer can not satisfy the root object's minimum " "thread requirements of %d with the requested max " "thread count of %zu", root->getMinRpcThreads(), threads); } mMaxThreads = threads; } Loading @@ -159,11 +166,26 @@ void RpcServer::setSupportedFileDescriptorTransportModes( } } static void logMaxThreadOverwrite(size_t max, uint16_t min, bool isPerSession) { ALOGW("Overriding this RpcServer's max threads (%zu) based on the min threads required " "(%d) by the %s object that is being set.", max, min, isPerSession ? "per-session root" : "root"); } void RpcServer::maybeOverwriteMaxThreads(const sp<IBinder>& binder) { uint16_t minThreads = binder->getMinRpcThreads(); if (mMaxThreads < minThreads) { logMaxThreadOverwrite(mMaxThreads, minThreads, false); mMaxThreads = binder->getMinRpcThreads(); } } void RpcServer::setRootObject(const sp<IBinder>& binder) { RpcMutexLockGuard _l(mLock); LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set root object while running"); mRootObjectFactory = nullptr; mRootObjectWeak = mRootObject = binder; maybeOverwriteMaxThreads(binder); } void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { Loading @@ -172,6 +194,10 @@ void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { mRootObject.clear(); mRootObjectFactory = nullptr; mRootObjectWeak = binder; sp<IBinder> s = binder.promote(); if (s == nullptr) return; maybeOverwriteMaxThreads(s); } void RpcServer::setPerSessionRootObject( std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& makeObject) { Loading Loading @@ -528,7 +554,6 @@ void RpcServer::establishConnection( } while (server->mSessions.end() != server->mSessions.find(sessionId)); session = sp<RpcSession>::make(nullptr); session->setMaxIncomingThreads(server->mMaxThreads); if (!session->setProtocolVersion(protocolVersion)) return; if (header.fileDescriptorTransportMode < Loading @@ -551,8 +576,11 @@ void RpcServer::establishConnection( server->mRootObjectFactory(wp<RpcSession>(session), addr.data(), addrLen); if (sessionSpecificRoot == nullptr) { ALOGE("Warning: server returned null from root object factory"); } else { server->maybeOverwriteMaxThreads(sessionSpecificRoot); } } session->setMaxIncomingThreads(server->mMaxThreads); if (!session->setForServer(server, server, sessionId, sessionSpecificRoot)) { ALOGE("Failed to attach server to session"); Loading libs/binder/include/binder/Binder.h +5 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,11 @@ public: // This must be called before the object is sent to another process. Not thread safe. LIBBINDER_EXPORTED void setInheritRt(bool inheritRt); // Default is 1. This is configured for each RpcSession attached to each // BBinder object in an RpcServer. LIBBINDER_EXPORTED void setMinRpcThreads(uint16_t min); LIBBINDER_EXPORTED uint16_t getMinRpcThreads() const; // Set default, overridden by setInheritRt. You must set this default early. // Any binder objects sent out of the process before this is called will // not use the updated value. Loading libs/binder/include/binder/IBinder.h +2 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,8 @@ public: typedef sp<IBinder> (*object_make_func)(const void* makeArgs); sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make, const void* makeArgs); void setMinRpcThreads(uint16_t min); uint16_t getMinRpcThreads(); protected: virtual ~IBinder(); Loading Loading
libs/binder/Binder.cpp +56 −1 Original line number Diff line number Diff line Loading @@ -238,6 +238,22 @@ sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func m return proxy->lookupOrCreateWeak(objectID, make, makeArgs); } void IBinder::setMinRpcThreads(uint16_t min) { if (BBinder* local = this->localBinder(); local != nullptr) { local->setMinRpcThreads(min); } else { LOG_ALWAYS_FATAL("setMinRpcThreads only works for local BBinders."); } } uint16_t IBinder::getMinRpcThreads() { if (BBinder* local = this->localBinder(); local != nullptr) { return local->getMinRpcThreads(); } else { LOG_ALWAYS_FATAL("getMinRpcThreads only works for local BBinders."); } } // --------------------------------------------------------------------------- class BBinder::RpcServerLink : public IBinder::DeathRecipient { Loading Loading @@ -273,6 +289,8 @@ private: }; BBinder::RpcServerLink::~RpcServerLink() {} static constexpr uint16_t kDefaultMinThreads = 1; class BBinder::Extras { public: Loading @@ -289,6 +307,7 @@ public: RpcMutex mLock; std::set<sp<RpcServerLink>> mRpcServerLinks; BpBinder::ObjectManager mObjectMgr; uint16_t mMinThreads = kDefaultMinThreads; unique_fd mRecordingFd; }; Loading Loading @@ -366,8 +385,24 @@ status_t BBinder::stopRecordingTransactions() { const String16& BBinder::getInterfaceDescriptor() const { // Throttle logging because getInterfaceDescriptor can be invoked a lot. static std::atomic<std::chrono::steady_clock::time_point> sLastLogTime = { std::chrono::steady_clock::time_point::min()}; auto lastLogTime = sLastLogTime.load(std::memory_order_acquire); auto currentTime = std::chrono::steady_clock::now(); // Don't log more than once per second. The check is not strict, since it may happen that // multiple theads read lastLogTime at the same time but we don't want it to be strict // for performance reasons. // Note: Do not subtract time_point::min(), that would cause an arithmetic overflow. if (lastLogTime == std::chrono::steady_clock::time_point::min() || to_ms(currentTime - lastLogTime) >= 1000) { ALOGW("BBinder::getInterfaceDescriptor (this=%p). Override?", this); sLastLogTime.store(currentTime, std::memory_order_release); } [[clang::no_destroy]] static StaticString16 sBBinder(u"BBinder"); ALOGW("Reached BBinder::getInterfaceDescriptor (this=%p). Override?", this); return sBBinder; } Loading Loading @@ -630,6 +665,26 @@ void BBinder::setInheritRt(bool inheritRt) { e->mInheritRt = inheritRt; } void BBinder::setMinRpcThreads(uint16_t min) { LOG_ALWAYS_FATAL_IF(mParceled, "setMinRpcThreads() should not be called after a binder object " "is parceled/sent to another process"); Extras* e = mExtras.load(std::memory_order_acquire); if (!e) { e = getOrCreateExtras(); if (!e) return; // out of memory } e->mMinThreads = min; } uint16_t BBinder::getMinRpcThreads() const { Extras* e = mExtras.load(std::memory_order_acquire); if (!e) { return kDefaultMinThreads; } return e->mMinThreads; } std::atomic<bool> BBinder::sGlobalInheritRt(false); void BBinder::setGlobalInheritRt(bool enabled) { Loading
libs/binder/IPCThreadState.cpp +16 −4 Original line number Diff line number Diff line Loading @@ -635,14 +635,15 @@ void IPCThreadState::clearCaller() mCallingUid = getuid(); } void IPCThreadState::flushCommands() { status_t IPCThreadState::flushCommands() { if (mProcess->mDriverFD < 0) return; return -EBADF; if (status_t res = talkWithDriver(false); res != OK) { // TODO: we may want to abort for some of these cases ALOGW("1st call to talkWithDriver returned error in flushCommands: %s", statusToString(res).c_str()); return res; } // The flush could have caused post-write refcount decrements to have Loading @@ -653,11 +654,14 @@ void IPCThreadState::flushCommands() { // TODO: we may want to abort for some of these cases ALOGW("2nd call to talkWithDriver returned error in flushCommands: %s", statusToString(res).c_str()); return res; } } if (mOut.dataSize() > 0) { ALOGW("mOut.dataSize() > 0 after flushCommands()"); } return NO_ERROR; } bool IPCThreadState::flushIfNeeded() Loading Loading @@ -1030,7 +1034,11 @@ status_t IPCThreadState::addFrozenStateChangeCallback(int32_t handle, BpBinder* mOut.writeInt32(BC_REQUEST_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); if (status_t res = flushCommands(); res != OK) { LOG_ALWAYS_FATAL("%s(%d): %s", __func__, handle, statusToString(res).c_str()); } return NO_ERROR; } Loading @@ -1043,7 +1051,11 @@ status_t IPCThreadState::removeFrozenStateChangeCallback(int32_t handle, BpBinde mOut.writeInt32(BC_CLEAR_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); if (status_t res = flushCommands(); res != OK) { LOG_ALWAYS_FATAL("%s(%d): %s", __func__, handle, statusToString(res).c_str()); } return NO_ERROR; } Loading
libs/binder/RpcServer.cpp +29 −1 Original line number Diff line number Diff line Loading @@ -135,6 +135,13 @@ void RpcServer::setMaxThreads(size_t threads) { #endif // BINDER_RPC_SINGLE_THREADED LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads"); LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running"); if (sp<IBinder> root = getRootObject(); root != nullptr) { LOG_ALWAYS_FATAL_IF(threads < root->getMinRpcThreads(), "RpcServer can not satisfy the root object's minimum " "thread requirements of %d with the requested max " "thread count of %zu", root->getMinRpcThreads(), threads); } mMaxThreads = threads; } Loading @@ -159,11 +166,26 @@ void RpcServer::setSupportedFileDescriptorTransportModes( } } static void logMaxThreadOverwrite(size_t max, uint16_t min, bool isPerSession) { ALOGW("Overriding this RpcServer's max threads (%zu) based on the min threads required " "(%d) by the %s object that is being set.", max, min, isPerSession ? "per-session root" : "root"); } void RpcServer::maybeOverwriteMaxThreads(const sp<IBinder>& binder) { uint16_t minThreads = binder->getMinRpcThreads(); if (mMaxThreads < minThreads) { logMaxThreadOverwrite(mMaxThreads, minThreads, false); mMaxThreads = binder->getMinRpcThreads(); } } void RpcServer::setRootObject(const sp<IBinder>& binder) { RpcMutexLockGuard _l(mLock); LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set root object while running"); mRootObjectFactory = nullptr; mRootObjectWeak = mRootObject = binder; maybeOverwriteMaxThreads(binder); } void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { Loading @@ -172,6 +194,10 @@ void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { mRootObject.clear(); mRootObjectFactory = nullptr; mRootObjectWeak = binder; sp<IBinder> s = binder.promote(); if (s == nullptr) return; maybeOverwriteMaxThreads(s); } void RpcServer::setPerSessionRootObject( std::function<sp<IBinder>(wp<RpcSession> session, const void*, size_t)>&& makeObject) { Loading Loading @@ -528,7 +554,6 @@ void RpcServer::establishConnection( } while (server->mSessions.end() != server->mSessions.find(sessionId)); session = sp<RpcSession>::make(nullptr); session->setMaxIncomingThreads(server->mMaxThreads); if (!session->setProtocolVersion(protocolVersion)) return; if (header.fileDescriptorTransportMode < Loading @@ -551,8 +576,11 @@ void RpcServer::establishConnection( server->mRootObjectFactory(wp<RpcSession>(session), addr.data(), addrLen); if (sessionSpecificRoot == nullptr) { ALOGE("Warning: server returned null from root object factory"); } else { server->maybeOverwriteMaxThreads(sessionSpecificRoot); } } session->setMaxIncomingThreads(server->mMaxThreads); if (!session->setForServer(server, server, sessionId, sessionSpecificRoot)) { ALOGE("Failed to attach server to session"); Loading
libs/binder/include/binder/Binder.h +5 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,11 @@ public: // This must be called before the object is sent to another process. Not thread safe. LIBBINDER_EXPORTED void setInheritRt(bool inheritRt); // Default is 1. This is configured for each RpcSession attached to each // BBinder object in an RpcServer. LIBBINDER_EXPORTED void setMinRpcThreads(uint16_t min); LIBBINDER_EXPORTED uint16_t getMinRpcThreads() const; // Set default, overridden by setInheritRt. You must set this default early. // Any binder objects sent out of the process before this is called will // not use the updated value. Loading
libs/binder/include/binder/IBinder.h +2 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,8 @@ public: typedef sp<IBinder> (*object_make_func)(const void* makeArgs); sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make, const void* makeArgs); void setMinRpcThreads(uint16_t min); uint16_t getMinRpcThreads(); protected: virtual ~IBinder(); Loading