diff options
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 1 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.cpp | 29 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.h | 1 | ||||
-rw-r--r-- | libs/binder/IServiceManager.cpp | 9 | ||||
-rw-r--r-- | libs/binder/aidl/android/os/IServiceManager.aidl | 7 | ||||
-rw-r--r-- | libs/binder/include/binder/IServiceManager.h | 15 | ||||
-rw-r--r-- | libs/binder/tests/binderStabilityTest.cpp | 21 |
7 files changed, 66 insertions, 17 deletions
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index cf4e0b5a4c..b9395ba4e2 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -54,6 +54,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int)); MOCK_METHOD1(listServices, Vector<String16>(int)); MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); + MOCK_METHOD1(isDeclared, bool(const String16&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 934646da41..91e89ae7e8 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -34,11 +34,7 @@ using ::android::internal::Stability; namespace android { #ifndef VENDORSERVICEMANAGER -static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) { - if (!Stability::requiresVintfDeclaration(binder)) { - return true; - } - +static bool isVintfDeclared(const std::string& name) { size_t firstSlash = name.find('/'); size_t lastDot = name.rfind('.', firstSlash); if (firstSlash == std::string::npos || lastDot == std::string::npos) { @@ -62,6 +58,14 @@ static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::s << " in the VINTF manifest."; return false; } + +static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) { + if (!Stability::requiresVintfDeclaration(binder)) { + return true; + } + + return isVintfDeclared(name); +} #endif // !VENDORSERVICEMANAGER ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {} @@ -270,6 +274,21 @@ Status ServiceManager::unregisterForNotifications( return Status::ok(); } +Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) { + auto ctx = mAccess->getCallingContext(); + + if (!mAccess->canFind(ctx, name)) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + *outReturn = false; + +#ifndef VENDORSERVICEMANAGER + *outReturn = isVintfDeclared(name); +#endif + return Status::ok(); +} + void ServiceManager::removeCallback(const wp<IBinder>& who, CallbackMap::iterator* it, bool* found) { diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h index 006e51947b..7dcdaa4661 100644 --- a/cmds/servicemanager/ServiceManager.h +++ b/cmds/servicemanager/ServiceManager.h @@ -40,6 +40,7 @@ public: const sp<IServiceCallback>& callback) override; binder::Status unregisterForNotifications(const std::string& name, const sp<IServiceCallback>& callback) override; + binder::Status isDeclared(const std::string& name, bool* outReturn) override; void binderDied(const wp<IBinder>& who) override; 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<String16> listServices(int dumpsysPriority) override; sp<IBinder> waitForService(const String16& name16) override; + bool isDeclared(const String16& name) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { @@ -321,4 +322,12 @@ sp<IBinder> 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<IBinder> 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<IServiceManager> defaultServiceManager(); @@ -99,6 +107,13 @@ sp<INTERFACE> waitForService(const String16& name) { } template<typename INTERFACE> +sp<INTERFACE> waitForDeclaredService(const String16& name) { + const sp<IServiceManager> sm = defaultServiceManager(); + if (!sm->isDeclared(name)) return nullptr; + return interface_cast<INTERFACE>(sm->waitForService(name)); +} + +template<typename INTERFACE> status_t getService(const String16& name, sp<INTERFACE>* outService) { const sp<IServiceManager> sm = defaultServiceManager(); 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<IBinder> 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) { |