Loading cmds/dumpsys/tests/dumpsys_test.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -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*()); }; Loading cmds/servicemanager/ServiceManager.cpp +74 −19 Original line number Diff line number Diff line Loading @@ -37,22 +37,12 @@ using ::android::internal::Stability; namespace android { #ifndef VENDORSERVICEMANAGER 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) { LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. " << "some.package.foo.IFoo/default) but got: " << name; return false; } const std::string package = name.substr(0, lastDot); 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; }; // 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" }, Loading @@ -63,17 +53,58 @@ static bool isVintfDeclared(const std::string& name) { // 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); if (firstSlash == std::string::npos || lastDot == std::string::npos) { LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. " << "some.package.foo.IFoo/default) but got: " << name; return false; } const std::string package = name.substr(0, lastDot); const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1); const std::string instance = name.substr(firstSlash+1); 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."; 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) { Loading Loading @@ -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) { Loading cmds/servicemanager/ServiceManager.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading libs/binder/IServiceManager.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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 libs/binder/aidl/android/os/IServiceManager.aidl +8 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,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. Loading Loading
cmds/dumpsys/tests/dumpsys_test.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -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*()); }; Loading
cmds/servicemanager/ServiceManager.cpp +74 −19 Original line number Diff line number Diff line Loading @@ -37,22 +37,12 @@ using ::android::internal::Stability; namespace android { #ifndef VENDORSERVICEMANAGER 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) { LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. " << "some.package.foo.IFoo/default) but got: " << name; return false; } const std::string package = name.substr(0, lastDot); 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; }; // 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" }, Loading @@ -63,17 +53,58 @@ static bool isVintfDeclared(const std::string& name) { // 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); if (firstSlash == std::string::npos || lastDot == std::string::npos) { LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. " << "some.package.foo.IFoo/default) but got: " << name; return false; } const std::string package = name.substr(0, lastDot); const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1); const std::string instance = name.substr(firstSlash+1); 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."; 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) { Loading Loading @@ -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) { Loading
cmds/servicemanager/ServiceManager.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/binder/IServiceManager.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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
libs/binder/aidl/android/os/IServiceManager.aidl +8 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,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. Loading