blob: ff1fbec4b210134d5d07ad88b75e70a430017169 [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 Bianchie672b872021-01-05 14:03:45 -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
33class ClientCounterCallback : public ::android::os::BnClientCallback {
34public:
Jon Spivack620d2dc2020-03-06 13:58:01 -080035 ClientCounterCallback() : 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);
39
Jon Spivack620d2dc2020-03-06 13:58:01 -080040 /**
41 * Set a flag to prevent services from automatically shutting down
42 */
43 void forcePersist(bool persist);
44
Amos Bianchie672b872021-01-05 14:03:45 -080045 void setActiveServicesCountCallback(const std::function<bool(int)>&
46 activeServicesCountCallback);
47
48 bool tryUnregister();
49
50 void reRegister();
51
Jon Spivack9f503a42019-10-22 16:49:19 -070052protected:
53 Status onClients(const sp<IBinder>& service, bool clients) override;
54
55private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070056 struct Service {
57 sp<IBinder> service;
58 bool allowIsolated;
59 int dumpFlags;
60
61 // whether, based on onClients calls, we know we have a client for this
62 // service or not
63 bool clients = false;
Amos Bianchie672b872021-01-05 14:03:45 -080064 bool registered = true;
Steven Morelanddd20e7c2020-04-10 11:51:14 -070065 };
66
67 /**
68 * Looks up a service guaranteed to be registered (service from onClients).
69 */
70 std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
71
Jon Spivack9f503a42019-10-22 16:49:19 -070072 /**
73 * Unregisters all services that we can. If we can't unregister all, re-register other
74 * services.
75 */
76 void tryShutdown();
77
Amos Bianchie672b872021-01-05 14:03:45 -080078 /**
79 * Try to shutdown the process, unless:
80 * - 'forcePersist' is 'true', or
81 * - The active services count callback returns 'true', or
82 * - Some services have clients.
83 */
84 void maybeTryShutdown();
85
Steven Morelanddd20e7c2020-04-10 11:51:14 -070086 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070087 size_t mNumConnectedServices;
88
Steven Morelanddd20e7c2020-04-10 11:51:14 -070089 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000090 std::map<std::string, Service> mRegisteredServices;
Jon Spivack620d2dc2020-03-06 13:58:01 -080091
92 bool mForcePersist;
Amos Bianchie672b872021-01-05 14:03:45 -080093
94 // Callback used to report the number of services with clients
95 std::function<bool(int)> mActiveServicesCountCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -070096};
97
98bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
99 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -0800100 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700101
Jon Spivackd9533c22020-01-27 22:19:22 +0000102 bool reRegister = mRegisteredServices.count(name) > 0;
103 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
104 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700105
106 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
107 ALOGE("Failed to register service %s", name.c_str());
108 return false;
109 }
110
Jon Spivackd9533c22020-01-27 22:19:22 +0000111 if (!reRegister) {
Steven Moreland1e2ba922020-04-10 15:25:01 -0700112 if (!manager->registerClientCallback(name, service, this).isOk()) {
113 ALOGE("Failed to add client callback for service %s", name.c_str());
114 return false;
115 }
116
Jon Spivackd9533c22020-01-27 22:19:22 +0000117 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700118 mRegisteredServices[name] = {
119 .service = service,
120 .allowIsolated = allowIsolated,
121 .dumpFlags = dumpFlags
122 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000123 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700124
125 return true;
126}
127
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700128std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) {
129 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
130 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
131 auto const& [name, registered] = *it;
132 (void) name;
133 if (registered.service != service) continue;
134 return it;
135 }
136 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
137 __builtin_unreachable();
138}
139
Jon Spivack620d2dc2020-03-06 13:58:01 -0800140void ClientCounterCallback::forcePersist(bool persist) {
141 mForcePersist = persist;
Amos Bianchie672b872021-01-05 14:03:45 -0800142 if (!mForcePersist && mNumConnectedServices == 0) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800143 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Amos Bianchie672b872021-01-05 14:03:45 -0800144 maybeTryShutdown();
145 }
146}
147
148bool ClientCounterCallback::tryUnregister() {
149 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
150
151 for (auto& [name, entry] : mRegisteredServices) {
152 bool success = manager->tryUnregisterService(name, entry.service).isOk();
153
154 if (!success) {
155 ALOGI("Failed to unregister service %s", name.c_str());
156 return false;
157 }
158 entry.registered = false;
159 }
160
161 return true;
162}
163
164void ClientCounterCallback::reRegister() {
165 for (auto& [name, entry] : mRegisteredServices) {
166 // re-register entry if not already registered
167 if (entry.registered) {
168 continue;
169 }
170
171 if (!registerService(entry.service, name, entry.allowIsolated,
172 entry.dumpFlags)) {
173 // Must restart. Otherwise, clients will never be able to get a hold of this service.
174 LOG_ALWAYS_FATAL("Bad state: could not re-register services");
175 }
176
177 entry.registered = true;
178 }
179}
180
181void ClientCounterCallback::maybeTryShutdown() {
182 if (mForcePersist) {
183 ALOGI("Shutdown prevented by forcePersist override flag.");
184 return;
185 }
186
187 bool handledInCallback = false;
188 if (mActiveServicesCountCallback != nullptr) {
189 handledInCallback = mActiveServicesCountCallback(mNumConnectedServices);
190 }
191
192 // If there is no callback defined or the callback did not handle this
193 // client count change event, try to shutdown the process if its services
194 // have no clients.
195 if (!handledInCallback && mNumConnectedServices == 0) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800196 tryShutdown();
197 }
198}
199
Jon Spivack9f503a42019-10-22 16:49:19 -0700200/**
201 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
202 * invocations could occur on different threads however.
203 */
204Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700205 auto & [name, registered] = *assertRegisteredService(service);
206 if (registered.clients == clients) {
207 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
208 "notified has clients: %d", name.c_str(), registered.clients, clients);
209 }
210 registered.clients = clients;
211
212 // update cache count of clients
213 {
214 size_t numWithClients = 0;
215 for (const auto& [name, registered] : mRegisteredServices) {
216 (void) name;
217 if (registered.clients) numWithClients++;
218 }
219 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700220 }
221
222 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700223 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700224
Amos Bianchie672b872021-01-05 14:03:45 -0800225 maybeTryShutdown();
226
Jon Spivack9f503a42019-10-22 16:49:19 -0700227 return Status::ok();
228}
229
230void ClientCounterCallback::tryShutdown() {
231 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
232
Amos Bianchie672b872021-01-05 14:03:45 -0800233 if (tryUnregister()) {
Jon Spivack9f503a42019-10-22 16:49:19 -0700234 ALOGI("Unregistered all clients and exiting");
235 exit(EXIT_SUCCESS);
236 }
237
Amos Bianchie672b872021-01-05 14:03:45 -0800238 reRegister();
239}
Jon Spivack9f503a42019-10-22 16:49:19 -0700240
Amos Bianchie672b872021-01-05 14:03:45 -0800241void ClientCounterCallback::setActiveServicesCountCallback(const std::function<bool(int)>&
242 activeServicesCountCallback) {
243 mActiveServicesCountCallback = activeServicesCountCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700244}
245
246} // namespace internal
247
248LazyServiceRegistrar::LazyServiceRegistrar() {
249 mClientCC = std::make_shared<internal::ClientCounterCallback>();
250}
251
252LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
253 static auto registrarInstance = new LazyServiceRegistrar();
254 return *registrarInstance;
255}
256
257status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
258 bool allowIsolated, int dumpFlags) {
259 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
260 return UNKNOWN_ERROR;
261 }
262 return OK;
263}
264
Jon Spivack620d2dc2020-03-06 13:58:01 -0800265void LazyServiceRegistrar::forcePersist(bool persist) {
266 mClientCC->forcePersist(persist);
267}
268
Amos Bianchie672b872021-01-05 14:03:45 -0800269void LazyServiceRegistrar::setActiveServicesCountCallback(const std::function<bool(int)>&
270 activeServicesCountCallback) {
271 mClientCC->setActiveServicesCountCallback(activeServicesCountCallback);
272}
273
274bool LazyServiceRegistrar::tryUnregister() {
275 return mClientCC->tryUnregister();
276}
277
278void LazyServiceRegistrar::reRegister() {
279 mClientCC->reRegister();
280}
281
Jon Spivack9f503a42019-10-22 16:49:19 -0700282} // namespace hardware
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700283} // namespace android