blob: bfd6942c3e59081b420e986a4c2637709478a3a6 [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 Bianchi844e19b2020-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:
52 /**
53 * Unregisters all services that we can. If we can't unregister all, re-register other
54 * services.
55 */
56 void tryShutdown();
57
58 /**
Amos Bianchi844e19b2020-12-23 09:57:02 -080059 * Try to shutdown the process, unless:
60 * - 'forcePersist' is 'true', or
61 * - The active services count callback returns 'true', or
62 * - Some services have clients.
63 */
64 void maybeTryShutdown();
65
66 /*
Jon Spivack9f503a42019-10-22 16:49:19 -070067 * Counter of the number of services that currently have at least one client.
68 */
69 size_t mNumConnectedServices;
70
71 struct Service {
72 sp<IBinder> service;
Jon Spivack9f503a42019-10-22 16:49:19 -070073 bool allowIsolated;
74 int dumpFlags;
Amos Bianchi844e19b2020-12-23 09:57:02 -080075
76 bool registered = true;
Jon Spivack9f503a42019-10-22 16:49:19 -070077 };
78 /**
Jon Spivackd9533c22020-01-27 22:19:22 +000079 * Map of registered names and services
Jon Spivack9f503a42019-10-22 16:49:19 -070080 */
Jon Spivackd9533c22020-01-27 22:19:22 +000081 std::map<std::string, Service> mRegisteredServices;
Jon Spivacke17055a2020-03-06 13:58:01 -080082
83 bool mForcePersist;
Amos Bianchi844e19b2020-12-23 09:57:02 -080084
85 // Callback used to report the number of services with clients
86 std::function<bool(int)> mActiveServicesCountCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -070087};
88
Jon Spivackdc6cb052020-10-27 19:29:14 -070089class ClientCounterCallback {
90public:
91 ClientCounterCallback();
92
93 bool registerService(const sp<IBinder>& service, const std::string& name,
94 bool allowIsolated, int dumpFlags);
95
96 /**
97 * Set a flag to prevent services from automatically shutting down
98 */
99 void forcePersist(bool persist);
100
Amos Bianchi844e19b2020-12-23 09:57:02 -0800101 void setActiveServicesCountCallback(const std::function<bool(int)>&
102 activeServicesCountCallback);
103
104 bool tryUnregister();
105
106 void reRegister();
107
Jon Spivackdc6cb052020-10-27 19:29:14 -0700108private:
109 sp<ClientCounterCallbackImpl> mImpl;
110};
111
112bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
Jon Spivack9f503a42019-10-22 16:49:19 -0700113 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -0800114 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700115
Jon Spivackd9533c22020-01-27 22:19:22 +0000116 bool reRegister = mRegisteredServices.count(name) > 0;
117 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
118 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700119
120 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
121 ALOGE("Failed to register service %s", name.c_str());
122 return false;
123 }
124
Jon Spivackd9533c22020-01-27 22:19:22 +0000125 if (!reRegister) {
Steven Moreland60774252020-04-10 15:25:01 -0700126 if (!manager->registerClientCallback(name, service, this).isOk()) {
127 ALOGE("Failed to add client callback for service %s", name.c_str());
128 return false;
129 }
130
Jon Spivackd9533c22020-01-27 22:19:22 +0000131 // Only add this when a service is added for the first time, as it is not removed
132 mRegisteredServices[name] = {service, allowIsolated, dumpFlags};
133 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700134
135 return true;
136}
137
Jon Spivackdc6cb052020-10-27 19:29:14 -0700138void ClientCounterCallbackImpl::forcePersist(bool persist) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800139 mForcePersist = persist;
Amos Bianchi844e19b2020-12-23 09:57:02 -0800140 if (!mForcePersist && mNumConnectedServices == 0) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800141 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
Amos Bianchi844e19b2020-12-23 09:57:02 -0800142 maybeTryShutdown();
143 }
144}
145
146bool ClientCounterCallbackImpl::tryUnregister() {
147 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
148
149 for (auto& [name, entry] : mRegisteredServices) {
150 bool success = manager->tryUnregisterService(name, entry.service).isOk();
151
152 if (!success) {
153 ALOGI("Failed to unregister service %s", name.c_str());
154 return false;
155 }
156 entry.registered = false;
157 }
158
159 return true;
160}
161
162void ClientCounterCallbackImpl::reRegister() {
163 for (auto& [name, entry] : mRegisteredServices) {
164 // re-register entry if not already registered
165 if (entry.registered) {
166 continue;
167 }
168
169 if (!registerService(entry.service, name, entry.allowIsolated,
170 entry.dumpFlags)) {
171 // Must restart. Otherwise, clients will never be able to get a hold of this service.
172 LOG_ALWAYS_FATAL("Bad state: could not re-register services");
173 }
174
175 entry.registered = true;
176 }
177}
178
179void ClientCounterCallbackImpl::maybeTryShutdown() {
180 if (mForcePersist) {
181 ALOGI("Shutdown prevented by forcePersist override flag.");
182 return;
183 }
184
185 bool handledInCallback = false;
186 if (mActiveServicesCountCallback != nullptr) {
187 handledInCallback = mActiveServicesCountCallback(mNumConnectedServices);
188 }
189
190 // If there is no callback defined or the callback did not handle this
191 // client count change event, try to shutdown the process if its services
192 // have no clients.
193 if (!handledInCallback && mNumConnectedServices == 0) {
Jon Spivacke17055a2020-03-06 13:58:01 -0800194 tryShutdown();
195 }
196}
197
Jon Spivack9f503a42019-10-22 16:49:19 -0700198/**
199 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
200 * invocations could occur on different threads however.
201 */
Jon Spivackdc6cb052020-10-27 19:29:14 -0700202Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
Jon Spivack9f503a42019-10-22 16:49:19 -0700203 if (clients) {
204 mNumConnectedServices++;
205 } else {
206 mNumConnectedServices--;
207 }
208
209 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
210 mNumConnectedServices, mRegisteredServices.size(),
211 String8(service->getInterfaceDescriptor()).string(), clients);
212
Amos Bianchi844e19b2020-12-23 09:57:02 -0800213 maybeTryShutdown();
Jon Spivack9f503a42019-10-22 16:49:19 -0700214 return Status::ok();
215}
216
Amos Bianchi844e19b2020-12-23 09:57:02 -0800217 void ClientCounterCallbackImpl::tryShutdown() {
218 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
Jon Spivacke17055a2020-03-06 13:58:01 -0800219
Amos Bianchi844e19b2020-12-23 09:57:02 -0800220 if (tryUnregister()) {
221 ALOGI("Unregistered all clients and exiting");
222 exit(EXIT_SUCCESS);
223 }
Jon Spivacke17055a2020-03-06 13:58:01 -0800224
Amos Bianchi844e19b2020-12-23 09:57:02 -0800225 reRegister();
226}
Jon Spivack9f503a42019-10-22 16:49:19 -0700227
Amos Bianchi844e19b2020-12-23 09:57:02 -0800228void ClientCounterCallbackImpl::setActiveServicesCountCallback(const std::function<bool(int)>&
229 activeServicesCountCallback) {
230 mActiveServicesCountCallback = activeServicesCountCallback;
Jon Spivack9f503a42019-10-22 16:49:19 -0700231}
232
Jon Spivackdc6cb052020-10-27 19:29:14 -0700233ClientCounterCallback::ClientCounterCallback() {
234 mImpl = new ClientCounterCallbackImpl();
235}
236
237bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
238 bool allowIsolated, int dumpFlags) {
239 return mImpl->registerService(service, name, allowIsolated, dumpFlags);
240}
241
242void ClientCounterCallback::forcePersist(bool persist) {
243 mImpl->forcePersist(persist);
244}
245
Amos Bianchi844e19b2020-12-23 09:57:02 -0800246void ClientCounterCallback::setActiveServicesCountCallback(const std::function<bool(int)>&
247 activeServicesCountCallback) {
248 mImpl->setActiveServicesCountCallback(activeServicesCountCallback);
249}
250
251bool ClientCounterCallback::tryUnregister() {
252 return mImpl->tryUnregister();
253}
254
255void ClientCounterCallback::reRegister() {
256 mImpl->reRegister();
257}
258
Jon Spivack9f503a42019-10-22 16:49:19 -0700259} // namespace internal
260
261LazyServiceRegistrar::LazyServiceRegistrar() {
262 mClientCC = std::make_shared<internal::ClientCounterCallback>();
263}
264
265LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
266 static auto registrarInstance = new LazyServiceRegistrar();
267 return *registrarInstance;
268}
269
270status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
271 bool allowIsolated, int dumpFlags) {
272 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
273 return UNKNOWN_ERROR;
274 }
275 return OK;
276}
277
Jon Spivacke17055a2020-03-06 13:58:01 -0800278void LazyServiceRegistrar::forcePersist(bool persist) {
279 mClientCC->forcePersist(persist);
280}
281
Amos Bianchi844e19b2020-12-23 09:57:02 -0800282void LazyServiceRegistrar::setActiveServicesCountCallback(const std::function<bool(int)>&
283 activeServicesCountCallback) {
284 mClientCC->setActiveServicesCountCallback(activeServicesCountCallback);
285}
286
287bool LazyServiceRegistrar::tryUnregister() {
288 return mClientCC->tryUnregister();
289}
290
291void LazyServiceRegistrar::reRegister() {
292 mClientCC->reRegister();
293}
294
Jon Spivack9f503a42019-10-22 16:49:19 -0700295} // namespace hardware
Amos Bianchi844e19b2020-12-23 09:57:02 -0800296} // namespace android