Loading cmds/dumpsys/tests/dumpsys_test.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); MOCK_METHOD1(isDeclared, bool(const String16&)); MOCK_METHOD1(isDeclared, bool(const String16&)); MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&)); protected: protected: MOCK_METHOD0(onAsBinder, IBinder*()); MOCK_METHOD0(onAsBinder, IBinder*()); }; }; Loading cmds/servicemanager/ServiceManager.cpp +64 −15 Original line number Original line Diff line number Diff line Loading @@ -58,7 +58,12 @@ static bool forEachManifest(const std::function<bool(const ManifestWithDescripti return false; return false; } } static bool isVintfDeclared(const std::string& name) { struct AidlName { std::string package; std::string iface; std::string instance; static bool fill(const std::string& name, AidlName* aname) { size_t firstSlash = name.find('/'); size_t firstSlash = name.find('/'); size_t lastDot = name.rfind('.', firstSlash); size_t lastDot = name.rfind('.', firstSlash); if (firstSlash == std::string::npos || lastDot == std::string::npos) { if (firstSlash == std::string::npos || lastDot == std::string::npos) { Loading @@ -66,14 +71,21 @@ static bool isVintfDeclared(const std::string& name) { << "some.package.foo.IFoo/default) but got: " << name; << "some.package.foo.IFoo/default) but got: " << name; return false; return false; } } const std::string package = name.substr(0, lastDot); aname->package = name.substr(0, lastDot); const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1); aname->iface = name.substr(lastDot + 1, firstSlash - lastDot - 1); const std::string instance = name.substr(firstSlash+1); aname->instance = name.substr(firstSlash + 1); return true; } }; static bool isVintfDeclared(const std::string& name) { AidlName aname; if (!AidlName::fill(name, &aname)) return false; bool found = forEachManifest([&](const ManifestWithDescription& mwd) { bool found = forEachManifest([&](const ManifestWithDescription& mwd) { if (mwd.manifest->hasAidlInstance(package, iface, instance)) { if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) { LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest."; LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest."; return true; return true; // break } } return false; // continue return false; // continue }); }); Loading @@ -81,13 +93,34 @@ static bool isVintfDeclared(const std::string& name) { if (!found) { if (!found) { // Although it is tested, explicitly rebuilding qualified name, in case it // Although it is tested, explicitly rebuilding qualified name, in case it // becomes something unexpected. // becomes something unexpected. LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance LOG(ERROR) << "Could not find " << aname.package << "." << aname.iface << "/" << " in the VINTF manifest."; << aname.instance << " in the VINTF manifest."; } } return found; return found; } } static std::optional<std::string> getVintfUpdatableApex(const std::string& name) { AidlName aname; if (!AidlName::fill(name, &aname)) return std::nullopt; std::optional<std::string> updatableViaApex; forEachManifest([&](const ManifestWithDescription& mwd) { mwd.manifest->forEachInstance([&](const auto& manifestInstance) { if (manifestInstance.format() != vintf::HalFormat::AIDL) return true; if (manifestInstance.package() != aname.package) return true; if (manifestInstance.interface() != aname.iface) return true; if (manifestInstance.instance() != aname.instance) return true; updatableViaApex = manifestInstance.updatableViaApex(); return false; // break (libvintf uses opposite convention) }); return false; // continue }); return updatableViaApex; } static std::vector<std::string> getVintfInstances(const std::string& interface) { static std::vector<std::string> getVintfInstances(const std::string& interface) { size_t lastDot = interface.rfind('.'); size_t lastDot = interface.rfind('.'); if (lastDot == std::string::npos) { if (lastDot == std::string::npos) { Loading Loading @@ -388,6 +421,22 @@ binder::Status ServiceManager::getDeclaredInstances(const std::string& interface return Status::ok(); return Status::ok(); } } Status ServiceManager::updatableViaApex(const std::string& name, std::optional<std::string>* outReturn) { auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { return Status::fromExceptionCode(Status::EX_SECURITY); } *outReturn = std::nullopt; #ifndef VENDORSERVICEMANAGER *outReturn = getVintfUpdatableApex(name); #endif return Status::ok(); } void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who, void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who, ServiceCallbackMap::iterator* it, ServiceCallbackMap::iterator* it, bool* found) { bool* found) { Loading cmds/servicemanager/ServiceManager.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,8 @@ public: binder::Status isDeclared(const std::string& name, bool* outReturn) 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 getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override; binder::Status updatableViaApex(const std::string& name, std::optional<std::string>* outReturn) override; binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, const sp<IClientCallback>& cb) override; const sp<IClientCallback>& cb) override; binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override; binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override; Loading libs/binder/IServiceManager.cpp +9 −0 Original line number Original line Diff line number Diff line Loading @@ -75,6 +75,7 @@ public: sp<IBinder> waitForService(const String16& name16) override; sp<IBinder> waitForService(const String16& name16) override; bool isDeclared(const String16& name) override; bool isDeclared(const String16& name) override; Vector<String16> getDeclaredInstances(const String16& interface) override; Vector<String16> getDeclaredInstances(const String16& interface) override; std::optional<String16> updatableViaApex(const String16& name) override; // for legacy ABI // for legacy ABI const String16& getInterfaceDescriptor() const override { const String16& getInterfaceDescriptor() const override { Loading Loading @@ -388,4 +389,12 @@ Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interf return res; return res; } } std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) { std::optional<std::string> declared; if (!mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared).isOk()) { return std::nullopt; } return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt; } } // namespace android } // namespace android libs/binder/aidl/android/os/IServiceManager.aidl +5 −0 Original line number Original line Diff line number Diff line Loading @@ -107,6 +107,11 @@ interface IServiceManager { */ */ @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface); @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface); /** * If updatable-via-apex, returns the APEX via which this is updated. */ @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name); /** /** * Request a callback when the number of clients of the service changes. * Request a callback when the number of clients of the service changes. * Used by LazyServiceRegistrar to dynamically stop services that have no clients. * Used by LazyServiceRegistrar to dynamically stop services that have no clients. Loading Loading
cmds/dumpsys/tests/dumpsys_test.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); MOCK_METHOD1(isDeclared, bool(const String16&)); MOCK_METHOD1(isDeclared, bool(const String16&)); MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&)); protected: protected: MOCK_METHOD0(onAsBinder, IBinder*()); MOCK_METHOD0(onAsBinder, IBinder*()); }; }; Loading
cmds/servicemanager/ServiceManager.cpp +64 −15 Original line number Original line Diff line number Diff line Loading @@ -58,7 +58,12 @@ static bool forEachManifest(const std::function<bool(const ManifestWithDescripti return false; return false; } } static bool isVintfDeclared(const std::string& name) { struct AidlName { std::string package; std::string iface; std::string instance; static bool fill(const std::string& name, AidlName* aname) { size_t firstSlash = name.find('/'); size_t firstSlash = name.find('/'); size_t lastDot = name.rfind('.', firstSlash); size_t lastDot = name.rfind('.', firstSlash); if (firstSlash == std::string::npos || lastDot == std::string::npos) { if (firstSlash == std::string::npos || lastDot == std::string::npos) { Loading @@ -66,14 +71,21 @@ static bool isVintfDeclared(const std::string& name) { << "some.package.foo.IFoo/default) but got: " << name; << "some.package.foo.IFoo/default) but got: " << name; return false; return false; } } const std::string package = name.substr(0, lastDot); aname->package = name.substr(0, lastDot); const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1); aname->iface = name.substr(lastDot + 1, firstSlash - lastDot - 1); const std::string instance = name.substr(firstSlash+1); aname->instance = name.substr(firstSlash + 1); return true; } }; static bool isVintfDeclared(const std::string& name) { AidlName aname; if (!AidlName::fill(name, &aname)) return false; bool found = forEachManifest([&](const ManifestWithDescription& mwd) { bool found = forEachManifest([&](const ManifestWithDescription& mwd) { if (mwd.manifest->hasAidlInstance(package, iface, instance)) { if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) { LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest."; LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest."; return true; return true; // break } } return false; // continue return false; // continue }); }); Loading @@ -81,13 +93,34 @@ static bool isVintfDeclared(const std::string& name) { if (!found) { if (!found) { // Although it is tested, explicitly rebuilding qualified name, in case it // Although it is tested, explicitly rebuilding qualified name, in case it // becomes something unexpected. // becomes something unexpected. LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance LOG(ERROR) << "Could not find " << aname.package << "." << aname.iface << "/" << " in the VINTF manifest."; << aname.instance << " in the VINTF manifest."; } } return found; return found; } } static std::optional<std::string> getVintfUpdatableApex(const std::string& name) { AidlName aname; if (!AidlName::fill(name, &aname)) return std::nullopt; std::optional<std::string> updatableViaApex; forEachManifest([&](const ManifestWithDescription& mwd) { mwd.manifest->forEachInstance([&](const auto& manifestInstance) { if (manifestInstance.format() != vintf::HalFormat::AIDL) return true; if (manifestInstance.package() != aname.package) return true; if (manifestInstance.interface() != aname.iface) return true; if (manifestInstance.instance() != aname.instance) return true; updatableViaApex = manifestInstance.updatableViaApex(); return false; // break (libvintf uses opposite convention) }); return false; // continue }); return updatableViaApex; } static std::vector<std::string> getVintfInstances(const std::string& interface) { static std::vector<std::string> getVintfInstances(const std::string& interface) { size_t lastDot = interface.rfind('.'); size_t lastDot = interface.rfind('.'); if (lastDot == std::string::npos) { if (lastDot == std::string::npos) { Loading Loading @@ -388,6 +421,22 @@ binder::Status ServiceManager::getDeclaredInstances(const std::string& interface return Status::ok(); return Status::ok(); } } Status ServiceManager::updatableViaApex(const std::string& name, std::optional<std::string>* outReturn) { auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { return Status::fromExceptionCode(Status::EX_SECURITY); } *outReturn = std::nullopt; #ifndef VENDORSERVICEMANAGER *outReturn = getVintfUpdatableApex(name); #endif return Status::ok(); } void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who, void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who, ServiceCallbackMap::iterator* it, ServiceCallbackMap::iterator* it, bool* found) { bool* found) { Loading
cmds/servicemanager/ServiceManager.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,8 @@ public: binder::Status isDeclared(const std::string& name, bool* outReturn) 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 getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override; binder::Status updatableViaApex(const std::string& name, std::optional<std::string>* outReturn) override; binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, const sp<IClientCallback>& cb) override; const sp<IClientCallback>& cb) override; binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override; binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override; Loading
libs/binder/IServiceManager.cpp +9 −0 Original line number Original line Diff line number Diff line Loading @@ -75,6 +75,7 @@ public: sp<IBinder> waitForService(const String16& name16) override; sp<IBinder> waitForService(const String16& name16) override; bool isDeclared(const String16& name) override; bool isDeclared(const String16& name) override; Vector<String16> getDeclaredInstances(const String16& interface) override; Vector<String16> getDeclaredInstances(const String16& interface) override; std::optional<String16> updatableViaApex(const String16& name) override; // for legacy ABI // for legacy ABI const String16& getInterfaceDescriptor() const override { const String16& getInterfaceDescriptor() const override { Loading Loading @@ -388,4 +389,12 @@ Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interf return res; return res; } } std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) { std::optional<std::string> declared; if (!mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared).isOk()) { return std::nullopt; } return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt; } } // namespace android } // namespace android
libs/binder/aidl/android/os/IServiceManager.aidl +5 −0 Original line number Original line Diff line number Diff line Loading @@ -107,6 +107,11 @@ interface IServiceManager { */ */ @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface); @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface); /** * If updatable-via-apex, returns the APEX via which this is updated. */ @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name); /** /** * Request a callback when the number of clients of the service changes. * Request a callback when the number of clients of the service changes. * Used by LazyServiceRegistrar to dynamically stop services that have no clients. * Used by LazyServiceRegistrar to dynamically stop services that have no clients. Loading