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
12using android::hardware::IPCThreadState;
13
14namespace android {
15namespace hidl {
16namespace manager {
17namespace V1_0 {
18namespace implementation {
19
20static constexpr uint64_t kServiceDiedCookie = 0;
21static constexpr uint64_t kPackageListenerDiedCookie = 1;
22static constexpr uint64_t kServiceListenerDiedCookie = 2;
23
24size_t ServiceManager::countExistingService() const {
25    size_t total = 0;
26    forEachExistingService([&] (const HidlService *) {
27        ++total;
28    });
29    return total;
30}
31
32void 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
41void 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
51void 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
65ServiceManager::InstanceMap &ServiceManager::PackageInterfaceMap::getInstanceMap() {
66    return mInstanceMap;
67}
68
69const ServiceManager::InstanceMap &ServiceManager::PackageInterfaceMap::getInstanceMap() const {
70    return mInstanceMap;
71}
72
73const 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
84HidlService *ServiceManager::PackageInterfaceMap::lookup(
85        const std::string &name) {
86
87    return const_cast<HidlService*>(
88        const_cast<const PackageInterfaceMap*>(this)->lookup(name));
89}
90
91void ServiceManager::PackageInterfaceMap::insertService(
92        std::unique_ptr<HidlService> &&service) {
93    mInstanceMap.insert({service->getInstanceName(), std::move(service)});
94}
95
96void 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
112void 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
134bool 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.
150Return<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
172Return<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
231Return<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
251Return<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
271Return<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
310Return<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
353Return<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
384Return<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
415bool 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
431bool 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
441bool 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