blob: 27cfe0cf2156ab71bc6cb6f4cc574a8dd40c2add [file] [log] [blame]
Jon Spivack9f503a42019-10-22 16:49:19 -07001/*
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
Jon Spivack9f503a42019-10-22 16:49:19 -070019#include <android/os/BnClientCallback.h>
20#include <android/os/IServiceManager.h>
Tomasz Wasilczykb70f4712024-06-21 11:58:54 -070021#include <binder/IPCThreadState.h>
Tomasz Wasilczykb70f4712024-06-21 11:58:54 -070022#include <binder/LazyServiceRegistrar.h>
Jon Spivack9f503a42019-10-22 16:49:19 -070023
24namespace android {
25namespace binder {
26namespace internal {
27
28using AidlServiceManager = android::os::IServiceManager;
29
Jon Spivackdc6cb052020-10-27 19:29:14 -070030class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
Jon Spivack9f503a42019-10-22 16:49:19 -070031public:
Jon Spivackdc6cb052020-10-27 19:29:14 -070032 ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {}
Jon Spivack9f503a42019-10-22 16:49:19 -070033
34 bool registerService(const sp<IBinder>& service, const std::string& name,
35 bool allowIsolated, int dumpFlags);
Jon Spivacke17055a2020-03-06 13:58:01 -080036 void forcePersist(bool persist);
37
Amos Bianchi3f796942021-01-20 16:06:56 -080038 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -080039
Steven Moreland7a5889c2021-06-22 19:18:28 +000040 bool tryUnregisterLocked();
Amos Bianchi844e19b2020-12-23 09:57:02 -080041
Steven Moreland7a5889c2021-06-22 19:18:28 +000042 void reRegisterLocked();
Amos Bianchi844e19b2020-12-23 09:57:02 -080043
Jon Spivack9f503a42019-10-22 16:49:19 -070044protected:
45 Status onClients(const sp<IBinder>& service, bool clients) override;
46
47private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070048 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;
Xin Lica3e5792021-02-21 09:43:11 -080056 bool registered = true;
Steven Morelanddd20e7c2020-04-10 11:51:14 -070057 };
58
Steven Moreland7a5889c2021-06-22 19:18:28 +000059 bool registerServiceLocked(const sp<IBinder>& service, const std::string& name,
60 bool allowIsolated, int dumpFlags);
61
Steven Morelanddd20e7c2020-04-10 11:51:14 -070062 /**
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
Jon Spivack9f503a42019-10-22 16:49:19 -070067 /**
68 * Unregisters all services that we can. If we can't unregister all, re-register other
69 * services.
70 */
Steven Moreland7a5889c2021-06-22 19:18:28 +000071 void tryShutdownLocked();
Jon Spivack9f503a42019-10-22 16:49:19 -070072
73 /**
Amos Bianchi844e19b2020-12-23 09:57:02 -080074 * 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 */
Steven Moreland7a5889c2021-06-22 19:18:28 +000079 void maybeTryShutdownLocked();
80
81 // for below
82 std::mutex mMutex;
Amos Bianchi844e19b2020-12-23 09:57:02 -080083
Steven Morelanddd20e7c2020-04-10 11:51:14 -070084 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070085 size_t mNumConnectedServices;
86
Amos Bianchi3f796942021-01-20 16:06:56 -080087 // previous value passed to the active services callback
88 std::optional<bool> mPreviousHasClients;
89
Steven Morelanddd20e7c2020-04-10 11:51:14 -070090 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000091 std::map<std::string, Service> mRegisteredServices;
Jon Spivacke17055a2020-03-06 13:58:01 -080092
93 bool mForcePersist;
Amos Bianchi844e19b2020-12-23 09:57:02 -080094
Amos Bianchi3f796942021-01-20 16:06:56 -080095 // Callback used to report if there are services with clients
96 std::function<bool(bool)> mActiveServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -070097};
98
Jon Spivackdc6cb052020-10-27 19:29:14 -070099class ClientCounterCallback {
100public:
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
Amos Bianchi3f796942021-01-20 16:06:56 -0800111 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800112
113 bool tryUnregister();
114
115 void reRegister();
116
Jon Spivackdc6cb052020-10-27 19:29:14 -0700117private:
118 sp<ClientCounterCallbackImpl> mImpl;
119};
120
121bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
Jon Spivack9f503a42019-10-22 16:49:19 -0700122 bool allowIsolated, int dumpFlags) {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000123 std::lock_guard<std::mutex> lock(mMutex);
124 return registerServiceLocked(service, name, allowIsolated, dumpFlags);
125}
126
127bool ClientCounterCallbackImpl::registerServiceLocked(const sp<IBinder>& service,
128 const std::string& name, bool allowIsolated,
129 int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -0800130 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700131
Jon Spivackd9533c22020-01-27 22:19:22 +0000132 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());
Jon Spivack9f503a42019-10-22 16:49:19 -0700135
Parth Sane5e1b7e12024-11-29 10:40:41 +0000136 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
Steven Moreland48c73e02021-05-10 18:31:34 +0000142 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());
Jon Spivack9f503a42019-10-22 16:49:19 -0700145 return false;
146 }
147
Jon Spivackd9533c22020-01-27 22:19:22 +0000148 if (!reRegister) {
Steven Moreland48c73e02021-05-10 18:31:34 +0000149 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());
Steven Moreland60774252020-04-10 15:25:01 -0700156 return false;
157 }
158
Jon Spivackd9533c22020-01-27 22:19:22 +0000159 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700160 mRegisteredServices[name] = {
161 .service = service,
162 .allowIsolated = allowIsolated,
163 .dumpFlags = dumpFlags
164 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000165 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700166
167 return true;
168}
169
Jon Spivack143a10d2020-10-27 19:29:14 -0700170std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700171 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
Jon Spivackdc6cb052020-10-27 19:29:14 -0700182void ClientCounterCallbackImpl::forcePersist(bool persist) {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000183 std::lock_guard<std::mutex> lock(mMutex);
Jon Spivacke17055a2020-03-06 13:58:01 -0800184 mForcePersist = persist;
Amos Bianchi3f796942021-01-20 16:06:56 -0800185 if (!mForcePersist) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800186 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Steven Moreland7a5889c2021-06-22 19:18:28 +0000187 maybeTryShutdownLocked();
Amos Bianchi844e19b2020-12-23 09:57:02 -0800188 }
189}
190
Steven Moreland7a5889c2021-06-22 19:18:28 +0000191bool ClientCounterCallbackImpl::tryUnregisterLocked() {
Amos Bianchi844e19b2020-12-23 09:57:02 -0800192 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
193
194 for (auto& [name, entry] : mRegisteredServices) {
Steven Moreland48c73e02021-05-10 18:31:34 +0000195 Status status = manager->tryUnregisterService(name, entry.service);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800196
Steven Moreland48c73e02021-05-10 18:31:34 +0000197 if (!status.isOk()) {
198 ALOGI("Failed to unregister service %s (%s)", name.c_str(), status.toString8().c_str());
Amos Bianchi844e19b2020-12-23 09:57:02 -0800199 return false;
200 }
201 entry.registered = false;
202 }
203
204 return true;
205}
206
Steven Moreland7a5889c2021-06-22 19:18:28 +0000207void ClientCounterCallbackImpl::reRegisterLocked() {
Amos Bianchi844e19b2020-12-23 09:57:02 -0800208 for (auto& [name, entry] : mRegisteredServices) {
209 // re-register entry if not already registered
210 if (entry.registered) {
211 continue;
212 }
213
Steven Moreland7a5889c2021-06-22 19:18:28 +0000214 if (!registerServiceLocked(entry.service, name, entry.allowIsolated, entry.dumpFlags)) {
Amos Bianchi844e19b2020-12-23 09:57:02 -0800215 // 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
Steven Moreland7a5889c2021-06-22 19:18:28 +0000223void ClientCounterCallbackImpl::maybeTryShutdownLocked() {
Amos Bianchi844e19b2020-12-23 09:57:02 -0800224 if (mForcePersist) {
225 ALOGI("Shutdown prevented by forcePersist override flag.");
226 return;
227 }
228
229 bool handledInCallback = false;
Amos Bianchi3f796942021-01-20 16:06:56 -0800230 if (mActiveServicesCallback != nullptr) {
231 bool hasClients = mNumConnectedServices != 0;
232 if (hasClients != mPreviousHasClients) {
233 handledInCallback = mActiveServicesCallback(hasClients);
234 mPreviousHasClients = hasClients;
235 }
Amos Bianchi844e19b2020-12-23 09:57:02 -0800236 }
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) {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000242 tryShutdownLocked();
Jon Spivacke17055a2020-03-06 13:58:01 -0800243 }
244}
245
Jon Spivackdc6cb052020-10-27 19:29:14 -0700246Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000247 std::lock_guard<std::mutex> lock(mMutex);
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700248 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;
Jon Spivack9f503a42019-10-22 16:49:19 -0700263 }
264
265 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700266 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700267
Steven Moreland7a5889c2021-06-22 19:18:28 +0000268 maybeTryShutdownLocked();
Jon Spivack9f503a42019-10-22 16:49:19 -0700269 return Status::ok();
270}
271
Steven Moreland7a5889c2021-06-22 19:18:28 +0000272void ClientCounterCallbackImpl::tryShutdownLocked() {
273 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
Jon Spivacke17055a2020-03-06 13:58:01 -0800274
Steven Moreland7a5889c2021-06-22 19:18:28 +0000275 if (tryUnregisterLocked()) {
276 ALOGI("Unregistered all clients and exiting");
277 exit(EXIT_SUCCESS);
278 }
Jon Spivacke17055a2020-03-06 13:58:01 -0800279
Steven Moreland7a5889c2021-06-22 19:18:28 +0000280 reRegisterLocked();
Amos Bianchi844e19b2020-12-23 09:57:02 -0800281}
Jon Spivack9f503a42019-10-22 16:49:19 -0700282
Amos Bianchi3f796942021-01-20 16:06:56 -0800283void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
284 activeServicesCallback) {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000285 std::lock_guard<std::mutex> lock(mMutex);
Amos Bianchi3f796942021-01-20 16:06:56 -0800286 mActiveServicesCallback = activeServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700287}
288
Jon Spivackdc6cb052020-10-27 19:29:14 -0700289ClientCounterCallback::ClientCounterCallback() {
Jon Spivack143a10d2020-10-27 19:29:14 -0700290 mImpl = sp<ClientCounterCallbackImpl>::make();
Jon Spivackdc6cb052020-10-27 19:29:14 -0700291}
292
293bool 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
298void ClientCounterCallback::forcePersist(bool persist) {
299 mImpl->forcePersist(persist);
300}
301
Amos Bianchi3f796942021-01-20 16:06:56 -0800302void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
303 activeServicesCallback) {
304 mImpl->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800305}
306
307bool ClientCounterCallback::tryUnregister() {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000308 // see comments in header, this should only be called from the active
309 // services callback, see also b/191781736
310 return mImpl->tryUnregisterLocked();
Amos Bianchi844e19b2020-12-23 09:57:02 -0800311}
312
313void ClientCounterCallback::reRegister() {
Steven Moreland7a5889c2021-06-22 19:18:28 +0000314 // see comments in header, this should only be called from the active
315 // services callback, see also b/191781736
316 mImpl->reRegisterLocked();
Amos Bianchi844e19b2020-12-23 09:57:02 -0800317}
318
Jon Spivack9f503a42019-10-22 16:49:19 -0700319} // namespace internal
320
321LazyServiceRegistrar::LazyServiceRegistrar() {
322 mClientCC = std::make_shared<internal::ClientCounterCallback>();
323}
324
325LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
326 static auto registrarInstance = new LazyServiceRegistrar();
327 return *registrarInstance;
328}
329
Steven Moreland9c864602023-04-13 20:29:33 +0000330LazyServiceRegistrar LazyServiceRegistrar::createExtraTestInstance() {
331 return LazyServiceRegistrar();
332}
333
Jon Spivack9f503a42019-10-22 16:49:19 -0700334status_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
Jon Spivacke17055a2020-03-06 13:58:01 -0800342void LazyServiceRegistrar::forcePersist(bool persist) {
343 mClientCC->forcePersist(persist);
344}
345
Amos Bianchi3f796942021-01-20 16:06:56 -0800346void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>&
347 activeServicesCallback) {
348 mClientCC->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800349}
350
351bool LazyServiceRegistrar::tryUnregister() {
352 return mClientCC->tryUnregister();
353}
354
355void LazyServiceRegistrar::reRegister() {
356 mClientCC->reRegister();
357}
358
Jon Spivack9f503a42019-10-22 16:49:19 -0700359} // namespace hardware
Amos Bianchi844e19b2020-12-23 09:57:02 -0800360} // namespace android