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 <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