ServiceManagement.cpp revision ec64c65eed4238de57461cd4e3cedbf42add182c
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 <unistd.h>
23
24#include <mutex>
25#include <regex>
26
27#include <hidl/HidlBinderSupport.h>
28#include <hidl/ServiceManagement.h>
29#include <hidl/Status.h>
30
31#include <android-base/logging.h>
32#include <hidl-util/FQName.h>
33#include <hidl-util/StringHelper.h>
34#include <hwbinder/IPCThreadState.h>
35#include <hwbinder/Parcel.h>
36
37#include <android/hidl/manager/1.0/IServiceManager.h>
38#include <android/hidl/manager/1.0/BpHwServiceManager.h>
39#include <android/hidl/manager/1.0/BnHwServiceManager.h>
40
41#define RE_COMPONENT    "[a-zA-Z_][a-zA-Z_0-9]*"
42#define RE_PATH         RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
43static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
44
45using android::hidl::manager::V1_0::IServiceManager;
46using android::hidl::manager::V1_0::IServiceNotification;
47using android::hidl::manager::V1_0::BpHwServiceManager;
48using android::hidl::manager::V1_0::BnHwServiceManager;
49
50namespace android {
51namespace hardware {
52
53namespace details {
54extern Mutex gDefaultServiceManagerLock;
55extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
56}  // namespace details
57
58sp<IServiceManager> defaultServiceManager() {
59
60    {
61        AutoMutex _l(details::gDefaultServiceManagerLock);
62        if (details::gDefaultServiceManager != NULL) {
63            return details::gDefaultServiceManager;
64        }
65        if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
66            // HwBinder not available on this device or not accessible to
67            // this process.
68            return nullptr;
69        }
70        while (details::gDefaultServiceManager == NULL) {
71            details::gDefaultServiceManager =
72                    fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
73                        ProcessState::self()->getContextObject(NULL));
74            if (details::gDefaultServiceManager == NULL) {
75                sleep(1);
76            }
77        }
78    }
79
80    return details::gDefaultServiceManager;
81}
82
83std::vector<std::string> search(const std::string &path,
84                              const std::string &prefix,
85                              const std::string &suffix) {
86    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
87    if (!dir) return {};
88
89    std::vector<std::string> results{};
90
91    dirent* dp;
92    while ((dp = readdir(dir.get())) != nullptr) {
93        std::string name = dp->d_name;
94
95        if (StringHelper::StartsWith(name, prefix) &&
96                StringHelper::EndsWith(name, suffix)) {
97            results.push_back(name);
98        }
99    }
100
101    return results;
102}
103
104bool matchPackageName(const std::string &lib, std::string *matchedName) {
105    std::smatch match;
106    if (std::regex_match(lib, match, gLibraryFileNamePattern)) {
107        *matchedName = match.str(1) + "::I*";
108        return true;
109    }
110    return false;
111}
112
113static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
114    sp<IServiceManager> binderizedManager = defaultServiceManager();
115    if (binderizedManager == nullptr) {
116        LOG(WARNING) << "Could not registerReference for "
117                     << interfaceName << "/" << instanceName
118                     << ": null binderized manager.";
119        return;
120    }
121    auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName, getpid());
122    if (!ret.isOk()) {
123        LOG(WARNING) << "Could not registerReference for "
124                     << interfaceName << "/" << instanceName
125                     << ": " << ret.description();
126        return;
127    }
128    LOG(VERBOSE) << "Successfully registerReference for "
129                 << interfaceName << "/" << instanceName;
130}
131
132struct PassthroughServiceManager : IServiceManager {
133    Return<sp<IBase>> get(const hidl_string& fqName,
134                     const hidl_string& name) override {
135        const FQName iface(fqName);
136
137        if (!iface.isValid() ||
138            !iface.isFullyQualified() ||
139            iface.isIdentifier()) {
140            LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
141            return nullptr;
142        }
143
144        const std::string prefix = iface.getPackageAndVersion().string() + "-impl";
145        const std::string sym = "HIDL_FETCH_" + iface.name();
146
147        const int dlMode = RTLD_LAZY;
148        void *handle = nullptr;
149
150        // TODO: lookup in VINTF instead
151        // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
152
153        dlerror(); // clear
154
155        for (const std::string &path : {
156            HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
157        }) {
158            std::vector<std::string> libs = search(path, prefix, ".so");
159
160            for (const std::string &lib : libs) {
161                const std::string fullPath = path + lib;
162
163                handle = dlopen(fullPath.c_str(), dlMode);
164                if (handle == nullptr) {
165                    const char* error = dlerror();
166                    LOG(ERROR) << "Failed to dlopen " << lib << ": "
167                               << (error == nullptr ? "unknown error" : error);
168                    continue;
169                }
170
171                IBase* (*generator)(const char* name);
172                *(void **)(&generator) = dlsym(handle, sym.c_str());
173                if(!generator) {
174                    const char* error = dlerror();
175                    LOG(ERROR) << "Passthrough lookup opened " << lib
176                               << " but could not find symbol " << sym << ": "
177                               << (error == nullptr ? "unknown error" : error);
178                    dlclose(handle);
179                    continue;
180                }
181
182                IBase *interface = (*generator)(name);
183
184                if (interface == nullptr) {
185                    dlclose(handle);
186                    continue; // this module doesn't provide this instance name
187                }
188
189                registerReference(fqName, name);
190
191                return interface;
192            }
193        }
194
195        return nullptr;
196    }
197
198    Return<bool> add(const hidl_string& /* name */,
199                     const sp<IBase>& /* service */) override {
200        LOG(FATAL) << "Cannot register services with passthrough service manager.";
201        return false;
202    }
203
204    Return<void> list(list_cb /* _hidl_cb */) override {
205        LOG(FATAL) << "Cannot list services with passthrough service manager.";
206        return Void();
207    }
208    Return<void> listByInterface(const hidl_string& /* fqInstanceName */,
209                                 listByInterface_cb /* _hidl_cb */) override {
210        // TODO: add this functionality
211        LOG(FATAL) << "Cannot list services with passthrough service manager.";
212        return Void();
213    }
214
215    Return<bool> registerForNotifications(const hidl_string& /* fqName */,
216                                          const hidl_string& /* name */,
217                                          const sp<IServiceNotification>& /* callback */) override {
218        // This makes no sense.
219        LOG(FATAL) << "Cannot register for notifications with passthrough service manager.";
220        return false;
221    }
222
223    Return<void> debugDump(debugDump_cb _hidl_cb) override {
224        using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture;
225        static std::vector<std::pair<Arch, std::vector<const char *>>> sAllPaths{
226            {Arch::IS_64BIT, {HAL_LIBRARY_PATH_ODM_64BIT,
227                                      HAL_LIBRARY_PATH_VENDOR_64BIT,
228                                      HAL_LIBRARY_PATH_SYSTEM_64BIT}},
229            {Arch::IS_32BIT, {HAL_LIBRARY_PATH_ODM_32BIT,
230                                      HAL_LIBRARY_PATH_VENDOR_32BIT,
231                                      HAL_LIBRARY_PATH_SYSTEM_32BIT}}
232        };
233        std::vector<InstanceDebugInfo> vec;
234        for (const auto &pair : sAllPaths) {
235            Arch arch = pair.first;
236            for (const auto &path : pair.second) {
237                std::vector<std::string> libs = search(path, "", ".so");
238                for (const std::string &lib : libs) {
239                    std::string matchedName;
240                    if (matchPackageName(lib, &matchedName)) {
241                        vec.push_back({
242                            .interfaceName = matchedName,
243                            .instanceName = "*",
244                            .clientPids = {},
245                            .arch = arch
246                        });
247                    }
248                }
249            }
250        }
251        _hidl_cb(vec);
252        return Void();
253    }
254
255    Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &, int32_t) override {
256        // This makes no sense.
257        LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
258                   << "Call it on defaultServiceManager() instead.";
259        return Void();
260    }
261
262};
263
264sp<IServiceManager> getPassthroughServiceManager() {
265    static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
266    return manager;
267}
268
269namespace details {
270
271struct Waiter : IServiceNotification {
272    Return<void> onRegistration(const hidl_string& /* fqName */,
273                                const hidl_string& /* name */,
274                                bool /* preexisting */) override {
275        std::unique_lock<std::mutex> lock(mMutex);
276        if (mRegistered) {
277            return Void();
278        }
279        mRegistered = true;
280        lock.unlock();
281
282        mCondition.notify_one();
283        return Void();
284    }
285
286    void wait() {
287        std::unique_lock<std::mutex> lock(mMutex);
288        mCondition.wait(lock, [this]{
289            return mRegistered;
290        });
291    }
292
293private:
294    std::mutex mMutex;
295    std::condition_variable mCondition;
296    bool mRegistered = false;
297};
298
299void waitForHwService(
300        const std::string &interface, const std::string &instanceName) {
301    const sp<IServiceManager> manager = defaultServiceManager();
302
303    if (manager == nullptr) {
304        LOG(ERROR) << "Could not get default service manager.";
305        return;
306    }
307
308    sp<Waiter> waiter = new Waiter();
309    Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter);
310
311    if (!ret.isOk()) {
312        LOG(ERROR) << "Transport error, " << ret.description()
313            << ", during notification registration for "
314            << interface << "/" << instanceName << ".";
315        return;
316    }
317
318    if (!ret) {
319        LOG(ERROR) << "Could not register for notifications for "
320            << interface << "/" << instanceName << ".";
321        return;
322    }
323
324    waiter->wait();
325}
326
327}; // namespace details
328
329}; // namespace hardware
330}; // namespace android
331