Add support for injecting RPC binder accessors to libbinder
This allows libbinder to set up client connections to binder RPC
services underneath the libbinder service manager APIs.
It requires callbacks to be added to the local process to get connection
information that the client is responsible for obtaining.
Once these callbacks are added to libbinder, any client elswhere in the
process using the service manager APIs will be able to get and use a
binder for the service in the same way they do for kernel binder
services.
Test: atest binderRpcTest vm_accessor_test
Bug: 358427181
Change-Id: Iec27d30a669e0673bd66c99fded1edc335f7dff1
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index 54f687b..fee36da 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -46,7 +46,9 @@
os::Service* _out) {
os::Service service;
binder::Status status = mTheRealServiceManager->getService2(name, &service);
- toBinderService(service, _out);
+ if (status.isOk()) {
+ return toBinderService(name, service, _out);
+ }
return status;
}
@@ -54,15 +56,38 @@
os::Service* _out) {
os::Service service;
binder::Status status = mTheRealServiceManager->checkService(name, &service);
- toBinderService(service, _out);
+ if (status.isOk()) {
+ return toBinderService(name, service, _out);
+ }
return status;
}
-void BackendUnifiedServiceManager::toBinderService(const os::Service& in, os::Service* _out) {
+binder::Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
+ const os::Service& in,
+ os::Service* _out) {
switch (in.getTag()) {
case os::Service::Tag::binder: {
+ if (in.get<os::Service::Tag::binder>() == nullptr) {
+ // failed to find a service. Check to see if we have any local
+ // injected Accessors for this service.
+ os::Service accessor;
+ binder::Status status = getInjectedAccessor(name, &accessor);
+ if (!status.isOk()) {
+ *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
+ return status;
+ }
+ if (accessor.getTag() == os::Service::Tag::accessor &&
+ accessor.get<os::Service::Tag::accessor>() != nullptr) {
+ ALOGI("Found local injected service for %s, will attempt to create connection",
+ name.c_str());
+ // Call this again using the accessor Service to get the real
+ // service's binder into _out
+ return toBinderService(name, accessor, _out);
+ }
+ }
+
*_out = in;
- break;
+ return binder::Status::ok();
}
case os::Service::Tag::accessor: {
sp<IBinder> accessorBinder = in.get<os::Service::Tag::accessor>();
@@ -70,7 +95,7 @@
if (accessor == nullptr) {
ALOGE("Service#accessor doesn't have accessor. VM is maybe starting...");
*_out = os::Service::make<os::Service::Tag::binder>(nullptr);
- break;
+ return binder::Status::ok();
}
auto request = [=] {
os::ParcelFileDescriptor fd;
@@ -83,10 +108,15 @@
}
};
auto session = RpcSession::make();
- session->setupPreconnectedClient(base::unique_fd{}, request);
+ status_t status = session->setupPreconnectedClient(base::unique_fd{}, request);
+ if (status != OK) {
+ ALOGE("Failed to set up preconnected binder RPC client: %s",
+ statusToString(status).c_str());
+ return binder::Status::fromStatusT(status);
+ }
session->setSessionSpecificRoot(accessorBinder);
*_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
- break;
+ return binder::Status::ok();
}
default: {
LOG_ALWAYS_FATAL("Unknown service type: %d", in.getTag());
@@ -177,4 +207,4 @@
return gUnifiedServiceManager;
}
-} // namespace android
\ No newline at end of file
+} // namespace android