From 3c93111ce80d2d7ea3375c39d75bf7dd54f3e15b Mon Sep 17 00:00:00 2001 From: Devin Moore Date: Wed, 23 Oct 2024 17:45:04 +0000 Subject: Enable ServiceManager APIs without servicemanager process In some devices, like Microdroid, there is no servicemanager process. These ServiceManager APIs may still be used with the new Accessor pattern for communication over sockets with binder RPC. This CL adds support for all of the getService APIs whithout relying on the servicemanager process. Future API support will be added separately. Test: atest vm_accessor_test binderLibTest Bug: 358427181 Change-Id: Ibef52415bf1509cdcd6c9cb65dbb8e20ec08d007 --- libs/binder/BackendUnifiedServiceManager.cpp | 113 ++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 21 deletions(-) (limited to 'libs/binder/BackendUnifiedServiceManager.cpp') diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp index 34d5a09948..9d0a557f4e 100644 --- a/libs/binder/BackendUnifiedServiceManager.cpp +++ b/libs/binder/BackendUnifiedServiceManager.cpp @@ -47,6 +47,9 @@ using AidlServiceManager = android::os::IServiceManager; using android::os::IAccessor; using binder::Status; +static const char* kUnsupportedOpNoServiceManager = + "Unsupported operation without a kernel binder servicemanager process"; + static const char* kStaticCachableList[] = { // go/keep-sorted start "accessibility", @@ -220,7 +223,10 @@ Status BackendUnifiedServiceManager::getService2(const ::std::string& name, os:: return Status::ok(); } os::Service service; - Status status = mTheRealServiceManager->getService2(name, &service); + Status status = Status::ok(); + if (mTheRealServiceManager) { + status = mTheRealServiceManager->getService2(name, &service); + } if (status.isOk()) { status = toBinderService(name, service, _out); @@ -237,7 +243,10 @@ Status BackendUnifiedServiceManager::checkService(const ::std::string& name, os: return Status::ok(); } - Status status = mTheRealServiceManager->checkService(name, &service); + Status status = Status::ok(); + if (mTheRealServiceManager) { + status = mTheRealServiceManager->checkService(name, &service); + } if (status.isOk()) { status = toBinderService(name, service, _out); if (status.isOk()) { @@ -315,66 +324,128 @@ Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name, Status BackendUnifiedServiceManager::addService(const ::std::string& name, const sp& service, bool allowIsolated, int32_t dumpPriority) { - Status status = mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority); - // mEnableAddServiceCache is true by default. - if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) { - return updateCache(name, service, - dumpPriority & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE); + if (mTheRealServiceManager) { + Status status = + mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority); + // mEnableAddServiceCache is true by default. + if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) { + return updateCache(name, service, + dumpPriority & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE); + } + return status; } - return status; + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::listServices(int32_t dumpPriority, ::std::vector<::std::string>* _aidl_return) { - return mTheRealServiceManager->listServices(dumpPriority, _aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->listServices(dumpPriority, _aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::registerForNotifications( const ::std::string& name, const sp& callback) { - return mTheRealServiceManager->registerForNotifications(name, callback); + if (mTheRealServiceManager) { + return mTheRealServiceManager->registerForNotifications(name, callback); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::unregisterForNotifications( const ::std::string& name, const sp& callback) { - return mTheRealServiceManager->unregisterForNotifications(name, callback); + if (mTheRealServiceManager) { + return mTheRealServiceManager->unregisterForNotifications(name, callback); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name, bool* _aidl_return) { - return mTheRealServiceManager->isDeclared(name, _aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->isDeclared(name, _aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::getDeclaredInstances( const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) { - return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::updatableViaApex( const ::std::string& name, ::std::optional<::std::string>* _aidl_return) { - return mTheRealServiceManager->updatableViaApex(name, _aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->updatableViaApex(name, _aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::getUpdatableNames(const ::std::string& apexName, ::std::vector<::std::string>* _aidl_return) { - return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::getConnectionInfo( const ::std::string& name, ::std::optional* _aidl_return) { - return mTheRealServiceManager->getConnectionInfo(name, _aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->getConnectionInfo(name, _aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::registerClientCallback( const ::std::string& name, const sp& service, const sp& callback) { - return mTheRealServiceManager->registerClientCallback(name, service, callback); + if (mTheRealServiceManager) { + return mTheRealServiceManager->registerClientCallback(name, service, callback); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name, const sp& service) { - return mTheRealServiceManager->tryUnregisterService(name, service); + if (mTheRealServiceManager) { + return mTheRealServiceManager->tryUnregisterService(name, service); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } Status BackendUnifiedServiceManager::getServiceDebugInfo( ::std::vector* _aidl_return) { - return mTheRealServiceManager->getServiceDebugInfo(_aidl_return); + if (mTheRealServiceManager) { + return mTheRealServiceManager->getServiceDebugInfo(_aidl_return); + } + return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION, + kUnsupportedOpNoServiceManager); } [[clang::no_destroy]] static std::once_flag gUSmOnce; [[clang::no_destroy]] static sp gUnifiedServiceManager; +static bool hasOutOfProcessServiceManager() { +#ifndef BINDER_WITH_KERNEL_IPC + return false; +#else +#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__) + return android::base::GetBoolProperty("servicemanager.installed", true); +#else + return true; +#endif +#endif // BINDER_WITH_KERNEL_IPC +} + sp getBackendUnifiedServiceManager() { std::call_once(gUSmOnce, []() { #if defined(__BIONIC__) && !defined(__ANDROID_VNDK__) - /* wait for service manager */ { + /* wait for service manager */ + if (hasOutOfProcessServiceManager()) { using std::literals::chrono_literals::operator""s; using android::base::WaitForProperty; while (!WaitForProperty("servicemanager.ready", "true", 1s)) { @@ -384,7 +455,7 @@ sp getBackendUnifiedServiceManager() { #endif sp sm = nullptr; - while (sm == nullptr) { + while (hasOutOfProcessServiceManager() && sm == nullptr) { sm = interface_cast( ProcessState::self()->getContextObject(nullptr)); if (sm == nullptr) { -- cgit v1.2.3-59-g8ed1b From a3867c739a80d0c8a58dcb00bcae8f98afdc78ef Mon Sep 17 00:00:00 2001 From: Devin Moore Date: Wed, 23 Oct 2024 19:29:49 +0000 Subject: 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 --- libs/binder/BackendUnifiedServiceManager.cpp | 47 +++++++++--- libs/binder/BackendUnifiedServiceManager.h | 4 ++ libs/binder/IServiceManager.cpp | 19 +++++ libs/binder/tests/binderRpcTest.cpp | 103 +++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 9 deletions(-) (limited to 'libs/binder/BackendUnifiedServiceManager.cpp') diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp index 9d0a557f4e..ee3d6af742 100644 --- a/libs/binder/BackendUnifiedServiceManager.cpp +++ b/libs/binder/BackendUnifiedServiceManager.cpp @@ -15,6 +15,7 @@ */ #include "BackendUnifiedServiceManager.h" +#include #include #include #include @@ -339,11 +340,15 @@ Status BackendUnifiedServiceManager::addService(const ::std::string& name, } 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& callback) { @@ -362,19 +367,43 @@ Status BackendUnifiedServiceManager::unregisterForNotifications( 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 + // /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 6a0d06a079..2496f62503 100644 --- a/libs/binder/BackendUnifiedServiceManager.h +++ b/libs/binder/BackendUnifiedServiceManager.h @@ -167,5 +167,9 @@ private: sp getBackendUnifiedServiceManager(); android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service); +void appendInjectedAccessorServices(std::vector* 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& f); } // namespace android diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 53435c357b..5c72ed3197 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -304,6 +304,25 @@ android::binder::Status getInjectedAccessor(const std::string& name, return android::binder::Status::ok(); } +void appendInjectedAccessorServices(std::vector* list) { + LOG_ALWAYS_FATAL_IF(list == nullptr, + "Attempted to get list of services from Accessors with nullptr"); + std::lock_guard lock(gAccessorProvidersMutex); + for (const auto& entry : gAccessorProviders) { + list->insert(list->end(), entry.mProvider->instances().begin(), + entry.mProvider->instances().end()); + } +} + +void forEachInjectedAccessorService(const std::function& f) { + std::lock_guard lock(gAccessorProvidersMutex); + for (const auto& entry : gAccessorProviders) { + for (const auto& instance : entry.mProvider->instances()) { + f(instance); + } + } +} + sp defaultServiceManager() { std::call_once(gSmOnce, []() { diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index da5a8e3881..9f656ec96c 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -1328,6 +1328,109 @@ TEST_P(BinderRpcAccessor, InjectNoSockaddrProvided) { 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 { return nullptr; }); + EXPECT_FALSE(receipt.expired()); + Vector 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 { 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 { return nullptr; }); + EXPECT_FALSE(receipt.expired()); + Vector 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 { return nullptr; }); + EXPECT_FALSE(receipt.expired()); + Vector 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 { return nullptr; }); + EXPECT_FALSE(receipt.expired()); + Vector 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, -- cgit v1.2.3-59-g8ed1b