Loading libs/binder/LazyServiceRegistrar.cpp +118 −42 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. * limitations under the License. */ */ #include "log/log_main.h" #define LOG_TAG "AidlLazyServiceRegistrar" #define LOG_TAG "AidlLazyServiceRegistrar" #include <binder/LazyServiceRegistrar.h> #include <binder/LazyServiceRegistrar.h> Loading @@ -37,6 +38,13 @@ public: bool allowIsolated, int dumpFlags); bool allowIsolated, int dumpFlags); void forcePersist(bool persist); void forcePersist(bool persist); void setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback); bool tryUnregister(); void reRegister(); protected: protected: Status onClients(const sp<IBinder>& service, bool clients) override; Status onClients(const sp<IBinder>& service, bool clients) override; Loading @@ -49,6 +57,7 @@ private: // whether, based on onClients calls, we know we have a client for this // whether, based on onClients calls, we know we have a client for this // service or not // service or not bool clients = false; bool clients = false; bool registered = true; }; }; /** /** Loading @@ -62,6 +71,14 @@ private: */ */ void tryShutdown(); void tryShutdown(); /** * Try to shutdown the process, unless: * - 'forcePersist' is 'true', or * - The active services count callback returns 'true', or * - Some services have clients. */ void maybeTryShutdown(); // count of services with clients // count of services with clients size_t mNumConnectedServices; size_t mNumConnectedServices; Loading @@ -69,6 +86,9 @@ private: std::map<std::string, Service> mRegisteredServices; std::map<std::string, Service> mRegisteredServices; bool mForcePersist; bool mForcePersist; // Callback used to report the number of services with clients std::function<bool(int)> mActiveServicesCountCallback; }; }; class ClientCounterCallback { class ClientCounterCallback { Loading @@ -83,6 +103,13 @@ public: */ */ void forcePersist(bool persist); void forcePersist(bool persist); void setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback); bool tryUnregister(); void reRegister(); private: private: sp<ClientCounterCallbackImpl> mImpl; sp<ClientCounterCallbackImpl> mImpl; }; }; Loading Loading @@ -131,8 +158,60 @@ std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounte void ClientCounterCallbackImpl::forcePersist(bool persist) { void ClientCounterCallbackImpl::forcePersist(bool persist) { mForcePersist = persist; mForcePersist = persist; if(!mForcePersist) { if (!mForcePersist && mNumConnectedServices == 0) { // Attempt a shutdown in case the number of clients hit 0 while the flag was on // Attempt a shutdown in case the number of clients hit 0 while the flag was on maybeTryShutdown(); } } bool ClientCounterCallbackImpl::tryUnregister() { auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); for (auto& [name, entry] : mRegisteredServices) { bool success = manager->tryUnregisterService(name, entry.service).isOk(); if (!success) { ALOGI("Failed to unregister service %s", name.c_str()); return false; } entry.registered = false; } return true; } void ClientCounterCallbackImpl::reRegister() { for (auto& [name, entry] : mRegisteredServices) { // re-register entry if not already registered if (entry.registered) { continue; } if (!registerService(entry.service, name, entry.allowIsolated, entry.dumpFlags)) { // Must restart. Otherwise, clients will never be able to get a hold of this service. LOG_ALWAYS_FATAL("Bad state: could not re-register services"); } entry.registered = true; } } void ClientCounterCallbackImpl::maybeTryShutdown() { if (mForcePersist) { ALOGI("Shutdown prevented by forcePersist override flag."); return; } bool handledInCallback = false; if (mActiveServicesCountCallback != nullptr) { handledInCallback = mActiveServicesCountCallback(mNumConnectedServices); } // If there is no callback defined or the callback did not handle this // client count change event, try to shutdown the process if its services // have no clients. if (!handledInCallback && mNumConnectedServices == 0) { tryShutdown(); tryShutdown(); } } } } Loading Loading @@ -162,53 +241,24 @@ Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool cli ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d", ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d", mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients); mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients); tryShutdown(); maybeTryShutdown(); return Status::ok(); return Status::ok(); } } void ClientCounterCallbackImpl::tryShutdown() { void ClientCounterCallbackImpl::tryShutdown() { if(mNumConnectedServices > 0) { // Should only shut down if there are no clients return; } if(mForcePersist) { ALOGI("Shutdown prevented by forcePersist override flag."); return; } ALOGI("Trying to shut down the service. No clients in use for any service in process."); ALOGI("Trying to shut down the service. No clients in use for any service in process."); auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); if (tryUnregister()) { auto unRegisterIt = mRegisteredServices.begin(); for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) { auto& entry = (*unRegisterIt); bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk(); if (!success) { ALOGI("Failed to unregister service %s", entry.first.c_str()); break; } } if (unRegisterIt == mRegisteredServices.end()) { ALOGI("Unregistered all clients and exiting"); ALOGI("Unregistered all clients and exiting"); exit(EXIT_SUCCESS); exit(EXIT_SUCCESS); } } for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt; reRegister(); reRegisterIt++) { auto& entry = (*reRegisterIt); // re-register entry if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated, entry.second.dumpFlags)) { // Must restart. Otherwise, clients will never be able to get a hold of this service. ALOGE("Bad state: could not re-register services"); } } } void ClientCounterCallbackImpl::setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback) { mActiveServicesCountCallback = activeServicesCountCallback; } } ClientCounterCallback::ClientCounterCallback() { ClientCounterCallback::ClientCounterCallback() { Loading @@ -224,6 +274,19 @@ void ClientCounterCallback::forcePersist(bool persist) { mImpl->forcePersist(persist); mImpl->forcePersist(persist); } } void ClientCounterCallback::setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback) { mImpl->setActiveServicesCountCallback(activeServicesCountCallback); } bool ClientCounterCallback::tryUnregister() { return mImpl->tryUnregister(); } void ClientCounterCallback::reRegister() { mImpl->reRegister(); } } // namespace internal } // namespace internal LazyServiceRegistrar::LazyServiceRegistrar() { LazyServiceRegistrar::LazyServiceRegistrar() { Loading @@ -247,5 +310,18 @@ void LazyServiceRegistrar::forcePersist(bool persist) { mClientCC->forcePersist(persist); mClientCC->forcePersist(persist); } } void LazyServiceRegistrar::setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback) { mClientCC->setActiveServicesCountCallback(activeServicesCountCallback); } bool LazyServiceRegistrar::tryUnregister() { return mClientCC->tryUnregister(); } void LazyServiceRegistrar::reRegister() { mClientCC->reRegister(); } } // namespace hardware } // namespace hardware } // namespace android } // namespace android libs/binder/include/binder/LazyServiceRegistrar.h +36 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #pragma once #include <functional> #include <binder/IServiceManager.h> #include <binder/IServiceManager.h> #include <binder/Status.h> #include <binder/Status.h> #include <utils/StrongPointer.h> #include <utils/StrongPointer.h> Loading Loading @@ -53,6 +55,40 @@ class LazyServiceRegistrar { */ */ void forcePersist(bool persist); void forcePersist(bool persist); /** * Set a callback that is executed when the total number of services with * clients changes. * The callback takes an argument, which is the number of registered * lazy services for this process which have clients. * * Callback return value: * - false: Default behavior for lazy services (shut down the process if there * are no clients). * - true: Don't shut down the process even if there are no clients. * * This callback gives a chance to: * 1 - Perform some additional operations before exiting; * 2 - Prevent the process from exiting by returning "true" from the * callback. * * This method should be called before 'registerService' to avoid races. */ void setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback); /** * Try to unregister all services previously registered with 'registerService'. * Returns 'true' if successful. */ bool tryUnregister(); /** * Re-register services that were unregistered by 'tryUnregister'. * This method should be called in the case 'tryUnregister' fails * (and should be called on the same thread). */ void reRegister(); private: private: std::shared_ptr<internal::ClientCounterCallback> mClientCC; std::shared_ptr<internal::ClientCounterCallback> mClientCC; LazyServiceRegistrar(); LazyServiceRegistrar(); Loading Loading
libs/binder/LazyServiceRegistrar.cpp +118 −42 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. * limitations under the License. */ */ #include "log/log_main.h" #define LOG_TAG "AidlLazyServiceRegistrar" #define LOG_TAG "AidlLazyServiceRegistrar" #include <binder/LazyServiceRegistrar.h> #include <binder/LazyServiceRegistrar.h> Loading @@ -37,6 +38,13 @@ public: bool allowIsolated, int dumpFlags); bool allowIsolated, int dumpFlags); void forcePersist(bool persist); void forcePersist(bool persist); void setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback); bool tryUnregister(); void reRegister(); protected: protected: Status onClients(const sp<IBinder>& service, bool clients) override; Status onClients(const sp<IBinder>& service, bool clients) override; Loading @@ -49,6 +57,7 @@ private: // whether, based on onClients calls, we know we have a client for this // whether, based on onClients calls, we know we have a client for this // service or not // service or not bool clients = false; bool clients = false; bool registered = true; }; }; /** /** Loading @@ -62,6 +71,14 @@ private: */ */ void tryShutdown(); void tryShutdown(); /** * Try to shutdown the process, unless: * - 'forcePersist' is 'true', or * - The active services count callback returns 'true', or * - Some services have clients. */ void maybeTryShutdown(); // count of services with clients // count of services with clients size_t mNumConnectedServices; size_t mNumConnectedServices; Loading @@ -69,6 +86,9 @@ private: std::map<std::string, Service> mRegisteredServices; std::map<std::string, Service> mRegisteredServices; bool mForcePersist; bool mForcePersist; // Callback used to report the number of services with clients std::function<bool(int)> mActiveServicesCountCallback; }; }; class ClientCounterCallback { class ClientCounterCallback { Loading @@ -83,6 +103,13 @@ public: */ */ void forcePersist(bool persist); void forcePersist(bool persist); void setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback); bool tryUnregister(); void reRegister(); private: private: sp<ClientCounterCallbackImpl> mImpl; sp<ClientCounterCallbackImpl> mImpl; }; }; Loading Loading @@ -131,8 +158,60 @@ std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounte void ClientCounterCallbackImpl::forcePersist(bool persist) { void ClientCounterCallbackImpl::forcePersist(bool persist) { mForcePersist = persist; mForcePersist = persist; if(!mForcePersist) { if (!mForcePersist && mNumConnectedServices == 0) { // Attempt a shutdown in case the number of clients hit 0 while the flag was on // Attempt a shutdown in case the number of clients hit 0 while the flag was on maybeTryShutdown(); } } bool ClientCounterCallbackImpl::tryUnregister() { auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); for (auto& [name, entry] : mRegisteredServices) { bool success = manager->tryUnregisterService(name, entry.service).isOk(); if (!success) { ALOGI("Failed to unregister service %s", name.c_str()); return false; } entry.registered = false; } return true; } void ClientCounterCallbackImpl::reRegister() { for (auto& [name, entry] : mRegisteredServices) { // re-register entry if not already registered if (entry.registered) { continue; } if (!registerService(entry.service, name, entry.allowIsolated, entry.dumpFlags)) { // Must restart. Otherwise, clients will never be able to get a hold of this service. LOG_ALWAYS_FATAL("Bad state: could not re-register services"); } entry.registered = true; } } void ClientCounterCallbackImpl::maybeTryShutdown() { if (mForcePersist) { ALOGI("Shutdown prevented by forcePersist override flag."); return; } bool handledInCallback = false; if (mActiveServicesCountCallback != nullptr) { handledInCallback = mActiveServicesCountCallback(mNumConnectedServices); } // If there is no callback defined or the callback did not handle this // client count change event, try to shutdown the process if its services // have no clients. if (!handledInCallback && mNumConnectedServices == 0) { tryShutdown(); tryShutdown(); } } } } Loading Loading @@ -162,53 +241,24 @@ Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool cli ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d", ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d", mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients); mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients); tryShutdown(); maybeTryShutdown(); return Status::ok(); return Status::ok(); } } void ClientCounterCallbackImpl::tryShutdown() { void ClientCounterCallbackImpl::tryShutdown() { if(mNumConnectedServices > 0) { // Should only shut down if there are no clients return; } if(mForcePersist) { ALOGI("Shutdown prevented by forcePersist override flag."); return; } ALOGI("Trying to shut down the service. No clients in use for any service in process."); ALOGI("Trying to shut down the service. No clients in use for any service in process."); auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); if (tryUnregister()) { auto unRegisterIt = mRegisteredServices.begin(); for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) { auto& entry = (*unRegisterIt); bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk(); if (!success) { ALOGI("Failed to unregister service %s", entry.first.c_str()); break; } } if (unRegisterIt == mRegisteredServices.end()) { ALOGI("Unregistered all clients and exiting"); ALOGI("Unregistered all clients and exiting"); exit(EXIT_SUCCESS); exit(EXIT_SUCCESS); } } for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt; reRegister(); reRegisterIt++) { auto& entry = (*reRegisterIt); // re-register entry if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated, entry.second.dumpFlags)) { // Must restart. Otherwise, clients will never be able to get a hold of this service. ALOGE("Bad state: could not re-register services"); } } } void ClientCounterCallbackImpl::setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback) { mActiveServicesCountCallback = activeServicesCountCallback; } } ClientCounterCallback::ClientCounterCallback() { ClientCounterCallback::ClientCounterCallback() { Loading @@ -224,6 +274,19 @@ void ClientCounterCallback::forcePersist(bool persist) { mImpl->forcePersist(persist); mImpl->forcePersist(persist); } } void ClientCounterCallback::setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback) { mImpl->setActiveServicesCountCallback(activeServicesCountCallback); } bool ClientCounterCallback::tryUnregister() { return mImpl->tryUnregister(); } void ClientCounterCallback::reRegister() { mImpl->reRegister(); } } // namespace internal } // namespace internal LazyServiceRegistrar::LazyServiceRegistrar() { LazyServiceRegistrar::LazyServiceRegistrar() { Loading @@ -247,5 +310,18 @@ void LazyServiceRegistrar::forcePersist(bool persist) { mClientCC->forcePersist(persist); mClientCC->forcePersist(persist); } } void LazyServiceRegistrar::setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback) { mClientCC->setActiveServicesCountCallback(activeServicesCountCallback); } bool LazyServiceRegistrar::tryUnregister() { return mClientCC->tryUnregister(); } void LazyServiceRegistrar::reRegister() { mClientCC->reRegister(); } } // namespace hardware } // namespace hardware } // namespace android } // namespace android
libs/binder/include/binder/LazyServiceRegistrar.h +36 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #pragma once #include <functional> #include <binder/IServiceManager.h> #include <binder/IServiceManager.h> #include <binder/Status.h> #include <binder/Status.h> #include <utils/StrongPointer.h> #include <utils/StrongPointer.h> Loading Loading @@ -53,6 +55,40 @@ class LazyServiceRegistrar { */ */ void forcePersist(bool persist); void forcePersist(bool persist); /** * Set a callback that is executed when the total number of services with * clients changes. * The callback takes an argument, which is the number of registered * lazy services for this process which have clients. * * Callback return value: * - false: Default behavior for lazy services (shut down the process if there * are no clients). * - true: Don't shut down the process even if there are no clients. * * This callback gives a chance to: * 1 - Perform some additional operations before exiting; * 2 - Prevent the process from exiting by returning "true" from the * callback. * * This method should be called before 'registerService' to avoid races. */ void setActiveServicesCountCallback(const std::function<bool(int)>& activeServicesCountCallback); /** * Try to unregister all services previously registered with 'registerService'. * Returns 'true' if successful. */ bool tryUnregister(); /** * Re-register services that were unregistered by 'tryUnregister'. * This method should be called in the case 'tryUnregister' fails * (and should be called on the same thread). */ void reRegister(); private: private: std::shared_ptr<internal::ClientCounterCallback> mClientCC; std::shared_ptr<internal::ClientCounterCallback> mClientCC; LazyServiceRegistrar(); LazyServiceRegistrar(); Loading