blob: 325e204203d279f69c41f5abf9f7cb5daf8932b2 [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
32class ClientCounterCallback : public ::android::os::BnClientCallback {
33public:
Jon Spivack620d2dc2020-03-06 13:58:01 -080034 ClientCounterCallback() : 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);
38
Jon Spivack620d2dc2020-03-06 13:58:01 -080039 /**
40 * Set a flag to prevent services from automatically shutting down
41 */
42 void forcePersist(bool persist);
43
Jon Spivack9f503a42019-10-22 16:49:19 -070044protected:
45 Status onClients(const sp<IBinder>& service, bool clients) override;
46
47private:
Steven Morelanddd20e7c2020-04-10 11:51:14 -070048 struct Service {
49 sp<IBinder> service;
50 bool allowIsolated;
51 int dumpFlags;
52
53 // whether, based on onClients calls, we know we have a client for this
54 // service or not
55 bool clients = false;
56 };
57
58 /**
59 * Looks up a service guaranteed to be registered (service from onClients).
60 */
61 std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
62
Jon Spivack9f503a42019-10-22 16:49:19 -070063 /**
64 * Unregisters all services that we can. If we can't unregister all, re-register other
65 * services.
66 */
67 void tryShutdown();
68
Steven Morelanddd20e7c2020-04-10 11:51:14 -070069 // count of services with clients
Jon Spivack9f503a42019-10-22 16:49:19 -070070 size_t mNumConnectedServices;
71
Steven Morelanddd20e7c2020-04-10 11:51:14 -070072 // map of registered names and services
Jon Spivackd9533c22020-01-27 22:19:22 +000073 std::map<std::string, Service> mRegisteredServices;
Jon Spivack620d2dc2020-03-06 13:58:01 -080074
75 bool mForcePersist;
Jon Spivack9f503a42019-10-22 16:49:19 -070076};
77
78bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
79 bool allowIsolated, int dumpFlags) {
Jon Spivack718470e2020-02-19 19:18:21 -080080 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -070081
Jon Spivackd9533c22020-01-27 22:19:22 +000082 bool reRegister = mRegisteredServices.count(name) > 0;
83 std::string regStr = (reRegister) ? "Re-registering" : "Registering";
84 ALOGI("%s service %s", regStr.c_str(), name.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -070085
86 if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
87 ALOGE("Failed to register service %s", name.c_str());
88 return false;
89 }
90
Jon Spivackd9533c22020-01-27 22:19:22 +000091 if (!reRegister) {
Steven Moreland1e2ba922020-04-10 15:25:01 -070092 if (!manager->registerClientCallback(name, service, this).isOk()) {
93 ALOGE("Failed to add client callback for service %s", name.c_str());
94 return false;
95 }
96
Jon Spivackd9533c22020-01-27 22:19:22 +000097 // Only add this when a service is added for the first time, as it is not removed
Steven Morelanddd20e7c2020-04-10 11:51:14 -070098 mRegisteredServices[name] = {
99 .service = service,
100 .allowIsolated = allowIsolated,
101 .dumpFlags = dumpFlags
102 };
Jon Spivackd9533c22020-01-27 22:19:22 +0000103 }
Jon Spivack9f503a42019-10-22 16:49:19 -0700104
105 return true;
106}
107
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700108std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) {
109 LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
110 for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
111 auto const& [name, registered] = *it;
112 (void) name;
113 if (registered.service != service) continue;
114 return it;
115 }
116 LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
117 __builtin_unreachable();
118}
119
Jon Spivack620d2dc2020-03-06 13:58:01 -0800120void ClientCounterCallback::forcePersist(bool persist) {
121 mForcePersist = persist;
122 if(!mForcePersist) {
123 // Attempt a shutdown in case the number of clients hit 0 while the flag was on
124 tryShutdown();
125 }
126}
127
Jon Spivack9f503a42019-10-22 16:49:19 -0700128/**
129 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
130 * invocations could occur on different threads however.
131 */
132Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) {
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700133 auto & [name, registered] = *assertRegisteredService(service);
134 if (registered.clients == clients) {
135 LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
136 "notified has clients: %d", name.c_str(), registered.clients, clients);
137 }
138 registered.clients = clients;
139
140 // update cache count of clients
141 {
142 size_t numWithClients = 0;
143 for (const auto& [name, registered] : mRegisteredServices) {
144 (void) name;
145 if (registered.clients) numWithClients++;
146 }
147 mNumConnectedServices = numWithClients;
Jon Spivack9f503a42019-10-22 16:49:19 -0700148 }
149
150 ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700151 mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
Jon Spivack9f503a42019-10-22 16:49:19 -0700152
Jon Spivack620d2dc2020-03-06 13:58:01 -0800153 tryShutdown();
Jon Spivack9f503a42019-10-22 16:49:19 -0700154 return Status::ok();
155}
156
157void ClientCounterCallback::tryShutdown() {
Jon Spivack620d2dc2020-03-06 13:58:01 -0800158 if(mNumConnectedServices > 0) {
159 // Should only shut down if there are no clients
160 return;
161 }
162
163 if(mForcePersist) {
164 ALOGI("Shutdown prevented by forcePersist override flag.");
165 return;
166 }
167
Jon Spivack9f503a42019-10-22 16:49:19 -0700168 ALOGI("Trying to shut down the service. No clients in use for any service in process.");
169
Jon Spivack718470e2020-02-19 19:18:21 -0800170 auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
Jon Spivack9f503a42019-10-22 16:49:19 -0700171
172 auto unRegisterIt = mRegisteredServices.begin();
173 for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
174 auto& entry = (*unRegisterIt);
175
Jon Spivackd9533c22020-01-27 22:19:22 +0000176 bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk();
177
Jon Spivack9f503a42019-10-22 16:49:19 -0700178
179 if (!success) {
Jon Spivackd9533c22020-01-27 22:19:22 +0000180 ALOGI("Failed to unregister service %s", entry.first.c_str());
Jon Spivack9f503a42019-10-22 16:49:19 -0700181 break;
182 }
183 }
184
185 if (unRegisterIt == mRegisteredServices.end()) {
186 ALOGI("Unregistered all clients and exiting");
187 exit(EXIT_SUCCESS);
188 }
189
190 for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
191 reRegisterIt++) {
192 auto& entry = (*reRegisterIt);
193
194 // re-register entry
Jon Spivackd9533c22020-01-27 22:19:22 +0000195 if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated,
196 entry.second.dumpFlags)) {
Jon Spivack9f503a42019-10-22 16:49:19 -0700197 // Must restart. Otherwise, clients will never be able to get a hold of this service.
198 ALOGE("Bad state: could not re-register services");
199 }
200 }
201}
202
203} // namespace internal
204
205LazyServiceRegistrar::LazyServiceRegistrar() {
206 mClientCC = std::make_shared<internal::ClientCounterCallback>();
207}
208
209LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
210 static auto registrarInstance = new LazyServiceRegistrar();
211 return *registrarInstance;
212}
213
214status_t LazyServiceRegistrar::registerService(const sp<IBinder>& service, const std::string& name,
215 bool allowIsolated, int dumpFlags) {
216 if (!mClientCC->registerService(service, name, allowIsolated, dumpFlags)) {
217 return UNKNOWN_ERROR;
218 }
219 return OK;
220}
221
Jon Spivack620d2dc2020-03-06 13:58:01 -0800222void LazyServiceRegistrar::forcePersist(bool persist) {
223 mClientCC->forcePersist(persist);
224}
225
Jon Spivack9f503a42019-10-22 16:49:19 -0700226} // namespace hardware
Steven Morelanddd20e7c2020-04-10 11:51:14 -0700227} // namespace android