Add listServices/isDeclared/getDeclaredInstances for Accessors
We associate specific accessors with instance names, so we can get
more information about what is available through the existing service
manager APIs.
Test: atest binderRpcTest
Bug: 358427181
Change-Id: I337430a222b537643351bfc70178ccd1dc06d73b
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index 9d0a557..ee3d6af 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -15,6 +15,7 @@
*/
#include "BackendUnifiedServiceManager.h"
+#include <android-base/strings.h>
#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>
@@ -339,11 +340,15 @@
}
Status BackendUnifiedServiceManager::listServices(int32_t dumpPriority,
::std::vector<::std::string>* _aidl_return) {
+ Status status = Status::ok();
if (mTheRealServiceManager) {
- return mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
+ status = mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
}
- return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
- kUnsupportedOpNoServiceManager);
+ if (!status.isOk()) return status;
+
+ appendInjectedAccessorServices(_aidl_return);
+
+ return status;
}
Status BackendUnifiedServiceManager::registerForNotifications(
const ::std::string& name, const sp<os::IServiceCallback>& callback) {
@@ -362,19 +367,43 @@
kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name, bool* _aidl_return) {
+ Status status = Status::ok();
if (mTheRealServiceManager) {
- return mTheRealServiceManager->isDeclared(name, _aidl_return);
+ status = mTheRealServiceManager->isDeclared(name, _aidl_return);
}
- return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
- kUnsupportedOpNoServiceManager);
+ if (!status.isOk()) return status;
+
+ if (!*_aidl_return) {
+ forEachInjectedAccessorService([&](const std::string& instance) {
+ if (name == instance) {
+ *_aidl_return = true;
+ }
+ });
+ }
+
+ return status;
}
Status BackendUnifiedServiceManager::getDeclaredInstances(
const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) {
+ Status status = Status::ok();
if (mTheRealServiceManager) {
- return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
+ status = mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
}
- return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
- kUnsupportedOpNoServiceManager);
+ if (!status.isOk()) return status;
+
+ forEachInjectedAccessorService([&](const std::string& instance) {
+ // Declared instances have the format
+ // <interface>/instance like foo.bar.ISomething/instance
+ // If it does not have that format, consider the instance to be ""
+ std::string_view name(instance);
+ if (base::ConsumePrefix(&name, iface + "/")) {
+ _aidl_return->emplace_back(name);
+ } else if (iface == instance) {
+ _aidl_return->push_back("");
+ }
+ });
+
+ return status;
}
Status BackendUnifiedServiceManager::updatableViaApex(
const ::std::string& name, ::std::optional<::std::string>* _aidl_return) {
diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h
index 6a0d06a..2496f62 100644
--- a/libs/binder/BackendUnifiedServiceManager.h
+++ b/libs/binder/BackendUnifiedServiceManager.h
@@ -167,5 +167,9 @@
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service);
+void appendInjectedAccessorServices(std::vector<std::string>* list);
+// Do not call any other service manager APIs that might take the accessor
+// mutex because this will be holding it!
+void forEachInjectedAccessorService(const std::function<void(const std::string&)>& f);
} // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 53435c3..5c72ed3 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -304,6 +304,25 @@
return android::binder::Status::ok();
}
+void appendInjectedAccessorServices(std::vector<std::string>* list) {
+ LOG_ALWAYS_FATAL_IF(list == nullptr,
+ "Attempted to get list of services from Accessors with nullptr");
+ std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
+ for (const auto& entry : gAccessorProviders) {
+ list->insert(list->end(), entry.mProvider->instances().begin(),
+ entry.mProvider->instances().end());
+ }
+}
+
+void forEachInjectedAccessorService(const std::function<void(const std::string&)>& f) {
+ std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
+ for (const auto& entry : gAccessorProviders) {
+ for (const auto& instance : entry.mProvider->instances()) {
+ f(instance);
+ }
+ }
+}
+
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index da5a8e3..9f656ec 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1328,6 +1328,109 @@
EXPECT_EQ(status, OK);
}
+class BinderRpcAccessorNoConnection : public ::testing::Test {};
+
+TEST_F(BinderRpcAccessorNoConnection, listServices) {
+ const String16 kInstanceName("super.cool.service/better_than_default");
+ const String16 kInstanceName2("super.cool.service/better_than_default2");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list =
+ defaultServiceManager()->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ bool name1 = false;
+ bool name2 = false;
+ for (auto name : list) {
+ if (name == kInstanceName) name1 = true;
+ if (name == kInstanceName2) name2 = true;
+ }
+ EXPECT_TRUE(name1);
+ EXPECT_TRUE(name2);
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, isDeclared) {
+ const String16 kInstanceName("super.cool.service/default");
+ const String16 kInstanceName2("still_counts_as_declared");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ EXPECT_TRUE(defaultServiceManager()->isDeclared(kInstanceName));
+ EXPECT_TRUE(defaultServiceManager()->isDeclared(kInstanceName2));
+ EXPECT_FALSE(defaultServiceManager()->isDeclared(String16("doesnt_exist")));
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, getDeclaredInstances) {
+ const String16 kInstanceName("super.cool.service.IFoo/default");
+ const String16 kInstanceName2("super.cool.service.IFoo/extra/default");
+ const String16 kInstanceName3("super.cool.service.IFoo");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str(),
+ String8(kInstanceName3).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list =
+ defaultServiceManager()->getDeclaredInstances(String16("super.cool.service.IFoo"));
+ // We would prefer ASSERT_EQ here, but we must call removeAccessorProvider
+ EXPECT_EQ(list.size(), 3u);
+ if (list.size() == 3) {
+ bool name1 = false;
+ bool name2 = false;
+ bool name3 = false;
+ for (auto name : list) {
+ if (name == String16("default")) name1 = true;
+ if (name == String16("extra/default")) name2 = true;
+ if (name == String16()) name3 = true;
+ }
+ EXPECT_TRUE(name1) << String8(list[0]);
+ EXPECT_TRUE(name2) << String8(list[1]);
+ EXPECT_TRUE(name3) << String8(list[2]);
+ }
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, getDeclaredWrongInstances) {
+ const String16 kInstanceName("super.cool.service.IFoo");
+
+ auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list = defaultServiceManager()->getDeclaredInstances(String16("unknown"));
+ EXPECT_TRUE(list.empty());
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, getDeclaredInstancesSlash) {
+ // This is treated as if there were no '/' and the declared instance is ""
+ const String16 kInstanceName("super.cool.service.IFoo/");
+
+ auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list =
+ defaultServiceManager()->getDeclaredInstances(String16("super.cool.service.IFoo"));
+ bool name1 = false;
+ for (auto name : list) {
+ if (name == String16("")) name1 = true;
+ }
+ EXPECT_TRUE(name1);
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
constexpr const char* kARpcInstance = "some.instance.name.IFoo/default";
const char* kARpcSupportedServices[] = {
kARpcInstance,