blob: 2e15e50e94f56464fc465b9e041e57f08d5b9437 [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
17#define LOG_TAG "AidlLazyServiceRegistrar"
18
19#include <binder/LazyServiceRegistrar.h>
20#include <binder/IPCThreadState.h>
21#include <binder/IServiceManager.h>
22#include <android/os/BnClientCallback.h>
23#include <android/os/IServiceManager.h>
24#include <utils/Log.h>
25
26namespace android {
27namespace binder {
28namespace internal {
29
30using AidlServiceManager = android::os::IServiceManager;
31
Jon Spivack143a10d2020-10-27 19:29:14 -070032class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
Jon Spivack9f503a42019-10-22 16:49:19 -070033public:
Jon Spivack143a10d2020-10-27 19:29:14 -070034 ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {}
Jon Spivack9f503a42019-10-22 16:49:19 -070035
36 bool registerService(const sp<IBinder>& service, const std::string& name,
37 bool allowIsolated, int dumpFlags);
Jon Spivack620d2dc2020-03-06 13:58:01 -080038 void forcePersist(bool persist);
39
Jon Spivack9f503a42019-10-22 16:49:19 -070040protected:
41 Status onClients(const sp<IBinder>& service, bool clients) override;
42
43private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070044 struct Service {
45 sp<IBinder> service;
46 bool allowIsolated;
47 int dumpFlags;
48
49 // whether, based on onClients calls, we know we have a client for this
50 // service or not
51 bool clients = false;
52 };
53
54 /**
55 * Looks up a service guaranteed to be registered (service from onClients).
56 */
57 std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
58
Jon Spivack9f503a42019-10-22 16:49:19 -070059 /**
60 * Unregisters all services that we can. If we can't unregister all, re-register other
61 * services.
62 */
63 void tryShutdown();
64
Steven Morelanddd20e7c2020-04-10 11:51:14 -070065 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070066 size_t mNumConnectedServices;
67
Steven Morelanddd20e7c2020-04-10 11:51:14 -070068 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000069 std::map<std::string, Service> mRegisteredServices;
Jon Spivack620d2dc2020-03-06 13:58:01 -080070
71 bool mForcePersist;
Jon Spivack9f503a42019-10-22 16:49:19 -070072};
73
Jon Spivack143a10d2020-10-27 19:29:14 -070074class ClientCounterCallback {
75public:
76 ClientCounterCallback();
77
78 bool registerService(const sp<IBinder>& service, const std::string& name,
79 bool allowIsolated, int dumpFlags);
80
81 /**
82 * Set a flag to prevent services from automatically shutting down
83 */
84 void forcePersist(bool persist);
85
86private:
87 sp<ClientCounterCallbackImpl> mImpl;
88};
89
90bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
Jon Spivack9f503a42019-10-22 16:49:19 -070091 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -080092 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -070093
Jon Spivackd9533c22020-01-27 22:19:22 +000094 bool reRegister = mRegisteredServices.count(name) > 0;
95 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
96 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -070097
98 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
99 ALOGE("Failed to register service %s", name.c_str());
100 return false;
101 }
102
Jon Spivackd9533c22020-01-27 22:19:22 +0000103 if (!reRegister) {
Jon Spivack143a10d2020-10-27 19:29:14 -0700104 if(!manager->registerClientCallback(name, service, this).isOk()) {
Steven Moreland1e2ba922020-04-10 15:25:01 -0700105 ALOGE("Failed to add client callback for service %s", name.c_str());
106 return false;
107 }
108
Jon Spivackd9533c22020-01-27 22:19:22 +0000109 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700110 mRegisteredServices[name] = {
111 .service = service,
112 .allowIsolated = allowIsolated,
113 .dumpFlags = dumpFlags
114 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000115 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700116
117 return true;
118}
119
Jon Spivack143a10d2020-10-27 19:29:14 -0700120std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700121 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
122 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
123 auto const& [name, registered] = *it;
124 (void) name;
125 if (registered.service != service) continue;
126 return it;
127 }
128 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
129 __builtin_unreachable();
130}
131
Jon Spivack143a10d2020-10-27 19:29:14 -0700132void ClientCounterCallbackImpl::forcePersist(bool persist) {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800133 mForcePersist = persist;
134 if(!mForcePersist) {
135 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
136 tryShutdown();
137 }
138}
139
Jon Spivack9f503a42019-10-22 16:49:19 -0700140/**
141 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
142 * invocations could occur on different threads however.
143 */
Jon Spivack143a10d2020-10-27 19:29:14 -0700144Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700145 auto & [name, registered] = *assertRegisteredService(service);
146 if (registered.clients == clients) {
147 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
148 "notified has clients: %d", name.c_str(), registered.clients, clients);
149 }
150 registered.clients = clients;
151
152 // update cache count of clients
153 {
154 size_t numWithClients = 0;
155 for (const auto& [name, registered] : mRegisteredServices) {
156 (void) name;
157 if (registered.clients) numWithClients++;
158 }
159 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700160 }
161
162 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700163 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700164
Jon Spivack620d2dc2020-03-06 13:58:01 -0800165 tryShutdown();
Jon Spivack9f503a42019-10-22 16:49:19 -0700166 return Status::ok();
167}
168
Jon Spivack143a10d2020-10-27 19:29:14 -0700169void ClientCounterCallbackImpl::tryShutdown() {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800170 if(mNumConnectedServices > 0) {
171 // Should only shut down if there are no clients
172 return;
173 }
174
175 if(mForcePersist) {
176 ALOGI("Shutdown prevented by forcePersist override flag.");
177 return;
178 }
179
Jon Spivack9f503a42019-10-22 16:49:19 -0700180 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
181
Jon Spivack718470e2020-02-19 19:18:21 -0800182 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700183
184 auto unRegisterIt = mRegisteredServices.begin();
185 for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
186 auto& entry = (*unRegisterIt);
187
Jon Spivackd9533c22020-01-27 22:19:22 +0000188 bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk();
189
Jon Spivack9f503a42019-10-22 16:49:19 -0700190 if (!success) {
Jon Spivackd9533c22020-01-27 22:19:22 +0000191 ALOGI("Failed to unregister service %s", entry.first.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700192 break;
193 }
194 }
195
196 if (unRegisterIt == mRegisteredServices.end()) {
197 ALOGI("Unregistered all clients and exiting");
198 exit(EXIT_SUCCESS);
199 }
200
201 for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
202 reRegisterIt++) {
203 auto& entry = (*reRegisterIt);
204
205 // re-register entry
Jon Spivackd9533c22020-01-27 22:19:22 +0000206 if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated,
207 entry.second.dumpFlags)) {
Jon Spivack9f503a42019-10-22 16:49:19 -0700208 // Must restart. Otherwise, clients will never be able to get a hold of this service.
209 ALOGE("Bad state: could not re-register services");
210 }
211 }
212}
213
Jon Spivack143a10d2020-10-27 19:29:14 -0700214ClientCounterCallback::ClientCounterCallback() {
215 mImpl = sp<ClientCounterCallbackImpl>::make();
216}
217
218bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
219 bool allowIsolated, int dumpFlags) {
220 return mImpl->registerService(service, name, allowIsolated, dumpFlags);
221}
222
223void ClientCounterCallback::forcePersist(bool persist) {
224 mImpl->forcePersist(persist);
225}
226
Jon Spivack9f503a42019-10-22 16:49:19 -0700227} // namespace internal
228
229LazyServiceRegistrar::LazyServiceRegistrar() {
230 mClientCC = std::make_shared<internal::ClientCounterCallback>();
231}
232
233LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
234 static auto registrarInstance = new LazyServiceRegistrar();
235 return *registrarInstance;
236}
237
238status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
239 bool allowIsolated, int dumpFlags) {
240 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
241 return UNKNOWN_ERROR;
242 }
243 return OK;
244}
245
Jon Spivack620d2dc2020-03-06 13:58:01 -0800246void LazyServiceRegistrar::forcePersist(bool persist) {
247 mClientCC->forcePersist(persist);
248}
249
Jon Spivack9f503a42019-10-22 16:49:19 -0700250} // namespace hardware
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700251} // namespace android