Implement host service manager
On the host, after
setDefaultServiceManager(createRpcDelegateServiceManager())
is called, defaultServiceManager() will return
a service manager delegate that calls into the service
manager on the device.
Test: binderHostDeviceTest with servicedispatcher installed
Bug: 190233850
Change-Id: I44f9d2e2419883e242fea0472d702f559dd0b283
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index d421060..2175fd4 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -35,6 +35,8 @@
#ifdef __ANDROID__
#include <cutils/properties.h>
+#else
+#include "ServiceManagerHost.h"
#endif
#include "Static.h"
@@ -84,8 +86,19 @@
IBinder* onAsBinder() override {
return IInterface::asBinder(mTheRealServiceManager).get();
}
-private:
+
+protected:
sp<AidlServiceManager> mTheRealServiceManager;
+
+ // Directly get the service in a way that, for lazy services, requests the service to be started
+ // if it is not currently started. This way, calls directly to ServiceManagerShim::getService
+ // will still have the 5s delay that is expected by a large amount of Android code.
+ //
+ // When implementing ServiceManagerShim, use realGetService instead of
+ // mTheRealServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
+ virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
+ return mTheRealServiceManager->getService(name, _aidl_return);
+ }
};
[[clang::no_destroy]] static std::once_flag gSmOnce;
@@ -319,7 +332,7 @@
const std::string name = String8(name16).c_str();
sp<IBinder> out;
- if (Status status = mTheRealServiceManager->getService(name, &out); !status.isOk()) {
+ if (Status status = realGetService(name, &out); !status.isOk()) {
ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
status.toString8().c_str());
return nullptr;
@@ -363,7 +376,7 @@
// - init gets death signal, but doesn't know it needs to restart
// the service
// - we need to request service again to get it to start
- if (Status status = mTheRealServiceManager->getService(name, &out); !status.isOk()) {
+ if (Status status = realGetService(name, &out); !status.isOk()) {
ALOGW("Failed to getService in waitForService on later try for %s: %s", name.c_str(),
status.toString8().c_str());
return nullptr;
@@ -412,4 +425,38 @@
return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
}
+#ifndef __ANDROID__
+// ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
+// The internal implementation of the AIDL interface android::os::IServiceManager calls into
+// on-device service manager.
+class ServiceManagerHostShim : public ServiceManagerShim {
+public:
+ using ServiceManagerShim::ServiceManagerShim;
+ // 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()});
+ }
+
+protected:
+ // Override realGetService for ServiceManagerShim::waitForService.
+ Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
+ *_aidl_return = getDeviceService({"-g", name});
+ return Status::ok();
+ }
+};
+sp<IServiceManager> createRpcDelegateServiceManager() {
+ auto binder = getDeviceService({"manager"});
+ if (binder == nullptr) {
+ ALOGE("getDeviceService(\"manager\") returns null");
+ return nullptr;
+ }
+ auto interface = AidlServiceManager::asInterface(binder);
+ if (interface == nullptr) {
+ ALOGE("getDeviceService(\"manager\") returns non service manager");
+ return nullptr;
+ }
+ return sp<ServiceManagerHostShim>::make(interface);
+}
+#endif
+
} // namespace android