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