• 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 <hidl/HidlLazyUtils.h>
20 #include <hidl/HidlTransportSupport.h>
21 
22 #include <android-base/logging.h>
23 
24 #include <android/hidl/manager/1.2/IClientCallback.h>
25 #include <android/hidl/manager/1.2/IServiceManager.h>
26 
27 namespace android {
28 namespace hardware {
29 namespace details {
30 
31 using ::android::hidl::base::V1_0::IBase;
32 
33 class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback {
34   public:
ClientCounterCallback()35     ClientCounterCallback() {}
36 
37     bool addRegisteredService(const sp<IBase>& service, const std::string& name);
38 
39     bool tryUnregisterLocked();
40 
41     void reRegisterLocked();
42 
43     void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
44 
45   protected:
46     Return<void> onClients(const sp<IBase>& service, bool clients) override;
47 
48   private:
49     struct Service {
50         sp<IBase> service;
51         std::string name;
52         bool clients = false;
53         // Used to keep track of unregistered services to allow re-registry
54         bool registered = true;
55     };
56 
57     /**
58      * Looks up service that is guaranteed to be registered (service from
59      * onClients).
60      */
61     Service& assertRegisteredServiceLocked(const sp<IBase>& service);
62 
63     /**
64      * Registers or re-registers services. Returns whether successful.
65      */
66     bool registerServiceLocked(const sp<IBase>& service, const std::string& name);
67 
68     /**
69      * Unregisters all services that we can. If we can't unregister all, re-register other
70      * services.
71      */
72     void tryShutdownLocked();
73 
74     /**
75      * For below.
76      */
77     std::mutex mMutex;
78 
79     /**
80      * Number of services that have been registered.
81      */
82     std::vector<Service> mRegisteredServices;
83 
84     /**
85      * Callback for reporting the number of services with clients.
86      */
87     std::function<bool(bool)> mActiveServicesCallback;
88 
89     /**
90      * Previous value passed to the active services callback.
91      */
92     std::optional<bool> mPreviousHasClients;
93 };
94 
95 class LazyServiceRegistrarImpl {
96   public:
LazyServiceRegistrarImpl()97     LazyServiceRegistrarImpl() : mClientCallback(new ClientCounterCallback) {}
98 
99     status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
100                              const std::string& name);
101     bool tryUnregister();
102     void reRegister();
103     void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
104 
105   private:
106     sp<ClientCounterCallback> mClientCallback;
107 };
108 
addRegisteredService(const sp<IBase> & service,const std::string & name)109 bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service,
110                                                  const std::string& name) {
111     std::lock_guard<std::mutex> lock(mMutex);
112     bool success = registerServiceLocked(service, name);
113 
114     if (success) {
115         mRegisteredServices.push_back({service, name});
116     }
117 
118     return success;
119 }
120 
assertRegisteredServiceLocked(const sp<IBase> & service)121 ClientCounterCallback::Service& ClientCounterCallback::assertRegisteredServiceLocked(
122         const sp<IBase>& service) {
123     for (Service& registered : mRegisteredServices) {
124         if (registered.service != service) continue;
125         return registered;
126     }
127     LOG(FATAL) << "Got callback on service " << getDescriptor(service.get())
128                << " which we did not register.";
129     __builtin_unreachable();
130 }
131 
registerServiceLocked(const sp<IBase> & service,const std::string & name)132 bool ClientCounterCallback::registerServiceLocked(const sp<IBase>& service,
133                                                   const std::string& name) {
134     auto manager = hardware::defaultServiceManager1_2();
135 
136     const std::string descriptor = getDescriptor(service.get());
137 
138     LOG(INFO) << "Registering HAL: " << descriptor << " with name: " << name;
139 
140     status_t res = android::hardware::details::registerAsServiceInternal(service, name);
141     if (res != android::OK) {
142         LOG(ERROR) << "Failed to register as service.";
143         return false;
144     }
145 
146     bool ret = manager->registerClientCallback(getDescriptor(service.get()), name, service, this);
147     if (!ret) {
148         LOG(ERROR) << "Failed to add client callback.";
149         return false;
150     }
151 
152     return true;
153 }
154 
onClients(const sp<::android::hidl::base::V1_0::IBase> & service,bool clients)155 Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
156                                               bool clients) {
157     std::lock_guard<std::mutex> lock(mMutex);
158     Service& registered = assertRegisteredServiceLocked(service);
159     if (registered.clients == clients) {
160         LOG(FATAL) << "Process already thought " << getDescriptor(service.get()) << "/"
161                    << registered.name << " had clients: " << registered.clients
162                    << " but hwservicemanager has notified has clients: " << clients;
163     }
164     registered.clients = clients;
165 
166     size_t numWithClients = 0;
167     for (const Service& registered : mRegisteredServices) {
168         if (registered.clients) numWithClients++;
169     }
170 
171     LOG(INFO) << "Process has " << numWithClients << " (of " << mRegisteredServices.size()
172               << " available) client(s) in use after notification " << getDescriptor(service.get())
173               << "/" << registered.name << " has clients: " << clients;
174 
175     bool handledInCallback = false;
176     if (mActiveServicesCallback != nullptr) {
177         bool hasClients = numWithClients != 0;
178         if (hasClients != mPreviousHasClients) {
179             handledInCallback = mActiveServicesCallback(hasClients);
180             mPreviousHasClients = hasClients;
181         }
182     }
183 
184     // If there is no callback defined or the callback did not handle this
185     // client count change event, try to shutdown the process if its services
186     // have no clients.
187     if (!handledInCallback && numWithClients == 0) {
188         tryShutdownLocked();
189     }
190 
191     return Status::ok();
192 }
193 
tryUnregisterLocked()194 bool ClientCounterCallback::tryUnregisterLocked() {
195     auto manager = hardware::defaultServiceManager1_2();
196 
197     for (Service& entry : mRegisteredServices) {
198         const std::string descriptor = getDescriptor(entry.service.get());
199         bool success = manager->tryUnregister(descriptor, entry.name, entry.service);
200 
201         if (!success) {
202             LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name;
203             return false;
204         }
205 
206         // Mark the entry unregistered, but do not remove it (may still be re-registered)
207         entry.registered = false;
208     }
209 
210     return true;
211 }
212 
reRegisterLocked()213 void ClientCounterCallback::reRegisterLocked() {
214     for (Service& entry : mRegisteredServices) {
215         // re-register entry if not already registered
216         if (entry.registered) {
217             continue;
218         }
219 
220         if (!registerServiceLocked(entry.service, entry.name)) {
221             // Must restart. Otherwise, clients will never be able to get ahold of this service.
222             LOG(FATAL) << "Bad state: could not re-register " << getDescriptor(entry.service.get());
223         }
224 
225         entry.registered = true;
226     }
227 }
228 
tryShutdownLocked()229 void ClientCounterCallback::tryShutdownLocked() {
230     LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process.";
231 
232     if (tryUnregisterLocked()) {
233         LOG(INFO) << "Unregistered all clients and exiting";
234         exit(EXIT_SUCCESS);
235     }
236 
237     // At this point, we failed to unregister some of the services, leaving the
238     // server in an inconsistent state. Re-register all services that were
239     // unregistered by tryUnregisterLocked().
240     reRegisterLocked();
241 }
242 
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)243 void ClientCounterCallback::setActiveServicesCallback(
244         const std::function<bool(bool)>& activeServicesCallback) {
245     std::lock_guard<std::mutex> lock(mMutex);
246 
247     mActiveServicesCallback = activeServicesCallback;
248 }
249 
registerService(const sp<::android::hidl::base::V1_0::IBase> & service,const std::string & name)250 status_t LazyServiceRegistrarImpl::registerService(
251     const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
252     if (!mClientCallback->addRegisteredService(service, name)) {
253         return ::android::UNKNOWN_ERROR;
254     }
255 
256     return ::android::OK;
257 }
258 
tryUnregister()259 bool LazyServiceRegistrarImpl::tryUnregister() {
260     // see comments in header, this should only be called from the active
261     // services callback, see also b/191781736
262     return mClientCallback->tryUnregisterLocked();
263 }
264 
reRegister()265 void LazyServiceRegistrarImpl::reRegister() {
266     // see comments in header, this should only be called from the active
267     // services callback, see also b/191781736
268     mClientCallback->reRegisterLocked();
269 }
270 
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)271 void LazyServiceRegistrarImpl::setActiveServicesCallback(
272         const std::function<bool(bool)>& activeServicesCallback) {
273     mClientCallback->setActiveServicesCallback(activeServicesCallback);
274 }
275 
276 }  // namespace details
277 
LazyServiceRegistrar()278 LazyServiceRegistrar::LazyServiceRegistrar() {
279     mImpl = std::make_shared<details::LazyServiceRegistrarImpl>();
280 }
281 
getInstance()282 LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
283     static auto registrarInstance = new LazyServiceRegistrar();
284     return *registrarInstance;
285 }
286 
registerService(const sp<::android::hidl::base::V1_0::IBase> & service,const std::string & name)287 status_t LazyServiceRegistrar::registerService(
288     const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
289     return mImpl->registerService(service, name);
290 }
291 
tryUnregister()292 bool LazyServiceRegistrar::tryUnregister() {
293     return mImpl->tryUnregister();
294 }
295 
reRegister()296 void LazyServiceRegistrar::reRegister() {
297     mImpl->reRegister();
298 }
299 
setActiveServicesCallback(const std::function<bool (bool)> & activeServicesCallback)300 void LazyServiceRegistrar::setActiveServicesCallback(
301         const std::function<bool(bool)>& activeServicesCallback) {
302     mImpl->setActiveServicesCallback(activeServicesCallback);
303 }
304 
305 }  // namespace hardware
306 }  // namespace android
307