From 0d84430bbc95036bd189105510ee693aa4f041d6 Mon Sep 17 00:00:00 2001 From: Jon Spivack Date: Mon, 22 Jul 2019 18:40:34 -0700 Subject: ServiceManager signals init to start lazy services This allows services to be disabled at boot and dynamically enabled as they are needed. When servicemanager receives a getService request, it will check whether the service is running. If it is not, servicemanager will attempt to start the service by signaling init with the ctl.interface_start control message. Bug: 138756857 Test: Manual (using mediaextractor as a test service), test_sm Change-Id: Ic2d47d21769b936381e3fae2f2cf739d3b7501a4 --- cmds/servicemanager/ServiceManager.cpp | 56 ++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'cmds/servicemanager/ServiceManager.cpp') diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index b3aa342a19..463d67f945 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -17,8 +17,10 @@ #include "ServiceManager.h" #include +#include #include #include +#include using ::android::binder::Status; @@ -41,39 +43,44 @@ ServiceManager::~ServiceManager() { } Status ServiceManager::getService(const std::string& name, sp* outBinder) { - // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons. - return checkService(name, outBinder); + *outBinder = tryGetService(name, true); + // returns ok regardless of result for legacy reasons + return Status::ok(); } Status ServiceManager::checkService(const std::string& name, sp* outBinder) { - auto ctx = mAccess->getCallingContext(); + *outBinder = tryGetService(name, false); + // returns ok regardless of result for legacy reasons + return Status::ok(); +} - auto it = mNameToService.find(name); - if (it == mNameToService.end()) { - *outBinder = nullptr; - return Status::ok(); - } +sp ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) { + auto ctx = mAccess->getCallingContext(); - const Service& service = it->second; + sp out; + if (auto it = mNameToService.find(name); it != mNameToService.end()) { + const Service& service = it->second; - if (!service.allowIsolated) { - uid_t appid = multiuser_get_app_id(ctx.uid); - bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; + if (!service.allowIsolated) { + uid_t appid = multiuser_get_app_id(ctx.uid); + bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; - if (isIsolated) { - *outBinder = nullptr; - return Status::ok(); + if (isIsolated) { + return nullptr; + } } + out = service.binder; } if (!mAccess->canFind(ctx, name)) { - // returns ok and null for legacy reasons - *outBinder = nullptr; - return Status::ok(); + return nullptr; } - *outBinder = service.binder; - return Status::ok(); + if (!out && startIfNotFound) { + tryStartService(name); + } + + return out; } bool isValidServiceName(const std::string& name) { @@ -253,4 +260,13 @@ void ServiceManager::binderDied(const wp& who) { } } +void ServiceManager::tryStartService(const std::string& name) { + ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service", + name.c_str()); + + std::thread([=] { + (void)base::SetProperty("ctl.interface_start", "aidl/" + name); + }).detach(); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b