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