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