blob: 8121911e31c3cc723e32122d7573d22511eda1aa [file] [log] [blame]
Steven Moreland5d5ef7f2016-10-20 19:19:55 -07001/*
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
Yifan Hong9a22d1d2017-01-25 14:19:26 -080019#include <condition_variable>
20#include <dlfcn.h>
21#include <dirent.h>
Steven Morelandcd4dbdf2017-04-07 20:31:22 -070022#include <fstream>
23#include <pthread.h>
Yifan Hong9a22d1d2017-01-25 14:19:26 -080024#include <unistd.h>
25
26#include <mutex>
27#include <regex>
28
Martijn Coenen12f04d92016-12-07 17:29:41 +010029#include <hidl/HidlBinderSupport.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070030#include <hidl/ServiceManagement.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070031#include <hidl/Status.h>
32
Steven Moreland337e6b62017-01-18 17:25:13 -080033#include <android-base/logging.h>
Steven Morelandc1cee2c2017-03-24 16:23:11 +000034#include <android-base/properties.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070035#include <hwbinder/IPCThreadState.h>
36#include <hwbinder/Parcel.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070037
38#include <android/hidl/manager/1.0/IServiceManager.h>
Yifan Hong4e925992017-01-09 17:47:17 -080039#include <android/hidl/manager/1.0/BpHwServiceManager.h>
40#include <android/hidl/manager/1.0/BnHwServiceManager.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070041
Yifan Hong9a22d1d2017-01-25 14:19:26 -080042#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
Steven Morelandc1cee2c2017-03-24 16:23:11 +000046using android::base::WaitForProperty;
47
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070048using android::hidl::manager::V1_0::IServiceManager;
Steven Moreland337e6b62017-01-18 17:25:13 -080049using android::hidl::manager::V1_0::IServiceNotification;
Yifan Hong4e925992017-01-09 17:47:17 -080050using android::hidl::manager::V1_0::BpHwServiceManager;
51using android::hidl::manager::V1_0::BnHwServiceManager;
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070052
53namespace android {
54namespace hardware {
55
Yifan Hong953e6b02017-03-16 14:52:40 -070056namespace details {
57extern Mutex gDefaultServiceManagerLock;
58extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
59} // namespace details
60
Steven Morelandc1cee2c2017-03-24 16:23:11 +000061static 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
Steven Morelandcd4dbdf2017-04-07 20:31:22 -070071bool endsWith(const std::string &in, const std::string &suffix) {
72 return in.size() >= suffix.size() &&
73 in.substr(in.size() - suffix.size()) == suffix;
74}
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070075
Steven Morelandcd4dbdf2017-04-07 20:31:22 -070076bool 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() {
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700133 {
Yifan Hong953e6b02017-03-16 14:52:40 -0700134 AutoMutex _l(details::gDefaultServiceManagerLock);
135 if (details::gDefaultServiceManager != NULL) {
136 return details::gDefaultServiceManager;
Yifan Hong8fb656b2017-03-16 14:30:40 -0700137 }
Steven Morelandcd4dbdf2017-04-07 20:31:22 -0700138
Yifan Hong8fb656b2017-03-16 14:30:40 -0700139 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 }
Steven Morelandc1cee2c2017-03-24 16:23:11 +0000144
145 waitForHwServiceManager();
146
Yifan Hong953e6b02017-03-16 14:52:40 -0700147 while (details::gDefaultServiceManager == NULL) {
148 details::gDefaultServiceManager =
Yifan Hong8fb656b2017-03-16 14:30:40 -0700149 fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
150 ProcessState::self()->getContextObject(NULL));
Yifan Hong953e6b02017-03-16 14:52:40 -0700151 if (details::gDefaultServiceManager == NULL) {
Steven Morelandc1cee2c2017-03-24 16:23:11 +0000152 LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700153 sleep(1);
Yifan Hong8fb656b2017-03-16 14:30:40 -0700154 }
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700155 }
156 }
157
Yifan Hong953e6b02017-03-16 14:52:40 -0700158 return details::gDefaultServiceManager;
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700159}
160
Steven Moreland0091c092017-01-20 23:15:18 +0000161std::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
Steven Morelandda8e6172017-04-06 17:24:22 -0700173 if (startsWith(name, prefix) &&
174 endsWith(name, suffix)) {
Steven Moreland0091c092017-01-20 23:15:18 +0000175 results.push_back(name);
176 }
177 }
178
179 return results;
180}
181
Yifan Hong9a22d1d2017-01-25 14:19:26 -0800182bool 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
Yifan Hong7f49f592017-02-03 15:11:44 -0800191static 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 }
Martijn Coenenbf13ad02017-04-27 09:41:13 -0700199 auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
Yifan Hong7f49f592017-02-03 15:11:44 -0800200 if (!ret.isOk()) {
201 LOG(WARNING) << "Could not registerReference for "
202 << interfaceName << "/" << instanceName
203 << ": " << ret.description();
Steven Moreland0aeaa782017-03-22 08:11:07 -0700204 return;
Yifan Hong7f49f592017-02-03 15:11:44 -0800205 }
Steven Morelande681aa52017-02-15 16:22:37 -0800206 LOG(VERBOSE) << "Successfully registerReference for "
207 << interfaceName << "/" << instanceName;
Yifan Hong7f49f592017-02-03 15:11:44 -0800208}
209
Steven Moreland337e6b62017-01-18 17:25:13 -0800210struct PassthroughServiceManager : IServiceManager {
211 Return<sp<IBase>> get(const hidl_string& fqName,
Steven Morelandda8e6172017-04-06 17:24:22 -0700212 const hidl_string& name) override {
213 std::string stdFqName(fqName.c_str());
Steven Moreland337e6b62017-01-18 17:25:13 -0800214
Steven Morelandda8e6172017-04-06 17:24:22 -0700215 //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()) {
Steven Moreland337e6b62017-01-18 17:25:13 -0800220 LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
221 return nullptr;
222 }
223
Steven Morelandda8e6172017-04-06 17:24:22 -0700224 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;
Steven Moreland348802d2017-02-23 12:48:55 -0800229
Steven Moreland337e6b62017-01-18 17:25:13 -0800230 const int dlMode = RTLD_LAZY;
231 void *handle = nullptr;
232
Steven Moreland0091c092017-01-20 23:15:18 +0000233 // TODO: lookup in VINTF instead
234 // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
235
Steven Morelanda29905c2017-03-01 10:42:35 -0800236 dlerror(); // clear
237
Steven Moreland337e6b62017-01-18 17:25:13 -0800238 for (const std::string &path : {
239 HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
240 }) {
Steven Moreland0091c092017-01-20 23:15:18 +0000241 std::vector<std::string> libs = search(path, prefix, ".so");
242
Steven Moreland0091c092017-01-20 23:15:18 +0000243 for (const std::string &lib : libs) {
Steven Moreland348802d2017-02-23 12:48:55 -0800244 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;
Steven Moreland0091c092017-01-20 23:15:18 +0000252 }
Steven Moreland348802d2017-02-23 12:48:55 -0800253
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
Scott Randolpheb0c3372017-04-03 14:07:14 -0700265 IBase *interface = (*generator)(name.c_str());
Steven Moreland348802d2017-02-23 12:48:55 -0800266
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;
Steven Moreland337e6b62017-01-18 17:25:13 -0800275 }
276 }
277
Steven Moreland348802d2017-02-23 12:48:55 -0800278 return nullptr;
Steven Moreland337e6b62017-01-18 17:25:13 -0800279 }
280
Martijn Coenen67a02492017-03-06 13:04:48 +0100281 Return<bool> add(const hidl_string& /* name */,
Steven Moreland337e6b62017-01-18 17:25:13 -0800282 const sp<IBase>& /* service */) override {
283 LOG(FATAL) << "Cannot register services with passthrough service manager.";
284 return false;
285 }
286
Steven Moreland330e3e22017-04-06 09:26:07 -0700287 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
Yifan Hong705e5da2017-03-02 16:59:39 -0800293 Return<void> list(list_cb /* _hidl_cb */) override {
294 LOG(FATAL) << "Cannot list services with passthrough service manager.";
Steven Moreland337e6b62017-01-18 17:25:13 -0800295 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
Yifan Hong705e5da2017-03-02 16:59:39 -0800312 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);
Yifan Hong7f49f592017-02-03 15:11:44 -0800341 return Void();
342 }
343
Martijn Coenenbf13ad02017-04-27 09:41:13 -0700344 Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override {
Yifan Hong7f49f592017-02-03 15:11:44 -0800345 // This makes no sense.
346 LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
347 << "Call it on defaultServiceManager() instead.";
Yifan Hong9a22d1d2017-01-25 14:19:26 -0800348 return Void();
349 }
350
Steven Moreland337e6b62017-01-18 17:25:13 -0800351};
352
353sp<IServiceManager> getPassthroughServiceManager() {
354 static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
355 return manager;
356}
357
Steven Morelandcbefd352017-01-23 20:29:05 -0800358namespace 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
Steven Morelandf1e14f22017-03-28 09:33:06 -0700375 void wait(const std::string &interface, const std::string &instanceName) {
376 using std::literals::chrono_literals::operator""s;
377
Steven Morelandcbefd352017-01-23 20:29:05 -0800378 std::unique_lock<std::mutex> lock(mMutex);
Steven Morelandf1e14f22017-03-28 09:33:06 -0700379 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 }
Steven Morelandcbefd352017-01-23 20:29:05 -0800392 }
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
Steven Morelandf1e14f22017-03-28 09:33:06 -0700425 waiter->wait(interface, instanceName);
Steven Morelandcbefd352017-01-23 20:29:05 -0800426}
427
428}; // namespace details
429
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700430}; // namespace hardware
431}; // namespace android