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