ServiceManagement.cpp revision 6fec3ba00a1db48a18047de00975bcd09ea0cc1c
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 <android/dlext.h>
20#include <condition_variable>
21#include <dlfcn.h>
22#include <dirent.h>
23#include <fstream>
24#include <pthread.h>
25#include <unistd.h>
26
27#include <mutex>
28#include <regex>
29#include <set>
30
31#include <hidl/HidlBinderSupport.h>
32#include <hidl/ServiceManagement.h>
33#include <hidl/Status.h>
34
35#include <android-base/logging.h>
36#include <android-base/properties.h>
37#include <hwbinder/IPCThreadState.h>
38#include <hwbinder/Parcel.h>
39#include <vndksupport/linker.h>
40
41#include <android/hidl/manager/1.0/IServiceManager.h>
42#include <android/hidl/manager/1.0/BpHwServiceManager.h>
43#include <android/hidl/manager/1.0/BnHwServiceManager.h>
44
45#define RE_COMPONENT    "[a-zA-Z_][a-zA-Z_0-9]*"
46#define RE_PATH         RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
47static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
48
49using android::base::WaitForProperty;
50
51using android::hidl::manager::V1_0::IServiceManager;
52using android::hidl::manager::V1_0::IServiceNotification;
53using android::hidl::manager::V1_0::BpHwServiceManager;
54using android::hidl::manager::V1_0::BnHwServiceManager;
55
56namespace android {
57namespace hardware {
58
59namespace details {
60extern Mutex gDefaultServiceManagerLock;
61extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
62}  // namespace details
63
64static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
65
66void waitForHwServiceManager() {
67    using std::literals::chrono_literals::operator""s;
68
69    while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
70        LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
71    }
72}
73
74bool endsWith(const std::string &in, const std::string &suffix) {
75    return in.size() >= suffix.size() &&
76           in.substr(in.size() - suffix.size()) == suffix;
77}
78
79bool startsWith(const std::string &in, const std::string &prefix) {
80    return in.size() >= prefix.size() &&
81           in.substr(0, prefix.size()) == prefix;
82}
83
84std::string binaryName() {
85    std::ifstream ifs("/proc/self/cmdline");
86    std::string cmdline;
87    if (!ifs.is_open()) {
88        return "";
89    }
90    ifs >> cmdline;
91
92    size_t idx = cmdline.rfind("/");
93    if (idx != std::string::npos) {
94        cmdline = cmdline.substr(idx + 1);
95    }
96
97    return cmdline;
98}
99
100void tryShortenProcessName(const std::string &packageName) {
101    std::string processName = binaryName();
102
103    if (!startsWith(processName, packageName)) {
104        return;
105    }
106
107    // e.x. android.hardware.module.foo@1.0 -> foo@1.0
108    size_t lastDot = packageName.rfind('.');
109    size_t secondDot = packageName.rfind('.', lastDot - 1);
110
111    if (secondDot == std::string::npos) {
112        return;
113    }
114
115    std::string newName = processName.substr(secondDot + 1,
116            16 /* TASK_COMM_LEN */ - 1);
117    ALOGI("Removing namespace from process name %s to %s.",
118            processName.c_str(), newName.c_str());
119
120    int rc = pthread_setname_np(pthread_self(), newName.c_str());
121    ALOGI_IF(rc != 0, "Removing namespace from process name %s failed.",
122            processName.c_str());
123}
124
125namespace details {
126
127void onRegistration(const std::string &packageName,
128                    const std::string& /* interfaceName */,
129                    const std::string& /* instanceName */) {
130    tryShortenProcessName(packageName);
131}
132
133}  // details
134
135sp<IServiceManager> defaultServiceManager() {
136    {
137        AutoMutex _l(details::gDefaultServiceManagerLock);
138        if (details::gDefaultServiceManager != NULL) {
139            return details::gDefaultServiceManager;
140        }
141
142        if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
143            // HwBinder not available on this device or not accessible to
144            // this process.
145            return nullptr;
146        }
147
148        waitForHwServiceManager();
149
150        while (details::gDefaultServiceManager == NULL) {
151            details::gDefaultServiceManager =
152                    fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
153                        ProcessState::self()->getContextObject(NULL));
154            if (details::gDefaultServiceManager == NULL) {
155                LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
156                sleep(1);
157            }
158        }
159    }
160
161    return details::gDefaultServiceManager;
162}
163
164std::vector<std::string> search(const std::string &path,
165                              const std::string &prefix,
166                              const std::string &suffix) {
167    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
168    if (!dir) return {};
169
170    std::vector<std::string> results{};
171
172    dirent* dp;
173    while ((dp = readdir(dir.get())) != nullptr) {
174        std::string name = dp->d_name;
175
176        if (startsWith(name, prefix) &&
177                endsWith(name, suffix)) {
178            results.push_back(name);
179        }
180    }
181
182    return results;
183}
184
185bool matchPackageName(const std::string& lib, std::string* matchedName, std::string* implName) {
186    std::smatch match;
187    if (std::regex_match(lib, match, gLibraryFileNamePattern)) {
188        *matchedName = match.str(1) + "::I*";
189        *implName = match.str(2);
190        return true;
191    }
192    return false;
193}
194
195static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
196    sp<IServiceManager> binderizedManager = defaultServiceManager();
197    if (binderizedManager == nullptr) {
198        LOG(WARNING) << "Could not registerReference for "
199                     << interfaceName << "/" << instanceName
200                     << ": null binderized manager.";
201        return;
202    }
203    auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
204    if (!ret.isOk()) {
205        LOG(WARNING) << "Could not registerReference for "
206                     << interfaceName << "/" << instanceName
207                     << ": " << ret.description();
208        return;
209    }
210    LOG(VERBOSE) << "Successfully registerReference for "
211                 << interfaceName << "/" << instanceName;
212}
213
214using InstanceDebugInfo = hidl::manager::V1_0::IServiceManager::InstanceDebugInfo;
215static inline void fetchPidsForPassthroughLibraries(
216    std::map<std::string, InstanceDebugInfo>* infos) {
217    static const std::string proc = "/proc/";
218
219    std::map<std::string, std::set<pid_t>> pids;
220    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(proc.c_str()), closedir);
221    if (!dir) return;
222    dirent* dp;
223    while ((dp = readdir(dir.get())) != nullptr) {
224        pid_t pid = strtoll(dp->d_name, NULL, 0);
225        if (pid == 0) continue;
226        std::string mapsPath = proc + dp->d_name + "/maps";
227        std::ifstream ifs{mapsPath};
228        if (!ifs.is_open()) continue;
229
230        for (std::string line; std::getline(ifs, line);) {
231            // The last token of line should look like
232            // vendor/lib64/hw/android.hardware.foo@1.0-impl-extra.so
233            // Use some simple filters to ignore bad lines before extracting libFileName
234            // and checking the key in info to make parsing faster.
235            if (line.back() != 'o') continue;
236            if (line.rfind('@') == std::string::npos) continue;
237
238            auto spacePos = line.rfind(' ');
239            if (spacePos == std::string::npos) continue;
240            auto libFileName = line.substr(spacePos + 1);
241            auto it = infos->find(libFileName);
242            if (it == infos->end()) continue;
243            pids[libFileName].insert(pid);
244        }
245    }
246    for (auto& pair : *infos) {
247        pair.second.clientPids =
248            std::vector<pid_t>{pids[pair.first].begin(), pids[pair.first].end()};
249    }
250}
251
252struct PassthroughServiceManager : IServiceManager {
253    static void openLibs(const std::string& fqName,
254            std::function<bool /* continue */(void* /* handle */,
255                const std::string& /* lib */, const std::string& /* sym */)> eachLib) {
256        //fqName looks like android.hardware.foo@1.0::IFoo
257        size_t idx = fqName.find("::");
258
259        if (idx == std::string::npos ||
260                idx + strlen("::") + 1 >= fqName.size()) {
261            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
262            return;
263        }
264
265        std::string packageAndVersion = fqName.substr(0, idx);
266        std::string ifaceName = fqName.substr(idx + strlen("::"));
267
268        const std::string prefix = packageAndVersion + "-impl";
269        const std::string sym = "HIDL_FETCH_" + ifaceName;
270
271        const int dlMode = RTLD_LAZY;
272        void *handle = nullptr;
273
274        dlerror(); // clear
275
276        std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
277                                          HAL_LIBRARY_PATH_SYSTEM};
278#ifdef LIBHIDL_TARGET_DEBUGGABLE
279        const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
280        const bool trebleTestingOverride = env && !strcmp(env, "true");
281        if (trebleTestingOverride) {
282            const char* vtsRootPath = std::getenv("VTS_ROOT_PATH");
283            if (vtsRootPath && strlen(vtsRootPath) > 0) {
284                const std::string halLibraryPathVtsOverride =
285                    std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM;
286                paths.push_back(halLibraryPathVtsOverride);
287            }
288        }
289#endif
290        for (const std::string& path : paths) {
291            std::vector<std::string> libs = search(path, prefix, ".so");
292
293            for (const std::string &lib : libs) {
294                const std::string fullPath = path + lib;
295
296                if (path != HAL_LIBRARY_PATH_SYSTEM) {
297                    handle = android_load_sphal_library(fullPath.c_str(), dlMode);
298                } else {
299                    handle = dlopen(fullPath.c_str(), dlMode);
300                }
301
302                if (handle == nullptr) {
303                    const char* error = dlerror();
304                    LOG(ERROR) << "Failed to dlopen " << lib << ": "
305                               << (error == nullptr ? "unknown error" : error);
306                    continue;
307                }
308
309                if (!eachLib(handle, lib, sym)) {
310                    return;
311                }
312            }
313        }
314    }
315
316    Return<sp<IBase>> get(const hidl_string& fqName,
317                          const hidl_string& name) override {
318        sp<IBase> ret = nullptr;
319
320        openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
321            IBase* (*generator)(const char* name);
322            *(void **)(&generator) = dlsym(handle, sym.c_str());
323            if(!generator) {
324                const char* error = dlerror();
325                LOG(ERROR) << "Passthrough lookup opened " << lib
326                           << " but could not find symbol " << sym << ": "
327                           << (error == nullptr ? "unknown error" : error);
328                dlclose(handle);
329                return true;
330            }
331
332            ret = (*generator)(name.c_str());
333
334            if (ret == nullptr) {
335                dlclose(handle);
336                return true; // this module doesn't provide this instance name
337            }
338
339            registerReference(fqName, name);
340            return false;
341        });
342
343        return ret;
344    }
345
346    Return<bool> add(const hidl_string& /* name */,
347                     const sp<IBase>& /* service */) override {
348        LOG(FATAL) << "Cannot register services with passthrough service manager.";
349        return false;
350    }
351
352    Return<Transport> getTransport(const hidl_string& /* fqName */,
353                                   const hidl_string& /* name */) {
354        LOG(FATAL) << "Cannot getTransport with passthrough service manager.";
355        return Transport::EMPTY;
356    }
357
358    Return<void> list(list_cb /* _hidl_cb */) override {
359        LOG(FATAL) << "Cannot list services with passthrough service manager.";
360        return Void();
361    }
362    Return<void> listByInterface(const hidl_string& /* fqInstanceName */,
363                                 listByInterface_cb /* _hidl_cb */) override {
364        // TODO: add this functionality
365        LOG(FATAL) << "Cannot list services with passthrough service manager.";
366        return Void();
367    }
368
369    Return<bool> registerForNotifications(const hidl_string& /* fqName */,
370                                          const hidl_string& /* name */,
371                                          const sp<IServiceNotification>& /* callback */) override {
372        // This makes no sense.
373        LOG(FATAL) << "Cannot register for notifications with passthrough service manager.";
374        return false;
375    }
376
377    Return<void> debugDump(debugDump_cb _hidl_cb) override {
378        using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture;
379        using std::literals::string_literals::operator""s;
380        static std::vector<std::pair<Arch, std::vector<const char *>>> sAllPaths{
381            {Arch::IS_64BIT, {HAL_LIBRARY_PATH_ODM_64BIT,
382                                      HAL_LIBRARY_PATH_VENDOR_64BIT,
383                                      HAL_LIBRARY_PATH_SYSTEM_64BIT}},
384            {Arch::IS_32BIT, {HAL_LIBRARY_PATH_ODM_32BIT,
385                                      HAL_LIBRARY_PATH_VENDOR_32BIT,
386                                      HAL_LIBRARY_PATH_SYSTEM_32BIT}}
387        };
388        std::map<std::string, InstanceDebugInfo> map;
389        for (const auto &pair : sAllPaths) {
390            Arch arch = pair.first;
391            for (const auto &path : pair.second) {
392                std::vector<std::string> libs = search(path, "", ".so");
393                for (const std::string &lib : libs) {
394                    std::string matchedName;
395                    std::string implName;
396                    if (matchPackageName(lib, &matchedName, &implName)) {
397                        std::string instanceName{"* ("s + path + ")"s};
398                        if (!implName.empty()) instanceName += " ("s + implName + ")"s;
399                        map.emplace(path + lib, InstanceDebugInfo{.interfaceName = matchedName,
400                                                                  .instanceName = instanceName,
401                                                                  .clientPids = {},
402                                                                  .arch = arch});
403                    }
404                }
405            }
406        }
407        fetchPidsForPassthroughLibraries(&map);
408        hidl_vec<InstanceDebugInfo> vec;
409        vec.resize(map.size());
410        size_t idx = 0;
411        for (auto&& pair : map) {
412            vec[idx++] = std::move(pair.second);
413        }
414        _hidl_cb(vec);
415        return Void();
416    }
417
418    Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override {
419        // This makes no sense.
420        LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
421                   << "Call it on defaultServiceManager() instead.";
422        return Void();
423    }
424
425};
426
427sp<IServiceManager> getPassthroughServiceManager() {
428    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
429    return manager;
430}
431
432namespace details {
433
434void preloadPassthroughService(const std::string &descriptor) {
435    PassthroughServiceManager::openLibs(descriptor,
436        [&](void* /* handle */, const std::string& /* lib */, const std::string& /* sym */) {
437            // do nothing
438            return true; // open all libs
439        });
440}
441
442struct Waiter : IServiceNotification {
443    Return<void> onRegistration(const hidl_string& /* fqName */,
444                                const hidl_string& /* name */,
445                                bool /* preexisting */) override {
446        std::unique_lock<std::mutex> lock(mMutex);
447        if (mRegistered) {
448            return Void();
449        }
450        mRegistered = true;
451        lock.unlock();
452
453        mCondition.notify_one();
454        return Void();
455    }
456
457    void wait(const std::string &interface, const std::string &instanceName) {
458        using std::literals::chrono_literals::operator""s;
459
460        std::unique_lock<std::mutex> lock(mMutex);
461        while(true) {
462            mCondition.wait_for(lock, 1s, [this]{
463                return mRegistered;
464            });
465
466            if (mRegistered) {
467                break;
468            }
469
470            LOG(WARNING) << "Waited one second for "
471                         << interface << "/" << instanceName
472                         << ". Waiting another...";
473        }
474    }
475
476private:
477    std::mutex mMutex;
478    std::condition_variable mCondition;
479    bool mRegistered = false;
480};
481
482void waitForHwService(
483        const std::string &interface, const std::string &instanceName) {
484    const sp<IServiceManager> manager = defaultServiceManager();
485
486    if (manager == nullptr) {
487        LOG(ERROR) << "Could not get default service manager.";
488        return;
489    }
490
491    sp<Waiter> waiter = new Waiter();
492    Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter);
493
494    if (!ret.isOk()) {
495        LOG(ERROR) << "Transport error, " << ret.description()
496            << ", during notification registration for "
497            << interface << "/" << instanceName << ".";
498        return;
499    }
500
501    if (!ret) {
502        LOG(ERROR) << "Could not register for notifications for "
503            << interface << "/" << instanceName << ".";
504        return;
505    }
506
507    waiter->wait(interface, instanceName);
508}
509
510}; // namespace details
511
512}; // namespace hardware
513}; // namespace android
514