diff options
author | 2020-09-23 00:25:16 +0000 | |
---|---|---|
committer | 2020-09-24 16:43:41 +0000 | |
commit | 2e293aa8ae8dd977e54aa2c2f2e1ede2af5792ed (patch) | |
tree | 0e8875e2f3251a8d04e6b4152261f39b492f1080 | |
parent | c68e32d3b03d1024d570dc4283a3201d7bc8429e (diff) |
servicemanager: vintf declared API
servicemanager already has to parse VINTF configurations, so exposing
this functionality here (mirroring hwservicemanager).
Note, this API, like isDeclared is not branded as "VINTF" for future
compatibility with APEX or other interfaces.
Bug: 168715768
Test: manual
Change-Id: Ifbc44677605de757c46ef17f7f29fd83e66a8161
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 1 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.cpp | 93 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.h | 1 | ||||
-rw-r--r-- | libs/binder/IServiceManager.cpp | 15 | ||||
-rw-r--r-- | libs/binder/aidl/android/os/IServiceManager.aidl | 8 | ||||
-rw-r--r-- | libs/binder/include/binder/IServiceManager.h | 5 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.cpp | 12 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.h | 2 |
8 files changed, 118 insertions, 19 deletions
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 3467898f3e..67a77f6015 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -55,6 +55,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(listServices, Vector<String16>(int)); MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); MOCK_METHOD1(isDeclared, bool(const String16&)); + MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index e80c3210f0..c8355e2b6b 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -37,6 +37,27 @@ using ::android::internal::Stability; namespace android { #ifndef VENDORSERVICEMANAGER +struct ManifestWithDescription { + std::shared_ptr<const vintf::HalManifest> manifest; + const char* description; +}; +// func true -> stop search and forEachManifest will return true +static bool forEachManifest(const std::function<bool(const ManifestWithDescription&)>& func) { + for (const ManifestWithDescription& mwd : { + ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" }, + ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" }, + }) { + if (mwd.manifest == nullptr) { + LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description; + // note, we explicitly do not retry here, so that we can detect VINTF + // or other bugs (b/151696835) + continue; + } + if (func(mwd)) return true; + } + return false; +} + static bool isVintfDeclared(const std::string& name) { size_t firstSlash = name.find('/'); size_t lastDot = name.rfind('.', firstSlash); @@ -49,31 +70,41 @@ static bool isVintfDeclared(const std::string& name) { const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1); const std::string instance = name.substr(firstSlash+1); - struct ManifestWithDescription { - std::shared_ptr<const vintf::HalManifest> manifest; - const char* description; - }; - for (const ManifestWithDescription& mwd : { - ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" }, - ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" }, - }) { - if (mwd.manifest == nullptr) { - LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description; - // note, we explicitly do not retry here, so that we can detect VINTF - // or other bugs (b/151696835) - continue; - } + bool found = forEachManifest([&] (const ManifestWithDescription& mwd) { if (mwd.manifest->hasAidlInstance(package, iface, instance)) { LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest."; return true; } + return false; // continue + }); + + if (!found) { + // Although it is tested, explicitly rebuilding qualified name, in case it + // becomes something unexpected. + LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance + << " in the VINTF manifest."; } - // Although it is tested, explicitly rebuilding qualified name, in case it - // becomes something unexpected. - LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance - << " in the VINTF manifest."; - return false; + return found; +} + +static std::vector<std::string> getVintfInstances(const std::string& interface) { + size_t lastDot = interface.rfind('.'); + if (lastDot == std::string::npos) { + LOG(ERROR) << "VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) but got: " << interface; + return {}; + } + const std::string package = interface.substr(0, lastDot); + const std::string iface = interface.substr(lastDot+1); + + std::vector<std::string> ret; + (void)forEachManifest([&](const ManifestWithDescription& mwd) { + auto instances = mwd.manifest->getAidlInstances(package, iface); + ret.insert(ret.end(), instances.begin(), instances.end()); + return false; // continue + }); + + return ret; } static bool meetsDeclarationRequirements(const sp<IBinder>& binder, const std::string& name) { @@ -331,6 +362,30 @@ Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) { return Status::ok(); } +binder::Status ServiceManager::getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) { + auto ctx = mAccess->getCallingContext(); + + std::vector<std::string> allInstances; +#ifndef VENDORSERVICEMANAGER + allInstances = getVintfInstances(interface); +#endif + + outReturn->clear(); + + for (const std::string& instance : allInstances) { + // TODO(b/169275998): allow checking policy only once for the interface + if (mAccess->canFind(ctx, interface + "/" + instance)) { + outReturn->push_back(instance); + } + } + + if (outReturn->size() == 0 && allInstances.size() != 0) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + return Status::ok(); +} + void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who, ServiceCallbackMap::iterator* it, bool* found) { diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h index a2fc5a84c5..9f43eb4f58 100644 --- a/cmds/servicemanager/ServiceManager.h +++ b/cmds/servicemanager/ServiceManager.h @@ -44,6 +44,7 @@ public: const sp<IServiceCallback>& callback) override; binder::Status isDeclared(const std::string& name, bool* outReturn) override; + binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override; binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, const sp<IClientCallback>& cb) override; binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override; diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 9aa82d908c..6d728dc6b1 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -74,6 +74,7 @@ public: Vector<String16> listServices(int dumpsysPriority) override; sp<IBinder> waitForService(const String16& name16) override; bool isDeclared(const String16& name) override; + Vector<String16> getDeclaredInstances(const String16& interface) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { @@ -373,4 +374,18 @@ bool ServiceManagerShim::isDeclared(const String16& name) { return declared; } +Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interface) { + std::vector<std::string> out; + if (!mTheRealServiceManager->getDeclaredInstances(String8(interface).c_str(), &out).isOk()) { + return {}; + } + + Vector<String16> res; + res.setCapacity(out.size()); + for (const std::string& instance : out) { + res.push(String16(instance.c_str())); + } + return res; +} + } // namespace android diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index ff154603e4..2b1e49283f 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -99,6 +99,14 @@ interface IServiceManager { boolean isDeclared(@utf8InCpp String name); /** + * Returns all declared instances for a particular interface. + * + * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is + * passed here, then ["foo"] would be returned. + */ + @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface); + + /** * Request a callback when the number of clients of the service changes. * Used by LazyServiceRegistrar to dynamically stop services that have no clients. */ diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index 1d520c127b..3c5ccc1922 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -96,6 +96,11 @@ public: * service. */ virtual bool isDeclared(const String16& name) = 0; + + /** + * Get all instances of a service as declared in the VINTF manifest + */ + virtual Vector<String16> getDeclaredInstances(const String16& interface) = 0; }; sp<IServiceManager> defaultServiceManager(); diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp index 69643249e3..4ecbe531c2 100644 --- a/libs/fakeservicemanager/ServiceManager.cpp +++ b/libs/fakeservicemanager/ServiceManager.cpp @@ -61,4 +61,16 @@ bool ServiceManager::isDeclared(const String16& name) { return mNameToService.find(name) != mNameToService.end(); } +Vector<String16> ServiceManager::getDeclaredInstances(const String16& name) { + Vector<String16> out; + const String16 prefix = name + String16("/"); + for (const auto& [registeredName, service] : mNameToService) { + (void) service; + if (registeredName.startsWith(prefix)) { + out.add(String16(registeredName.string() + prefix.size())); + } + } + return out; +} + } // namespace android diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h index a6b6b84219..4ef47fb043 100644 --- a/libs/fakeservicemanager/ServiceManager.h +++ b/libs/fakeservicemanager/ServiceManager.h @@ -46,6 +46,8 @@ public: bool isDeclared(const String16& name) override; + Vector<String16> getDeclaredInstances(const String16& iface) override; + private: std::map<String16, sp<IBinder>> mNameToService; }; |