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
30#include <hidl/HidlBinderSupport.h>
31#include <hidl/ServiceManagement.h>
32#include <hidl/Status.h>
33
34#include <android-base/logging.h>
35#include <android-base/properties.h>
36#include <hwbinder/IPCThreadState.h>
37#include <hwbinder/Parcel.h>
38
39#include <android/hidl/manager/1.0/IServiceManager.h>
40#include <android/hidl/manager/1.0/BpHwServiceManager.h>
41#include <android/hidl/manager/1.0/BnHwServiceManager.h>
42
43#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
47extern "C" {
48    android_namespace_t* android_get_exported_namespace(const char*);
49}
50
51using android::base::WaitForProperty;
52
53using android::hidl::manager::V1_0::IServiceManager;
54using android::hidl::manager::V1_0::IServiceNotification;
55using android::hidl::manager::V1_0::BpHwServiceManager;
56using android::hidl::manager::V1_0::BnHwServiceManager;
57
58namespace android {
59namespace hardware {
60
61namespace details {
62extern Mutex gDefaultServiceManagerLock;
63extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
64}  // namespace details
65
66static 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
76bool endsWith(const std::string &in, const std::string &suffix) {
77    return in.size() >= suffix.size() &&
78           in.substr(in.size() - suffix.size()) == suffix;
79}
80
81bool 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() {
138    {
139        AutoMutex _l(details::gDefaultServiceManagerLock);
140        if (details::gDefaultServiceManager != NULL) {
141            return details::gDefaultServiceManager;
142        }
143
144        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        }
149
150        waitForHwServiceManager();
151
152        while (details::gDefaultServiceManager == NULL) {
153            details::gDefaultServiceManager =
154                    fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
155                        ProcessState::self()->getContextObject(NULL));
156            if (details::gDefaultServiceManager == NULL) {
157                LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
158                sleep(1);
159            }
160        }
161    }
162
163    return details::gDefaultServiceManager;
164}
165
166std::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
178        if (startsWith(name, prefix) &&
179                endsWith(name, suffix)) {
180            results.push_back(name);
181        }
182    }
183
184    return results;
185}
186
187bool 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
196static 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    }
204    auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
205    if (!ret.isOk()) {
206        LOG(WARNING) << "Could not registerReference for "
207                     << interfaceName << "/" << instanceName
208                     << ": " << ret.description();
209        return;
210    }
211    LOG(VERBOSE) << "Successfully registerReference for "
212                 << interfaceName << "/" << instanceName;
213}
214
215struct PassthroughServiceManager : IServiceManager {
216    Return<sp<IBase>> get(const hidl_string& fqName,
217                          const hidl_string& name) override {
218        std::string stdFqName(fqName.c_str());
219
220        //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()) {
225            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
226            return nullptr;
227        }
228
229        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;
234
235        const android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
236        const int dlMode = RTLD_LAZY;
237        void *handle = nullptr;
238
239        // TODO: lookup in VINTF instead
240        // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
241
242        dlerror(); // clear
243
244        for (const std::string &path : {
245            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
246        }) {
247            std::vector<std::string> libs = search(path, prefix, ".so");
248
249            for (const std::string &lib : libs) {
250                const std::string fullPath = path + lib;
251
252                // 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
275                if (handle == nullptr) {
276                    const char* error = dlerror();
277                    LOG(ERROR) << "Failed to dlopen " << lib << ": "
278                               << (error == nullptr ? "unknown error" : error);
279                    continue;
280                }
281
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
293                IBase *interface = (*generator)(name.c_str());
294
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;
303            }
304        }
305
306        return nullptr;
307    }
308
309    Return<bool> add(const hidl_string& /* name */,
310                     const sp<IBase>& /* service */) override {
311        LOG(FATAL) << "Cannot register services with passthrough service manager.";
312        return false;
313    }
314
315    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
321    Return<void> list(list_cb /* _hidl_cb */) override {
322        LOG(FATAL) << "Cannot list services with passthrough service manager.";
323        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
340    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);
369        return Void();
370    }
371
372    Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override {
373        // This makes no sense.
374        LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
375                   << "Call it on defaultServiceManager() instead.";
376        return Void();
377    }
378
379};
380
381sp<IServiceManager> getPassthroughServiceManager() {
382    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
383    return manager;
384}
385
386namespace 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
403    void wait(const std::string &interface, const std::string &instanceName) {
404        using std::literals::chrono_literals::operator""s;
405
406        std::unique_lock<std::mutex> lock(mMutex);
407        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        }
420    }
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
453    waiter->wait(interface, instanceName);
454}
455
456}; // namespace details
457
458}; // namespace hardware
459}; // namespace android
460