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