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: 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: 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 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 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 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 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 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 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 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 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 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 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 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 271 void LazyServiceRegistrarImpl::setActiveServicesCallback( 272 const std::function<bool(bool)>& activeServicesCallback) { 273 mClientCallback->setActiveServicesCallback(activeServicesCallback); 274 } 275 276 } // namespace details 277 278 LazyServiceRegistrar::LazyServiceRegistrar() { 279 mImpl = std::make_shared<details::LazyServiceRegistrarImpl>(); 280 } 281 282 LazyServiceRegistrar& LazyServiceRegistrar::getInstance() { 283 static auto registrarInstance = new LazyServiceRegistrar(); 284 return *registrarInstance; 285 } 286 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 292 bool LazyServiceRegistrar::tryUnregister() { 293 return mImpl->tryUnregister(); 294 } 295 296 void LazyServiceRegistrar::reRegister() { 297 mImpl->reRegister(); 298 } 299 300 void LazyServiceRegistrar::setActiveServicesCallback( 301 const std::function<bool(bool)>& activeServicesCallback) { 302 mImpl->setActiveServicesCallback(activeServicesCallback); 303 } 304 305 } // namespace hardware 306 } // namespace android 307