blob: 616591182adbb9be62b21b24d5afaa463ebdb39c [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
Amos Bianchi844e19b2020-12-23 09:57:02 -080017#include "log/log_main.h"
Jon Spivack9f503a42019-10-22 16:49:19 -070018#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
27namespace android {
28namespace binder {
29namespace internal {
30
31using AidlServiceManager = android::os::IServiceManager;
32
Jon Spivackdc6cb052020-10-27 19:29:14 -070033class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
Jon Spivack9f503a42019-10-22 16:49:19 -070034public:
Jon Spivackdc6cb052020-10-27 19:29:14 -070035 ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {}
Jon Spivack9f503a42019-10-22 16:49:19 -070036
37 bool registerService(const sp<IBinder>& service, const std::string& name,
38 bool allowIsolated, int dumpFlags);
Jon Spivacke17055a2020-03-06 13:58:01 -080039 void forcePersist(bool persist);
40
Amos Bianchi3f796942021-01-20 16:06:56 -080041 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -080042
43 bool tryUnregister();
44
45 void reRegister();
46
Jon Spivack9f503a42019-10-22 16:49:19 -070047protected:
48 Status onClients(const sp<IBinder>& service, bool clients) override;
49
50private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070051 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;
Xin Lica3e5792021-02-21 09:43:11 -080059 bool registered = true;
Steven Morelanddd20e7c2020-04-10 11:51:14 -070060 };
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
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 */
71 void tryShutdown();
72
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 */
79 void maybeTryShutdown();
80
Steven Morelanddd20e7c2020-04-10 11:51:14 -070081 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070082 size_t mNumConnectedServices;
83
Amos Bianchi3f796942021-01-20 16:06:56 -080084 // previous value passed to the active services callback
85 std::optional<bool> mPreviousHasClients;
86
Steven Morelanddd20e7c2020-04-10 11:51:14 -070087 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000088 std::map<std::string, Service> mRegisteredServices;
Jon Spivacke17055a2020-03-06 13:58:01 -080089
90 bool mForcePersist;
Amos Bianchi844e19b2020-12-23 09:57:02 -080091
Amos Bianchi3f796942021-01-20 16:06:56 -080092 // Callback used to report if there are services with clients
93 std::function<bool(bool)> mActiveServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -070094};
95
Jon Spivackdc6cb052020-10-27 19:29:14 -070096class ClientCounterCallback {
97public:
98 ClientCounterCallback();
99
100 bool registerService(const sp<IBinder>& service, const std::string& name,
101 bool allowIsolated, int dumpFlags);
102
103 /**
104 * Set a flag to prevent services from automatically shutting down
105 */
106 void forcePersist(bool persist);
107
Amos Bianchi3f796942021-01-20 16:06:56 -0800108 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800109
110 bool tryUnregister();
111
112 void reRegister();
113
Jon Spivackdc6cb052020-10-27 19:29:14 -0700114private:
115 sp<ClientCounterCallbackImpl> mImpl;
116};
117
118bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
Jon Spivack9f503a42019-10-22 16:49:19 -0700119 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -0800120 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700121
Jon Spivackd9533c22020-01-27 22:19:22 +0000122 bool reRegister = mRegisteredServices.count(name) > 0;
123 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
124 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700125
Steven Moreland48c73e02021-05-10 18:31:34 +0000126 if (Status status = manager->addService(name.c_str(), service, allowIsolated, dumpFlags);
127 !status.isOk()) {
128 ALOGE("Failed to register service %s (%s)", name.c_str(), status.toString8().c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700129 return false;
130 }
131
Jon Spivackd9533c22020-01-27 22:19:22 +0000132 if (!reRegister) {
Steven Moreland48c73e02021-05-10 18:31:34 +0000133 if (Status status =
134 manager->registerClientCallback(name, service,
135 sp<android::os::IClientCallback>::fromExisting(
136 this));
137 !status.isOk()) {
138 ALOGE("Failed to add client callback for service %s (%s)", name.c_str(),
139 status.toString8().c_str());
Steven Moreland60774252020-04-10 15:25:01 -0700140 return false;
141 }
142
Jon Spivackd9533c22020-01-27 22:19:22 +0000143 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700144 mRegisteredServices[name] = {
145 .service = service,
146 .allowIsolated = allowIsolated,
147 .dumpFlags = dumpFlags
148 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000149 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700150
151 return true;
152}
153
Jon Spivack143a10d2020-10-27 19:29:14 -0700154std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700155 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
156 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
157 auto const& [name, registered] = *it;
158 (void) name;
159 if (registered.service != service) continue;
160 return it;
161 }
162 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
163 __builtin_unreachable();
164}
165
Jon Spivackdc6cb052020-10-27 19:29:14 -0700166void ClientCounterCallbackImpl::forcePersist(bool persist) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800167 mForcePersist = persist;
Amos Bianchi3f796942021-01-20 16:06:56 -0800168 if (!mForcePersist) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800169 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Amos Bianchi844e19b2020-12-23 09:57:02 -0800170 maybeTryShutdown();
171 }
172}
173
174bool ClientCounterCallbackImpl::tryUnregister() {
175 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
176
177 for (auto& [name, entry] : mRegisteredServices) {
Steven Moreland48c73e02021-05-10 18:31:34 +0000178 Status status = manager->tryUnregisterService(name, entry.service);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800179
Steven Moreland48c73e02021-05-10 18:31:34 +0000180 if (!status.isOk()) {
181 ALOGI("Failed to unregister service %s (%s)", name.c_str(), status.toString8().c_str());
Amos Bianchi844e19b2020-12-23 09:57:02 -0800182 return false;
183 }
184 entry.registered = false;
185 }
186
187 return true;
188}
189
190void ClientCounterCallbackImpl::reRegister() {
191 for (auto& [name, entry] : mRegisteredServices) {
192 // re-register entry if not already registered
193 if (entry.registered) {
194 continue;
195 }
196
197 if (!registerService(entry.service, name, entry.allowIsolated,
198 entry.dumpFlags)) {
199 // Must restart. Otherwise, clients will never be able to get a hold of this service.
200 LOG_ALWAYS_FATAL("Bad state: could not re-register services");
201 }
202
203 entry.registered = true;
204 }
205}
206
207void ClientCounterCallbackImpl::maybeTryShutdown() {
208 if (mForcePersist) {
209 ALOGI("Shutdown prevented by forcePersist override flag.");
210 return;
211 }
212
213 bool handledInCallback = false;
Amos Bianchi3f796942021-01-20 16:06:56 -0800214 if (mActiveServicesCallback != nullptr) {
215 bool hasClients = mNumConnectedServices != 0;
216 if (hasClients != mPreviousHasClients) {
217 handledInCallback = mActiveServicesCallback(hasClients);
218 mPreviousHasClients = hasClients;
219 }
Amos Bianchi844e19b2020-12-23 09:57:02 -0800220 }
221
222 // If there is no callback defined or the callback did not handle this
223 // client count change event, try to shutdown the process if its services
224 // have no clients.
225 if (!handledInCallback && mNumConnectedServices == 0) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800226 tryShutdown();
227 }
228}
229
Jon Spivack9f503a42019-10-22 16:49:19 -0700230/**
231 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
232 * invocations could occur on different threads however.
233 */
Jon Spivackdc6cb052020-10-27 19:29:14 -0700234Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700235 auto & [name, registered] = *assertRegisteredService(service);
236 if (registered.clients == clients) {
237 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
238 "notified has clients: %d", name.c_str(), registered.clients, clients);
239 }
240 registered.clients = clients;
241
242 // update cache count of clients
243 {
244 size_t numWithClients = 0;
245 for (const auto& [name, registered] : mRegisteredServices) {
246 (void) name;
247 if (registered.clients) numWithClients++;
248 }
249 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700250 }
251
252 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700253 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700254
Amos Bianchi844e19b2020-12-23 09:57:02 -0800255 maybeTryShutdown();
Jon Spivack9f503a42019-10-22 16:49:19 -0700256 return Status::ok();
257}
258
Amos Bianchi844e19b2020-12-23 09:57:02 -0800259 void ClientCounterCallbackImpl::tryShutdown() {
260 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
Jon Spivacke17055a2020-03-06 13:58:01 -0800261
Amos Bianchi844e19b2020-12-23 09:57:02 -0800262 if (tryUnregister()) {
263 ALOGI("Unregistered all clients and exiting");
264 exit(EXIT_SUCCESS);
265 }
Jon Spivacke17055a2020-03-06 13:58:01 -0800266
Amos Bianchi844e19b2020-12-23 09:57:02 -0800267 reRegister();
268}
Jon Spivack9f503a42019-10-22 16:49:19 -0700269
Amos Bianchi3f796942021-01-20 16:06:56 -0800270void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
271 activeServicesCallback) {
272 mActiveServicesCallback = activeServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700273}
274
Jon Spivackdc6cb052020-10-27 19:29:14 -0700275ClientCounterCallback::ClientCounterCallback() {
Jon Spivack143a10d2020-10-27 19:29:14 -0700276 mImpl = sp<ClientCounterCallbackImpl>::make();
Jon Spivackdc6cb052020-10-27 19:29:14 -0700277}
278
279bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
280 bool allowIsolated, int dumpFlags) {
281 return mImpl->registerService(service, name, allowIsolated, dumpFlags);
282}
283
284void ClientCounterCallback::forcePersist(bool persist) {
285 mImpl->forcePersist(persist);
286}
287
Amos Bianchi3f796942021-01-20 16:06:56 -0800288void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
289 activeServicesCallback) {
290 mImpl->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800291}
292
293bool ClientCounterCallback::tryUnregister() {
294 return mImpl->tryUnregister();
295}
296
297void ClientCounterCallback::reRegister() {
298 mImpl->reRegister();
299}
300
Jon Spivack9f503a42019-10-22 16:49:19 -0700301} // namespace internal
302
303LazyServiceRegistrar::LazyServiceRegistrar() {
304 mClientCC = std::make_shared<internal::ClientCounterCallback>();
305}
306
307LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
308 static auto registrarInstance = new LazyServiceRegistrar();
309 return *registrarInstance;
310}
311
312status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
313 bool allowIsolated, int dumpFlags) {
314 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
315 return UNKNOWN_ERROR;
316 }
317 return OK;
318}
319
Jon Spivacke17055a2020-03-06 13:58:01 -0800320void LazyServiceRegistrar::forcePersist(bool persist) {
321 mClientCC->forcePersist(persist);
322}
323
Amos Bianchi3f796942021-01-20 16:06:56 -0800324void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>&
325 activeServicesCallback) {
326 mClientCC->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800327}
328
329bool LazyServiceRegistrar::tryUnregister() {
330 return mClientCC->tryUnregister();
331}
332
333void LazyServiceRegistrar::reRegister() {
334 mClientCC->reRegister();
335}
336
Jon Spivack9f503a42019-10-22 16:49:19 -0700337} // namespace hardware
Amos Bianchi844e19b2020-12-23 09:57:02 -0800338} // namespace android