blob: 618f2796850f359409f8c1567f9d1f9964b43e8a [file] [log] [blame]
Peter Kalauskas3373cd32018-10-24 15:37:00 -07001/*
2 * Copyright (C) 2018 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
Peter Kalauskas365a0f92020-06-10 11:43:01 -070017#define LOG_TAG "HidlLazyUtils"
18
Elliott Hughes87396022025-02-18 09:40:57 -050019#include <mutex>
20
Peter Kalauskas3373cd32018-10-24 15:37:00 -070021#include <hidl/HidlLazyUtils.h>
22#include <hidl/HidlTransportSupport.h>
23
24#include <android-base/logging.h>
25
26#include <android/hidl/manager/1.2/IClientCallback.h>
27#include <android/hidl/manager/1.2/IServiceManager.h>
28
29namespace android {
30namespace hardware {
31namespace details {
32
Steven Moreland40b3ab42019-01-25 13:23:20 -080033using ::android::hidl::base::V1_0::IBase;
34
Peter Kalauskas3373cd32018-10-24 15:37:00 -070035class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback {
Steven Morelandbd603f72020-04-06 14:21:55 -070036 public:
37 ClientCounterCallback() {}
Peter Kalauskas3373cd32018-10-24 15:37:00 -070038
Steven Moreland40b3ab42019-01-25 13:23:20 -080039 bool addRegisteredService(const sp<IBase>& service, const std::string& name);
Peter Kalauskas3373cd32018-10-24 15:37:00 -070040
Steven Moreland3d5b1782021-06-22 18:40:27 +000041 bool tryUnregisterLocked();
Amos Bianchi57341bb2020-12-23 11:11:37 -080042
Steven Moreland3d5b1782021-06-22 18:40:27 +000043 void reRegisterLocked();
Amos Bianchi57341bb2020-12-23 11:11:37 -080044
Amos Bianchifb918632021-01-20 17:41:02 -080045 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Amos Bianchi57341bb2020-12-23 11:11:37 -080046
Steven Morelandbd603f72020-04-06 14:21:55 -070047 protected:
Steven Moreland40b3ab42019-01-25 13:23:20 -080048 Return<void> onClients(const sp<IBase>& service, bool clients) override;
Peter Kalauskas3373cd32018-10-24 15:37:00 -070049
Steven Morelandbd603f72020-04-06 14:21:55 -070050 private:
51 struct Service {
52 sp<IBase> service;
53 std::string name;
54 bool clients = false;
Amos Bianchi57341bb2020-12-23 11:11:37 -080055 // Used to keep track of unregistered services to allow re-registry
56 bool registered = true;
Steven Morelandbd603f72020-04-06 14:21:55 -070057 };
58
59 /**
60 * Looks up service that is guaranteed to be registered (service from
61 * onClients).
62 */
Steven Moreland3d5b1782021-06-22 18:40:27 +000063 Service& assertRegisteredServiceLocked(const sp<IBase>& service);
Steven Morelandbd603f72020-04-06 14:21:55 -070064
Peter Kalauskas3373cd32018-10-24 15:37:00 -070065 /**
Steven Moreland40b3ab42019-01-25 13:23:20 -080066 * Registers or re-registers services. Returns whether successful.
67 */
Steven Moreland3d5b1782021-06-22 18:40:27 +000068 bool registerServiceLocked(const sp<IBase>& service, const std::string& name);
Steven Moreland40b3ab42019-01-25 13:23:20 -080069
70 /**
71 * Unregisters all services that we can. If we can't unregister all, re-register other
72 * services.
73 */
Steven Moreland3d5b1782021-06-22 18:40:27 +000074 void tryShutdownLocked();
75
76 /**
77 * For below.
78 */
79 std::mutex mMutex;
Steven Moreland40b3ab42019-01-25 13:23:20 -080080
81 /**
Peter Kalauskas3373cd32018-10-24 15:37:00 -070082 * Number of services that have been registered.
83 */
Steven Moreland40b3ab42019-01-25 13:23:20 -080084 std::vector<Service> mRegisteredServices;
Amos Bianchi57341bb2020-12-23 11:11:37 -080085
86 /**
87 * Callback for reporting the number of services with clients.
88 */
Amos Bianchifb918632021-01-20 17:41:02 -080089 std::function<bool(bool)> mActiveServicesCallback;
90
91 /**
92 * Previous value passed to the active services callback.
93 */
94 std::optional<bool> mPreviousHasClients;
Peter Kalauskas3373cd32018-10-24 15:37:00 -070095};
96
97class LazyServiceRegistrarImpl {
Steven Morelandbd603f72020-04-06 14:21:55 -070098 public:
Peter Kalauskas3373cd32018-10-24 15:37:00 -070099 LazyServiceRegistrarImpl() : mClientCallback(new ClientCounterCallback) {}
100
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800101 status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
102 const std::string& name);
Amos Bianchi57341bb2020-12-23 11:11:37 -0800103 bool tryUnregister();
104 void reRegister();
Amos Bianchifb918632021-01-20 17:41:02 -0800105 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700106
Steven Morelandbd603f72020-04-06 14:21:55 -0700107 private:
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700108 sp<ClientCounterCallback> mClientCallback;
109};
110
Steven Moreland40b3ab42019-01-25 13:23:20 -0800111bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service,
112 const std::string& name) {
Steven Moreland3d5b1782021-06-22 18:40:27 +0000113 std::lock_guard<std::mutex> lock(mMutex);
114 bool success = registerServiceLocked(service, name);
Steven Moreland40b3ab42019-01-25 13:23:20 -0800115
116 if (success) {
117 mRegisteredServices.push_back({service, name});
118 }
119
120 return success;
121}
122
Steven Moreland3d5b1782021-06-22 18:40:27 +0000123ClientCounterCallback::Service& ClientCounterCallback::assertRegisteredServiceLocked(
Steven Morelandbd603f72020-04-06 14:21:55 -0700124 const sp<IBase>& service) {
125 for (Service& registered : mRegisteredServices) {
126 if (registered.service != service) continue;
127 return registered;
128 }
129 LOG(FATAL) << "Got callback on service " << getDescriptor(service.get())
130 << " which we did not register.";
131 __builtin_unreachable();
132}
133
Steven Moreland3d5b1782021-06-22 18:40:27 +0000134bool ClientCounterCallback::registerServiceLocked(const sp<IBase>& service,
135 const std::string& name) {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800136 auto manager = hardware::defaultServiceManager1_2();
137
138 const std::string descriptor = getDescriptor(service.get());
139
140 LOG(INFO) << "Registering HAL: " << descriptor << " with name: " << name;
141
142 status_t res = android::hardware::details::registerAsServiceInternal(service, name);
143 if (res != android::OK) {
144 LOG(ERROR) << "Failed to register as service.";
145 return false;
146 }
147
148 bool ret = manager->registerClientCallback(getDescriptor(service.get()), name, service, this);
149 if (!ret) {
150 LOG(ERROR) << "Failed to add client callback.";
151 return false;
152 }
153
154 return true;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700155}
156
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700157Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
158 bool clients) {
Steven Moreland3d5b1782021-06-22 18:40:27 +0000159 std::lock_guard<std::mutex> lock(mMutex);
160 Service& registered = assertRegisteredServiceLocked(service);
Steven Morelandbd603f72020-04-06 14:21:55 -0700161 if (registered.clients == clients) {
162 LOG(FATAL) << "Process already thought " << getDescriptor(service.get()) << "/"
163 << registered.name << " had clients: " << registered.clients
164 << " but hwservicemanager has notified has clients: " << clients;
165 }
166 registered.clients = clients;
167
168 size_t numWithClients = 0;
169 for (const Service& registered : mRegisteredServices) {
170 if (registered.clients) numWithClients++;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700171 }
Steven Moreland40b3ab42019-01-25 13:23:20 -0800172
Steven Morelandbd603f72020-04-06 14:21:55 -0700173 LOG(INFO) << "Process has " << numWithClients << " (of " << mRegisteredServices.size()
Steven Moreland06d58be2019-02-04 14:20:13 -0800174 << " available) client(s) in use after notification " << getDescriptor(service.get())
Steven Morelandbd603f72020-04-06 14:21:55 -0700175 << "/" << registered.name << " has clients: " << clients;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700176
Amos Bianchi57341bb2020-12-23 11:11:37 -0800177 bool handledInCallback = false;
Amos Bianchifb918632021-01-20 17:41:02 -0800178 if (mActiveServicesCallback != nullptr) {
179 bool hasClients = numWithClients != 0;
180 if (hasClients != mPreviousHasClients) {
181 handledInCallback = mActiveServicesCallback(hasClients);
182 mPreviousHasClients = hasClients;
183 }
Amos Bianchi57341bb2020-12-23 11:11:37 -0800184 }
185
186 // If there is no callback defined or the callback did not handle this
187 // client count change event, try to shutdown the process if its services
188 // have no clients.
189 if (!handledInCallback && numWithClients == 0) {
Steven Moreland3d5b1782021-06-22 18:40:27 +0000190 tryShutdownLocked();
Steven Moreland40b3ab42019-01-25 13:23:20 -0800191 }
192
193 return Status::ok();
194}
195
Steven Moreland3d5b1782021-06-22 18:40:27 +0000196bool ClientCounterCallback::tryUnregisterLocked() {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800197 auto manager = hardware::defaultServiceManager1_2();
198
Amos Bianchi57341bb2020-12-23 11:11:37 -0800199 for (Service& entry : mRegisteredServices) {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800200 const std::string descriptor = getDescriptor(entry.service.get());
201 bool success = manager->tryUnregister(descriptor, entry.name, entry.service);
202
203 if (!success) {
Steven Moreland06d58be2019-02-04 14:20:13 -0800204 LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name;
Amos Bianchi57341bb2020-12-23 11:11:37 -0800205 return false;
Steven Moreland40b3ab42019-01-25 13:23:20 -0800206 }
Amos Bianchi57341bb2020-12-23 11:11:37 -0800207
208 // Mark the entry unregistered, but do not remove it (may still be re-registered)
209 entry.registered = false;
Steven Moreland40b3ab42019-01-25 13:23:20 -0800210 }
211
Amos Bianchi57341bb2020-12-23 11:11:37 -0800212 return true;
213}
Steven Moreland40b3ab42019-01-25 13:23:20 -0800214
Steven Moreland3d5b1782021-06-22 18:40:27 +0000215void ClientCounterCallback::reRegisterLocked() {
Amos Bianchi57341bb2020-12-23 11:11:37 -0800216 for (Service& entry : mRegisteredServices) {
217 // re-register entry if not already registered
218 if (entry.registered) {
219 continue;
220 }
Steven Moreland40b3ab42019-01-25 13:23:20 -0800221
Steven Moreland3d5b1782021-06-22 18:40:27 +0000222 if (!registerServiceLocked(entry.service, entry.name)) {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800223 // Must restart. Otherwise, clients will never be able to get ahold of this service.
224 LOG(FATAL) << "Bad state: could not re-register " << getDescriptor(entry.service.get());
225 }
Amos Bianchi57341bb2020-12-23 11:11:37 -0800226
227 entry.registered = true;
Steven Moreland40b3ab42019-01-25 13:23:20 -0800228 }
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700229}
230
Steven Moreland3d5b1782021-06-22 18:40:27 +0000231void ClientCounterCallback::tryShutdownLocked() {
Amos Bianchi57341bb2020-12-23 11:11:37 -0800232 LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process.";
233
Steven Moreland3d5b1782021-06-22 18:40:27 +0000234 if (tryUnregisterLocked()) {
Amos Bianchi57341bb2020-12-23 11:11:37 -0800235 LOG(INFO) << "Unregistered all clients and exiting";
236 exit(EXIT_SUCCESS);
237 }
238
239 // At this point, we failed to unregister some of the services, leaving the
240 // server in an inconsistent state. Re-register all services that were
Steven Moreland3d5b1782021-06-22 18:40:27 +0000241 // unregistered by tryUnregisterLocked().
242 reRegisterLocked();
Amos Bianchi57341bb2020-12-23 11:11:37 -0800243}
244
Amos Bianchifb918632021-01-20 17:41:02 -0800245void ClientCounterCallback::setActiveServicesCallback(
246 const std::function<bool(bool)>& activeServicesCallback) {
Steven Moreland3d5b1782021-06-22 18:40:27 +0000247 std::lock_guard<std::mutex> lock(mMutex);
248
Amos Bianchifb918632021-01-20 17:41:02 -0800249 mActiveServicesCallback = activeServicesCallback;
Amos Bianchi57341bb2020-12-23 11:11:37 -0800250}
251
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800252status_t LazyServiceRegistrarImpl::registerService(
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700253 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800254 if (!mClientCallback->addRegisteredService(service, name)) {
255 return ::android::UNKNOWN_ERROR;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700256 }
Steven Moreland40b3ab42019-01-25 13:23:20 -0800257
258 return ::android::OK;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700259}
260
Amos Bianchi57341bb2020-12-23 11:11:37 -0800261bool LazyServiceRegistrarImpl::tryUnregister() {
Steven Moreland3d5b1782021-06-22 18:40:27 +0000262 // see comments in header, this should only be called from the active
263 // services callback, see also b/191781736
264 return mClientCallback->tryUnregisterLocked();
Amos Bianchi57341bb2020-12-23 11:11:37 -0800265}
266
267void LazyServiceRegistrarImpl::reRegister() {
Steven Moreland3d5b1782021-06-22 18:40:27 +0000268 // see comments in header, this should only be called from the active
269 // services callback, see also b/191781736
270 mClientCallback->reRegisterLocked();
Amos Bianchi57341bb2020-12-23 11:11:37 -0800271}
272
Amos Bianchifb918632021-01-20 17:41:02 -0800273void LazyServiceRegistrarImpl::setActiveServicesCallback(
274 const std::function<bool(bool)>& activeServicesCallback) {
275 mClientCallback->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi57341bb2020-12-23 11:11:37 -0800276}
277
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700278} // namespace details
279
280LazyServiceRegistrar::LazyServiceRegistrar() {
281 mImpl = std::make_shared<details::LazyServiceRegistrarImpl>();
282}
283
Peter Kalauskas1e969222019-08-14 12:13:11 -0700284LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
285 static auto registrarInstance = new LazyServiceRegistrar();
286 return *registrarInstance;
287}
288
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800289status_t LazyServiceRegistrar::registerService(
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700290 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800291 return mImpl->registerService(service, name);
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700292}
293
Amos Bianchi57341bb2020-12-23 11:11:37 -0800294bool LazyServiceRegistrar::tryUnregister() {
295 return mImpl->tryUnregister();
296}
297
298void LazyServiceRegistrar::reRegister() {
299 mImpl->reRegister();
300}
301
Amos Bianchifb918632021-01-20 17:41:02 -0800302void LazyServiceRegistrar::setActiveServicesCallback(
303 const std::function<bool(bool)>& activeServicesCallback) {
304 mImpl->setActiveServicesCallback(activeServicesCallback);
Amos Bianchi57341bb2020-12-23 11:11:37 -0800305}
306
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700307} // namespace hardware
308} // namespace android