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 
     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 
     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 
     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 
     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 
     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 
    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 (at) 1.0 -> foo (at) 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 
    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 
    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 
    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 
    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 
    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 {
    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 (at) 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 
    381 sp<IServiceManager> getPassthroughServiceManager() {
    382     static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
    383     return manager;
    384 }
    385 
    386 namespace details {
    387 
    388 struct 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 
    422 private:
    423     std::mutex mMutex;
    424     std::condition_variable mCondition;
    425     bool mRegistered = false;
    426 };
    427 
    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