Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5a05ef70 authored by Yifan Hong's avatar Yifan Hong
Browse files

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
parent 1f44f98d
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -448,21 +448,27 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnection
// 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 @@ sp<IServiceManager> createRpcDelegateServiceManager() {
        ALOGE("getDeviceService(\"manager\") returns non service manager");
        return nullptr;
    }
    return sp<ServiceManagerHostShim>::make(interface);
    return sp<ServiceManagerHostShim>::make(interface, options);
}
#endif

+6 −1
Original line number Diff line number Diff line
@@ -124,7 +124,8 @@ void cleanupCommandResult(const void* id, void* obj, void* /* cookie */) {

} // 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 @@ sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs) {
    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(),
+4 −1
Original line number Diff line number Diff line
@@ -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
+10 −1
Original line number Diff line number Diff line
@@ -188,7 +188,16 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid,
//        // ...
//    }
// 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
+3 −1
Original line number Diff line number Diff line
@@ -65,7 +65,9 @@ MATCHER_P(StatusEq, expected, (negation ? "not " : "") + statusToString(expected

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.