binder: host service manager limits max outgoing threads
... for each returned binder object. By default, the limit
is SIZE_MAX.
Test: aservice
... with max outgoing threads = 1, `aservice list` takes 19s.
... with max outgoing threads = SIZE_MAX, `aservice list` takes 30s.
Test: binderHostDeviceTest
Fixes: 194225767
Change-Id: Ib51fa41970fff804f40b7604a6a195ce0b16f89d
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index aff9e0d..81e61da 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -448,21 +448,27 @@
// on-device service manager.
class ServiceManagerHostShim : public ServiceManagerShim {
public:
- using ServiceManagerShim::ServiceManagerShim;
+ ServiceManagerHostShim(const sp<AidlServiceManager>& impl,
+ const RpcDelegateServiceManagerOptions& options)
+ : ServiceManagerShim(impl), mOptions(options) {}
// ServiceManagerShim::getService is based on checkService, so no need to override it.
sp<IBinder> checkService(const String16& name) const override {
- return getDeviceService({String8(name).c_str()});
+ return getDeviceService({String8(name).c_str()}, mOptions);
}
protected:
// Override realGetService for ServiceManagerShim::waitForService.
Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
- *_aidl_return = getDeviceService({"-g", name});
+ *_aidl_return = getDeviceService({"-g", name}, mOptions);
return Status::ok();
}
+
+private:
+ RpcDelegateServiceManagerOptions mOptions;
};
-sp<IServiceManager> createRpcDelegateServiceManager() {
- auto binder = getDeviceService({"manager"});
+sp<IServiceManager> createRpcDelegateServiceManager(
+ const RpcDelegateServiceManagerOptions& options) {
+ auto binder = getDeviceService({"manager"}, options);
if (binder == nullptr) {
ALOGE("getDeviceService(\"manager\") returns null");
return nullptr;
@@ -472,7 +478,7 @@
ALOGE("getDeviceService(\"manager\") returns non service manager");
return nullptr;
}
- return sp<ServiceManagerHostShim>::make(interface);
+ return sp<ServiceManagerHostShim>::make(interface, options);
}
#endif
diff --git a/libs/binder/ServiceManagerHost.cpp b/libs/binder/ServiceManagerHost.cpp
index 27cc563..194254a 100644
--- a/libs/binder/ServiceManagerHost.cpp
+++ b/libs/binder/ServiceManagerHost.cpp
@@ -124,7 +124,8 @@
} // namespace
-sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs) {
+sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs,
+ const RpcDelegateServiceManagerOptions& options) {
std::vector<std::string> prefix{"adb", "shell", "servicedispatcher"};
serviceDispatcherArgs.insert(serviceDispatcherArgs.begin(), prefix.begin(), prefix.end());
@@ -158,6 +159,10 @@
LOG_ALWAYS_FATAL_IF(!forwardResult->hostPort().has_value());
auto rpcSession = RpcSession::make();
+ if (options.maxOutgoingThreads.has_value()) {
+ rpcSession->setMaxOutgoingThreads(*options.maxOutgoingThreads);
+ }
+
if (status_t status = rpcSession->setupInetClient("127.0.0.1", *forwardResult->hostPort());
status != OK) {
ALOGE("Unable to set up inet client on host port %u: %s", *forwardResult->hostPort(),
diff --git a/libs/binder/ServiceManagerHost.h b/libs/binder/ServiceManagerHost.h
index e59724c..c5310da 100644
--- a/libs/binder/ServiceManagerHost.h
+++ b/libs/binder/ServiceManagerHost.h
@@ -21,11 +21,14 @@
namespace android {
+struct RpcDelegateServiceManagerOptions;
+
// Get a service on device by running servicedispatcher with the given args, e.g.
// getDeviceService({"foo"});
// Return nullptr on any error.
// When the returned binder object is destroyed, remove adb forwarding and kills
// the long-running servicedispatcher process.
-sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs);
+sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs,
+ const RpcDelegateServiceManagerOptions& options);
} // namespace android
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index a48075d..240e3c2 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -188,7 +188,16 @@
// // ...
// }
// Resources are cleaned up when the object is destroyed.
-sp<IServiceManager> createRpcDelegateServiceManager();
+//
+// For each returned binder object, at most |maxOutgoingThreads| outgoing threads are instantiated.
+// Hence, only |maxOutgoingThreads| calls can be made simultaneously. Additional calls are blocked
+// if there are |maxOutgoingThreads| ongoing calls. See RpcSession::setMaxOutgoingThreads.
+// If |maxOutgoingThreads| is not set, default is |RpcSession::kDefaultMaxOutgoingThreads|.
+struct RpcDelegateServiceManagerOptions {
+ std::optional<size_t> maxOutgoingThreads;
+};
+sp<IServiceManager> createRpcDelegateServiceManager(
+ const RpcDelegateServiceManagerOptions& options);
#endif
} // namespace android
diff --git a/libs/binder/tests/binderHostDeviceTest.cpp b/libs/binder/tests/binderHostDeviceTest.cpp
index eec3b44..464da60 100644
--- a/libs/binder/tests/binderHostDeviceTest.cpp
+++ b/libs/binder/tests/binderHostDeviceTest.cpp
@@ -65,7 +65,9 @@
void initHostRpcServiceManagerOnce() {
static std::once_flag gSmOnce;
- std::call_once(gSmOnce, [] { setDefaultServiceManager(createRpcDelegateServiceManager()); });
+ std::call_once(gSmOnce, [] {
+ setDefaultServiceManager(createRpcDelegateServiceManager({.maxOutgoingThreads = 1}));
+ });
}
// Test for host service manager.