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