blob: 617a85839937191858816c4aa1864bde28151c7c [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
Jiyong Park3ab546c2017-04-06 20:28:07 +090019#include <android/dlext.h>
Yifan Hong9a22d1d2017-01-25 14:19:26 -080020#include <condition_variable>
21#include <dlfcn.h>
22#include <dirent.h>
Steven Moreland405d7612017-04-07 20:31:22 -070023#include <fstream>
24#include <pthread.h>
Yifan Hong9a22d1d2017-01-25 14:19:26 -080025#include <unistd.h>
26
27#include <mutex>
28#include <regex>
29
Martijn Coenen12f04d92016-12-07 17:29:41 +010030#include <hidl/HidlBinderSupport.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070031#include <hidl/ServiceManagement.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070032#include <hidl/Status.h>
33
Steven Moreland337e6b62017-01-18 17:25:13 -080034#include <android-base/logging.h>
Steven Morelandc1cee2c2017-03-24 16:23:11 +000035#include <android-base/properties.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070036#include <hwbinder/IPCThreadState.h>
37#include <hwbinder/Parcel.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070038
39#include <android/hidl/manager/1.0/IServiceManager.h>
Yifan Hong4e925992017-01-09 17:47:17 -080040#include <android/hidl/manager/1.0/BpHwServiceManager.h>
41#include <android/hidl/manager/1.0/BnHwServiceManager.h>
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070042
Yifan Hong9a22d1d2017-01-25 14:19:26 -080043#define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*"
44#define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
45static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
46
Jiyong Park3ab546c2017-04-06 20:28:07 +090047extern "C" {
48 android_namespace_t* android_get_exported_namespace(const char*);
49}
50
Steven Morelandc1cee2c2017-03-24 16:23:11 +000051using android::base::WaitForProperty;
52
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070053using android::hidl::manager::V1_0::IServiceManager;
Steven Moreland337e6b62017-01-18 17:25:13 -080054using android::hidl::manager::V1_0::IServiceNotification;
Yifan Hong4e925992017-01-09 17:47:17 -080055using android::hidl::manager::V1_0::BpHwServiceManager;
56using android::hidl::manager::V1_0::BnHwServiceManager;
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070057
58namespace android {
59namespace hardware {
60
Yifan Hong953e6b02017-03-16 14:52:40 -070061namespace details {
62extern Mutex gDefaultServiceManagerLock;
63extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
64} // namespace details
65
Steven Morelandc1cee2c2017-03-24 16:23:11 +000066static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
67
68void waitForHwServiceManager() {
69 using std::literals::chrono_literals::operator""s;
70
71 while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
72 LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
73 }
74}
75
Steven Moreland405d7612017-04-07 20:31:22 -070076bool endsWith(const std::string &in, const std::string &suffix) {
77 return in.size() >= suffix.size() &&
78 in.substr(in.size() - suffix.size()) == suffix;
79}
Steven Moreland5d5ef7f2016-10-20 19:19:55 -070080
Steven Moreland405d7612017-04-07 20:31:22 -070081bool startsWith(const std::string &in, const std::string &prefix) {
82 return in.size() >= prefix.size() &&
83 in.substr(0, prefix.size()) == prefix;
84}
85
86std::string binaryName() {
87 std::ifstream ifs("/proc/self/cmdline");
88 std::string cmdline;
89 if (!ifs.is_open()) {
90 return "";
91 }
92 ifs >> cmdline;
93
94 size_t idx = cmdline.rfind("/");
95 if (idx != std::string::npos) {
96 cmdline = cmdline.substr(idx + 1);
97 }
98
99 return cmdline;
100}
101
102void tryShortenProcessName(const std::string &packageName) {
103 std::string processName = binaryName();
104
105 if (!startsWith(processName, packageName)) {
106 return;
107 }
108
109 // e.x. android.hardware.module.foo@1.0 -> foo@1.0
110 size_t lastDot = packageName.rfind('.');
111 size_t secondDot = packageName.rfind('.', lastDot - 1);
112
113 if (secondDot == std::string::npos) {
114 return;
115 }
116
117 std::string newName = processName.substr(secondDot + 1,
118 16 /* TASK_COMM_LEN */ - 1);
119 ALOGI("Removing namespace from process name %s to %s.",
120 processName.c_str(), newName.c_str());
121
122 int rc = pthread_setname_np(pthread_self(), newName.c_str());
123 ALOGI_IF(rc != 0, "Removing namespace from process name %s failed.",
124 processName.c_str());
125}
126
127namespace details {
128
129void onRegistration(const std::string &packageName,
130 const std::string& /* interfaceName */,
131 const std::string& /* instanceName */) {
132 tryShortenProcessName(packageName);
133}
134
135} // details
136
137sp<IServiceManager> defaultServiceManager() {
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700138 {
Yifan Hong953e6b02017-03-16 14:52:40 -0700139 AutoMutex _l(details::gDefaultServiceManagerLock);
140 if (details::gDefaultServiceManager != NULL) {
141 return details::gDefaultServiceManager;
Yifan Hong8fb656b2017-03-16 14:30:40 -0700142 }
Steven Moreland405d7612017-04-07 20:31:22 -0700143
Yifan Hong8fb656b2017-03-16 14:30:40 -0700144 if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
145 // HwBinder not available on this device or not accessible to
146 // this process.
147 return nullptr;
148 }
Steven Morelandc1cee2c2017-03-24 16:23:11 +0000149
150 waitForHwServiceManager();
151
Yifan Hong953e6b02017-03-16 14:52:40 -0700152 while (details::gDefaultServiceManager == NULL) {
153 details::gDefaultServiceManager =
Yifan Hong8fb656b2017-03-16 14:30:40 -0700154 fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
155 ProcessState::self()->getContextObject(NULL));
Yifan Hong953e6b02017-03-16 14:52:40 -0700156 if (details::gDefaultServiceManager == NULL) {
Steven Morelandc1cee2c2017-03-24 16:23:11 +0000157 LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700158 sleep(1);
Yifan Hong8fb656b2017-03-16 14:30:40 -0700159 }
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700160 }
161 }
162
Yifan Hong953e6b02017-03-16 14:52:40 -0700163 return details::gDefaultServiceManager;
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700164}
165
Steven Moreland0091c092017-01-20 23:15:18 +0000166std::vector<std::string> search(const std::string &path,
167 const std::string &prefix,
168 const std::string &suffix) {
169 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
170 if (!dir) return {};
171
172 std::vector<std::string> results{};
173
174 dirent* dp;
175 while ((dp = readdir(dir.get())) != nullptr) {
176 std::string name = dp->d_name;
177
Steven Moreland819c05d2017-04-06 17:24:22 -0700178 if (startsWith(name, prefix) &&
179 endsWith(name, suffix)) {
Steven Moreland0091c092017-01-20 23:15:18 +0000180 results.push_back(name);
181 }
182 }
183
184 return results;
185}
186
Yifan Hong9a22d1d2017-01-25 14:19:26 -0800187bool matchPackageName(const std::string &lib, std::string *matchedName) {
188 std::smatch match;
189 if (std::regex_match(lib, match, gLibraryFileNamePattern)) {
190 *matchedName = match.str(1) + "::I*";
191 return true;
192 }
193 return false;
194}
195
Yifan Hong7f49f592017-02-03 15:11:44 -0800196static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
197 sp<IServiceManager> binderizedManager = defaultServiceManager();
198 if (binderizedManager == nullptr) {
199 LOG(WARNING) << "Could not registerReference for "
200 << interfaceName << "/" << instanceName
201 << ": null binderized manager.";
202 return;
203 }
Martijn Coenenaf4aba52017-04-27 09:41:13 -0700204 auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
Yifan Hong7f49f592017-02-03 15:11:44 -0800205 if (!ret.isOk()) {
206 LOG(WARNING) << "Could not registerReference for "
207 << interfaceName << "/" << instanceName
208 << ": " << ret.description();
Steven Moreland0aeaa782017-03-22 08:11:07 -0700209 return;
Yifan Hong7f49f592017-02-03 15:11:44 -0800210 }
Steven Morelande681aa52017-02-15 16:22:37 -0800211 LOG(VERBOSE) << "Successfully registerReference for "
212 << interfaceName << "/" << instanceName;
Yifan Hong7f49f592017-02-03 15:11:44 -0800213}
214
Steven Moreland337e6b62017-01-18 17:25:13 -0800215struct PassthroughServiceManager : IServiceManager {
216 Return<sp<IBase>> get(const hidl_string& fqName,
Steven Moreland819c05d2017-04-06 17:24:22 -0700217 const hidl_string& name) override {
218 std::string stdFqName(fqName.c_str());
Steven Moreland337e6b62017-01-18 17:25:13 -0800219
Steven Moreland819c05d2017-04-06 17:24:22 -0700220 //fqName looks like android.hardware.foo@1.0::IFoo
221 size_t idx = stdFqName.find("::");
222
223 if (idx == std::string::npos ||
224 idx + strlen("::") + 1 >= stdFqName.size()) {
Steven Moreland337e6b62017-01-18 17:25:13 -0800225 LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
226 return nullptr;
227 }
228
Steven Moreland819c05d2017-04-06 17:24:22 -0700229 std::string packageAndVersion = stdFqName.substr(0, idx);
230 std::string ifaceName = stdFqName.substr(idx + strlen("::"));
231
232 const std::string prefix = packageAndVersion + "-impl";
233 const std::string sym = "HIDL_FETCH_" + ifaceName;
Steven Moreland348802d2017-02-23 12:48:55 -0800234
Jiyong Park3ab546c2017-04-06 20:28:07 +0900235 const android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
Steven Moreland337e6b62017-01-18 17:25:13 -0800236 const int dlMode = RTLD_LAZY;
237 void *handle = nullptr;
238
Steven Moreland0091c092017-01-20 23:15:18 +0000239 // TODO: lookup in VINTF instead
240 // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
241
Steven Morelanda29905c2017-03-01 10:42:35 -0800242 dlerror(); // clear
243
Steven Moreland337e6b62017-01-18 17:25:13 -0800244 for (const std::string &path : {
245 HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
246 }) {
Steven Moreland0091c092017-01-20 23:15:18 +0000247 std::vector<std::string> libs = search(path, prefix, ".so");
248
Steven Moreland0091c092017-01-20 23:15:18 +0000249 for (const std::string &lib : libs) {
Steven Moreland348802d2017-02-23 12:48:55 -0800250 const std::string fullPath = path + lib;
251
Jiyong Park3ab546c2017-04-06 20:28:07 +0900252 // If sphal namespace is available, try to load from the
253 // namespace first. If it fails, fall back to the original
254 // dlopen, which loads from the current namespace.
255 if (sphal_namespace != nullptr && path != HAL_LIBRARY_PATH_SYSTEM) {
256 const android_dlextinfo dlextinfo = {
257 .flags = ANDROID_DLEXT_USE_NAMESPACE,
258 // const_cast is dirty but required because
259 // library_namespace field is non-const.
260 .library_namespace = const_cast<android_namespace_t*>(sphal_namespace),
261 };
262 handle = android_dlopen_ext(fullPath.c_str(), dlMode, &dlextinfo);
263 if (handle == nullptr) {
264 const char* error = dlerror();
265 LOG(WARNING) << "Failed to dlopen " << lib << " from sphal namespace:"
266 << (error == nullptr ? "unknown error" : error);
267 } else {
268 LOG(DEBUG) << lib << " loaded from sphal namespace.";
269 }
270 }
271 if (handle == nullptr) {
272 handle = dlopen(fullPath.c_str(), dlMode);
273 }
274
Steven Moreland348802d2017-02-23 12:48:55 -0800275 if (handle == nullptr) {
276 const char* error = dlerror();
277 LOG(ERROR) << "Failed to dlopen " << lib << ": "
278 << (error == nullptr ? "unknown error" : error);
279 continue;
Steven Moreland0091c092017-01-20 23:15:18 +0000280 }
Steven Moreland348802d2017-02-23 12:48:55 -0800281
282 IBase* (*generator)(const char* name);
283 *(void **)(&generator) = dlsym(handle, sym.c_str());
284 if(!generator) {
285 const char* error = dlerror();
286 LOG(ERROR) << "Passthrough lookup opened " << lib
287 << " but could not find symbol " << sym << ": "
288 << (error == nullptr ? "unknown error" : error);
289 dlclose(handle);
290 continue;
291 }
292
Scott Randolph0c84ab42017-04-03 14:07:14 -0700293 IBase *interface = (*generator)(name.c_str());
Steven Moreland348802d2017-02-23 12:48:55 -0800294
295 if (interface == nullptr) {
296 dlclose(handle);
297 continue; // this module doesn't provide this instance name
298 }
299
300 registerReference(fqName, name);
301
302 return interface;
Steven Moreland337e6b62017-01-18 17:25:13 -0800303 }
304 }
305
Steven Moreland348802d2017-02-23 12:48:55 -0800306 return nullptr;
Steven Moreland337e6b62017-01-18 17:25:13 -0800307 }
308
Martijn Coenen67a02492017-03-06 13:04:48 +0100309 Return<bool> add(const hidl_string& /* name */,
Steven Moreland337e6b62017-01-18 17:25:13 -0800310 const sp<IBase>& /* service */) override {
311 LOG(FATAL) << "Cannot register services with passthrough service manager.";
312 return false;
313 }
314
Steven Morelandc601c5f2017-04-06 09:26:07 -0700315 Return<Transport> getTransport(const hidl_string& /* fqName */,
316 const hidl_string& /* name */) {
317 LOG(FATAL) << "Cannot getTransport with passthrough service manager.";
318 return Transport::EMPTY;
319 }
320
Yifan Hong705e5da2017-03-02 16:59:39 -0800321 Return<void> list(list_cb /* _hidl_cb */) override {
322 LOG(FATAL) << "Cannot list services with passthrough service manager.";
Steven Moreland337e6b62017-01-18 17:25:13 -0800323 return Void();
324 }
325 Return<void> listByInterface(const hidl_string& /* fqInstanceName */,
326 listByInterface_cb /* _hidl_cb */) override {
327 // TODO: add this functionality
328 LOG(FATAL) << "Cannot list services with passthrough service manager.";
329 return Void();
330 }
331
332 Return<bool> registerForNotifications(const hidl_string& /* fqName */,
333 const hidl_string& /* name */,
334 const sp<IServiceNotification>& /* callback */) override {
335 // This makes no sense.
336 LOG(FATAL) << "Cannot register for notifications with passthrough service manager.";
337 return false;
338 }
339
Yifan Hong705e5da2017-03-02 16:59:39 -0800340 Return<void> debugDump(debugDump_cb _hidl_cb) override {
341 using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture;
342 static std::vector<std::pair<Arch, std::vector<const char *>>> sAllPaths{
343 {Arch::IS_64BIT, {HAL_LIBRARY_PATH_ODM_64BIT,
344 HAL_LIBRARY_PATH_VENDOR_64BIT,
345 HAL_LIBRARY_PATH_SYSTEM_64BIT}},
346 {Arch::IS_32BIT, {HAL_LIBRARY_PATH_ODM_32BIT,
347 HAL_LIBRARY_PATH_VENDOR_32BIT,
348 HAL_LIBRARY_PATH_SYSTEM_32BIT}}
349 };
350 std::vector<InstanceDebugInfo> vec;
351 for (const auto &pair : sAllPaths) {
352 Arch arch = pair.first;
353 for (const auto &path : pair.second) {
354 std::vector<std::string> libs = search(path, "", ".so");
355 for (const std::string &lib : libs) {
356 std::string matchedName;
357 if (matchPackageName(lib, &matchedName)) {
358 vec.push_back({
359 .interfaceName = matchedName,
360 .instanceName = "*",
361 .clientPids = {},
362 .arch = arch
363 });
364 }
365 }
366 }
367 }
368 _hidl_cb(vec);
Yifan Hong7f49f592017-02-03 15:11:44 -0800369 return Void();
370 }
371
Martijn Coenenaf4aba52017-04-27 09:41:13 -0700372 Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override {
Yifan Hong7f49f592017-02-03 15:11:44 -0800373 // This makes no sense.
374 LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
375 << "Call it on defaultServiceManager() instead.";
Yifan Hong9a22d1d2017-01-25 14:19:26 -0800376 return Void();
377 }
378
Steven Moreland337e6b62017-01-18 17:25:13 -0800379};
380
381sp<IServiceManager> getPassthroughServiceManager() {
382 static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
383 return manager;
384}
385
Steven Morelandcbefd352017-01-23 20:29:05 -0800386namespace details {
387
388struct Waiter : IServiceNotification {
389 Return<void> onRegistration(const hidl_string& /* fqName */,
390 const hidl_string& /* name */,
391 bool /* preexisting */) override {
392 std::unique_lock<std::mutex> lock(mMutex);
393 if (mRegistered) {
394 return Void();
395 }
396 mRegistered = true;
397 lock.unlock();
398
399 mCondition.notify_one();
400 return Void();
401 }
402
Steven Moreland49605102017-03-28 09:33:06 -0700403 void wait(const std::string &interface, const std::string &instanceName) {
404 using std::literals::chrono_literals::operator""s;
405
Steven Morelandcbefd352017-01-23 20:29:05 -0800406 std::unique_lock<std::mutex> lock(mMutex);
Steven Moreland49605102017-03-28 09:33:06 -0700407 while(true) {
408 mCondition.wait_for(lock, 1s, [this]{
409 return mRegistered;
410 });
411
412 if (mRegistered) {
413 break;
414 }
415
416 LOG(WARNING) << "Waited one second for "
417 << interface << "/" << instanceName
418 << ". Waiting another...";
419 }
Steven Morelandcbefd352017-01-23 20:29:05 -0800420 }
421
422private:
423 std::mutex mMutex;
424 std::condition_variable mCondition;
425 bool mRegistered = false;
426};
427
428void waitForHwService(
429 const std::string &interface, const std::string &instanceName) {
430 const sp<IServiceManager> manager = defaultServiceManager();
431
432 if (manager == nullptr) {
433 LOG(ERROR) << "Could not get default service manager.";
434 return;
435 }
436
437 sp<Waiter> waiter = new Waiter();
438 Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter);
439
440 if (!ret.isOk()) {
441 LOG(ERROR) << "Transport error, " << ret.description()
442 << ", during notification registration for "
443 << interface << "/" << instanceName << ".";
444 return;
445 }
446
447 if (!ret) {
448 LOG(ERROR) << "Could not register for notifications for "
449 << interface << "/" << instanceName << ".";
450 return;
451 }
452
Steven Moreland49605102017-03-28 09:33:06 -0700453 waiter->wait(interface, instanceName);
Steven Morelandcbefd352017-01-23 20:29:05 -0800454}
455
456}; // namespace details
457
Steven Moreland5d5ef7f2016-10-20 19:19:55 -0700458}; // namespace hardware
459}; // namespace android