1 /*
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
17 #define LOG_TAG "HidlLazyUtils"
18
19 #include <mutex>
20
21 #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
29 namespace android {
30 namespace hardware {
31 namespace details {
32
33 using ::android::hidl::base::V1_0::IBase;
34
35 class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback {
36 public:
ClientCounterCallback()37 ClientCounterCallback() {}
38
39 bool addRegisteredService(const sp<IBase>& service, const std::string& name);
40
41 bool tryUnregisterLocked();
42
43 void reRegisterLocked();
44
45 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
46
47 protected:
48 Return<void> onClients(const sp<IBase>& service, bool clients) override;
49
50 private:
51 struct Service {
52 sp<IBase> service;
53 std::string name;
54 bool clients = false;
55 // Used to keep track of unregistered services to allow re-registry
56 bool registered = true;
57 };
58
59 /**
60 * Looks up service that is guaranteed to be registered (service from
61 * onClients).
62 */
63 Service& assertRegisteredServiceLocked(const sp<IBase>& service);
64
65 /**
66 * Registers or re-registers services. Returns whether successful.
67 */
68 bool registerServiceLocked(const sp<IBase>& service, const std::string& name);
69
70 /**
71 * Unregisters all services that we can. If we can't unregister all, re-register other
72 * services.
73 */
74 void tryShutdownLocked();
75
76 /**
77 * For below.
78 */
79 std::mutex mMutex;
80
81 /**
82 * Number of services that have been registered.
83 */
84 std::vector<Service> mRegisteredServices;
85
86 /**
87 * Callback for reporting the number of services with clients.
88 */
89 std::function<bool(bool)> mActiveServicesCallback;
90
91 /**
92 * Previous value passed to the active services callback.
93 */
94 std::optional<bool> mPreviousHasClients;
95 };
96
97 class LazyServiceRegistrarImpl {
98 public:
LazyServiceRegistrarImpl()99 LazyServiceRegistrarImpl() : mClientCallback(new ClientCounterCallback) {}
100
101 status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
102 const std::string& name);
103 bool tryUnregister();
104 void reRegister();
105 void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
106
107 private:
108 sp<ClientCounterCallback> mClientCallback;
109 };
110
addRegisteredService(const sp<IBase> & service,const std::string & name)111 bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service,
112 const std::string& name) {
113 std::lock_guard<std::mutex> lock(mMutex);
114 bool success = registerServiceLocked(service, name);
115
116 if (success) {
117 mRegisteredServices.push_back({service, name});
118 }
119
120 return success;
121 }
122
assertRegisteredServiceLocked(const sp<IBase> & service)123 ClientCounterCallback::Service& ClientCounterCallback::assertRegisteredServiceLocked(
124 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
registerServiceLocked(const sp<IBase> & service,const std::string & name)134 bool ClientCounterCallback::registerServiceLocked(const sp<IBase>& service,
135 const std::string& name) {
136 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;
155 }
156
onClients(const sp<::android::hidl::base::V1_0::IBase> & service,bool clients)157 Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
158 bool clients) {
159 std::lock_guard<std::mutex> lock(mMutex);
160 Service& registered = assertRegisteredServiceLocked(service);
161 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++;
171 }
172
173 LOG(INFO) << "Process has " << numWithClients << " (of " << mRegisteredServices.size()
174 << " available) client(s) in use after notification " << getDescriptor(service.get())
175 << "/" << registered.name << " has clients: " << clients;
176
177 bool handledInCallback = false;
178 if (mActiveServicesCallback != nullptr) {
179 bool hasClients = numWithClients != 0;
180 if (hasClients != mPreviousHasClients) {
181 handledInCallback = mActiveServicesCallback(hasClients);
182 mPreviousHasClients = hasClients;
183 }
184 }
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) {
190 tryShutdownLocked();
191 }
192
193 return Status::ok();
194 }
195
tryUnregisterLocked()196 bool ClientCounterCallback::tryUnregisterLocked() {
197 auto manager = hardware::defaultServiceManager1_2();
198
199 for (Service& entry : mRegisteredServices) {
200 const std::string descriptor = getDescriptor(entry.service.get());
201 bool success = manager->tryUnregister(descriptor, entry.name, entry.service);
202
203 if (!success) {
204 LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name;
205 return false;
206 }
207
208 // Mark the entry unregistered, but do not remove it (may still be re-registered)
209 entry.registered = false;
210 }
211
212 return true;
213 }
214
reRegisterLocked()215 void ClientCounterCallback::reRegisterLocked() {
216 for (Service& entry : mRegisteredServices) {
217 // re-register entry if not already registered
218 if (entry.registered) {
219 continue;
220 }
221
222 if (!registerServiceLocked(entry.service, entry.name)) {
223 // 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 }
226
227 entry.registered = true;
228 }
229 }
230
tryShutdownLocked()231 void ClientCounterCallback::tryShutdownLocked() {
232 LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process.";
233
234 if (tryUnregisterLocked()) {
235 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
241 // unregistered by tryUnregisterLocked().
242 reRegisterLocked();
243 }
244
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)245 void ClientCounterCallback::setActiveServicesCallback(
246 const std::function<bool(bool)>& activeServicesCallback) {
247 std::lock_guard<std::mutex> lock(mMutex);
248
249 mActiveServicesCallback = activeServicesCallback;
250 }
251
registerService(const sp<::android::hidl::base::V1_0::IBase> & service,const std::string & name)252 status_t LazyServiceRegistrarImpl::registerService(
253 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
254 if (!mClientCallback->addRegisteredService(service, name)) {
255 return ::android::UNKNOWN_ERROR;
256 }
257
258 return ::android::OK;
259 }
260
tryUnregister()261 bool LazyServiceRegistrarImpl::tryUnregister() {
262 // see comments in header, this should only be called from the active
263 // services callback, see also b/191781736
264 return mClientCallback->tryUnregisterLocked();
265 }
266
reRegister()267 void LazyServiceRegistrarImpl::reRegister() {
268 // see comments in header, this should only be called from the active
269 // services callback, see also b/191781736
270 mClientCallback->reRegisterLocked();
271 }
272
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)273 void LazyServiceRegistrarImpl::setActiveServicesCallback(
274 const std::function<bool(bool)>& activeServicesCallback) {
275 mClientCallback->setActiveServicesCallback(activeServicesCallback);
276 }
277
278 } // namespace details
279
LazyServiceRegistrar()280 LazyServiceRegistrar::LazyServiceRegistrar() {
281 mImpl = std::make_shared<details::LazyServiceRegistrarImpl>();
282 }
283
getInstance()284 LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
285 static auto registrarInstance = new LazyServiceRegistrar();
286 return *registrarInstance;
287 }
288
registerService(const sp<::android::hidl::base::V1_0::IBase> & service,const std::string & name)289 status_t LazyServiceRegistrar::registerService(
290 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
291 return mImpl->registerService(service, name);
292 }
293
tryUnregister()294 bool LazyServiceRegistrar::tryUnregister() {
295 return mImpl->tryUnregister();
296 }
297
reRegister()298 void LazyServiceRegistrar::reRegister() {
299 mImpl->reRegister();
300 }
301
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)302 void LazyServiceRegistrar::setActiveServicesCallback(
303 const std::function<bool(bool)>& activeServicesCallback) {
304 mImpl->setActiveServicesCallback(activeServicesCallback);
305 }
306
307 } // namespace hardware
308 } // namespace android
309