1 #define LOG_TAG "hwservicemanager" 2 3 #include "ServiceManager.h" 4 #include "Vintf.h" 5 6 #include <android-base/logging.h> 7 #include <hwbinder/IPCThreadState.h> 8 #include <hidl/HidlSupport.h> 9 #include <hidl/HidlTransportSupport.h> 10 #include <regex> 11 #include <sstream> 12 13 using android::hardware::IPCThreadState; 14 15 namespace android { 16 namespace hidl { 17 namespace manager { 18 namespace implementation { 19 20 static constexpr uint64_t kServiceDiedCookie = 0; 21 static constexpr uint64_t kPackageListenerDiedCookie = 1; 22 static constexpr uint64_t kServiceListenerDiedCookie = 2; 23 24 size_t ServiceManager::countExistingService() const { 25 size_t total = 0; 26 forEachExistingService([&] (const HidlService *) { 27 ++total; 28 }); 29 return total; 30 } 31 32 void ServiceManager::forEachExistingService(std::function<void(const HidlService *)> f) const { 33 forEachServiceEntry([f] (const HidlService *service) { 34 if (service->getService() == nullptr) { 35 return; 36 } 37 f(service); 38 }); 39 } 40 41 void ServiceManager::forEachServiceEntry(std::function<void(const HidlService *)> f) const { 42 for (const auto &interfaceMapping : mServiceMap) { 43 const auto &instanceMap = interfaceMapping.second.getInstanceMap(); 44 45 for (const auto &instanceMapping : instanceMap) { 46 f(instanceMapping.second.get()); 47 } 48 } 49 } 50 51 void ServiceManager::serviceDied(uint64_t cookie, const wp<IBase>& who) { 52 switch (cookie) { 53 case kServiceDiedCookie: 54 removeService(who); 55 break; 56 case kPackageListenerDiedCookie: 57 removePackageListener(who); 58 break; 59 case kServiceListenerDiedCookie: 60 removeServiceListener(who); 61 break; 62 } 63 } 64 65 ServiceManager::InstanceMap &ServiceManager::PackageInterfaceMap::getInstanceMap() { 66 return mInstanceMap; 67 } 68 69 const ServiceManager::InstanceMap &ServiceManager::PackageInterfaceMap::getInstanceMap() const { 70 return mInstanceMap; 71 } 72 73 const HidlService *ServiceManager::PackageInterfaceMap::lookup( 74 const std::string &name) const { 75 auto it = mInstanceMap.find(name); 76 77 if (it == mInstanceMap.end()) { 78 return nullptr; 79 } 80 81 return it->second.get(); 82 } 83 84 HidlService *ServiceManager::PackageInterfaceMap::lookup( 85 const std::string &name) { 86 87 return const_cast<HidlService*>( 88 const_cast<const PackageInterfaceMap*>(this)->lookup(name)); 89 } 90 91 void ServiceManager::PackageInterfaceMap::insertService( 92 std::unique_ptr<HidlService> &&service) { 93 mInstanceMap.insert({service->getInstanceName(), std::move(service)}); 94 } 95 96 void ServiceManager::PackageInterfaceMap::sendPackageRegistrationNotification( 97 const hidl_string &fqName, 98 const hidl_string &instanceName) { 99 100 for (auto it = mPackageListeners.begin(); it != mPackageListeners.end();) { 101 auto ret = (*it)->onRegistration(fqName, instanceName, false /* preexisting */); 102 if (ret.isOk()) { 103 ++it; 104 } else { 105 LOG(ERROR) << "Dropping registration callback for " << fqName << "/" << instanceName 106 << ": transport error."; 107 it = mPackageListeners.erase(it); 108 } 109 } 110 } 111 112 void ServiceManager::PackageInterfaceMap::addPackageListener(sp<IServiceNotification> listener) { 113 for (const auto &instanceMapping : mInstanceMap) { 114 const std::unique_ptr<HidlService> &service = instanceMapping.second; 115 116 if (service->getService() == nullptr) { 117 continue; 118 } 119 120 auto ret = listener->onRegistration( 121 service->getInterfaceName(), 122 service->getInstanceName(), 123 true /* preexisting */); 124 if (!ret.isOk()) { 125 LOG(ERROR) << "Not adding package listener for " << service->getInterfaceName() 126 << "/" << service->getInstanceName() << ": transport error " 127 << "when sending notification for already registered instance."; 128 return; 129 } 130 } 131 mPackageListeners.push_back(listener); 132 } 133 134 bool ServiceManager::PackageInterfaceMap::removePackageListener(const wp<IBase>& who) { 135 using ::android::hardware::interfacesEqual; 136 137 bool found = false; 138 139 for (auto it = mPackageListeners.begin(); it != mPackageListeners.end();) { 140 if (interfacesEqual(*it, who.promote())) { 141 it = mPackageListeners.erase(it); 142 found = true; 143 } else { 144 ++it; 145 } 146 } 147 148 return found; 149 } 150 151 bool ServiceManager::PackageInterfaceMap::removeServiceListener(const wp<IBase>& who) { 152 using ::android::hardware::interfacesEqual; 153 154 bool found = false; 155 156 for (auto &servicePair : getInstanceMap()) { 157 const std::unique_ptr<HidlService> &service = servicePair.second; 158 found |= service->removeListener(who); 159 } 160 161 return found; 162 } 163 164 // Methods from ::android::hidl::manager::V1_0::IServiceManager follow. 165 Return<sp<IBase>> ServiceManager::get(const hidl_string& fqName, 166 const hidl_string& name) { 167 pid_t pid = IPCThreadState::self()->getCallingPid(); 168 if (!mAcl.canGet(fqName, pid)) { 169 return nullptr; 170 } 171 172 auto ifaceIt = mServiceMap.find(fqName); 173 if (ifaceIt == mServiceMap.end()) { 174 return nullptr; 175 } 176 177 const PackageInterfaceMap &ifaceMap = ifaceIt->second; 178 const HidlService *hidlService = ifaceMap.lookup(name); 179 180 if (hidlService == nullptr) { 181 return nullptr; 182 } 183 184 return hidlService->getService(); 185 } 186 187 Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& service) { 188 bool isValidService = false; 189 190 if (service == nullptr) { 191 return false; 192 } 193 194 // TODO(b/34235311): use HIDL way to determine this 195 // also, this assumes that the PID that is registering is the pid that is the service 196 pid_t pid = IPCThreadState::self()->getCallingPid(); 197 198 auto ret = service->interfaceChain([&](const auto &interfaceChain) { 199 if (interfaceChain.size() == 0) { 200 return; 201 } 202 203 // First, verify you're allowed to add() the whole interface hierarchy 204 for(size_t i = 0; i < interfaceChain.size(); i++) { 205 std::string fqName = interfaceChain[i]; 206 207 if (!mAcl.canAdd(fqName, pid)) { 208 return; 209 } 210 } 211 212 for(size_t i = 0; i < interfaceChain.size(); i++) { 213 std::string fqName = interfaceChain[i]; 214 215 PackageInterfaceMap &ifaceMap = mServiceMap[fqName]; 216 HidlService *hidlService = ifaceMap.lookup(name); 217 218 if (hidlService == nullptr) { 219 ifaceMap.insertService( 220 std::make_unique<HidlService>(fqName, name, service, pid)); 221 } else { 222 if (hidlService->getService() != nullptr) { 223 auto ret = hidlService->getService()->unlinkToDeath(this); 224 ret.isOk(); // ignore 225 } 226 hidlService->setService(service, pid); 227 } 228 229 ifaceMap.sendPackageRegistrationNotification(fqName, name); 230 } 231 232 auto linkRet = service->linkToDeath(this, 0 /*cookie*/); 233 linkRet.isOk(); // ignore 234 235 isValidService = true; 236 }); 237 238 if (!ret.isOk()) { 239 LOG(ERROR) << "Failed to retrieve interface chain."; 240 return false; 241 } 242 243 return isValidService; 244 } 245 246 Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName, 247 const hidl_string& name) { 248 using ::android::hardware::getTransport; 249 250 pid_t pid = IPCThreadState::self()->getCallingPid(); 251 if (!mAcl.canGet(fqName, pid)) { 252 return Transport::EMPTY; 253 } 254 255 switch (getTransport(fqName, name)) { 256 case vintf::Transport::HWBINDER: 257 return Transport::HWBINDER; 258 case vintf::Transport::PASSTHROUGH: 259 return Transport::PASSTHROUGH; 260 case vintf::Transport::EMPTY: 261 default: 262 return Transport::EMPTY; 263 } 264 } 265 266 Return<void> ServiceManager::list(list_cb _hidl_cb) { 267 pid_t pid = IPCThreadState::self()->getCallingPid(); 268 if (!mAcl.canList(pid)) { 269 _hidl_cb({}); 270 return Void(); 271 } 272 273 hidl_vec<hidl_string> list; 274 275 list.resize(countExistingService()); 276 277 size_t idx = 0; 278 forEachExistingService([&] (const HidlService *service) { 279 list[idx++] = service->string(); 280 }); 281 282 _hidl_cb(list); 283 return Void(); 284 } 285 286 Return<void> ServiceManager::listByInterface(const hidl_string& fqName, 287 listByInterface_cb _hidl_cb) { 288 pid_t pid = IPCThreadState::self()->getCallingPid(); 289 if (!mAcl.canGet(fqName, pid)) { 290 _hidl_cb({}); 291 return Void(); 292 } 293 294 auto ifaceIt = mServiceMap.find(fqName); 295 if (ifaceIt == mServiceMap.end()) { 296 _hidl_cb(hidl_vec<hidl_string>()); 297 return Void(); 298 } 299 300 const auto &instanceMap = ifaceIt->second.getInstanceMap(); 301 302 hidl_vec<hidl_string> list; 303 304 size_t total = 0; 305 for (const auto &serviceMapping : instanceMap) { 306 const std::unique_ptr<HidlService> &service = serviceMapping.second; 307 if (service->getService() == nullptr) continue; 308 309 ++total; 310 } 311 list.resize(total); 312 313 size_t idx = 0; 314 for (const auto &serviceMapping : instanceMap) { 315 const std::unique_ptr<HidlService> &service = serviceMapping.second; 316 if (service->getService() == nullptr) continue; 317 318 list[idx++] = service->getInstanceName(); 319 } 320 321 _hidl_cb(list); 322 return Void(); 323 } 324 325 Return<bool> ServiceManager::registerForNotifications(const hidl_string& fqName, 326 const hidl_string& name, 327 const sp<IServiceNotification>& callback) { 328 if (callback == nullptr) { 329 return false; 330 } 331 332 pid_t pid = IPCThreadState::self()->getCallingPid(); 333 if (!mAcl.canGet(fqName, pid)) { 334 return false; 335 } 336 337 PackageInterfaceMap &ifaceMap = mServiceMap[fqName]; 338 339 if (name.empty()) { 340 auto ret = callback->linkToDeath(this, kPackageListenerDiedCookie /*cookie*/); 341 if (!ret.isOk()) { 342 LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name; 343 return false; 344 } 345 ifaceMap.addPackageListener(callback); 346 return true; 347 } 348 349 HidlService *service = ifaceMap.lookup(name); 350 351 auto ret = callback->linkToDeath(this, kServiceListenerDiedCookie); 352 if (!ret.isOk()) { 353 LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name; 354 return false; 355 } 356 357 if (service == nullptr) { 358 auto adding = std::make_unique<HidlService>(fqName, name); 359 adding->addListener(callback); 360 ifaceMap.insertService(std::move(adding)); 361 } else { 362 service->addListener(callback); 363 } 364 365 return true; 366 } 367 368 Return<bool> ServiceManager::unregisterForNotifications(const hidl_string& fqName, 369 const hidl_string& name, 370 const sp<IServiceNotification>& callback) { 371 if (callback == nullptr) { 372 LOG(ERROR) << "Cannot unregister null callback for " << fqName << "/" << name; 373 return false; 374 } 375 376 // NOTE: don't need ACL since callback is binder token, and if someone has gotten it, 377 // then they already have access to it. 378 379 if (fqName.empty()) { 380 bool success = false; 381 success |= removePackageListener(callback); 382 success |= removeServiceListener(callback); 383 return success; 384 } 385 386 PackageInterfaceMap &ifaceMap = mServiceMap[fqName]; 387 388 if (name.empty()) { 389 bool success = false; 390 success |= ifaceMap.removePackageListener(callback); 391 success |= ifaceMap.removeServiceListener(callback); 392 return success; 393 } 394 395 HidlService *service = ifaceMap.lookup(name); 396 397 if (service == nullptr) { 398 return false; 399 } 400 401 return service->removeListener(callback); 402 } 403 404 Return<void> ServiceManager::debugDump(debugDump_cb _cb) { 405 pid_t pid = IPCThreadState::self()->getCallingPid(); 406 if (!mAcl.canList(pid)) { 407 _cb({}); 408 return Void(); 409 } 410 411 std::vector<IServiceManager::InstanceDebugInfo> list; 412 forEachServiceEntry([&] (const HidlService *service) { 413 hidl_vec<int32_t> clientPids; 414 clientPids.resize(service->getPassthroughClients().size()); 415 416 size_t i = 0; 417 for (pid_t p : service->getPassthroughClients()) { 418 clientPids[i++] = p; 419 } 420 421 list.push_back({ 422 .pid = service->getPid(), 423 .interfaceName = service->getInterfaceName(), 424 .instanceName = service->getInstanceName(), 425 .clientPids = clientPids, 426 .arch = ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN 427 }); 428 }); 429 430 _cb(list); 431 return Void(); 432 } 433 434 435 Return<void> ServiceManager::registerPassthroughClient(const hidl_string &fqName, 436 const hidl_string &name) { 437 pid_t pid = IPCThreadState::self()->getCallingPid(); 438 if (!mAcl.canGet(fqName, pid)) { 439 /* We guard this function with "get", because it's typically used in 440 * the getService() path, albeit for a passthrough service in this 441 * case 442 */ 443 return Void(); 444 } 445 446 PackageInterfaceMap &ifaceMap = mServiceMap[fqName]; 447 448 if (name.empty()) { 449 LOG(WARNING) << "registerPassthroughClient encounters empty instance name for " 450 << fqName.c_str(); 451 return Void(); 452 } 453 454 HidlService *service = ifaceMap.lookup(name); 455 456 if (service == nullptr) { 457 auto adding = std::make_unique<HidlService>(fqName, name); 458 adding->registerPassthroughClient(pid); 459 ifaceMap.insertService(std::move(adding)); 460 } else { 461 service->registerPassthroughClient(pid); 462 } 463 return Void(); 464 } 465 466 bool ServiceManager::removeService(const wp<IBase>& who) { 467 using ::android::hardware::interfacesEqual; 468 469 bool found = false; 470 for (auto &interfaceMapping : mServiceMap) { 471 auto &instanceMap = interfaceMapping.second.getInstanceMap(); 472 473 for (auto &servicePair : instanceMap) { 474 const std::unique_ptr<HidlService> &service = servicePair.second; 475 if (interfacesEqual(service->getService(), who.promote())) { 476 service->setService(nullptr, static_cast<pid_t>(IServiceManager::PidConstant::NO_PID)); 477 found = true; 478 } 479 } 480 } 481 return found; 482 } 483 484 bool ServiceManager::removePackageListener(const wp<IBase>& who) { 485 bool found = false; 486 487 for (auto &interfaceMapping : mServiceMap) { 488 found |= interfaceMapping.second.removePackageListener(who); 489 } 490 491 return found; 492 } 493 494 bool ServiceManager::removeServiceListener(const wp<IBase>& who) { 495 bool found = false; 496 for (auto &interfaceMapping : mServiceMap) { 497 auto &packageInterfaceMap = interfaceMapping.second; 498 499 found |= packageInterfaceMap.removeServiceListener(who); 500 } 501 return found; 502 } 503 } // namespace implementation 504 } // namespace manager 505 } // namespace hidl 506 } // namespace android 507