diff options
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 1 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.cpp | 79 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.h | 2 | ||||
-rw-r--r-- | libs/binder/IServiceManager.cpp | 9 | ||||
-rw-r--r-- | libs/binder/aidl/android/os/IServiceManager.aidl | 5 | ||||
-rw-r--r-- | libs/binder/include/binder/IServiceManager.h | 8 | ||||
-rw-r--r-- | libs/binder/ndk/include_platform/android/binder_manager.h | 9 | ||||
-rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 9 | ||||
-rw-r--r-- | libs/binder/ndk/service_manager.cpp | 8 | ||||
-rw-r--r-- | libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp | 5 | ||||
-rw-r--r-- | libs/binder/tests/binderStabilityTest.cpp | 2 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.cpp | 5 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.h | 3 |
13 files changed, 126 insertions, 19 deletions
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 67a77f6015..0ad256471f 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -56,6 +56,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(waitForService, sp<IBinder>(const String16&)); MOCK_METHOD1(isDeclared, bool(const String16&)); MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); + MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 2f5524940e..b429fb3440 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -58,22 +58,34 @@ static bool forEachManifest(const std::function<bool(const ManifestWithDescripti 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; +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 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; + } + aname->package = name.substr(0, lastDot); + aname->iface = name.substr(lastDot + 1, firstSlash - lastDot - 1); + aname->instance = name.substr(firstSlash + 1); + return true; } - 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); +}; + +static bool isVintfDeclared(const std::string& name) { + AidlName aname; + if (!AidlName::fill(name, &aname)) return false; - bool found = forEachManifest([&] (const ManifestWithDescription& mwd) { - if (mwd.manifest->hasAidlInstance(package, iface, instance)) { + bool found = forEachManifest([&](const ManifestWithDescription& mwd) { + if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) { LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest."; - return true; + return true; // break } return false; // continue }); @@ -81,13 +93,34 @@ static bool isVintfDeclared(const std::string& name) { 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."; + LOG(ERROR) << "Could not find " << aname.package << "." << aname.iface << "/" + << aname.instance << " in the VINTF manifest."; } 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) { size_t lastDot = interface.rfind('.'); if (lastDot == std::string::npos) { @@ -388,6 +421,22 @@ binder::Status ServiceManager::getDeclaredInstances(const std::string& interface 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, ServiceCallbackMap::iterator* it, bool* found) { diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h index c0891152e6..4f23c21078 100644 --- a/cmds/servicemanager/ServiceManager.h +++ b/cmds/servicemanager/ServiceManager.h @@ -46,6 +46,8 @@ public: 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 updatableViaApex(const std::string& name, + std::optional<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 61f4581df3..f684cf672f 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -75,6 +75,7 @@ public: sp<IBinder> waitForService(const String16& name16) override; bool isDeclared(const String16& name) override; Vector<String16> getDeclaredInstances(const String16& interface) override; + std::optional<String16> updatableViaApex(const String16& name) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { @@ -388,4 +389,12 @@ Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interf 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 diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index 2fabf947cd..75c4092559 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -108,6 +108,11 @@ interface IServiceManager { @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. * 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 5f0d056c5d..3dbe2c49f4 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -20,6 +20,8 @@ #include <utils/Vector.h> #include <utils/String16.h> +#include <optional> + namespace android { // ---------------------------------------------------------------------- @@ -99,6 +101,12 @@ public: * Get all instances of a service as declared in the VINTF manifest */ virtual Vector<String16> getDeclaredInstances(const String16& interface) = 0; + + /** + * If this instance is updatable via an APEX, returns the APEX with which + * this can be updated. + */ + virtual std::optional<String16> updatableViaApex(const String16& name) = 0; }; sp<IServiceManager> defaultServiceManager(); diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 55169140df..a90b4aabca 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -124,6 +124,15 @@ void AServiceManager_forEachDeclaredInstance(const char* interface, void* contex __INTRODUCED_IN(31); /** + * Check if a service is updatable via an APEX module. + * + * \param instance identifier of the service + * + * \return whether the interface is updatable via APEX + */ +bool AServiceManager_isUpdatableViaApex(const char* instance) __INTRODUCED_IN(31); + +/** * Prevent lazy services without client from shutting down their process * * \param persist 'true' if the process should not exit. diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 67c85b66d4..7d4b82e4b6 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -118,14 +118,15 @@ LIBBINDER_NDK31 { # introduced=31 AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex AParcel_markSensitive; # llndk - AServiceManager_isDeclared; # apex llndk AServiceManager_forEachDeclaredInstance; # apex llndk - AServiceManager_registerLazyService; # llndk - AServiceManager_waitForService; # apex llndk AServiceManager_forceLazyServicesPersist; # llndk + AServiceManager_isDeclared; # apex llndk + AServiceManager_isUpdatableViaApex; # apex + AServiceManager_reRegister; # llndk + AServiceManager_registerLazyService; # llndk AServiceManager_setActiveServicesCallback; # llndk AServiceManager_tryUnregister; # llndk - AServiceManager_reRegister; # llndk + AServiceManager_waitForService; # apex llndk AIBinder_forceDowngradeToSystemStability; # apex AIBinder_forceDowngradeToVendorStability; # llndk diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index 1ccd0d2a2b..7649a26ff6 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -105,6 +105,14 @@ void AServiceManager_forEachDeclaredInstance(const char* interface, void* contex callback(String8(instance).c_str(), context); } } +bool AServiceManager_isUpdatableViaApex(const char* instance) { + if (instance == nullptr) { + return false; + } + + sp<IServiceManager> sm = defaultServiceManager(); + return sm->updatableViaApex(String16(instance)) != std::nullopt; +} void AServiceManager_forceLazyServicesPersist(bool persist) { auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); serviceRegistrar.forcePersist(persist); diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index 496a915f8b..1c43948930 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -280,6 +280,11 @@ TEST(NdkBinder, GetLazyService) { EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())); } +TEST(NdkBinder, IsUpdatable) { + bool isUpdatable = AServiceManager_isUpdatableViaApex("android.hardware.light.ILights/default"); + EXPECT_EQ(isUpdatable, false); +} + // This is too slow TEST(NdkBinder, CheckLazyServiceShutDown) { ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService)); diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp index cb309bdd81..2ce13df4b3 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -192,6 +192,8 @@ TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) { EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT, android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8; EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8; + EXPECT_EQ(std::nullopt, android::defaultServiceManager()->updatableViaApex(instance)) + << instance8; } } diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp index 4ecbe531c2..761e45c967 100644 --- a/libs/fakeservicemanager/ServiceManager.cpp +++ b/libs/fakeservicemanager/ServiceManager.cpp @@ -73,4 +73,9 @@ Vector<String16> ServiceManager::getDeclaredInstances(const String16& name) { return out; } +std::optional<String16> ServiceManager::updatableViaApex(const String16& name) { + (void)name; + return std::nullopt; +} + } // namespace android diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h index 4ef47fb043..e26c21b9e9 100644 --- a/libs/fakeservicemanager/ServiceManager.h +++ b/libs/fakeservicemanager/ServiceManager.h @@ -19,6 +19,7 @@ #include <binder/IServiceManager.h> #include <map> +#include <optional> namespace android { @@ -48,6 +49,8 @@ public: Vector<String16> getDeclaredInstances(const String16& iface) override; + std::optional<String16> updatableViaApex(const String16& name) override; + private: std::map<String16, sp<IBinder>> mNameToService; }; |