• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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