From b82b8f84b48616c124e1d1421a985328c1df53dc Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 28 Oct 2019 10:52:34 -0700 Subject: ServiceManager: add isDeclared Most of the time, AIDL services exist in client/service pairs. In this context, `while(true) getService` or `waitForService` makes sense. However, for VINTF services, this client/server coupling isn't guaranteed. A device may or may not have specific hardware. So, now IServiceManager can tell a client when a server will exist so it will know if it needs to wait for this service during boot-up. The function waitForDeclaredService is provided for this. These functions are generic (not referring to VINTF specifically) because they may be expanded to include information about APEX services in the future OR the infrastructure may be made generic to work, if desired, on system services. Bug: 141828236 Test: binderStabilityTest, using waitForDeclaredService function Change-Id: Ia230625e44e1685cc3fa9230ece8f0a25c88585e --- libs/binder/IServiceManager.cpp | 9 +++++++++ libs/binder/aidl/android/os/IServiceManager.aidl | 7 +++++++ libs/binder/include/binder/IServiceManager.h | 15 +++++++++++++++ libs/binder/tests/binderStabilityTest.cpp | 21 +++++++++------------ 4 files changed, 40 insertions(+), 12 deletions(-) (limited to 'libs') diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index a30df14bd6..4f47db199e 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -72,6 +72,7 @@ public: bool allowIsolated, int dumpsysPriority) override; Vector listServices(int dumpsysPriority) override; sp waitForService(const String16& name16) override; + bool isDeclared(const String16& name) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { @@ -321,4 +322,12 @@ sp ServiceManagerShim::waitForService(const String16& name16) } } +bool ServiceManagerShim::isDeclared(const String16& name) { + bool declared; + if (!mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared).isOk()) { + return false; + } + return declared; +} + } // namespace android diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index 471b63fb5e..8c7ebbaf36 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -89,4 +89,11 @@ interface IServiceManager { * Unregisters all requests for notifications for a specific callback. */ void unregisterForNotifications(@utf8InCpp String name, IServiceCallback callback); + + /** + * Returns whether a given interface is declared on the device, even if it + * is not started yet. For instance, this could be a service declared in the VINTF + * manifest. + */ + boolean isDeclared(@utf8InCpp String name); } diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index a675513793..4a44c5a7da 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -88,6 +88,14 @@ public: * Returns nullptr only for permission problem or fatal error. */ virtual sp waitForService(const String16& name) = 0; + + /** + * Check if a service is declared (e.g. VINTF manifest). + * + * If this returns true, waitForService should always be able to return the + * service. + */ + virtual bool isDeclared(const String16& name) = 0; }; sp defaultServiceManager(); @@ -98,6 +106,13 @@ sp waitForService(const String16& name) { return interface_cast(sm->waitForService(name)); } +template +sp waitForDeclaredService(const String16& name) { + const sp sm = defaultServiceManager(); + if (!sm->isDeclared(name)) return nullptr; + return interface_cast(sm->waitForService(name)); +} + template status_t getService(const String16& name, sp* outService) { diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp index 0bee56c943..1f2779abf0 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -134,18 +134,15 @@ TEST(BinderStability, OnlyVintfStabilityBinderNeedsVintfDeclaration) { TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) { sp vintfServer = BadStableBinder::vintf(); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("."), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("/"), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("/."), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("a.d.IFoo"), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("foo"), vintfServer)); - EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, - android::defaultServiceManager()->addService(String16("a.d.IFoo/foo"), vintfServer)); + for (const char* instance8 : { + ".", "/", "/.", "a.d.IFoo", "foo", "a.d.IFoo/foo" + }) { + String16 instance (instance8); + + EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, + android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8; + EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8; + } } TEST(BinderStability, CantCallVendorBinderInSystemContext) { -- cgit v1.2.3-59-g8ed1b