blob: b503bebc5eee15b31e1acffee94e7a7e08ebc379 [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
126 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
127 ALOGE("Failed to register service %s", name.c_str());
128 return false;
129 }
130
Jon Spivackd9533c22020-01-27 22:19:22 +0000131 if (!reRegister) {
Steven Moreland1a3a8ef2021-04-02 02:52:46 +0000132 if (!manager->registerClientCallback(name, service,
133 sp<android::os::IClientCallback>::fromExisting(this))
134 .isOk()) {
Steven Moreland60774252020-04-10 15:25:01 -0700135 ALOGE("Failed to add client callback for service %s", name.c_str());
136 return false;
137 }
138
Jon Spivackd9533c22020-01-27 22:19:22 +0000139 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700140 mRegisteredServices[name] = {
141 .service = service,
142 .allowIsolated = allowIsolated,
143 .dumpFlags = dumpFlags
144 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000145 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700146
147 return true;
148}
149
Jon Spivack143a10d2020-10-27 19:29:14 -0700150std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700151 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
152 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
153 auto const& [name, registered] = *it;
154 (void) name;
155 if (registered.service != service) continue;
156 return it;
157 }
158 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
159 __builtin_unreachable();
160}
161
Jon Spivackdc6cb052020-10-27 19:29:14 -0700162void ClientCounterCallbackImpl::forcePersist(bool persist) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800163 mForcePersist = persist;
Amos Bianchi3f796942021-01-20 16:06:56 -0800164 if (!mForcePersist) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800165 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Amos Bianchi844e19b2020-12-23 09:57:02 -0800166 maybeTryShutdown();
167 }
168}
169
170bool ClientCounterCallbackImpl::tryUnregister() {
171 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
172
173 for (auto& [name, entry] : mRegisteredServices) {
174 bool success = manager->tryUnregisterService(name, entry.service).isOk();
175
176 if (!success) {
177 ALOGI("Failed to unregister service %s", name.c_str());
178 return false;
179 }
180 entry.registered = false;
181 }
182
183 return true;
184}
185
186void ClientCounterCallbackImpl::reRegister() {
187 for (auto& [name, entry] : mRegisteredServices) {
188 // re-register entry if not already registered
189 if (entry.registered) {
190 continue;
191 }
192
193 if (!registerService(entry.service, name, entry.allowIsolated,
194 entry.dumpFlags)) {
195 // Must restart. Otherwise, clients will never be able to get a hold of this service.
196 LOG_ALWAYS_FATAL("Bad state: could not re-register services");
197 }
198
199 entry.registered = true;
200 }
201}
202
203void ClientCounterCallbackImpl::maybeTryShutdown() {
204 if (mForcePersist) {
205 ALOGI("Shutdown prevented by forcePersist override flag.");
206 return;
207 }
208
209 bool handledInCallback = false;
Amos Bianchi3f796942021-01-20 16:06:56 -0800210 if (mActiveServicesCallback != nullptr) {
211 bool hasClients = mNumConnectedServices != 0;
212 if (hasClients != mPreviousHasClients) {
213 handledInCallback = mActiveServicesCallback(hasClients);
214 mPreviousHasClients = hasClients;
215 }
Amos Bianchi844e19b2020-12-23 09:57:02 -0800216 }
217
218 // If there is no callback defined or the callback did not handle this
219 // client count change event, try to shutdown the process if its services
220 // have no clients.
221 if (!handledInCallback && mNumConnectedServices == 0) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800222 tryShutdown();
223 }
224}
225
Jon Spivack9f503a42019-10-22 16:49:19 -0700226/**
227 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
228 * invocations could occur on different threads however.
229 */
Jon Spivackdc6cb052020-10-27 19:29:14 -0700230Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700231 auto & [name, registered] = *assertRegisteredService(service);
232 if (registered.clients == clients) {
233 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
234 "notified has clients: %d", name.c_str(), registered.clients, clients);
235 }
236 registered.clients = clients;
237
238 // update cache count of clients
239 {
240 size_t numWithClients = 0;
241 for (const auto& [name, registered] : mRegisteredServices) {
242 (void) name;
243 if (registered.clients) numWithClients++;
244 }
245 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700246 }
247
248 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700249 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700250
Amos Bianchi844e19b2020-12-23 09:57:02 -0800251 maybeTryShutdown();
Jon Spivack9f503a42019-10-22 16:49:19 -0700252 return Status::ok();
253}
254
Amos Bianchi844e19b2020-12-23 09:57:02 -0800255 void ClientCounterCallbackImpl::tryShutdown() {
256 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
Jon Spivacke17055a2020-03-06 13:58:01 -0800257
Amos Bianchi844e19b2020-12-23 09:57:02 -0800258 if (tryUnregister()) {
259 ALOGI("Unregistered all clients and exiting");
260 exit(EXIT_SUCCESS);
261 }
Jon Spivacke17055a2020-03-06 13:58:01 -0800262
Amos Bianchi844e19b2020-12-23 09:57:02 -0800263 reRegister();
264}
Jon Spivack9f503a42019-10-22 16:49:19 -0700265
Amos Bianchi3f796942021-01-20 16:06:56 -0800266void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
267 activeServicesCallback) {
268 mActiveServicesCallback = activeServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700269}
270
Jon Spivackdc6cb052020-10-27 19:29:14 -0700271ClientCounterCallback::ClientCounterCallback() {
Jon Spivack143a10d2020-10-27 19:29:14 -0700272 mImpl = sp<ClientCounterCallbackImpl>::make();
Jon Spivackdc6cb052020-10-27 19:29:14 -0700273}
274
275bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
276 bool allowIsolated, int dumpFlags) {
277 return mImpl->registerService(service, name, allowIsolated, dumpFlags);
278}
279
280void ClientCounterCallback::forcePersist(bool persist) {
281 mImpl->forcePersist(persist);
282}
283
Amos Bianchi3f796942021-01-20 16:06:56 -0800284void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
285 activeServicesCallback) {
286 mImpl->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800287}
288
289bool ClientCounterCallback::tryUnregister() {
290 return mImpl->tryUnregister();
291}
292
293void ClientCounterCallback::reRegister() {
294 mImpl->reRegister();
295}
296
Jon Spivack9f503a42019-10-22 16:49:19 -0700297} // namespace internal
298
299LazyServiceRegistrar::LazyServiceRegistrar() {
300 mClientCC = std::make_shared<internal::ClientCounterCallback>();
301}
302
303LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
304 static auto registrarInstance = new LazyServiceRegistrar();
305 return *registrarInstance;
306}
307
308status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
309 bool allowIsolated, int dumpFlags) {
310 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
311 return UNKNOWN_ERROR;
312 }
313 return OK;
314}
315
Jon Spivacke17055a2020-03-06 13:58:01 -0800316void LazyServiceRegistrar::forcePersist(bool persist) {
317 mClientCC->forcePersist(persist);
318}
319
Amos Bianchi3f796942021-01-20 16:06:56 -0800320void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>&
321 activeServicesCallback) {
322 mClientCC->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi844e19b2020-12-23 09:57:02 -0800323}
324
325bool LazyServiceRegistrar::tryUnregister() {
326 return mClientCC->tryUnregister();
327}
328
329void LazyServiceRegistrar::reRegister() {
330 mClientCC->reRegister();
331}
332
Jon Spivack9f503a42019-10-22 16:49:19 -0700333} // namespace hardware
Amos Bianchi844e19b2020-12-23 09:57:02 -0800334} // namespace android