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 
countExistingService() const24 size_t ServiceManager::countExistingService() const {
25     size_t total = 0;
26     forEachExistingService([&] (const HidlService *) {
27         ++total;
28     });
29     return total;
30 }
31 
forEachExistingService(std::function<void (const HidlService *)> f) const32 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 
forEachServiceEntry(std::function<void (const HidlService *)> f) const41 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 
serviceDied(uint64_t cookie,const wp<IBase> & who)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 
getInstanceMap()65 ServiceManager::InstanceMap &ServiceManager::PackageInterfaceMap::getInstanceMap() {
66     return mInstanceMap;
67 }
68 
getInstanceMap() const69 const ServiceManager::InstanceMap &ServiceManager::PackageInterfaceMap::getInstanceMap() const {
70     return mInstanceMap;
71 }
72 
lookup(const std::string & name) const73 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 
lookup(const std::string & name)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 
insertService(std::unique_ptr<HidlService> && service)91 void ServiceManager::PackageInterfaceMap::insertService(
92         std::unique_ptr<HidlService> &&service) {
93     mInstanceMap.insert({service->getInstanceName(), std::move(service)});
94 }
95 
sendPackageRegistrationNotification(const hidl_string & fqName,const hidl_string & instanceName)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 
addPackageListener(sp<IServiceNotification> listener)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 
removePackageListener(const wp<IBase> & who)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.
get(const hidl_string & fqName,const hidl_string & name)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 
add(const hidl_string & name,const sp<IBase> & service)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 
getTransport(const hidl_string & fqName,const hidl_string & name)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 
list(list_cb _hidl_cb)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 
listByInterface(const hidl_string & fqName,listByInterface_cb _hidl_cb)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 
registerForNotifications(const hidl_string & fqName,const hidl_string & name,const sp<IServiceNotification> & callback)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 
debugDump(debugDump_cb _cb)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 
registerPassthroughClient(const hidl_string & fqName,const hidl_string & name)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 
remove(const wp<IBase> & who)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 
removePackageListener(const wp<IBase> & who)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 
removeServiceListener(const wp<IBase> & who)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