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