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 #include <hidl/HidlLazyUtils.h>
18 #include <hidl/HidlTransportSupport.h>
19
20 #include <android-base/logging.h>
21
22 #include <android/hidl/manager/1.2/IClientCallback.h>
23 #include <android/hidl/manager/1.2/IServiceManager.h>
24
25 namespace android {
26 namespace hardware {
27 namespace details {
28
29 using ::android::hidl::base::V1_0::IBase;
30
31 class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback {
32 public:
ClientCounterCallback()33 ClientCounterCallback() : mNumConnectedServices(0) {}
34
35 bool addRegisteredService(const sp<IBase>& service, const std::string& name);
36
37 protected:
38 Return<void> onClients(const sp<IBase>& service, bool clients) override;
39
40 private:
41 /**
42 * Registers or re-registers services. Returns whether successful.
43 */
44 bool registerService(const sp<IBase>& service, const std::string& name);
45
46 /**
47 * Unregisters all services that we can. If we can't unregister all, re-register other
48 * services.
49 */
50 void tryShutdown();
51
52 /**
53 * Counter of the number of services that currently have at least one client.
54 */
55 size_t mNumConnectedServices;
56
57 struct Service {
58 sp<IBase> service;
59 std::string name;
60 };
61 /**
62 * Number of services that have been registered.
63 */
64 std::vector<Service> mRegisteredServices;
65 };
66
67 class LazyServiceRegistrarImpl {
68 public:
LazyServiceRegistrarImpl()69 LazyServiceRegistrarImpl() : mClientCallback(new ClientCounterCallback) {}
70
71 status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
72 const std::string& name);
73
74 private:
75 sp<ClientCounterCallback> mClientCallback;
76 };
77
addRegisteredService(const sp<IBase> & service,const std::string & name)78 bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service,
79 const std::string& name) {
80 bool success = registerService(service, name);
81
82 if (success) {
83 mRegisteredServices.push_back({service, name});
84 }
85
86 return success;
87 }
88
registerService(const sp<IBase> & service,const std::string & name)89 bool ClientCounterCallback::registerService(const sp<IBase>& service, const std::string& name) {
90 auto manager = hardware::defaultServiceManager1_2();
91
92 const std::string descriptor = getDescriptor(service.get());
93
94 LOG(INFO) << "Registering HAL: " << descriptor << " with name: " << name;
95
96 status_t res = android::hardware::details::registerAsServiceInternal(service, name);
97 if (res != android::OK) {
98 LOG(ERROR) << "Failed to register as service.";
99 return false;
100 }
101
102 bool ret = manager->registerClientCallback(getDescriptor(service.get()), name, service, this);
103 if (!ret) {
104 LOG(ERROR) << "Failed to add client callback.";
105 return false;
106 }
107
108 return true;
109 }
110
111 /**
112 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
113 * invocations could occur on different threads however.
114 */
onClients(const sp<::android::hidl::base::V1_0::IBase> & service,bool clients)115 Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
116 bool clients) {
117 if (clients) {
118 mNumConnectedServices++;
119 } else {
120 mNumConnectedServices--;
121 }
122
123 LOG(INFO) << "Process has " << mNumConnectedServices << " (of " << mRegisteredServices.size()
124 << " available) client(s) in use after notification " << getDescriptor(service.get())
125 << " has clients: " << clients;
126
127 if (mNumConnectedServices == 0) {
128 tryShutdown();
129 }
130
131 return Status::ok();
132 }
133
tryShutdown()134 void ClientCounterCallback::tryShutdown() {
135 LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process.";
136
137 auto manager = hardware::defaultServiceManager1_2();
138
139 auto unRegisterIt = mRegisteredServices.begin();
140 for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
141 auto& entry = (*unRegisterIt);
142
143 const std::string descriptor = getDescriptor(entry.service.get());
144 bool success = manager->tryUnregister(descriptor, entry.name, entry.service);
145
146 if (!success) {
147 LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name;
148 break;
149 }
150 }
151
152 if (unRegisterIt == mRegisteredServices.end()) {
153 LOG(INFO) << "Unregistered all clients and exiting";
154 exit(EXIT_SUCCESS);
155 }
156
157 for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
158 reRegisterIt++) {
159 auto& entry = (*reRegisterIt);
160
161 // re-register entry
162 if (!registerService(entry.service, entry.name)) {
163 // Must restart. Otherwise, clients will never be able to get ahold of this service.
164 LOG(FATAL) << "Bad state: could not re-register " << getDescriptor(entry.service.get());
165 }
166 }
167 }
168
registerService(const sp<::android::hidl::base::V1_0::IBase> & service,const std::string & name)169 status_t LazyServiceRegistrarImpl::registerService(
170 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
171 if (!mClientCallback->addRegisteredService(service, name)) {
172 return ::android::UNKNOWN_ERROR;
173 }
174
175 return ::android::OK;
176 }
177
178 } // namespace details
179
LazyServiceRegistrar()180 LazyServiceRegistrar::LazyServiceRegistrar() {
181 mImpl = std::make_shared<details::LazyServiceRegistrarImpl>();
182 }
183
registerService(const sp<::android::hidl::base::V1_0::IBase> & service,const std::string & name)184 status_t LazyServiceRegistrar::registerService(
185 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
186 return mImpl->registerService(service, name);
187 }
188
189 } // namespace hardware
190 } // namespace android
191