Home | History | Annotate | Download | only in transport
      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 #include <set>
     30 
     31 #include <hidl/HidlBinderSupport.h>
     32 #include <hidl/ServiceManagement.h>
     33 #include <hidl/Status.h>
     34 
     35 #include <android-base/logging.h>
     36 #include <android-base/properties.h>
     37 #include <hwbinder/IPCThreadState.h>
     38 #include <hwbinder/Parcel.h>
     39 #include <vndksupport/linker.h>
     40 
     41 #include <android/hidl/manager/1.1/IServiceManager.h>
     42 #include <android/hidl/manager/1.1/BpHwServiceManager.h>
     43 #include <android/hidl/manager/1.1/BnHwServiceManager.h>
     44 
     45 #define RE_COMPONENT    "[a-zA-Z_][a-zA-Z_0-9]*"
     46 #define RE_PATH         RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
     47 static const std::regex gLibraryFileNamePattern("(" RE_PATH "@[0-9]+[.][0-9]+)-impl(.*?).so");
     48 
     49 using android::base::WaitForProperty;
     50 
     51 using IServiceManager1_0 = android::hidl::manager::V1_0::IServiceManager;
     52 using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager;
     53 using android::hidl::manager::V1_0::IServiceNotification;
     54 using android::hidl::manager::V1_1::BpHwServiceManager;
     55 using android::hidl::manager::V1_1::BnHwServiceManager;
     56 
     57 namespace android {
     58 namespace hardware {
     59 
     60 namespace details {
     61 extern Mutex gDefaultServiceManagerLock;
     62 extern sp<android::hidl::manager::V1_1::IServiceManager> gDefaultServiceManager;
     63 }  // namespace details
     64 
     65 static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
     66 
     67 void waitForHwServiceManager() {
     68     using std::literals::chrono_literals::operator""s;
     69 
     70     while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
     71         LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
     72     }
     73 }
     74 
     75 bool endsWith(const std::string &in, const std::string &suffix) {
     76     return in.size() >= suffix.size() &&
     77            in.substr(in.size() - suffix.size()) == suffix;
     78 }
     79 
     80 bool startsWith(const std::string &in, const std::string &prefix) {
     81     return in.size() >= prefix.size() &&
     82            in.substr(0, prefix.size()) == prefix;
     83 }
     84 
     85 std::string binaryName() {
     86     std::ifstream ifs("/proc/self/cmdline");
     87     std::string cmdline;
     88     if (!ifs.is_open()) {
     89         return "";
     90     }
     91     ifs >> cmdline;
     92 
     93     size_t idx = cmdline.rfind("/");
     94     if (idx != std::string::npos) {
     95         cmdline = cmdline.substr(idx + 1);
     96     }
     97 
     98     return cmdline;
     99 }
    100 
    101 void tryShortenProcessName(const std::string &packageName) {
    102     std::string processName = binaryName();
    103 
    104     if (!startsWith(processName, packageName)) {
    105         return;
    106     }
    107 
    108     // e.x. android.hardware.module.foo (at) 1.0 -> foo (at) 1.0
    109     size_t lastDot = packageName.rfind('.');
    110     size_t secondDot = packageName.rfind('.', lastDot - 1);
    111 
    112     if (secondDot == std::string::npos) {
    113         return;
    114     }
    115 
    116     std::string newName = processName.substr(secondDot + 1,
    117             16 /* TASK_COMM_LEN */ - 1);
    118     ALOGI("Removing namespace from process name %s to %s.",
    119             processName.c_str(), newName.c_str());
    120 
    121     int rc = pthread_setname_np(pthread_self(), newName.c_str());
    122     ALOGI_IF(rc != 0, "Removing namespace from process name %s failed.",
    123             processName.c_str());
    124 }
    125 
    126 namespace details {
    127 
    128 void onRegistration(const std::string &packageName,
    129                     const std::string& /* interfaceName */,
    130                     const std::string& /* instanceName */) {
    131     tryShortenProcessName(packageName);
    132 }
    133 
    134 }  // details
    135 
    136 sp<IServiceManager1_0> defaultServiceManager() {
    137     return defaultServiceManager1_1();
    138 }
    139 sp<IServiceManager1_1> defaultServiceManager1_1() {
    140     {
    141         AutoMutex _l(details::gDefaultServiceManagerLock);
    142         if (details::gDefaultServiceManager != NULL) {
    143             return details::gDefaultServiceManager;
    144         }
    145 
    146         if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
    147             // HwBinder not available on this device or not accessible to
    148             // this process.
    149             return nullptr;
    150         }
    151 
    152         waitForHwServiceManager();
    153 
    154         while (details::gDefaultServiceManager == NULL) {
    155             details::gDefaultServiceManager =
    156                     fromBinder<IServiceManager1_1, BpHwServiceManager, BnHwServiceManager>(
    157                         ProcessState::self()->getContextObject(NULL));
    158             if (details::gDefaultServiceManager == NULL) {
    159                 LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
    160                 sleep(1);
    161             }
    162         }
    163     }
    164 
    165     return details::gDefaultServiceManager;
    166 }
    167 
    168 std::vector<std::string> search(const std::string &path,
    169                               const std::string &prefix,
    170                               const std::string &suffix) {
    171     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
    172     if (!dir) return {};
    173 
    174     std::vector<std::string> results{};
    175 
    176     dirent* dp;
    177     while ((dp = readdir(dir.get())) != nullptr) {
    178         std::string name = dp->d_name;
    179 
    180         if (startsWith(name, prefix) &&
    181                 endsWith(name, suffix)) {
    182             results.push_back(name);
    183         }
    184     }
    185 
    186     return results;
    187 }
    188 
    189 bool matchPackageName(const std::string& lib, std::string* matchedName, std::string* implName) {
    190     std::smatch match;
    191     if (std::regex_match(lib, match, gLibraryFileNamePattern)) {
    192         *matchedName = match.str(1) + "::I*";
    193         *implName = match.str(2);
    194         return true;
    195     }
    196     return false;
    197 }
    198 
    199 static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
    200     sp<IServiceManager1_0> binderizedManager = defaultServiceManager();
    201     if (binderizedManager == nullptr) {
    202         LOG(WARNING) << "Could not registerReference for "
    203                      << interfaceName << "/" << instanceName
    204                      << ": null binderized manager.";
    205         return;
    206     }
    207     auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
    208     if (!ret.isOk()) {
    209         LOG(WARNING) << "Could not registerReference for "
    210                      << interfaceName << "/" << instanceName
    211                      << ": " << ret.description();
    212         return;
    213     }
    214     LOG(VERBOSE) << "Successfully registerReference for "
    215                  << interfaceName << "/" << instanceName;
    216 }
    217 
    218 using InstanceDebugInfo = hidl::manager::V1_0::IServiceManager::InstanceDebugInfo;
    219 static inline void fetchPidsForPassthroughLibraries(
    220     std::map<std::string, InstanceDebugInfo>* infos) {
    221     static const std::string proc = "/proc/";
    222 
    223     std::map<std::string, std::set<pid_t>> pids;
    224     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(proc.c_str()), closedir);
    225     if (!dir) return;
    226     dirent* dp;
    227     while ((dp = readdir(dir.get())) != nullptr) {
    228         pid_t pid = strtoll(dp->d_name, NULL, 0);
    229         if (pid == 0) continue;
    230         std::string mapsPath = proc + dp->d_name + "/maps";
    231         std::ifstream ifs{mapsPath};
    232         if (!ifs.is_open()) continue;
    233 
    234         for (std::string line; std::getline(ifs, line);) {
    235             // The last token of line should look like
    236             // vendor/lib64/hw/android.hardware.foo@1.0-impl-extra.so
    237             // Use some simple filters to ignore bad lines before extracting libFileName
    238             // and checking the key in info to make parsing faster.
    239             if (line.back() != 'o') continue;
    240             if (line.rfind('@') == std::string::npos) continue;
    241 
    242             auto spacePos = line.rfind(' ');
    243             if (spacePos == std::string::npos) continue;
    244             auto libFileName = line.substr(spacePos + 1);
    245             auto it = infos->find(libFileName);
    246             if (it == infos->end()) continue;
    247             pids[libFileName].insert(pid);
    248         }
    249     }
    250     for (auto& pair : *infos) {
    251         pair.second.clientPids =
    252             std::vector<pid_t>{pids[pair.first].begin(), pids[pair.first].end()};
    253     }
    254 }
    255 
    256 struct PassthroughServiceManager : IServiceManager1_1 {
    257     static void openLibs(const std::string& fqName,
    258             std::function<bool /* continue */(void* /* handle */,
    259                 const std::string& /* lib */, const std::string& /* sym */)> eachLib) {
    260         //fqName looks like android.hardware.foo (at) 1.0::IFoo
    261         size_t idx = fqName.find("::");
    262 
    263         if (idx == std::string::npos ||
    264                 idx + strlen("::") + 1 >= fqName.size()) {
    265             LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
    266             return;
    267         }
    268 
    269         std::string packageAndVersion = fqName.substr(0, idx);
    270         std::string ifaceName = fqName.substr(idx + strlen("::"));
    271 
    272         const std::string prefix = packageAndVersion + "-impl";
    273         const std::string sym = "HIDL_FETCH_" + ifaceName;
    274 
    275         const int dlMode = RTLD_LAZY;
    276         void *handle = nullptr;
    277 
    278         dlerror(); // clear
    279 
    280         std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
    281                                           HAL_LIBRARY_PATH_VNDK_SP, HAL_LIBRARY_PATH_SYSTEM};
    282 #ifdef LIBHIDL_TARGET_DEBUGGABLE
    283         const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
    284         const bool trebleTestingOverride = env && !strcmp(env, "true");
    285         if (trebleTestingOverride) {
    286             const char* vtsRootPath = std::getenv("VTS_ROOT_PATH");
    287             if (vtsRootPath && strlen(vtsRootPath) > 0) {
    288                 const std::string halLibraryPathVtsOverride =
    289                     std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM;
    290                 paths.push_back(halLibraryPathVtsOverride);
    291             }
    292         }
    293 #endif
    294         for (const std::string& path : paths) {
    295             std::vector<std::string> libs = search(path, prefix, ".so");
    296 
    297             for (const std::string &lib : libs) {
    298                 const std::string fullPath = path + lib;
    299 
    300                 if (path != HAL_LIBRARY_PATH_SYSTEM) {
    301                     handle = android_load_sphal_library(fullPath.c_str(), dlMode);
    302                 } else {
    303                     handle = dlopen(fullPath.c_str(), dlMode);
    304                 }
    305 
    306                 if (handle == nullptr) {
    307                     const char* error = dlerror();
    308                     LOG(ERROR) << "Failed to dlopen " << lib << ": "
    309                                << (error == nullptr ? "unknown error" : error);
    310                     continue;
    311                 }
    312 
    313                 if (!eachLib(handle, lib, sym)) {
    314                     return;
    315                 }
    316             }
    317         }
    318     }
    319 
    320     Return<sp<IBase>> get(const hidl_string& fqName,
    321                           const hidl_string& name) override {
    322         sp<IBase> ret = nullptr;
    323 
    324         openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
    325             IBase* (*generator)(const char* name);
    326             *(void **)(&generator) = dlsym(handle, sym.c_str());
    327             if(!generator) {
    328                 const char* error = dlerror();
    329                 LOG(ERROR) << "Passthrough lookup opened " << lib
    330                            << " but could not find symbol " << sym << ": "
    331                            << (error == nullptr ? "unknown error" : error);
    332                 dlclose(handle);
    333                 return true;
    334             }
    335 
    336             ret = (*generator)(name.c_str());
    337 
    338             if (ret == nullptr) {
    339                 dlclose(handle);
    340                 return true; // this module doesn't provide this instance name
    341             }
    342 
    343             registerReference(fqName, name);
    344             return false;
    345         });
    346 
    347         return ret;
    348     }
    349 
    350     Return<bool> add(const hidl_string& /* name */,
    351                      const sp<IBase>& /* service */) override {
    352         LOG(FATAL) << "Cannot register services with passthrough service manager.";
    353         return false;
    354     }
    355 
    356     Return<Transport> getTransport(const hidl_string& /* fqName */,
    357                                    const hidl_string& /* name */) {
    358         LOG(FATAL) << "Cannot getTransport with passthrough service manager.";
    359         return Transport::EMPTY;
    360     }
    361 
    362     Return<void> list(list_cb /* _hidl_cb */) override {
    363         LOG(FATAL) << "Cannot list services with passthrough service manager.";
    364         return Void();
    365     }
    366     Return<void> listByInterface(const hidl_string& /* fqInstanceName */,
    367                                  listByInterface_cb /* _hidl_cb */) override {
    368         // TODO: add this functionality
    369         LOG(FATAL) << "Cannot list services with passthrough service manager.";
    370         return Void();
    371     }
    372 
    373     Return<bool> registerForNotifications(const hidl_string& /* fqName */,
    374                                           const hidl_string& /* name */,
    375                                           const sp<IServiceNotification>& /* callback */) override {
    376         // This makes no sense.
    377         LOG(FATAL) << "Cannot register for notifications with passthrough service manager.";
    378         return false;
    379     }
    380 
    381     Return<void> debugDump(debugDump_cb _hidl_cb) override {
    382         using Arch = ::android::hidl::base::V1_0::DebugInfo::Architecture;
    383         using std::literals::string_literals::operator""s;
    384         static std::vector<std::pair<Arch, std::vector<const char*>>> sAllPaths{
    385             {Arch::IS_64BIT,
    386              {HAL_LIBRARY_PATH_ODM_64BIT, HAL_LIBRARY_PATH_VENDOR_64BIT,
    387               HAL_LIBRARY_PATH_VNDK_SP_64BIT, HAL_LIBRARY_PATH_SYSTEM_64BIT}},
    388             {Arch::IS_32BIT,
    389              {HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT,
    390               HAL_LIBRARY_PATH_VNDK_SP_32BIT, HAL_LIBRARY_PATH_SYSTEM_32BIT}}};
    391         std::map<std::string, InstanceDebugInfo> map;
    392         for (const auto &pair : sAllPaths) {
    393             Arch arch = pair.first;
    394             for (const auto &path : pair.second) {
    395                 std::vector<std::string> libs = search(path, "", ".so");
    396                 for (const std::string &lib : libs) {
    397                     std::string matchedName;
    398                     std::string implName;
    399                     if (matchPackageName(lib, &matchedName, &implName)) {
    400                         std::string instanceName{"* ("s + path + ")"s};
    401                         if (!implName.empty()) instanceName += " ("s + implName + ")"s;
    402                         map.emplace(path + lib, InstanceDebugInfo{.interfaceName = matchedName,
    403                                                                   .instanceName = instanceName,
    404                                                                   .clientPids = {},
    405                                                                   .arch = arch});
    406                     }
    407                 }
    408             }
    409         }
    410         fetchPidsForPassthroughLibraries(&map);
    411         hidl_vec<InstanceDebugInfo> vec;
    412         vec.resize(map.size());
    413         size_t idx = 0;
    414         for (auto&& pair : map) {
    415             vec[idx++] = std::move(pair.second);
    416         }
    417         _hidl_cb(vec);
    418         return Void();
    419     }
    420 
    421     Return<void> registerPassthroughClient(const hidl_string &, const hidl_string &) override {
    422         // This makes no sense.
    423         LOG(FATAL) << "Cannot call registerPassthroughClient on passthrough service manager. "
    424                    << "Call it on defaultServiceManager() instead.";
    425         return Void();
    426     }
    427 
    428     Return<bool> unregisterForNotifications(const hidl_string& /* fqName */,
    429                                             const hidl_string& /* name */,
    430                                             const sp<IServiceNotification>& /* callback */) override {
    431         // This makes no sense.
    432         LOG(FATAL) << "Cannot unregister for notifications with passthrough service manager.";
    433         return false;
    434     }
    435 
    436 };
    437 
    438 sp<IServiceManager1_0> getPassthroughServiceManager() {
    439     return getPassthroughServiceManager1_1();
    440 }
    441 sp<IServiceManager1_1> getPassthroughServiceManager1_1() {
    442     static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
    443     return manager;
    444 }
    445 
    446 namespace details {
    447 
    448 void preloadPassthroughService(const std::string &descriptor) {
    449     PassthroughServiceManager::openLibs(descriptor,
    450         [&](void* /* handle */, const std::string& /* lib */, const std::string& /* sym */) {
    451             // do nothing
    452             return true; // open all libs
    453         });
    454 }
    455 
    456 struct Waiter : IServiceNotification {
    457     Return<void> onRegistration(const hidl_string& /* fqName */,
    458                                 const hidl_string& /* name */,
    459                                 bool /* preexisting */) override {
    460         std::unique_lock<std::mutex> lock(mMutex);
    461         if (mRegistered) {
    462             return Void();
    463         }
    464         mRegistered = true;
    465         lock.unlock();
    466 
    467         mCondition.notify_one();
    468         return Void();
    469     }
    470 
    471     void wait(const std::string &interface, const std::string &instanceName) {
    472         using std::literals::chrono_literals::operator""s;
    473 
    474         std::unique_lock<std::mutex> lock(mMutex);
    475         while(true) {
    476             mCondition.wait_for(lock, 1s, [this]{
    477                 return mRegistered;
    478             });
    479 
    480             if (mRegistered) {
    481                 break;
    482             }
    483 
    484             LOG(WARNING) << "Waited one second for "
    485                          << interface << "/" << instanceName
    486                          << ". Waiting another...";
    487         }
    488     }
    489 
    490 private:
    491     std::mutex mMutex;
    492     std::condition_variable mCondition;
    493     bool mRegistered = false;
    494 };
    495 
    496 void waitForHwService(
    497         const std::string &interface, const std::string &instanceName) {
    498     const sp<IServiceManager1_1> manager = defaultServiceManager1_1();
    499 
    500     if (manager == nullptr) {
    501         LOG(ERROR) << "Could not get default service manager.";
    502         return;
    503     }
    504 
    505     sp<Waiter> waiter = new Waiter();
    506     Return<bool> ret = manager->registerForNotifications(interface, instanceName, waiter);
    507 
    508     if (!ret.isOk()) {
    509         LOG(ERROR) << "Transport error, " << ret.description()
    510             << ", during notification registration for "
    511             << interface << "/" << instanceName << ".";
    512         return;
    513     }
    514 
    515     if (!ret) {
    516         LOG(ERROR) << "Could not register for notifications for "
    517             << interface << "/" << instanceName << ".";
    518         return;
    519     }
    520 
    521     waiter->wait(interface, instanceName);
    522 
    523     if (!manager->unregisterForNotifications(interface, instanceName, waiter).withDefault(false)) {
    524         LOG(ERROR) << "Could not unregister service notification for "
    525             << interface << "/" << instanceName << ".";
    526     }
    527 }
    528 
    529 }; // namespace details
    530 
    531 }; // namespace hardware
    532 }; // namespace android
    533