xref: /aosp_15_r20/frameworks/native/libs/binder/LazyServiceRegistrar.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "AidlLazyServiceRegistrar"
18 
19 #include <android/os/BnClientCallback.h>
20 #include <android/os/IServiceManager.h>
21 #include <binder/IPCThreadState.h>
22 #include <binder/LazyServiceRegistrar.h>
23 
24 namespace android {
25 namespace binder {
26 namespace internal {
27 
28 using AidlServiceManager = android::os::IServiceManager;
29 
30 class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
31 public:
ClientCounterCallbackImpl()32     ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {}
33 
34     bool registerService(const sp<IBinder>& service, const std::string& name,
35                          bool allowIsolated, int dumpFlags);
36     void forcePersist(bool persist);
37 
38     void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
39 
40     bool tryUnregisterLocked();
41 
42     void reRegisterLocked();
43 
44 protected:
45     Status onClients(const sp<IBinder>& service, bool clients) override;
46 
47 private:
48     struct Service {
49         sp<IBinder> service;
50         bool allowIsolated;
51         int dumpFlags;
52 
53         // whether, based on onClients calls, we know we have a client for this
54         // service or not
55         bool clients = false;
56         bool registered = true;
57     };
58 
59     bool registerServiceLocked(const sp<IBinder>& service, const std::string& name,
60                                bool allowIsolated, int dumpFlags);
61 
62     /**
63      * Looks up a service guaranteed to be registered (service from onClients).
64      */
65     std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
66 
67     /**
68      * Unregisters all services that we can. If we can't unregister all, re-register other
69      * services.
70      */
71     void tryShutdownLocked();
72 
73     /**
74      * Try to shutdown the process, unless:
75      * - 'forcePersist' is 'true', or
76      * - The active services count callback returns 'true', or
77      * - Some services have clients.
78      */
79     void maybeTryShutdownLocked();
80 
81     // for below
82     std::mutex mMutex;
83 
84     // count of services with clients
85     size_t mNumConnectedServices;
86 
87     // previous value passed to the active services callback
88     std::optional<bool> mPreviousHasClients;
89 
90     // map of registered names and services
91     std::map<std::string, Service> mRegisteredServices;
92 
93     bool mForcePersist;
94 
95     // Callback used to report if there are services with clients
96     std::function<bool(bool)> mActiveServicesCallback;
97 };
98 
99 class ClientCounterCallback {
100 public:
101     ClientCounterCallback();
102 
103     bool registerService(const sp<IBinder>& service, const std::string& name,
104                                             bool allowIsolated, int dumpFlags);
105 
106     /**
107      * Set a flag to prevent services from automatically shutting down
108      */
109     void forcePersist(bool persist);
110 
111     void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
112 
113     bool tryUnregister();
114 
115     void reRegister();
116 
117 private:
118     sp<ClientCounterCallbackImpl> mImpl;
119 };
120 
registerService(const sp<IBinder> & service,const std::string & name,bool allowIsolated,int dumpFlags)121 bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
122                                             bool allowIsolated, int dumpFlags) {
123     std::lock_guard<std::mutex> lock(mMutex);
124     return registerServiceLocked(service, name, allowIsolated, dumpFlags);
125 }
126 
registerServiceLocked(const sp<IBinder> & service,const std::string & name,bool allowIsolated,int dumpFlags)127 bool ClientCounterCallbackImpl::registerServiceLocked(const sp<IBinder>& service,
128                                                       const std::string& name, bool allowIsolated,
129                                                       int dumpFlags) {
130     auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
131 
132     bool reRegister = mRegisteredServices.count(name) > 0;
133     std::string regStr = (reRegister) ? "Re-registering" : "Registering";
134     ALOGI("%s service %s", regStr.c_str(), name.c_str());
135 
136     if (dumpFlags & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE) {
137         ALOGW("FLAG_IS_LAZY_SERVICE flag already set. This should only be set by "
138               "ClientCounterCallbackImpl in LazyServiceRegistrar");
139     }
140     dumpFlags |= android::os::IServiceManager::FLAG_IS_LAZY_SERVICE;
141 
142     if (Status status = manager->addService(name.c_str(), service, allowIsolated, dumpFlags);
143         !status.isOk()) {
144         ALOGE("Failed to register service %s (%s)", name.c_str(), status.toString8().c_str());
145         return false;
146     }
147 
148     if (!reRegister) {
149         if (Status status =
150                     manager->registerClientCallback(name, service,
151                                                     sp<android::os::IClientCallback>::fromExisting(
152                                                             this));
153             !status.isOk()) {
154             ALOGE("Failed to add client callback for service %s (%s)", name.c_str(),
155                   status.toString8().c_str());
156             return false;
157         }
158 
159         // Only add this when a service is added for the first time, as it is not removed
160         mRegisteredServices[name] = {
161               .service = service,
162               .allowIsolated = allowIsolated,
163               .dumpFlags = dumpFlags
164         };
165     }
166 
167     return true;
168 }
169 
assertRegisteredService(const sp<IBinder> & service)170 std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
171     LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
172     for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
173         auto const& [name, registered] = *it;
174         (void) name;
175         if (registered.service != service) continue;
176         return it;
177     }
178     LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
179     __builtin_unreachable();
180 }
181 
forcePersist(bool persist)182 void ClientCounterCallbackImpl::forcePersist(bool persist) {
183     std::lock_guard<std::mutex> lock(mMutex);
184     mForcePersist = persist;
185     if (!mForcePersist) {
186         // Attempt a shutdown in case the number of clients hit 0 while the flag was on
187         maybeTryShutdownLocked();
188     }
189 }
190 
tryUnregisterLocked()191 bool ClientCounterCallbackImpl::tryUnregisterLocked() {
192     auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
193 
194     for (auto& [name, entry] : mRegisteredServices) {
195         Status status = manager->tryUnregisterService(name, entry.service);
196 
197         if (!status.isOk()) {
198             ALOGI("Failed to unregister service %s (%s)", name.c_str(), status.toString8().c_str());
199             return false;
200         }
201         entry.registered = false;
202     }
203 
204     return true;
205 }
206 
reRegisterLocked()207 void ClientCounterCallbackImpl::reRegisterLocked() {
208     for (auto& [name, entry] : mRegisteredServices) {
209         // re-register entry if not already registered
210         if (entry.registered) {
211             continue;
212         }
213 
214         if (!registerServiceLocked(entry.service, name, entry.allowIsolated, entry.dumpFlags)) {
215             // Must restart. Otherwise, clients will never be able to get a hold of this service.
216             LOG_ALWAYS_FATAL("Bad state: could not re-register services");
217         }
218 
219         entry.registered = true;
220     }
221 }
222 
maybeTryShutdownLocked()223 void ClientCounterCallbackImpl::maybeTryShutdownLocked() {
224     if (mForcePersist) {
225         ALOGI("Shutdown prevented by forcePersist override flag.");
226         return;
227     }
228 
229     bool handledInCallback = false;
230     if (mActiveServicesCallback != nullptr) {
231         bool hasClients = mNumConnectedServices != 0;
232         if (hasClients != mPreviousHasClients) {
233             handledInCallback = mActiveServicesCallback(hasClients);
234             mPreviousHasClients = hasClients;
235         }
236     }
237 
238     // If there is no callback defined or the callback did not handle this
239     // client count change event, try to shutdown the process if its services
240     // have no clients.
241     if (!handledInCallback && mNumConnectedServices == 0) {
242         tryShutdownLocked();
243     }
244 }
245 
onClients(const sp<IBinder> & service,bool clients)246 Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
247     std::lock_guard<std::mutex> lock(mMutex);
248     auto & [name, registered] = *assertRegisteredService(service);
249     if (registered.clients == clients) {
250         LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
251                          "notified has clients: %d", name.c_str(), registered.clients, clients);
252     }
253     registered.clients = clients;
254 
255     // update cache count of clients
256     {
257          size_t numWithClients = 0;
258          for (const auto& [name, registered] : mRegisteredServices) {
259              (void) name;
260              if (registered.clients) numWithClients++;
261          }
262          mNumConnectedServices = numWithClients;
263     }
264 
265     ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
266           mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
267 
268     maybeTryShutdownLocked();
269     return Status::ok();
270 }
271 
tryShutdownLocked()272 void ClientCounterCallbackImpl::tryShutdownLocked() {
273     ALOGI("Trying to shut down the service. No clients in use for any service in process.");
274 
275     if (tryUnregisterLocked()) {
276         ALOGI("Unregistered all clients and exiting");
277         exit(EXIT_SUCCESS);
278     }
279 
280     reRegisterLocked();
281 }
282 
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)283 void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
284                                                           activeServicesCallback) {
285     std::lock_guard<std::mutex> lock(mMutex);
286     mActiveServicesCallback = activeServicesCallback;
287 }
288 
ClientCounterCallback()289 ClientCounterCallback::ClientCounterCallback() {
290       mImpl = sp<ClientCounterCallbackImpl>::make();
291 }
292 
registerService(const sp<IBinder> & service,const std::string & name,bool allowIsolated,int dumpFlags)293 bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
294                                             bool allowIsolated, int dumpFlags) {
295     return mImpl->registerService(service, name, allowIsolated, dumpFlags);
296 }
297 
forcePersist(bool persist)298 void ClientCounterCallback::forcePersist(bool persist) {
299     mImpl->forcePersist(persist);
300 }
301 
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)302 void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
303                                                       activeServicesCallback) {
304     mImpl->setActiveServicesCallback(activeServicesCallback);
305 }
306 
tryUnregister()307 bool ClientCounterCallback::tryUnregister() {
308     // see comments in header, this should only be called from the active
309     // services callback, see also b/191781736
310     return mImpl->tryUnregisterLocked();
311 }
312 
reRegister()313 void ClientCounterCallback::reRegister() {
314     // see comments in header, this should only be called from the active
315     // services callback, see also b/191781736
316     mImpl->reRegisterLocked();
317 }
318 
319 }  // namespace internal
320 
LazyServiceRegistrar()321 LazyServiceRegistrar::LazyServiceRegistrar() {
322     mClientCC = std::make_shared<internal::ClientCounterCallback>();
323 }
324 
getInstance()325 LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
326     static auto registrarInstance = new LazyServiceRegistrar();
327     return *registrarInstance;
328 }
329 
createExtraTestInstance()330 LazyServiceRegistrar LazyServiceRegistrar::createExtraTestInstance() {
331     return LazyServiceRegistrar();
332 }
333 
registerService(const sp<IBinder> & service,const std::string & name,bool allowIsolated,int dumpFlags)334 status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
335                                                bool allowIsolated, int dumpFlags) {
336     if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
337         return UNKNOWN_ERROR;
338     }
339     return OK;
340 }
341 
forcePersist(bool persist)342 void LazyServiceRegistrar::forcePersist(bool persist) {
343     mClientCC->forcePersist(persist);
344 }
345 
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)346 void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>&
347                                                      activeServicesCallback) {
348     mClientCC->setActiveServicesCallback(activeServicesCallback);
349 }
350 
tryUnregister()351 bool LazyServiceRegistrar::tryUnregister() {
352     return mClientCC->tryUnregister();
353 }
354 
reRegister()355 void LazyServiceRegistrar::reRegister() {
356     mClientCC->reRegister();
357 }
358 
359 }  // namespace hardware
360 }  // namespace android
361