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