diff options
-rw-r--r-- | libs/binder/BackendUnifiedServiceManager.cpp | 113 | ||||
-rw-r--r-- | libs/binder/include/binder/IServiceManager.h | 8 | ||||
-rw-r--r-- | libs/binder/tests/binderLibTest.cpp | 57 |
3 files changed, 145 insertions, 33 deletions
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<IBinder>& 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<os::IServiceCallback>& 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<os::IServiceCallback>& 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<os::ConnectionInfo>* _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<IBinder>& service, const sp<os::IClientCallback>& 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<IBinder>& 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<os::ServiceDebugInfo>* _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<BackendUnifiedServiceManager> 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<BackendUnifiedServiceManager> 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<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() { #endif sp<AidlServiceManager> sm = nullptr; - while (sm == nullptr) { + while (hasOutOfProcessServiceManager() && sm == nullptr) { sm = interface_cast<AidlServiceManager>( ProcessState::self()->getContextObject(nullptr)); if (sm == nullptr) { diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index 7d79baa34d..d248f22e89 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -80,6 +80,14 @@ public: /** * Register a service. + * + * Note: + * This status_t return value may be an exception code from an underlying + * Status type that doesn't have a representive error code in + * utils/Errors.h. + * One example of this is a return value of -7 + * (Status::Exception::EX_UNSUPPORTED_OPERATION) when the service manager + * process is not installed on the device when addService is called. */ // NOLINTNEXTLINE(google-default-arguments) virtual status_t addService(const String16& name, const sp<IBinder>& service, diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index d6cb508d7f..391a57010a 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -44,6 +44,7 @@ #include <processgroup/processgroup.h> #include <utils/Flattenable.h> #include <utils/SystemClock.h> +#include "binder/IServiceManagerUnitTestHelper.h" #include <linux/sched.h> #include <sys/epoll.h> @@ -558,14 +559,14 @@ TEST_F(BinderLibTest, AddManagerToManager) { EXPECT_EQ(NO_ERROR, sm->addService(String16("binderLibTest-manager"), binder)); } +class LocalRegistrationCallbackImpl : public virtual IServiceManager::LocalRegistrationCallback { + void onServiceRegistration(const String16&, const sp<IBinder>&) override {} + virtual ~LocalRegistrationCallbackImpl() {} +}; + TEST_F(BinderLibTest, RegisterForNotificationsFailure) { auto sm = defaultServiceManager(); - using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback; - class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback { - void onServiceRegistration(const String16&, const sp<IBinder>&) override {} - virtual ~LocalRegistrationCallbackImpl() {} - }; - sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); + sp<IServiceManager::LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); EXPECT_EQ(BAD_VALUE, sm->registerForNotifications(String16("ValidName"), nullptr)); EXPECT_EQ(UNKNOWN_ERROR, sm->registerForNotifications(String16("InvalidName!$"), cb)); @@ -573,12 +574,7 @@ TEST_F(BinderLibTest, RegisterForNotificationsFailure) { TEST_F(BinderLibTest, UnregisterForNotificationsFailure) { auto sm = defaultServiceManager(); - using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback; - class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback { - void onServiceRegistration(const String16&, const sp<IBinder>&) override {} - virtual ~LocalRegistrationCallbackImpl() {} - }; - sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); + sp<IServiceManager::LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); EXPECT_EQ(OK, sm->registerForNotifications(String16("ValidName"), cb)); @@ -1667,6 +1663,43 @@ TEST(ServiceNotifications, Unregister) { EXPECT_EQ(sm->unregisterForNotifications(String16("RogerRafa"), cb), OK); } +// Make sure all IServiceManager APIs will function without an AIDL service +// manager registered on the device. +TEST(ServiceManagerNoAidlServer, SanityCheck) { + String16 kServiceName("no_services_exist"); + // This is what clients will see when there is no servicemanager process + // that registers itself as context object 0. + // Can't use setDefaultServiceManager() here because these test cases run in + // the same process and will abort when called twice or before/after + // defaultServiceManager(). + sp<IServiceManager> sm = getServiceManagerShimFromAidlServiceManagerForTests(nullptr); + auto status = sm->addService(kServiceName, sp<BBinder>::make()); + // CppBackendShim returns Status::exceptionCode as the status_t + EXPECT_EQ(status, Status::Exception::EX_UNSUPPORTED_OPERATION) << statusToString(status); + auto service = sm->checkService(String16("no_services_exist")); + EXPECT_TRUE(service == nullptr); + auto list = sm->listServices(android::IServiceManager::DUMP_FLAG_PRIORITY_ALL); + EXPECT_TRUE(list.isEmpty()); + bool declared = sm->isDeclared(kServiceName); + EXPECT_FALSE(declared); + list = sm->getDeclaredInstances(kServiceName); + EXPECT_TRUE(list.isEmpty()); + auto updatable = sm->updatableViaApex(kServiceName); + EXPECT_EQ(updatable, std::nullopt); + list = sm->getUpdatableNames(kServiceName); + EXPECT_TRUE(list.isEmpty()); + auto conInfo = sm->getConnectionInfo(kServiceName); + EXPECT_EQ(conInfo, std::nullopt); + auto cb = sp<LocalRegistrationCallbackImpl>::make(); + status = sm->registerForNotifications(kServiceName, cb); + EXPECT_EQ(status, UNKNOWN_ERROR) << statusToString(status); + status = sm->unregisterForNotifications(kServiceName, cb); + EXPECT_EQ(status, BAD_VALUE) << statusToString(status); + auto dbgInfos = sm->getServiceDebugInfo(); + EXPECT_TRUE(dbgInfos.empty()); + sm->enableAddServiceCache(true); +} + TEST_F(BinderLibTest, ThreadPoolAvailableThreads) { Parcel data, reply; sp<IBinder> server = addServer(); |