Loading cmds/dumpsys/tests/dumpsys_test.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,10 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&)); MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&)); MOCK_METHOD2(registerForNotifications, status_t(const String16&, const sp<LocalRegistrationCallback>&)); MOCK_METHOD2(unregisterForNotifications, status_t(const String16&, const sp<LocalRegistrationCallback>&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; Loading libs/binder/IServiceManager.cpp +101 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ namespace android { using AidlRegistrationCallback = IServiceManager::LocalRegistrationCallback; using AidlServiceManager = android::os::IServiceManager; using android::binder::Status; Loading Loading @@ -79,7 +81,24 @@ public: Vector<String16> getDeclaredInstances(const String16& interface) override; std::optional<String16> updatableViaApex(const String16& name) override; std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override; class RegistrationWaiter : public android::os::BnServiceCallback { public: explicit RegistrationWaiter(const sp<AidlRegistrationCallback>& callback) : mImpl(callback) {} Status onRegistration(const std::string& name, const sp<IBinder>& binder) override { mImpl->onServiceRegistration(String16(name.c_str()), binder); return Status::ok(); } private: sp<AidlRegistrationCallback> mImpl; }; status_t registerForNotifications(const String16& service, const sp<AidlRegistrationCallback>& cb) override; status_t unregisterForNotifications(const String16& service, const sp<AidlRegistrationCallback>& cb) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { return mTheRealServiceManager->getInterfaceDescriptor(); Loading @@ -90,6 +109,17 @@ public: protected: sp<AidlServiceManager> mTheRealServiceManager; // AidlRegistrationCallback -> services that its been registered for // notifications. using LocalRegistrationAndWaiter = std::pair<sp<LocalRegistrationCallback>, sp<RegistrationWaiter>>; using ServiceCallbackMap = std::map<std::string, std::vector<LocalRegistrationAndWaiter>>; ServiceCallbackMap mNameToRegistrationCallback; std::mutex mNameToRegistrationLock; void removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb, ServiceCallbackMap::iterator* it, sp<RegistrationWaiter>* waiter); // Directly get the service in a way that, for lazy services, requests the service to be started // if it is not currently started. This way, calls directly to ServiceManagerShim::getService Loading Loading @@ -442,6 +472,77 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnection : std::nullopt; } status_t ServiceManagerShim::registerForNotifications(const String16& name, const sp<AidlRegistrationCallback>& cb) { if (cb == nullptr) { ALOGE("%s: null cb passed", __FUNCTION__); return BAD_VALUE; } std::string nameStr = String8(name).c_str(); sp<RegistrationWaiter> registrationWaiter = sp<RegistrationWaiter>::make(cb); std::lock_guard<std::mutex> lock(mNameToRegistrationLock); if (Status status = mTheRealServiceManager->registerForNotifications(nameStr, registrationWaiter); !status.isOk()) { ALOGW("Failed to registerForNotifications for %s: %s", nameStr.c_str(), status.toString8().c_str()); return UNKNOWN_ERROR; } mNameToRegistrationCallback[nameStr].push_back(std::make_pair(cb, registrationWaiter)); return OK; } void ServiceManagerShim::removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb, ServiceCallbackMap::iterator* it, sp<RegistrationWaiter>* waiter) { std::vector<LocalRegistrationAndWaiter>& localRegistrationAndWaiters = (*it)->second; for (auto lit = localRegistrationAndWaiters.begin(); lit != localRegistrationAndWaiters.end();) { if (lit->first == cb) { if (waiter) { *waiter = lit->second; } lit = localRegistrationAndWaiters.erase(lit); } else { ++lit; } } if (localRegistrationAndWaiters.empty()) { mNameToRegistrationCallback.erase(*it); } } status_t ServiceManagerShim::unregisterForNotifications(const String16& name, const sp<AidlRegistrationCallback>& cb) { if (cb == nullptr) { ALOGE("%s: null cb passed", __FUNCTION__); return BAD_VALUE; } std::string nameStr = String8(name).c_str(); std::lock_guard<std::mutex> lock(mNameToRegistrationLock); auto it = mNameToRegistrationCallback.find(nameStr); sp<RegistrationWaiter> registrationWaiter; if (it != mNameToRegistrationCallback.end()) { removeRegistrationCallbackLocked(cb, &it, ®istrationWaiter); } else { ALOGE("%s no callback registered for notifications on %s", __FUNCTION__, nameStr.c_str()); return BAD_VALUE; } if (registrationWaiter == nullptr) { ALOGE("%s Callback passed wasn't used to register for notifications", __FUNCTION__); return BAD_VALUE; } if (Status status = mTheRealServiceManager->unregisterForNotifications(String8(name).c_str(), registrationWaiter); !status.isOk()) { ALOGW("Failed to get service manager to unregisterForNotifications for %s: %s", String8(name).c_str(), status.toString8().c_str()); return UNKNOWN_ERROR; } return OK; } #ifndef __ANDROID__ // ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API. // The internal implementation of the AIDL interface android::os::IServiceManager calls into Loading libs/binder/include/binder/IServiceManager.h +11 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,17 @@ public: unsigned int port; }; virtual std::optional<ConnectionInfo> getConnectionInfo(const String16& name) = 0; struct LocalRegistrationCallback : public virtual RefBase { virtual void onServiceRegistration(const String16& instance, const sp<IBinder>& binder) = 0; virtual ~LocalRegistrationCallback() {} }; virtual status_t registerForNotifications(const String16& name, const sp<LocalRegistrationCallback>& callback) = 0; virtual status_t unregisterForNotifications(const String16& name, const sp<LocalRegistrationCallback>& callback) = 0; }; sp<IServiceManager> defaultServiceManager(); Loading libs/binder/tests/binderLibTest.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -1220,6 +1220,19 @@ TEST_F(BinderLibTest, GotSid) { EXPECT_THAT(server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr), StatusEq(OK)); } TEST(ServiceNotifications, Unregister) { auto sm = defaultServiceManager(); using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback; class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback { void onServiceRegistration(const String16 &, const sp<IBinder> &) override {} virtual ~LocalRegistrationCallbackImpl() {} }; sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); EXPECT_EQ(sm->registerForNotifications(String16("RogerRafa"), cb), OK); EXPECT_EQ(sm->unregisterForNotifications(String16("RogerRafa"), cb), OK); } class BinderLibRpcTestBase : public BinderLibTest { public: void SetUp() override { Loading libs/fakeservicemanager/ServiceManager.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -84,4 +84,14 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo return std::nullopt; } status_t ServiceManager::registerForNotifications(const String16&, const sp<LocalRegistrationCallback>&) { return INVALID_OPERATION; } status_t ServiceManager::unregisterForNotifications(const String16&, const sp<LocalRegistrationCallback>&) { return INVALID_OPERATION; } } // namespace android Loading
cmds/dumpsys/tests/dumpsys_test.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,10 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&)); MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&)); MOCK_METHOD2(registerForNotifications, status_t(const String16&, const sp<LocalRegistrationCallback>&)); MOCK_METHOD2(unregisterForNotifications, status_t(const String16&, const sp<LocalRegistrationCallback>&)); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; Loading
libs/binder/IServiceManager.cpp +101 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,8 @@ namespace android { using AidlRegistrationCallback = IServiceManager::LocalRegistrationCallback; using AidlServiceManager = android::os::IServiceManager; using android::binder::Status; Loading Loading @@ -79,7 +81,24 @@ public: Vector<String16> getDeclaredInstances(const String16& interface) override; std::optional<String16> updatableViaApex(const String16& name) override; std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override; class RegistrationWaiter : public android::os::BnServiceCallback { public: explicit RegistrationWaiter(const sp<AidlRegistrationCallback>& callback) : mImpl(callback) {} Status onRegistration(const std::string& name, const sp<IBinder>& binder) override { mImpl->onServiceRegistration(String16(name.c_str()), binder); return Status::ok(); } private: sp<AidlRegistrationCallback> mImpl; }; status_t registerForNotifications(const String16& service, const sp<AidlRegistrationCallback>& cb) override; status_t unregisterForNotifications(const String16& service, const sp<AidlRegistrationCallback>& cb) override; // for legacy ABI const String16& getInterfaceDescriptor() const override { return mTheRealServiceManager->getInterfaceDescriptor(); Loading @@ -90,6 +109,17 @@ public: protected: sp<AidlServiceManager> mTheRealServiceManager; // AidlRegistrationCallback -> services that its been registered for // notifications. using LocalRegistrationAndWaiter = std::pair<sp<LocalRegistrationCallback>, sp<RegistrationWaiter>>; using ServiceCallbackMap = std::map<std::string, std::vector<LocalRegistrationAndWaiter>>; ServiceCallbackMap mNameToRegistrationCallback; std::mutex mNameToRegistrationLock; void removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb, ServiceCallbackMap::iterator* it, sp<RegistrationWaiter>* waiter); // Directly get the service in a way that, for lazy services, requests the service to be started // if it is not currently started. This way, calls directly to ServiceManagerShim::getService Loading Loading @@ -442,6 +472,77 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnection : std::nullopt; } status_t ServiceManagerShim::registerForNotifications(const String16& name, const sp<AidlRegistrationCallback>& cb) { if (cb == nullptr) { ALOGE("%s: null cb passed", __FUNCTION__); return BAD_VALUE; } std::string nameStr = String8(name).c_str(); sp<RegistrationWaiter> registrationWaiter = sp<RegistrationWaiter>::make(cb); std::lock_guard<std::mutex> lock(mNameToRegistrationLock); if (Status status = mTheRealServiceManager->registerForNotifications(nameStr, registrationWaiter); !status.isOk()) { ALOGW("Failed to registerForNotifications for %s: %s", nameStr.c_str(), status.toString8().c_str()); return UNKNOWN_ERROR; } mNameToRegistrationCallback[nameStr].push_back(std::make_pair(cb, registrationWaiter)); return OK; } void ServiceManagerShim::removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb, ServiceCallbackMap::iterator* it, sp<RegistrationWaiter>* waiter) { std::vector<LocalRegistrationAndWaiter>& localRegistrationAndWaiters = (*it)->second; for (auto lit = localRegistrationAndWaiters.begin(); lit != localRegistrationAndWaiters.end();) { if (lit->first == cb) { if (waiter) { *waiter = lit->second; } lit = localRegistrationAndWaiters.erase(lit); } else { ++lit; } } if (localRegistrationAndWaiters.empty()) { mNameToRegistrationCallback.erase(*it); } } status_t ServiceManagerShim::unregisterForNotifications(const String16& name, const sp<AidlRegistrationCallback>& cb) { if (cb == nullptr) { ALOGE("%s: null cb passed", __FUNCTION__); return BAD_VALUE; } std::string nameStr = String8(name).c_str(); std::lock_guard<std::mutex> lock(mNameToRegistrationLock); auto it = mNameToRegistrationCallback.find(nameStr); sp<RegistrationWaiter> registrationWaiter; if (it != mNameToRegistrationCallback.end()) { removeRegistrationCallbackLocked(cb, &it, ®istrationWaiter); } else { ALOGE("%s no callback registered for notifications on %s", __FUNCTION__, nameStr.c_str()); return BAD_VALUE; } if (registrationWaiter == nullptr) { ALOGE("%s Callback passed wasn't used to register for notifications", __FUNCTION__); return BAD_VALUE; } if (Status status = mTheRealServiceManager->unregisterForNotifications(String8(name).c_str(), registrationWaiter); !status.isOk()) { ALOGW("Failed to get service manager to unregisterForNotifications for %s: %s", String8(name).c_str(), status.toString8().c_str()); return UNKNOWN_ERROR; } return OK; } #ifndef __ANDROID__ // ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API. // The internal implementation of the AIDL interface android::os::IServiceManager calls into Loading
libs/binder/include/binder/IServiceManager.h +11 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,17 @@ public: unsigned int port; }; virtual std::optional<ConnectionInfo> getConnectionInfo(const String16& name) = 0; struct LocalRegistrationCallback : public virtual RefBase { virtual void onServiceRegistration(const String16& instance, const sp<IBinder>& binder) = 0; virtual ~LocalRegistrationCallback() {} }; virtual status_t registerForNotifications(const String16& name, const sp<LocalRegistrationCallback>& callback) = 0; virtual status_t unregisterForNotifications(const String16& name, const sp<LocalRegistrationCallback>& callback) = 0; }; sp<IServiceManager> defaultServiceManager(); Loading
libs/binder/tests/binderLibTest.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -1220,6 +1220,19 @@ TEST_F(BinderLibTest, GotSid) { EXPECT_THAT(server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr), StatusEq(OK)); } TEST(ServiceNotifications, Unregister) { auto sm = defaultServiceManager(); using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback; class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback { void onServiceRegistration(const String16 &, const sp<IBinder> &) override {} virtual ~LocalRegistrationCallbackImpl() {} }; sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make(); EXPECT_EQ(sm->registerForNotifications(String16("RogerRafa"), cb), OK); EXPECT_EQ(sm->unregisterForNotifications(String16("RogerRafa"), cb), OK); } class BinderLibRpcTestBase : public BinderLibTest { public: void SetUp() override { Loading
libs/fakeservicemanager/ServiceManager.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -84,4 +84,14 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo return std::nullopt; } status_t ServiceManager::registerForNotifications(const String16&, const sp<LocalRegistrationCallback>&) { return INVALID_OPERATION; } status_t ServiceManager::unregisterForNotifications(const String16&, const sp<LocalRegistrationCallback>&) { return INVALID_OPERATION; } } // namespace android