blob: 21a9251b79aa4807e8c3306e527d636188aecf90 [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 Bianchi7a6cef92021-01-21 17:48:17 -080045 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Amos Bianchie672b872021-01-05 14:03:45 -080046
47 bool tryUnregister();
48
49 void reRegister();
50
Jon Spivack9f503a42019-10-22 16:49:19 -070051protected:
52 Status onClients(const sp<IBinder>& service, bool clients) override;
53
54private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070055 struct Service {
56 sp<IBinder> service;
57 bool allowIsolated;
58 int dumpFlags;
59
60 // whether, based on onClients calls, we know we have a client for this
61 // service or not
62 bool clients = false;
Amos Bianchie672b872021-01-05 14:03:45 -080063 bool registered = true;
Steven Morelanddd20e7c2020-04-10 11:51:14 -070064 };
65
66 /**
67 * Looks up a service guaranteed to be registered (service from onClients).
68 */
69 std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
70
Jon Spivack9f503a42019-10-22 16:49:19 -070071 /**
72 * Unregisters all services that we can. If we can't unregister all, re-register other
73 * services.
74 */
75 void tryShutdown();
76
Amos Bianchie672b872021-01-05 14:03:45 -080077 /**
78 * Try to shutdown the process, unless:
79 * - 'forcePersist' is 'true', or
80 * - The active services count callback returns 'true', or
81 * - Some services have clients.
82 */
83 void maybeTryShutdown();
84
Steven Morelanddd20e7c2020-04-10 11:51:14 -070085 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070086 size_t mNumConnectedServices;
87
Amos Bianchi7a6cef92021-01-21 17:48:17 -080088 // previous value passed to the active services callback
89 std::optional<bool> mPreviousHasClients;
90
Steven Morelanddd20e7c2020-04-10 11:51:14 -070091 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000092 std::map<std::string, Service> mRegisteredServices;
Jon Spivack620d2dc2020-03-06 13:58:01 -080093
94 bool mForcePersist;
Amos Bianchie672b872021-01-05 14:03:45 -080095
Amos Bianchi7a6cef92021-01-21 17:48:17 -080096 // Callback used to report if there are services with clients
97 std::function<bool(bool)> mActiveServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -070098};
99
100bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
101 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -0800102 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700103
Jon Spivackd9533c22020-01-27 22:19:22 +0000104 bool reRegister = mRegisteredServices.count(name) > 0;
105 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
106 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700107
108 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
109 ALOGE("Failed to register service %s", name.c_str());
110 return false;
111 }
112
Jon Spivackd9533c22020-01-27 22:19:22 +0000113 if (!reRegister) {
Steven Moreland1e2ba922020-04-10 15:25:01 -0700114 if (!manager->registerClientCallback(name, service, this).isOk()) {
115 ALOGE("Failed to add client callback for service %s", name.c_str());
116 return false;
117 }
118
Jon Spivackd9533c22020-01-27 22:19:22 +0000119 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700120 mRegisteredServices[name] = {
121 .service = service,
122 .allowIsolated = allowIsolated,
123 .dumpFlags = dumpFlags
124 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000125 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700126
127 return true;
128}
129
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700130std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) {
131 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
132 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
133 auto const& [name, registered] = *it;
134 (void) name;
135 if (registered.service != service) continue;
136 return it;
137 }
138 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
139 __builtin_unreachable();
140}
141
Jon Spivack620d2dc2020-03-06 13:58:01 -0800142void ClientCounterCallback::forcePersist(bool persist) {
143 mForcePersist = persist;
Amos Bianchi7a6cef92021-01-21 17:48:17 -0800144 if (!mForcePersist) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800145 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Amos Bianchie672b872021-01-05 14:03:45 -0800146 maybeTryShutdown();
147 }
148}
149
150bool ClientCounterCallback::tryUnregister() {
151 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
152
153 for (auto& [name, entry] : mRegisteredServices) {
154 bool success = manager->tryUnregisterService(name, entry.service).isOk();
155
156 if (!success) {
157 ALOGI("Failed to unregister service %s", name.c_str());
158 return false;
159 }
160 entry.registered = false;
161 }
162
163 return true;
164}
165
166void ClientCounterCallback::reRegister() {
167 for (auto& [name, entry] : mRegisteredServices) {
168 // re-register entry if not already registered
169 if (entry.registered) {
170 continue;
171 }
172
173 if (!registerService(entry.service, name, entry.allowIsolated,
174 entry.dumpFlags)) {
175 // Must restart. Otherwise, clients will never be able to get a hold of this service.
176 LOG_ALWAYS_FATAL("Bad state: could not re-register services");
177 }
178
179 entry.registered = true;
180 }
181}
182
183void ClientCounterCallback::maybeTryShutdown() {
184 if (mForcePersist) {
185 ALOGI("Shutdown prevented by forcePersist override flag.");
186 return;
187 }
188
189 bool handledInCallback = false;
Amos Bianchi7a6cef92021-01-21 17:48:17 -0800190 if (mActiveServicesCallback != nullptr) {
191 bool hasClients = mNumConnectedServices != 0;
192 if (hasClients != mPreviousHasClients) {
193 handledInCallback = mActiveServicesCallback(hasClients);
194 mPreviousHasClients = hasClients;
195 }
Amos Bianchie672b872021-01-05 14:03:45 -0800196 }
197
198 // If there is no callback defined or the callback did not handle this
199 // client count change event, try to shutdown the process if its services
200 // have no clients.
201 if (!handledInCallback && mNumConnectedServices == 0) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800202 tryShutdown();
203 }
204}
205
Jon Spivack9f503a42019-10-22 16:49:19 -0700206/**
207 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
208 * invocations could occur on different threads however.
209 */
210Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700211 auto & [name, registered] = *assertRegisteredService(service);
212 if (registered.clients == clients) {
213 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
214 "notified has clients: %d", name.c_str(), registered.clients, clients);
215 }
216 registered.clients = clients;
217
218 // update cache count of clients
219 {
220 size_t numWithClients = 0;
221 for (const auto& [name, registered] : mRegisteredServices) {
222 (void) name;
223 if (registered.clients) numWithClients++;
224 }
225 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700226 }
227
228 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700229 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700230
Amos Bianchie672b872021-01-05 14:03:45 -0800231 maybeTryShutdown();
232
Jon Spivack9f503a42019-10-22 16:49:19 -0700233 return Status::ok();
234}
235
236void ClientCounterCallback::tryShutdown() {
237 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
238
Amos Bianchie672b872021-01-05 14:03:45 -0800239 if (tryUnregister()) {
Jon Spivack9f503a42019-10-22 16:49:19 -0700240 ALOGI("Unregistered all clients and exiting");
241 exit(EXIT_SUCCESS);
242 }
243
Amos Bianchie672b872021-01-05 14:03:45 -0800244 reRegister();
245}
Jon Spivack9f503a42019-10-22 16:49:19 -0700246
Amos Bianchi7a6cef92021-01-21 17:48:17 -0800247void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
248 activeServicesCallback) {
249 mActiveServicesCallback = activeServicesCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700250}
251
252} // namespace internal
253
254LazyServiceRegistrar::LazyServiceRegistrar() {
255 mClientCC = std::make_shared<internal::ClientCounterCallback>();
256}
257
258LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
259 static auto registrarInstance = new LazyServiceRegistrar();
260 return *registrarInstance;
261}
262
263status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
264 bool allowIsolated, int dumpFlags) {
265 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
266 return UNKNOWN_ERROR;
267 }
268 return OK;
269}
270
Jon Spivack620d2dc2020-03-06 13:58:01 -0800271void LazyServiceRegistrar::forcePersist(bool persist) {
272 mClientCC->forcePersist(persist);
273}
274
Amos Bianchi7a6cef92021-01-21 17:48:17 -0800275void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>&
276 activeServicesCallback) {
277 mClientCC->setActiveServicesCallback(activeServicesCallback);
Amos Bianchie672b872021-01-05 14:03:45 -0800278}
279
280bool LazyServiceRegistrar::tryUnregister() {
281 return mClientCC->tryUnregister();
282}
283
284void LazyServiceRegistrar::reRegister() {
285 mClientCC->reRegister();
286}
287
Jon Spivack9f503a42019-10-22 16:49:19 -0700288} // namespace hardware
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700289} // namespace android