ServiceManagement.cpp revision bf13ad09b72a4a7ffd70a65ccd7a7ed722bfe517
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 <condition_variable> 20#include <dlfcn.h> 21#include <dirent.h> 22#include <fstream> 23#include <pthread.h> 24#include <unistd.h> 25 26#include <mutex> 27#include <regex> 28 29#include <hidl/HidlBinderSupport.h> 30#include <hidl/ServiceManagement.h> 31#include <hidl/Status.h> 32 33#include <android-base/logging.h> 34#include <android-base/properties.h> 35#include <hwbinder/IPCThreadState.h> 36#include <hwbinder/Parcel.h> 37 38#include <android/hidl/manager/1.0/IServiceManager.h> 39#include <android/hidl/manager/1.0/BpHwServiceManager.h> 40#include <android/hidl/manager/1.0/BnHwServiceManager.h> 41 42#define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*" 43#define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*" 44static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so"); 45 46using android::base::WaitForProperty; 47 48using android::hidl::manager::V1_0::IServiceManager; 49using android::hidl::manager::V1_0::IServiceNotification; 50using android::hidl::manager::V1_0::BpHwServiceManager; 51using android::hidl::manager::V1_0::BnHwServiceManager; 52 53namespace android { 54namespace hardware { 55 56namespace details { 57extern Mutex gDefaultServiceManagerLock; 58extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager; 59} // namespace details 60 61static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready"; 62 63void waitForHwServiceManager() { 64 using std::literals::chrono_literals::operator""s; 65 66 while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) { 67 LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another..."; 68 } 69} 70 71bool endsWith(const std::string &in, const std::string &suffix) { 72 return in.size() >= suffix.size() && 73 in.substr(in.size() - suffix.size()) == suffix; 74} 75 76bool startsWith(const std::string &in, const std::string &prefix) { 77 return in.size() >= prefix.size() && 78 in.substr(0, prefix.size()) == prefix; 79} 80 81std::string binaryName() { 82 std::ifstream ifs("/proc/self/cmdline"); 83 std::string cmdline; 84 if (!ifs.is_open()) { 85 return ""; 86 } 87 ifs >> cmdline; 88 89 size_t idx = cmdline.rfind("/"); 90 if (idx != std::string::npos) { 91 cmdline = cmdline.substr(idx + 1); 92 } 93 94 return cmdline; 95} 96 97void tryShortenProcessName(const std::string &packageName) { 98 std::string processName = binaryName(); 99 100 if (!startsWith(processName, packageName)) { 101 return; 102 } 103 104 // e.x. android.hardware.module.foo@1.0 -> foo@1.0 105 size_t lastDot = packageName.rfind('.'); 106 size_t secondDot = packageName.rfind('.', lastDot - 1); 107 108 if (secondDot == std::string::npos) { 109 return; 110 } 111 112 std::string newName = processName.substr(secondDot + 1, 113 16 /* TASK_COMM_LEN */ - 1); 114 ALOGI("Removing namespace from process name %s to %s.", 115 processName.c_str(), newName.c_str()); 116 117 int rc = pthread_setname_np(pthread_self(), newName.c_str()); 118 ALOGI_IF(rc != 0, "Removing namespace from process name %s failed.", 119 processName.c_str()); 120} 121 122namespace details { 123 124void onRegistration(const std::string &packageName, 125 const std::string& /* interfaceName */, 126 const std::string& /* instanceName */) { 127 tryShortenProcessName(packageName); 128} 129 130} // details 131 132sp<IServiceManager> defaultServiceManager() { 133 { 134 AutoMutex _l(details::gDefaultServiceManagerLock); 135 if (details::gDefaultServiceManager != NULL) { 136 return details::gDefaultServiceManager; 137 } 138 139 if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) { 140 // HwBinder not available on this device or not accessible to 141 // this process. 142 return nullptr; 143 } 144 145 waitForHwServiceManager(); 146 147 while (details::gDefaultServiceManager == NULL) { 148 details::gDefaultServiceManager = 149 fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>( 150 ProcessState::self()->getContextObject(NULL)); 151 if (details::gDefaultServiceManager == NULL) { 152 LOG(ERROR) << "Waited for hwservicemanager, but got nullptr."; 153 sleep(1); 154 } 155 } 156 } 157 158 return details::gDefaultServiceManager; 159} 160 161std::vector<std::string> search(const std::string &path, 162 const std::string &prefix, 163 const std::string &suffix) { 164 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir); 165 if (!dir) return {}; 166 167 std::vector<std::string> results{}; 168 169 dirent* dp; 170 while ((dp = readdir(dir.get())) != nullptr) { 171 std::string name = dp->d_name; 172 173 if (startsWith(name, prefix) && 174 endsWith(name, suffix)) { 175 results.push_back(name); 176 } 177 } 178 179 return results; 180} 181 182bool matchPackageName(const std::string &lib, std::string *matchedName) { 183 std::smatch match; 184 if (std::regex_match(lib, match, gLibraryFileNamePattern)) { 185 *matchedName = match.str(1) + "::I*"; 186 return true; 187 } 188 return false; 189} 190 191static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) { 192 sp<IServiceManager> binderizedManager = defaultServiceManager(); 193 if (binderizedManager == nullptr) { 194 LOG(WARNING) << "Could not registerReference for " 195 << interfaceName << "/" << instanceName 196 << ": null binderized manager."; 197 return; 198 } 199 auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName); 200 if (!ret.isOk()) { 201 LOG(WARNING) << "Could not registerReference for " 202 << interfaceName << "/" << instanceName 203 << ": " << ret.description(); 204 return; 205 } 206 LOG(VERBOSE) << "Successfully registerReference for " 207 << interfaceName << "/" << instanceName; 208} 209 210struct PassthroughServiceManager : IServiceManager { 211 Return<sp<IBase>> get(const hidl_string& fqName, 212 const hidl_string& name) override { 213 std::string stdFqName(fqName.c_str()); 214 215 //fqName looks like android.hardware.foo@1.0::IFoo 216 size_t idx = stdFqName.find("::"); 217 218 if (idx == std::string::npos || 219 idx + strlen("::") + 1 >= stdFqName.size()) { 220 LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName; 221 return nullptr; 222 } 223 224 std::string packageAndVersion = stdFqName.substr(0, idx); 225 std::string ifaceName = stdFqName.substr(idx + strlen("::")); 226 227 const std::string prefix = packageAndVersion + "-impl"; 228 const std::string sym = "HIDL_FETCH_" + ifaceName; 229 230 const int dlMode = RTLD_LAZY; 231 void *handle = nullptr; 232 233 // TODO: lookup in VINTF instead 234 // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM 235 236 dlerror(); // clear 237 238 for (const std::string &path : { 239 HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM 240 }) { 241 std::vector<std::string> libs = search(path, prefix, ".so"); 242 243 for (const std::string &lib : libs) { 244 const std::string fullPath = path + lib; 245 246 handle = dlopen(fullPath.c_str(), dlMode); 247 if (handle == nullptr) { 248 const char* error = dlerror(); 249 LOG(ERROR) << "Failed to dlopen " << lib << ": " 250 << (error == nullptr ? "unknown error" : error); 251 continue; 252 } 253 254 IBase* (*generator)(const char* name); 255 *(void **)(&generator) = dlsym(handle, sym.c_str()); 256 if(!generator) { 257 const char* error = dlerror(); 258 LOG(ERROR) << "Passthrough lookup opened " << lib 259 << " but could not find symbol " << sym << ": " 260 << (error == nullptr ? "unknown error" : error); 261 dlclose(handle); 262 continue; 263 } 264 265 IBase *interface = (*generator)(name.c_str()); 266 267 if (interface == nullptr) { 268 dlclose(handle); 269 continue; // this module doesn't provide this instance name 270 } 271 272 registerReference(fqName, name); 273 274 return interface; 275 } 276 } 277 278 return nullptr; 279 } 280 281 Return<bool> add(const hidl_string& /* name */, 282 const sp<IBase>& /* service */) override { 283 LOG(FATAL) << "Cannot register services with passthrough service manager."; 284 return false; 285 } 286 287 Return<Transport> getTransport(const hidl_string& /* fqName */, 288 const hidl_string& /* name */) { 289 LOG(FATAL) << "Cannot getTransport with passthrough service manager."; 290 return Transport::EMPTY; 291 } 292 293 Return<void> list(list_cb /* _hidl_cb */) override { 294 LOG(FATAL) << "Cannot list services with passthrough service manager."; 295 return Void(); 296 } 297 Return<void> listByInterface(const hidl_string& /* fqInstanceName */, 298 listByInterface_cb /* _hidl_cb */) override { 299 // TODO: add this functionality 300 LOG(FATAL) << "Cannot list services with passthrough service manager."; 301 return Void(); 302 } 303 304 Return<bool> registerForNotifications(const hidl_string& /* fqName */, 305 const hidl_string& /* name */, 306 const sp<IServiceNotification>& /* callback */) override { 307 // This makes no sense. 308 LOG(FATAL) << "Cannot register for notifications with passthrough service manager."; 309 return false; 310 } 311 312 Return<void> debugDump(debugDump_cb _hidl_cb) override { 313 using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture; 314 static std::vector<std::pair<Arch, std::vector<const char *>>> sAllPaths{ 315 {Arch::IS_64BIT, {HAL_LIBRARY_PATH_ODM_64BIT, 316 HAL_LIBRARY_PATH_VENDOR_64BIT, 317 HAL_LIBRARY_PATH_SYSTEM_64BIT}}, 318 {Arch::IS_32BIT, {HAL_LIBRARY_PATH_ODM_32BIT, 319 HAL_LIBRARY_PATH_VENDOR_32BIT, 320 HAL_LIBRARY_PATH_SYSTEM_32BIT}} 321 }; 322 std::vector<InstanceDebugInfo> vec; 323 for (const auto &pair : sAllPaths) { 324 Arch arch = pair.first; 325 for (const auto &path : pair.second) { 326 std::vector<std::string> libs = search(path, "", ".so"); 327 for (const std::string &lib : libs) { 328 std::string matchedName; 329 if (matchPackageName(lib, &matchedName)) { 330 vec.push_back({ 331 .interfaceName = matchedName, 332 .instanceName = "*", 333 .clientPids = {}, 334 .arch = arch 335 }); 336 } 337 } 338 } 339 } 340 _hidl_cb(vec); 341 return Void(); 342 } 343 344 Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override { 345 // This makes no sense. 346 LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. " 347 << "Call it on defaultServiceManager() instead."; 348 return Void(); 349 } 350 351}; 352 353sp<IServiceManager> getPassthroughServiceManager() { 354 static sp<PassthroughServiceManager> manager(new PassthroughServiceManager()); 355 return manager; 356} 357 358namespace details { 359 360struct Waiter : IServiceNotification { 361 Return<void> onRegistration(const hidl_string& /* fqName */, 362 const hidl_string& /* name */, 363 bool /* preexisting */) override { 364 std::unique_lock<std::mutex> lock(mMutex); 365 if (mRegistered) { 366 return Void(); 367 } 368 mRegistered = true; 369 lock.unlock(); 370 371 mCondition.notify_one(); 372 return Void(); 373 } 374 375 void wait(const std::string &interface, const std::string &instanceName) { 376 using std::literals::chrono_literals::operator""s; 377 378 std::unique_lock<std::mutex> lock(mMutex); 379 while(true) { 380 mCondition.wait_for(lock, 1s, [this]{ 381 return mRegistered; 382 }); 383 384 if (mRegistered) { 385 break; 386 } 387 388 LOG(WARNING) << "Waited one second for " 389 << interface << "/" << instanceName 390 << ". Waiting another..."; 391 } 392 } 393 394private: 395 std::mutex mMutex; 396 std::condition_variable mCondition; 397 bool mRegistered = false; 398}; 399 400void waitForHwService( 401 const std::string &interface, const std::string &instanceName) { 402 const sp<IServiceManager> manager = defaultServiceManager(); 403 404 if (manager == nullptr) { 405 LOG(ERROR) << "Could not get default service manager."; 406 return; 407 } 408 409 sp<Waiter> waiter = new Waiter(); 410 Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter); 411 412 if (!ret.isOk()) { 413 LOG(ERROR) << "Transport error, " << ret.description() 414 << ", during notification registration for " 415 << interface << "/" << instanceName << "."; 416 return; 417 } 418 419 if (!ret) { 420 LOG(ERROR) << "Could not register for notifications for " 421 << interface << "/" << instanceName << "."; 422 return; 423 } 424 425 waiter->wait(interface, instanceName); 426} 427 428}; // namespace details 429 430}; // namespace hardware 431}; // namespace android 432