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 <regex>
     10 #include <sstream>
     11 
     12 using android::hardware::IPCThreadState;
     13 
     14 namespace android {
     15 namespace hidl {
     16 namespace manager {
     17 namespace V1_0 {
     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             remove(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     bool found = false;
    136 
    137     for (auto it = mPackageListeners.begin(); it != mPackageListeners.end();) {
    138         if (*it == who) {
    139             it = mPackageListeners.erase(it);
    140             found = true;
    141         } else {
    142             ++it;
    143         }
    144     }
    145 
    146     return found;
    147 }
    148 
    149 // Methods from ::android::hidl::manager::V1_0::IServiceManager follow.
    150 Return<sp<IBase>> ServiceManager::get(const hidl_string& fqName,
    151                                       const hidl_string& name) {
    152     pid_t pid = IPCThreadState::self()->getCallingPid();
    153     if (!mAcl.canGet(fqName, pid)) {
    154         return nullptr;
    155     }
    156 
    157     auto ifaceIt = mServiceMap.find(fqName);
    158     if (ifaceIt == mServiceMap.end()) {
    159         return nullptr;
    160     }
    161 
    162     const PackageInterfaceMap &ifaceMap = ifaceIt->second;
    163     const HidlService *hidlService = ifaceMap.lookup(name);
    164 
    165     if (hidlService == nullptr) {
    166         return nullptr;
    167     }
    168 
    169     return hidlService->getService();
    170 }
    171 
    172 Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& service) {
    173     bool isValidService = false;
    174 
    175     if (service == nullptr) {
    176         return false;
    177     }
    178 
    179     // TODO(b/34235311): use HIDL way to determine this
    180     // also, this assumes that the PID that is registering is the pid that is the service
    181     pid_t pid = IPCThreadState::self()->getCallingPid();
    182 
    183     auto ret = service->interfaceChain([&](const auto &interfaceChain) {
    184         if (interfaceChain.size() == 0) {
    185             return;
    186         }
    187 
    188         // First, verify you're allowed to add() the whole interface hierarchy
    189         for(size_t i = 0; i < interfaceChain.size(); i++) {
    190             std::string fqName = interfaceChain[i];
    191 
    192             if (!mAcl.canAdd(fqName, pid)) {
    193                 return;
    194             }
    195         }
    196 
    197         for(size_t i = 0; i < interfaceChain.size(); i++) {
    198             std::string fqName = interfaceChain[i];
    199 
    200             PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
    201             HidlService *hidlService = ifaceMap.lookup(name);
    202 
    203             if (hidlService == nullptr) {
    204                 ifaceMap.insertService(
    205                     std::make_unique<HidlService>(fqName, name, service, pid));
    206             } else {
    207                 if (hidlService->getService() != nullptr) {
    208                     auto ret = hidlService->getService()->unlinkToDeath(this);
    209                     ret.isOk(); // ignore
    210                 }
    211                 hidlService->setService(service, pid);
    212             }
    213 
    214             ifaceMap.sendPackageRegistrationNotification(fqName, name);
    215         }
    216 
    217         auto linkRet = service->linkToDeath(this, 0 /*cookie*/);
    218         linkRet.isOk(); // ignore
    219 
    220         isValidService = true;
    221     });
    222 
    223     if (!ret.isOk()) {
    224         LOG(ERROR) << "Failed to retrieve interface chain.";
    225         return false;
    226     }
    227 
    228     return isValidService;
    229 }
    230 
    231 Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName,
    232                                                                const hidl_string& name) {
    233     using ::android::hardware::getTransport;
    234 
    235     pid_t pid = IPCThreadState::self()->getCallingPid();
    236     if (!mAcl.canGet(fqName, pid)) {
    237         return Transport::EMPTY;
    238     }
    239 
    240     switch (getTransport(fqName, name)) {
    241         case vintf::Transport::HWBINDER:
    242              return Transport::HWBINDER;
    243         case vintf::Transport::PASSTHROUGH:
    244              return Transport::PASSTHROUGH;
    245         case vintf::Transport::EMPTY:
    246         default:
    247              return Transport::EMPTY;
    248     }
    249 }
    250 
    251 Return<void> ServiceManager::list(list_cb _hidl_cb) {
    252     pid_t pid = IPCThreadState::self()->getCallingPid();
    253     if (!mAcl.canList(pid)) {
    254         _hidl_cb({});
    255         return Void();
    256     }
    257 
    258     hidl_vec<hidl_string> list;
    259 
    260     list.resize(countExistingService());
    261 
    262     size_t idx = 0;
    263     forEachExistingService([&] (const HidlService *service) {
    264         list[idx++] = service->string();
    265     });
    266 
    267     _hidl_cb(list);
    268     return Void();
    269 }
    270 
    271 Return<void> ServiceManager::listByInterface(const hidl_string& fqName,
    272                                              listByInterface_cb _hidl_cb) {
    273     pid_t pid = IPCThreadState::self()->getCallingPid();
    274     if (!mAcl.canGet(fqName, pid)) {
    275         _hidl_cb({});
    276         return Void();
    277     }
    278 
    279     auto ifaceIt = mServiceMap.find(fqName);
    280     if (ifaceIt == mServiceMap.end()) {
    281         _hidl_cb(hidl_vec<hidl_string>());
    282         return Void();
    283     }
    284 
    285     const auto &instanceMap = ifaceIt->second.getInstanceMap();
    286 
    287     hidl_vec<hidl_string> list;
    288 
    289     size_t total = 0;
    290     for (const auto &serviceMapping : instanceMap) {
    291         const std::unique_ptr<HidlService> &service = serviceMapping.second;
    292         if (service->getService() == nullptr) continue;
    293 
    294         ++total;
    295     }
    296     list.resize(total);
    297 
    298     size_t idx = 0;
    299     for (const auto &serviceMapping : instanceMap) {
    300         const std::unique_ptr<HidlService> &service = serviceMapping.second;
    301         if (service->getService() == nullptr) continue;
    302 
    303         list[idx++] = service->getInstanceName();
    304     }
    305 
    306     _hidl_cb(list);
    307     return Void();
    308 }
    309 
    310 Return<bool> ServiceManager::registerForNotifications(const hidl_string& fqName,
    311                                                       const hidl_string& name,
    312                                                       const sp<IServiceNotification>& callback) {
    313     if (callback == nullptr) {
    314         return false;
    315     }
    316 
    317     pid_t pid = IPCThreadState::self()->getCallingPid();
    318     if (!mAcl.canGet(fqName, pid)) {
    319         return false;
    320     }
    321 
    322     PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
    323 
    324     if (name.empty()) {
    325         auto ret = callback->linkToDeath(this, kPackageListenerDiedCookie /*cookie*/);
    326         if (!ret.isOk()) {
    327             LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name;
    328             return false;
    329         }
    330         ifaceMap.addPackageListener(callback);
    331         return true;
    332     }
    333 
    334     HidlService *service = ifaceMap.lookup(name);
    335 
    336     auto ret = callback->linkToDeath(this, kServiceListenerDiedCookie);
    337     if (!ret.isOk()) {
    338         LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name;
    339         return false;
    340     }
    341 
    342     if (service == nullptr) {
    343         auto adding = std::make_unique<HidlService>(fqName, name);
    344         adding->addListener(callback);
    345         ifaceMap.insertService(std::move(adding));
    346     } else {
    347         service->addListener(callback);
    348     }
    349 
    350     return true;
    351 }
    352 
    353 Return<void> ServiceManager::debugDump(debugDump_cb _cb) {
    354     pid_t pid = IPCThreadState::self()->getCallingPid();
    355     if (!mAcl.canList(pid)) {
    356         _cb({});
    357         return Void();
    358     }
    359 
    360     std::vector<IServiceManager::InstanceDebugInfo> list;
    361     forEachServiceEntry([&] (const HidlService *service) {
    362         hidl_vec<int32_t> clientPids;
    363         clientPids.resize(service->getPassthroughClients().size());
    364 
    365         size_t i = 0;
    366         for (pid_t p : service->getPassthroughClients()) {
    367             clientPids[i++] = p;
    368         }
    369 
    370         list.push_back({
    371             .pid = service->getPid(),
    372             .interfaceName = service->getInterfaceName(),
    373             .instanceName = service->getInstanceName(),
    374             .clientPids = clientPids,
    375             .arch = ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN
    376         });
    377     });
    378 
    379     _cb(list);
    380     return Void();
    381 }
    382 
    383 
    384 Return<void> ServiceManager::registerPassthroughClient(const hidl_string &fqName,
    385         const hidl_string &name) {
    386     pid_t pid = IPCThreadState::self()->getCallingPid();
    387     if (!mAcl.canGet(fqName, pid)) {
    388         /* We guard this function with "get", because it's typically used in
    389          * the getService() path, albeit for a passthrough service in this
    390          * case
    391          */
    392         return Void();
    393     }
    394 
    395     PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
    396 
    397     if (name.empty()) {
    398         LOG(WARNING) << "registerPassthroughClient encounters empty instance name for "
    399                      << fqName.c_str();
    400         return Void();
    401     }
    402 
    403     HidlService *service = ifaceMap.lookup(name);
    404 
    405     if (service == nullptr) {
    406         auto adding = std::make_unique<HidlService>(fqName, name);
    407         adding->registerPassthroughClient(pid);
    408         ifaceMap.insertService(std::move(adding));
    409     } else {
    410         service->registerPassthroughClient(pid);
    411     }
    412     return Void();
    413 }
    414 
    415 bool ServiceManager::remove(const wp<IBase>& who) {
    416     bool found = false;
    417     for (auto &interfaceMapping : mServiceMap) {
    418         auto &instanceMap = interfaceMapping.second.getInstanceMap();
    419 
    420         for (auto &servicePair : instanceMap) {
    421             const std::unique_ptr<HidlService> &service = servicePair.second;
    422             if (service->getService() == who) {
    423                 service->setService(nullptr, static_cast<pid_t>(IServiceManager::PidConstant::NO_PID));
    424                 found = true;
    425             }
    426         }
    427     }
    428     return found;
    429 }
    430 
    431 bool ServiceManager::removePackageListener(const wp<IBase>& who) {
    432     bool found = false;
    433 
    434     for (auto &interfaceMapping : mServiceMap) {
    435         found |= interfaceMapping.second.removePackageListener(who);
    436     }
    437 
    438     return found;
    439 }
    440 
    441 bool ServiceManager::removeServiceListener(const wp<IBase>& who) {
    442     bool found = false;
    443     for (auto &interfaceMapping : mServiceMap) {
    444         auto &instanceMap = interfaceMapping.second.getInstanceMap();
    445 
    446         for (auto &servicePair : instanceMap) {
    447             const std::unique_ptr<HidlService> &service = servicePair.second;
    448             found |= service->removeListener(who);
    449         }
    450     }
    451     return found;
    452 }
    453 } // namespace implementation
    454 }  // namespace V1_0
    455 }  // namespace manager
    456 }  // namespace hidl
    457 }  // namespace android
    458