ServiceManagement.cpp revision cbefd35d5c607fa245855ce897ae08369e667222
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 <hidl/HidlBinderSupport.h> 20#include <hidl/ServiceManagement.h> 21#include <hidl/Static.h> 22#include <hidl/Status.h> 23 24#include <android-base/logging.h> 25#include <condition_variable> 26#include <dlfcn.h> 27#include <dirent.h> 28#include <hidl-util/FQName.h> 29#include <hidl-util/StringHelper.h> 30#include <hwbinder/IPCThreadState.h> 31#include <hwbinder/Parcel.h> 32#include <mutex> 33#include <unistd.h> 34 35#include <android/hidl/manager/1.0/IServiceManager.h> 36#include <android/hidl/manager/1.0/BpHwServiceManager.h> 37#include <android/hidl/manager/1.0/BnHwServiceManager.h> 38 39using android::hidl::manager::V1_0::IServiceManager; 40using android::hidl::manager::V1_0::IServiceNotification; 41using android::hidl::manager::V1_0::BpHwServiceManager; 42using android::hidl::manager::V1_0::BnHwServiceManager; 43 44namespace android { 45namespace hardware { 46 47sp<IServiceManager> defaultServiceManager() { 48 49 if (gDefaultServiceManager != NULL) return gDefaultServiceManager; 50 if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) { 51 // HwBinder not available on this device or not accessible to 52 // this process. 53 return nullptr; 54 } 55 { 56 AutoMutex _l(gDefaultServiceManagerLock); 57 while (gDefaultServiceManager == NULL) { 58 gDefaultServiceManager = fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>( 59 ProcessState::self()->getContextObject(NULL)); 60 if (gDefaultServiceManager == NULL) 61 sleep(1); 62 } 63 } 64 65 return gDefaultServiceManager; 66} 67 68std::vector<std::string> search(const std::string &path, 69 const std::string &prefix, 70 const std::string &suffix) { 71 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir); 72 if (!dir) return {}; 73 74 std::vector<std::string> results{}; 75 76 dirent* dp; 77 while ((dp = readdir(dir.get())) != nullptr) { 78 std::string name = dp->d_name; 79 80 if (StringHelper::StartsWith(name, prefix) && 81 StringHelper::EndsWith(name, suffix)) { 82 results.push_back(name); 83 } 84 } 85 86 return results; 87} 88 89struct PassthroughServiceManager : IServiceManager { 90 Return<sp<IBase>> get(const hidl_string& fqName, 91 const hidl_string& name) override { 92 FQName iface(fqName); 93 94 if (!iface.isValid() || 95 !iface.isFullyQualified() || 96 iface.isIdentifier()) { 97 LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName; 98 return nullptr; 99 } 100 101 const int dlMode = RTLD_LAZY; 102 void *handle = nullptr; 103 104 std::string library; 105 106 // TODO: lookup in VINTF instead 107 // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM 108 109 for (const std::string &path : { 110 HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM 111 }) { 112 const std::string prefix = iface.getPackageAndVersion().string() + "-impl"; 113 114 std::vector<std::string> libs = search(path, prefix, ".so"); 115 116 if (libs.size() > 1) { 117 LOG(WARNING) << "Multiple libraries found: " << StringHelper::JoinStrings(libs, ", "); 118 } 119 120 for (const std::string &lib : libs) { 121 handle = dlopen((path + lib).c_str(), dlMode); 122 if (handle != nullptr) { 123 library = lib; 124 goto beginLookup; 125 } 126 } 127 } 128 129 if (handle == nullptr) { 130 return nullptr; 131 } 132beginLookup: 133 134 const std::string sym = "HIDL_FETCH_" + iface.name(); 135 136 IBase* (*generator)(const char* name); 137 *(void **)(&generator) = dlsym(handle, sym.c_str()); 138 if(!generator) { 139 LOG(ERROR) << "Passthrough lookup opened " << library 140 << " but could not find symbol " << sym; 141 return nullptr; 142 } 143 return (*generator)(name); 144 } 145 146 Return<bool> add(const hidl_vec<hidl_string>& /* interfaceChain */, 147 const hidl_string& /* name */, 148 const sp<IBase>& /* service */) override { 149 LOG(FATAL) << "Cannot register services with passthrough service manager."; 150 return false; 151 } 152 153 Return<void> list(list_cb /* _hidl_cb */) override { 154 // TODO: add this functionality 155 LOG(FATAL) << "Cannot list services with passthrough service manager."; 156 return Void(); 157 } 158 Return<void> listByInterface(const hidl_string& /* fqInstanceName */, 159 listByInterface_cb /* _hidl_cb */) override { 160 // TODO: add this functionality 161 LOG(FATAL) << "Cannot list services with passthrough service manager."; 162 return Void(); 163 } 164 165 Return<bool> registerForNotifications(const hidl_string& /* fqName */, 166 const hidl_string& /* name */, 167 const sp<IServiceNotification>& /* callback */) override { 168 // This makes no sense. 169 LOG(FATAL) << "Cannot register for notifications with passthrough service manager."; 170 return false; 171 } 172 173}; 174 175sp<IServiceManager> getPassthroughServiceManager() { 176 static sp<PassthroughServiceManager> manager(new PassthroughServiceManager()); 177 return manager; 178} 179 180namespace details { 181 182struct Waiter : IServiceNotification { 183 Return<void> onRegistration(const hidl_string& /* fqName */, 184 const hidl_string& /* name */, 185 bool /* preexisting */) override { 186 std::unique_lock<std::mutex> lock(mMutex); 187 if (mRegistered) { 188 return Void(); 189 } 190 mRegistered = true; 191 lock.unlock(); 192 193 mCondition.notify_one(); 194 return Void(); 195 } 196 197 void wait() { 198 std::unique_lock<std::mutex> lock(mMutex); 199 mCondition.wait(lock, [this]{ 200 return mRegistered; 201 }); 202 } 203 204private: 205 std::mutex mMutex; 206 std::condition_variable mCondition; 207 bool mRegistered = false; 208}; 209 210void waitForHwService( 211 const std::string &interface, const std::string &instanceName) { 212 const sp<IServiceManager> manager = defaultServiceManager(); 213 214 if (manager == nullptr) { 215 LOG(ERROR) << "Could not get default service manager."; 216 return; 217 } 218 219 sp<Waiter> waiter = new Waiter(); 220 Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter); 221 222 if (!ret.isOk()) { 223 LOG(ERROR) << "Transport error, " << ret.description() 224 << ", during notification registration for " 225 << interface << "/" << instanceName << "."; 226 return; 227 } 228 229 if (!ret) { 230 LOG(ERROR) << "Could not register for notifications for " 231 << interface << "/" << instanceName << "."; 232 return; 233 } 234 235 waiter->wait(); 236} 237 238}; // namespace details 239 240}; // namespace hardware 241}; // namespace android 242