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 ")*"
45 static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
46 
47 extern "C" {
48     android_namespace_t* android_get_exported_namespace(const char*);
49 }
50 
51 using android::base::WaitForProperty;
52 
53 using android::hidl::manager::V1_0::IServiceManager;
54 using android::hidl::manager::V1_0::IServiceNotification;
55 using android::hidl::manager::V1_0::BpHwServiceManager;
56 using android::hidl::manager::V1_0::BnHwServiceManager;
57 
58 namespace android {
59 namespace hardware {
60 
61 namespace details {
62 extern Mutex gDefaultServiceManagerLock;
63 extern sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
64 }  // namespace details
65 
66 static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
67 
waitForHwServiceManager()68 void 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 
endsWith(const std::string & in,const std::string & suffix)76 bool 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 
startsWith(const std::string & in,const std::string & prefix)81 bool startsWith(const std::string &in, const std::string &prefix) {
82     return in.size() >= prefix.size() &&
83            in.substr(0, prefix.size()) == prefix;
84 }
85 
binaryName()86 std::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 
tryShortenProcessName(const std::string & packageName)102 void 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 
127 namespace details {
128 
onRegistration(const std::string & packageName,const std::string &,const std::string &)129 void onRegistration(const std::string &packageName,
130                     const std::string& /* interfaceName */,
131                     const std::string& /* instanceName */) {
132     tryShortenProcessName(packageName);
133 }
134 
135 }  // details
136 
defaultServiceManager()137 sp<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 
search(const std::string & path,const std::string & prefix,const std::string & suffix)166 std::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 
matchPackageName(const std::string & lib,std::string * matchedName)187 bool 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 
registerReference(const hidl_string & interfaceName,const hidl_string & instanceName)196 static 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 
215 struct PassthroughServiceManager : IServiceManager {
getandroid::hardware::PassthroughServiceManager216     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 
addandroid::hardware::PassthroughServiceManager309     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 
getTransportandroid::hardware::PassthroughServiceManager315     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 
listandroid::hardware::PassthroughServiceManager321     Return<void> list(list_cb /* _hidl_cb */) override {
322         LOG(FATAL) << "Cannot list services with passthrough service manager.";
323         return Void();
324     }
listByInterfaceandroid::hardware::PassthroughServiceManager325     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 
registerForNotificationsandroid::hardware::PassthroughServiceManager332     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 
debugDumpandroid::hardware::PassthroughServiceManager340     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 
registerPassthroughClientandroid::hardware::PassthroughServiceManager372     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 
getPassthroughServiceManager()381 sp<IServiceManager> getPassthroughServiceManager() {
382     static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
383     return manager;
384 }
385 
386 namespace details {
387 
388 struct Waiter : IServiceNotification {
onRegistrationandroid::hardware::details::Waiter389     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 
waitandroid::hardware::details::Waiter403     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 
422 private:
423     std::mutex mMutex;
424     std::condition_variable mCondition;
425     bool mRegistered = false;
426 };
427 
waitForHwService(const std::string & interface,const std::string & instanceName)428 void 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