blob: 1173138615c0846a5b016838918c58793ed16b97 [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 Bianchi2055e9b2020-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 Spivacke31d33a2020-10-27 19:29:14 -070033class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
Jon Spivack9f503a42019-10-22 16:49:19 -070034public:
Jon Spivacke31d33a2020-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 Spivack620d2dc2020-03-06 13:58:01 -080039 void forcePersist(bool persist);
40
Amos Bianchi2055e9b2020-12-23 09:57:02 -080041 void setActiveServicesCountCallback(const std::function<bool(int)>&
42 activeServicesCountCallback);
43
44 bool tryUnregister();
45
46 void reRegister();
47
Jon Spivack9f503a42019-10-22 16:49:19 -070048protected:
49 Status onClients(const sp<IBinder>& service, bool clients) override;
50
51private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070052 struct Service {
53 sp<IBinder> service;
54 bool allowIsolated;
55 int dumpFlags;
56
57 // whether, based on onClients calls, we know we have a client for this
58 // service or not
59 bool clients = false;
Amos Bianchi2055e9b2020-12-23 09:57:02 -080060 bool registered = true;
Steven Morelanddd20e7c2020-04-10 11:51:14 -070061 };
62
63 /**
64 * Looks up a service guaranteed to be registered (service from onClients).
65 */
66 std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
67
Jon Spivack9f503a42019-10-22 16:49:19 -070068 /**
69 * Unregisters all services that we can. If we can't unregister all, re-register other
70 * services.
71 */
72 void tryShutdown();
73
Amos Bianchi2055e9b2020-12-23 09:57:02 -080074 /**
75 * Try to shutdown the process, unless:
76 * - 'forcePersist' is 'true', or
77 * - The active services count callback returns 'true', or
78 * - Some services have clients.
79 */
80 void maybeTryShutdown();
81
Steven Morelanddd20e7c2020-04-10 11:51:14 -070082 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070083 size_t mNumConnectedServices;
84
Steven Morelanddd20e7c2020-04-10 11:51:14 -070085 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000086 std::map<std::string, Service> mRegisteredServices;
Jon Spivack620d2dc2020-03-06 13:58:01 -080087
88 bool mForcePersist;
Amos Bianchi2055e9b2020-12-23 09:57:02 -080089
90 // Callback used to report the number of services with clients
91 std::function<bool(int)> mActiveServicesCountCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -070092};
93
Jon Spivacke31d33a2020-10-27 19:29:14 -070094class ClientCounterCallback {
95public:
96 ClientCounterCallback();
97
98 bool registerService(const sp<IBinder>& service, const std::string& name,
99 bool allowIsolated, int dumpFlags);
100
101 /**
102 * Set a flag to prevent services from automatically shutting down
103 */
104 void forcePersist(bool persist);
105
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800106 void setActiveServicesCountCallback(const std::function<bool(int)>&
107 activeServicesCountCallback);
108
109 bool tryUnregister();
110
111 void reRegister();
112
Jon Spivacke31d33a2020-10-27 19:29:14 -0700113private:
114 sp<ClientCounterCallbackImpl> mImpl;
115};
116
117bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
Jon Spivack9f503a42019-10-22 16:49:19 -0700118 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -0800119 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700120
Jon Spivackd9533c22020-01-27 22:19:22 +0000121 bool reRegister = mRegisteredServices.count(name) > 0;
122 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
123 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700124
125 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
126 ALOGE("Failed to register service %s", name.c_str());
127 return false;
128 }
129
Jon Spivackd9533c22020-01-27 22:19:22 +0000130 if (!reRegister) {
Jon Spivacke31d33a2020-10-27 19:29:14 -0700131 if(!manager->registerClientCallback(name, service, this).isOk()) {
Steven Moreland1e2ba922020-04-10 15:25:01 -0700132 ALOGE("Failed to add client callback for service %s", name.c_str());
133 return false;
134 }
135
Jon Spivackd9533c22020-01-27 22:19:22 +0000136 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700137 mRegisteredServices[name] = {
138 .service = service,
139 .allowIsolated = allowIsolated,
140 .dumpFlags = dumpFlags
141 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000142 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700143
144 return true;
145}
146
Jon Spivacke31d33a2020-10-27 19:29:14 -0700147std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700148 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
149 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
150 auto const& [name, registered] = *it;
151 (void) name;
152 if (registered.service != service) continue;
153 return it;
154 }
155 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
156 __builtin_unreachable();
157}
158
Jon Spivacke31d33a2020-10-27 19:29:14 -0700159void ClientCounterCallbackImpl::forcePersist(bool persist) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800160 mForcePersist = persist;
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800161 if (!mForcePersist && mNumConnectedServices == 0) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800162 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800163 maybeTryShutdown();
164 }
165}
166
167bool ClientCounterCallbackImpl::tryUnregister() {
168 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
169
170 for (auto& [name, entry] : mRegisteredServices) {
171 bool success = manager->tryUnregisterService(name, entry.service).isOk();
172
173 if (!success) {
174 ALOGI("Failed to unregister service %s", name.c_str());
175 return false;
176 }
177 entry.registered = false;
178 }
179
180 return true;
181}
182
183void ClientCounterCallbackImpl::reRegister() {
184 for (auto& [name, entry] : mRegisteredServices) {
185 // re-register entry if not already registered
186 if (entry.registered) {
187 continue;
188 }
189
190 if (!registerService(entry.service, name, entry.allowIsolated,
191 entry.dumpFlags)) {
192 // Must restart. Otherwise, clients will never be able to get a hold of this service.
193 LOG_ALWAYS_FATAL("Bad state: could not re-register services");
194 }
195
196 entry.registered = true;
197 }
198}
199
200void ClientCounterCallbackImpl::maybeTryShutdown() {
201 if (mForcePersist) {
202 ALOGI("Shutdown prevented by forcePersist override flag.");
203 return;
204 }
205
206 bool handledInCallback = false;
207 if (mActiveServicesCountCallback != nullptr) {
208 handledInCallback = mActiveServicesCountCallback(mNumConnectedServices);
209 }
210
211 // If there is no callback defined or the callback did not handle this
212 // client count change event, try to shutdown the process if its services
213 // have no clients.
214 if (!handledInCallback && mNumConnectedServices == 0) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800215 tryShutdown();
216 }
217}
218
Jon Spivack9f503a42019-10-22 16:49:19 -0700219/**
220 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
221 * invocations could occur on different threads however.
222 */
Jon Spivacke31d33a2020-10-27 19:29:14 -0700223Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700224 auto & [name, registered] = *assertRegisteredService(service);
225 if (registered.clients == clients) {
226 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
227 "notified has clients: %d", name.c_str(), registered.clients, clients);
228 }
229 registered.clients = clients;
230
231 // update cache count of clients
232 {
233 size_t numWithClients = 0;
234 for (const auto& [name, registered] : mRegisteredServices) {
235 (void) name;
236 if (registered.clients) numWithClients++;
237 }
238 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700239 }
240
241 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700242 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700243
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800244 maybeTryShutdown();
Jon Spivack9f503a42019-10-22 16:49:19 -0700245 return Status::ok();
246}
247
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800248 void ClientCounterCallbackImpl::tryShutdown() {
249 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
Jon Spivack620d2dc2020-03-06 13:58:01 -0800250
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800251 if (tryUnregister()) {
252 ALOGI("Unregistered all clients and exiting");
253 exit(EXIT_SUCCESS);
254 }
Jon Spivack620d2dc2020-03-06 13:58:01 -0800255
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800256 reRegister();
257}
Jon Spivack9f503a42019-10-22 16:49:19 -0700258
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800259void ClientCounterCallbackImpl::setActiveServicesCountCallback(const std::function<bool(int)>&
260 activeServicesCountCallback) {
261 mActiveServicesCountCallback = activeServicesCountCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700262}
263
Jon Spivacke31d33a2020-10-27 19:29:14 -0700264ClientCounterCallback::ClientCounterCallback() {
265 mImpl = sp<ClientCounterCallbackImpl>::make();
266}
267
268bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
269 bool allowIsolated, int dumpFlags) {
270 return mImpl->registerService(service, name, allowIsolated, dumpFlags);
271}
272
273void ClientCounterCallback::forcePersist(bool persist) {
274 mImpl->forcePersist(persist);
275}
276
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800277void ClientCounterCallback::setActiveServicesCountCallback(const std::function<bool(int)>&
278 activeServicesCountCallback) {
279 mImpl->setActiveServicesCountCallback(activeServicesCountCallback);
280}
281
282bool ClientCounterCallback::tryUnregister() {
283 return mImpl->tryUnregister();
284}
285
286void ClientCounterCallback::reRegister() {
287 mImpl->reRegister();
288}
289
Jon Spivack9f503a42019-10-22 16:49:19 -0700290} // namespace internal
291
292LazyServiceRegistrar::LazyServiceRegistrar() {
293 mClientCC = std::make_shared<internal::ClientCounterCallback>();
294}
295
296LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
297 static auto registrarInstance = new LazyServiceRegistrar();
298 return *registrarInstance;
299}
300
301status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
302 bool allowIsolated, int dumpFlags) {
303 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
304 return UNKNOWN_ERROR;
305 }
306 return OK;
307}
308
Jon Spivack620d2dc2020-03-06 13:58:01 -0800309void LazyServiceRegistrar::forcePersist(bool persist) {
310 mClientCC->forcePersist(persist);
311}
312
Amos Bianchi2055e9b2020-12-23 09:57:02 -0800313void LazyServiceRegistrar::setActiveServicesCountCallback(const std::function<bool(int)>&
314 activeServicesCountCallback) {
315 mClientCC->setActiveServicesCountCallback(activeServicesCountCallback);
316}
317
318bool LazyServiceRegistrar::tryUnregister() {
319 return mClientCC->tryUnregister();
320}
321
322void LazyServiceRegistrar::reRegister() {
323 mClientCC->reRegister();
324}
325
Jon Spivack9f503a42019-10-22 16:49:19 -0700326} // namespace hardware
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700327} // namespace android