ServiceManagement.cpp revision 496051047ce92b23c1027fe77242f386fae940c4
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<void> list(list_cb /* _hidl_cb */) override { 222 LOG(FATAL) << "Cannot list services with passthrough service manager."; 223 return Void(); 224 } 225 Return<void> listByInterface(const hidl_string& /* fqInstanceName */, 226 listByInterface_cb /* _hidl_cb */) override { 227 // TODO: add this functionality 228 LOG(FATAL) << "Cannot list services with passthrough service manager."; 229 return Void(); 230 } 231 232 Return<bool> registerForNotifications(const hidl_string& /* fqName */, 233 const hidl_string& /* name */, 234 const sp<IServiceNotification>& /* callback */) override { 235 // This makes no sense. 236 LOG(FATAL) << "Cannot register for notifications with passthrough service manager."; 237 return false; 238 } 239 240 Return<void> debugDump(debugDump_cb _hidl_cb) override { 241 using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture; 242 static std::vector<std::pair<Arch, std::vector<const char *>>> sAllPaths{ 243 {Arch::IS_64BIT, {HAL_LIBRARY_PATH_ODM_64BIT, 244 HAL_LIBRARY_PATH_VENDOR_64BIT, 245 HAL_LIBRARY_PATH_SYSTEM_64BIT}}, 246 {Arch::IS_32BIT, {HAL_LIBRARY_PATH_ODM_32BIT, 247 HAL_LIBRARY_PATH_VENDOR_32BIT, 248 HAL_LIBRARY_PATH_SYSTEM_32BIT}} 249 }; 250 std::vector<InstanceDebugInfo> vec; 251 for (const auto &pair : sAllPaths) { 252 Arch arch = pair.first; 253 for (const auto &path : pair.second) { 254 std::vector<std::string> libs = search(path, "", ".so"); 255 for (const std::string &lib : libs) { 256 std::string matchedName; 257 if (matchPackageName(lib, &matchedName)) { 258 vec.push_back({ 259 .interfaceName = matchedName, 260 .instanceName = "*", 261 .clientPids = {}, 262 .arch = arch 263 }); 264 } 265 } 266 } 267 } 268 _hidl_cb(vec); 269 return Void(); 270 } 271 272 Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &, int32_t) override { 273 // This makes no sense. 274 LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. " 275 << "Call it on defaultServiceManager() instead."; 276 return Void(); 277 } 278 279}; 280 281sp<IServiceManager> getPassthroughServiceManager() { 282 static sp<PassthroughServiceManager> manager(new PassthroughServiceManager()); 283 return manager; 284} 285 286namespace details { 287 288struct Waiter : IServiceNotification { 289 Return<void> onRegistration(const hidl_string& /* fqName */, 290 const hidl_string& /* name */, 291 bool /* preexisting */) override { 292 std::unique_lock<std::mutex> lock(mMutex); 293 if (mRegistered) { 294 return Void(); 295 } 296 mRegistered = true; 297 lock.unlock(); 298 299 mCondition.notify_one(); 300 return Void(); 301 } 302 303 void wait(const std::string &interface, const std::string &instanceName) { 304 using std::literals::chrono_literals::operator""s; 305 306 std::unique_lock<std::mutex> lock(mMutex); 307 while(true) { 308 mCondition.wait_for(lock, 1s, [this]{ 309 return mRegistered; 310 }); 311 312 if (mRegistered) { 313 break; 314 } 315 316 LOG(WARNING) << "Waited one second for " 317 << interface << "/" << instanceName 318 << ". Waiting another..."; 319 } 320 } 321 322private: 323 std::mutex mMutex; 324 std::condition_variable mCondition; 325 bool mRegistered = false; 326}; 327 328void waitForHwService( 329 const std::string &interface, const std::string &instanceName) { 330 const sp<IServiceManager> manager = defaultServiceManager(); 331 332 if (manager == nullptr) { 333 LOG(ERROR) << "Could not get default service manager."; 334 return; 335 } 336 337 sp<Waiter> waiter = new Waiter(); 338 Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter); 339 340 if (!ret.isOk()) { 341 LOG(ERROR) << "Transport error, " << ret.description() 342 << ", during notification registration for " 343 << interface << "/" << instanceName << "."; 344 return; 345 } 346 347 if (!ret) { 348 LOG(ERROR) << "Could not register for notifications for " 349 << interface << "/" << instanceName << "."; 350 return; 351 } 352 353 waiter->wait(interface, instanceName); 354} 355 356}; // namespace details 357 358}; // namespace hardware 359}; // namespace android 360