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