ServiceManagement.cpp revision bf13ad09b72a4a7ffd70a65ccd7a7ed722bfe517
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 <fstream>
23#include <pthread.h>
24#include <unistd.h>
25
26#include <mutex>
27#include <regex>
28
29#include <hidl/HidlBinderSupport.h>
30#include <hidl/ServiceManagement.h>
31#include <hidl/Status.h>
32
33#include <android-base/logging.h>
34#include <android-base/properties.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
71bool endsWith(const std::string &in, const std::string &suffix) {
72    return in.size() >= suffix.size() &&
73           in.substr(in.size() - suffix.size()) == suffix;
74}
75
76bool 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() {
133    {
134        AutoMutex _l(details::gDefaultServiceManagerLock);
135        if (details::gDefaultServiceManager != NULL) {
136            return details::gDefaultServiceManager;
137        }
138
139        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        }
144
145        waitForHwServiceManager();
146
147        while (details::gDefaultServiceManager == NULL) {
148            details::gDefaultServiceManager =
149                    fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
150                        ProcessState::self()->getContextObject(NULL));
151            if (details::gDefaultServiceManager == NULL) {
152                LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
153                sleep(1);
154            }
155        }
156    }
157
158    return details::gDefaultServiceManager;
159}
160
161std::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
173        if (startsWith(name, prefix) &&
174                endsWith(name, suffix)) {
175            results.push_back(name);
176        }
177    }
178
179    return results;
180}
181
182bool 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
191static 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    }
199    auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
200    if (!ret.isOk()) {
201        LOG(WARNING) << "Could not registerReference for "
202                     << interfaceName << "/" << instanceName
203                     << ": " << ret.description();
204        return;
205    }
206    LOG(VERBOSE) << "Successfully registerReference for "
207                 << interfaceName << "/" << instanceName;
208}
209
210struct PassthroughServiceManager : IServiceManager {
211    Return<sp<IBase>> get(const hidl_string& fqName,
212                          const hidl_string& name) override {
213        std::string stdFqName(fqName.c_str());
214
215        //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()) {
220            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
221            return nullptr;
222        }
223
224        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;
229
230        const int dlMode = RTLD_LAZY;
231        void *handle = nullptr;
232
233        // TODO: lookup in VINTF instead
234        // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
235
236        dlerror(); // clear
237
238        for (const std::string &path : {
239            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
240        }) {
241            std::vector<std::string> libs = search(path, prefix, ".so");
242
243            for (const std::string &lib : libs) {
244                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;
252                }
253
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
265                IBase *interface = (*generator)(name.c_str());
266
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;
275            }
276        }
277
278        return nullptr;
279    }
280
281    Return<bool> add(const hidl_string& /* name */,
282                     const sp<IBase>& /* service */) override {
283        LOG(FATAL) << "Cannot register services with passthrough service manager.";
284        return false;
285    }
286
287    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
293    Return<void> list(list_cb /* _hidl_cb */) override {
294        LOG(FATAL) << "Cannot list services with passthrough service manager.";
295        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
312    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);
341        return Void();
342    }
343
344    Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override {
345        // This makes no sense.
346        LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
347                   << "Call it on defaultServiceManager() instead.";
348        return Void();
349    }
350
351};
352
353sp<IServiceManager> getPassthroughServiceManager() {
354    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
355    return manager;
356}
357
358namespace 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
375    void wait(const std::string &interface, const std::string &instanceName) {
376        using std::literals::chrono_literals::operator""s;
377
378        std::unique_lock<std::mutex> lock(mMutex);
379        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        }
392    }
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
425    waiter->wait(interface, instanceName);
426}
427
428}; // namespace details
429
430}; // namespace hardware
431}; // namespace android
432