1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "ServiceManagement" 18 19 #include <android/dlext.h> 20 #include <condition_variable> 21 #include <dlfcn.h> 22 #include <dirent.h> 23 #include <fstream> 24 #include <pthread.h> 25 #include <unistd.h> 26 27 #include <mutex> 28 #include <regex> 29 #include <set> 30 31 #include <hidl/HidlBinderSupport.h> 32 #include <hidl/ServiceManagement.h> 33 #include <hidl/Status.h> 34 35 #include <android-base/logging.h> 36 #include <android-base/properties.h> 37 #include <hwbinder/IPCThreadState.h> 38 #include <hwbinder/Parcel.h> 39 #include <vndksupport/linker.h> 40 41 #include <android/hidl/manager/1.1/IServiceManager.h> 42 #include <android/hidl/manager/1.1/BpHwServiceManager.h> 43 #include <android/hidl/manager/1.1/BnHwServiceManager.h> 44 45 #define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*" 46 #define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*" 47 static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so"); 48 49 using android::base::WaitForProperty; 50 51 using IServiceManager1_0 = android::hidl::manager::V1_0::IServiceManager; 52 using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager; 53 using android::hidl::manager::V1_0::IServiceNotification; 54 using android::hidl::manager::V1_1::BpHwServiceManager; 55 using android::hidl::manager::V1_1::BnHwServiceManager; 56 57 namespace android { 58 namespace hardware { 59 60 namespace details { 61 extern Mutex gDefaultServiceManagerLock; 62 extern sp<android::hidl::manager::V1_1::IServiceManager> gDefaultServiceManager; 63 } // namespace details 64 65 static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready"; 66 67 void waitForHwServiceManager() { 68 using std::literals::chrono_literals::operator""s; 69 70 while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) { 71 LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another..."; 72 } 73 } 74 75 bool endsWith(const std::string &in, const std::string &suffix) { 76 return in.size() >= suffix.size() && 77 in.substr(in.size() - suffix.size()) == suffix; 78 } 79 80 bool startsWith(const std::string &in, const std::string &prefix) { 81 return in.size() >= prefix.size() && 82 in.substr(0, prefix.size()) == prefix; 83 } 84 85 std::string binaryName() { 86 std::ifstream ifs("/proc/self/cmdline"); 87 std::string cmdline; 88 if (!ifs.is_open()) { 89 return ""; 90 } 91 ifs >> cmdline; 92 93 size_t idx = cmdline.rfind("/"); 94 if (idx != std::string::npos) { 95 cmdline = cmdline.substr(idx + 1); 96 } 97 98 return cmdline; 99 } 100 101 void tryShortenProcessName(const std::string &packageName) { 102 std::string processName = binaryName(); 103 104 if (!startsWith(processName, packageName)) { 105 return; 106 } 107 108 // e.x. android.hardware.module.foo (at) 1.0 -> foo (at) 1.0 109 size_t lastDot = packageName.rfind('.'); 110 size_t secondDot = packageName.rfind('.', lastDot - 1); 111 112 if (secondDot == std::string::npos) { 113 return; 114 } 115 116 std::string newName = processName.substr(secondDot + 1, 117 16 /* TASK_COMM_LEN */ - 1); 118 ALOGI("Removing namespace from process name %s to %s.", 119 processName.c_str(), newName.c_str()); 120 121 int rc = pthread_setname_np(pthread_self(), newName.c_str()); 122 ALOGI_IF(rc != 0, "Removing namespace from process name %s failed.", 123 processName.c_str()); 124 } 125 126 namespace details { 127 128 void onRegistration(const std::string &packageName, 129 const std::string& /* interfaceName */, 130 const std::string& /* instanceName */) { 131 tryShortenProcessName(packageName); 132 } 133 134 } // details 135 136 sp<IServiceManager1_0> defaultServiceManager() { 137 return defaultServiceManager1_1(); 138 } 139 sp<IServiceManager1_1> defaultServiceManager1_1() { 140 { 141 AutoMutex _l(details::gDefaultServiceManagerLock); 142 if (details::gDefaultServiceManager != NULL) { 143 return details::gDefaultServiceManager; 144 } 145 146 if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) { 147 // HwBinder not available on this device or not accessible to 148 // this process. 149 return nullptr; 150 } 151 152 waitForHwServiceManager(); 153 154 while (details::gDefaultServiceManager == NULL) { 155 details::gDefaultServiceManager = 156 fromBinder<IServiceManager1_1, BpHwServiceManager, BnHwServiceManager>( 157 ProcessState::self()->getContextObject(NULL)); 158 if (details::gDefaultServiceManager == NULL) { 159 LOG(ERROR) << "Waited for hwservicemanager, but got nullptr."; 160 sleep(1); 161 } 162 } 163 } 164 165 return details::gDefaultServiceManager; 166 } 167 168 std::vector<std::string> search(const std::string &path, 169 const std::string &prefix, 170 const std::string &suffix) { 171 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir); 172 if (!dir) return {}; 173 174 std::vector<std::string> results{}; 175 176 dirent* dp; 177 while ((dp = readdir(dir.get())) != nullptr) { 178 std::string name = dp->d_name; 179 180 if (startsWith(name, prefix) && 181 endsWith(name, suffix)) { 182 results.push_back(name); 183 } 184 } 185 186 return results; 187 } 188 189 bool matchPackageName(const std::string& lib, std::string* matchedName, std::string* implName) { 190 std::smatch match; 191 if (std::regex_match(lib, match, gLibraryFileNamePattern)) { 192 *matchedName = match.str(1) + "::I*"; 193 *implName = match.str(2); 194 return true; 195 } 196 return false; 197 } 198 199 static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) { 200 sp<IServiceManager1_0> binderizedManager = defaultServiceManager(); 201 if (binderizedManager == nullptr) { 202 LOG(WARNING) << "Could not registerReference for " 203 << interfaceName << "/" << instanceName 204 << ": null binderized manager."; 205 return; 206 } 207 auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName); 208 if (!ret.isOk()) { 209 LOG(WARNING) << "Could not registerReference for " 210 << interfaceName << "/" << instanceName 211 << ": " << ret.description(); 212 return; 213 } 214 LOG(VERBOSE) << "Successfully registerReference for " 215 << interfaceName << "/" << instanceName; 216 } 217 218 using InstanceDebugInfo = hidl::manager::V1_0::IServiceManager::InstanceDebugInfo; 219 static inline void fetchPidsForPassthroughLibraries( 220 std::map<std::string, InstanceDebugInfo>* infos) { 221 static const std::string proc = "/proc/"; 222 223 std::map<std::string, std::set<pid_t>> pids; 224 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(proc.c_str()), closedir); 225 if (!dir) return; 226 dirent* dp; 227 while ((dp = readdir(dir.get())) != nullptr) { 228 pid_t pid = strtoll(dp->d_name, NULL, 0); 229 if (pid == 0) continue; 230 std::string mapsPath = proc + dp->d_name + "/maps"; 231 std::ifstream ifs{mapsPath}; 232 if (!ifs.is_open()) continue; 233 234 for (std::string line; std::getline(ifs, line);) { 235 // The last token of line should look like 236 // vendor/lib64/hw/android.hardware.foo@1.0-impl-extra.so 237 // Use some simple filters to ignore bad lines before extracting libFileName 238 // and checking the key in info to make parsing faster. 239 if (line.back() != 'o') continue; 240 if (line.rfind('@') == std::string::npos) continue; 241 242 auto spacePos = line.rfind(' '); 243 if (spacePos == std::string::npos) continue; 244 auto libFileName = line.substr(spacePos + 1); 245 auto it = infos->find(libFileName); 246 if (it == infos->end()) continue; 247 pids[libFileName].insert(pid); 248 } 249 } 250 for (auto& pair : *infos) { 251 pair.second.clientPids = 252 std::vector<pid_t>{pids[pair.first].begin(), pids[pair.first].end()}; 253 } 254 } 255 256 struct PassthroughServiceManager : IServiceManager1_1 { 257 static void openLibs(const std::string& fqName, 258 std::function<bool /* continue */(void* /* handle */, 259 const std::string& /* lib */, const std::string& /* sym */)> eachLib) { 260 //fqName looks like android.hardware.foo (at) 1.0::IFoo 261 size_t idx = fqName.find("::"); 262 263 if (idx == std::string::npos || 264 idx + strlen("::") + 1 >= fqName.size()) { 265 LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName; 266 return; 267 } 268 269 std::string packageAndVersion = fqName.substr(0, idx); 270 std::string ifaceName = fqName.substr(idx + strlen("::")); 271 272 const std::string prefix = packageAndVersion + "-impl"; 273 const std::string sym = "HIDL_FETCH_" + ifaceName; 274 275 const int dlMode = RTLD_LAZY; 276 void *handle = nullptr; 277 278 dlerror(); // clear 279 280 std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, 281 HAL_LIBRARY_PATH_VNDK_SP, HAL_LIBRARY_PATH_SYSTEM}; 282 #ifdef LIBHIDL_TARGET_DEBUGGABLE 283 const char* env = std::getenv("TREBLE_TESTING_OVERRIDE"); 284 const bool trebleTestingOverride = env && !strcmp(env, "true"); 285 if (trebleTestingOverride) { 286 const char* vtsRootPath = std::getenv("VTS_ROOT_PATH"); 287 if (vtsRootPath && strlen(vtsRootPath) > 0) { 288 const std::string halLibraryPathVtsOverride = 289 std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM; 290 paths.push_back(halLibraryPathVtsOverride); 291 } 292 } 293 #endif 294 for (const std::string& path : paths) { 295 std::vector<std::string> libs = search(path, prefix, ".so"); 296 297 for (const std::string &lib : libs) { 298 const std::string fullPath = path + lib; 299 300 if (path != HAL_LIBRARY_PATH_SYSTEM) { 301 handle = android_load_sphal_library(fullPath.c_str(), dlMode); 302 } else { 303 handle = dlopen(fullPath.c_str(), dlMode); 304 } 305 306 if (handle == nullptr) { 307 const char* error = dlerror(); 308 LOG(ERROR) << "Failed to dlopen " << lib << ": " 309 << (error == nullptr ? "unknown error" : error); 310 continue; 311 } 312 313 if (!eachLib(handle, lib, sym)) { 314 return; 315 } 316 } 317 } 318 } 319 320 Return<sp<IBase>> get(const hidl_string& fqName, 321 const hidl_string& name) override { 322 sp<IBase> ret = nullptr; 323 324 openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) { 325 IBase* (*generator)(const char* name); 326 *(void **)(&generator) = dlsym(handle, sym.c_str()); 327 if(!generator) { 328 const char* error = dlerror(); 329 LOG(ERROR) << "Passthrough lookup opened " << lib 330 << " but could not find symbol " << sym << ": " 331 << (error == nullptr ? "unknown error" : error); 332 dlclose(handle); 333 return true; 334 } 335 336 ret = (*generator)(name.c_str()); 337 338 if (ret == nullptr) { 339 dlclose(handle); 340 return true; // this module doesn't provide this instance name 341 } 342 343 registerReference(fqName, name); 344 return false; 345 }); 346 347 return ret; 348 } 349 350 Return<bool> add(const hidl_string& /* name */, 351 const sp<IBase>& /* service */) override { 352 LOG(FATAL) << "Cannot register services with passthrough service manager."; 353 return false; 354 } 355 356 Return<Transport> getTransport(const hidl_string& /* fqName */, 357 const hidl_string& /* name */) { 358 LOG(FATAL) << "Cannot getTransport with passthrough service manager."; 359 return Transport::EMPTY; 360 } 361 362 Return<void> list(list_cb /* _hidl_cb */) override { 363 LOG(FATAL) << "Cannot list services with passthrough service manager."; 364 return Void(); 365 } 366 Return<void> listByInterface(const hidl_string& /* fqInstanceName */, 367 listByInterface_cb /* _hidl_cb */) override { 368 // TODO: add this functionality 369 LOG(FATAL) << "Cannot list services with passthrough service manager."; 370 return Void(); 371 } 372 373 Return<bool> registerForNotifications(const hidl_string& /* fqName */, 374 const hidl_string& /* name */, 375 const sp<IServiceNotification>& /* callback */) override { 376 // This makes no sense. 377 LOG(FATAL) << "Cannot register for notifications with passthrough service manager."; 378 return false; 379 } 380 381 Return<void> debugDump(debugDump_cb _hidl_cb) override { 382 using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture; 383 using std::literals::string_literals::operator""s; 384 static std::vector<std::pair<Arch, std::vector<const char*>>> sAllPaths{ 385 {Arch::IS_64BIT, 386 {HAL_LIBRARY_PATH_ODM_64BIT, HAL_LIBRARY_PATH_VENDOR_64BIT, 387 HAL_LIBRARY_PATH_VNDK_SP_64BIT, HAL_LIBRARY_PATH_SYSTEM_64BIT}}, 388 {Arch::IS_32BIT, 389 {HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT, 390 HAL_LIBRARY_PATH_VNDK_SP_32BIT, HAL_LIBRARY_PATH_SYSTEM_32BIT}}}; 391 std::map<std::string, InstanceDebugInfo> map; 392 for (const auto &pair : sAllPaths) { 393 Arch arch = pair.first; 394 for (const auto &path : pair.second) { 395 std::vector<std::string> libs = search(path, "", ".so"); 396 for (const std::string &lib : libs) { 397 std::string matchedName; 398 std::string implName; 399 if (matchPackageName(lib, &matchedName, &implName)) { 400 std::string instanceName{"* ("s + path + ")"s}; 401 if (!implName.empty()) instanceName += " ("s + implName + ")"s; 402 map.emplace(path + lib, InstanceDebugInfo{.interfaceName = matchedName, 403 .instanceName = instanceName, 404 .clientPids = {}, 405 .arch = arch}); 406 } 407 } 408 } 409 } 410 fetchPidsForPassthroughLibraries(&map); 411 hidl_vec<InstanceDebugInfo> vec; 412 vec.resize(map.size()); 413 size_t idx = 0; 414 for (auto&& pair : map) { 415 vec[idx++] = std::move(pair.second); 416 } 417 _hidl_cb(vec); 418 return Void(); 419 } 420 421 Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override { 422 // This makes no sense. 423 LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. " 424 << "Call it on defaultServiceManager() instead."; 425 return Void(); 426 } 427 428 Return<bool> unregisterForNotifications(const hidl_string& /* fqName */, 429 const hidl_string& /* name */, 430 const sp<IServiceNotification>& /* callback */) override { 431 // This makes no sense. 432 LOG(FATAL) << "Cannot unregister for notifications with passthrough service manager."; 433 return false; 434 } 435 436 }; 437 438 sp<IServiceManager1_0> getPassthroughServiceManager() { 439 return getPassthroughServiceManager1_1(); 440 } 441 sp<IServiceManager1_1> getPassthroughServiceManager1_1() { 442 static sp<PassthroughServiceManager> manager(new PassthroughServiceManager()); 443 return manager; 444 } 445 446 namespace details { 447 448 void preloadPassthroughService(const std::string &descriptor) { 449 PassthroughServiceManager::openLibs(descriptor, 450 [&](void* /* handle */, const std::string& /* lib */, const std::string& /* sym */) { 451 // do nothing 452 return true; // open all libs 453 }); 454 } 455 456 struct Waiter : IServiceNotification { 457 Return<void> onRegistration(const hidl_string& /* fqName */, 458 const hidl_string& /* name */, 459 bool /* preexisting */) override { 460 std::unique_lock<std::mutex> lock(mMutex); 461 if (mRegistered) { 462 return Void(); 463 } 464 mRegistered = true; 465 lock.unlock(); 466 467 mCondition.notify_one(); 468 return Void(); 469 } 470 471 void wait(const std::string &interface, const std::string &instanceName) { 472 using std::literals::chrono_literals::operator""s; 473 474 std::unique_lock<std::mutex> lock(mMutex); 475 while(true) { 476 mCondition.wait_for(lock, 1s, [this]{ 477 return mRegistered; 478 }); 479 480 if (mRegistered) { 481 break; 482 } 483 484 LOG(WARNING) << "Waited one second for " 485 << interface << "/" << instanceName 486 << ". Waiting another..."; 487 } 488 } 489 490 private: 491 std::mutex mMutex; 492 std::condition_variable mCondition; 493 bool mRegistered = false; 494 }; 495 496 void waitForHwService( 497 const std::string &interface, const std::string &instanceName) { 498 const sp<IServiceManager1_1> manager = defaultServiceManager1_1(); 499 500 if (manager == nullptr) { 501 LOG(ERROR) << "Could not get default service manager."; 502 return; 503 } 504 505 sp<Waiter> waiter = new Waiter(); 506 Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter); 507 508 if (!ret.isOk()) { 509 LOG(ERROR) << "Transport error, " << ret.description() 510 << ", during notification registration for " 511 << interface << "/" << instanceName << "."; 512 return; 513 } 514 515 if (!ret) { 516 LOG(ERROR) << "Could not register for notifications for " 517 << interface << "/" << instanceName << "."; 518 return; 519 } 520 521 waiter->wait(interface, instanceName); 522 523 if (!manager->unregisterForNotifications(interface, instanceName, waiter).withDefault(false)) { 524 LOG(ERROR) << "Could not unregister service notification for " 525 << interface << "/" << instanceName << "."; 526 } 527 } 528 529 }; // namespace details 530 531 }; // namespace hardware 532 }; // namespace android 533