Home | History | Annotate | Download | only in vintf
      1 /*
      2  * Copyright (C) 2017 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 #include "VtsTrebleVintfTestBase.h"
     18 
     19 #include <chrono>
     20 #include <condition_variable>
     21 #include <functional>
     22 #include <future>
     23 #include <iostream>
     24 #include <map>
     25 #include <mutex>
     26 #include <set>
     27 #include <sstream>
     28 #include <string>
     29 #include <thread>
     30 #include <vector>
     31 
     32 #include <android-base/logging.h>
     33 #include <android-base/strings.h>
     34 #include <android/hidl/manager/1.0/IServiceManager.h>
     35 #include <gtest/gtest.h>
     36 #include <hidl-hash/Hash.h>
     37 #include <hidl-util/FQName.h>
     38 #include <hidl-util/FqInstance.h>
     39 #include <hidl/HidlTransportUtils.h>
     40 #include <hidl/ServiceManagement.h>
     41 #include <procpartition/procpartition.h>
     42 #include <vintf/HalManifest.h>
     43 #include <vintf/VintfObject.h>
     44 #include <vintf/parse_string.h>
     45 
     46 #include "SingleManifestTest.h"
     47 #include "utils.h"
     48 
     49 namespace android {
     50 namespace vintf {
     51 namespace testing {
     52 
     53 using android::FqInstance;
     54 using android::FQName;
     55 using android::Hash;
     56 using android::sp;
     57 using android::hardware::hidl_array;
     58 using android::hardware::hidl_string;
     59 using android::hardware::hidl_vec;
     60 using android::hardware::Return;
     61 using android::hidl::base::V1_0::IBase;
     62 using android::hidl::manager::V1_0::IServiceManager;
     63 using android::procpartition::Partition;
     64 using android::vintf::HalManifest;
     65 using android::vintf::Level;
     66 using android::vintf::ManifestHal;
     67 using android::vintf::Transport;
     68 using android::vintf::Version;
     69 using android::vintf::VintfObject;
     70 using android::vintf::operator<<;
     71 using android::vintf::to_string;
     72 using android::vintf::toFQNameString;
     73 
     74 using std::cout;
     75 using std::endl;
     76 using std::map;
     77 using std::set;
     78 using std::string;
     79 using std::vector;
     80 
     81 void VtsTrebleVintfTestBase::SetUp() {
     82   default_manager_ = ::android::hardware::defaultServiceManager();
     83   ASSERT_NE(default_manager_, nullptr)
     84       << "Failed to get default service manager." << endl;
     85 }
     86 
     87 void VtsTrebleVintfTestBase::ForEachHalInstance(const HalManifestPtr &manifest,
     88                                                 HalVerifyFn fn) {
     89   manifest->forEachInstance([manifest, fn](const auto &manifest_instance) {
     90     const FQName fq_name{manifest_instance.package(),
     91                          to_string(manifest_instance.version()),
     92                          manifest_instance.interface()};
     93     const Transport transport = manifest_instance.transport();
     94     const std::string instance_name = manifest_instance.instance();
     95 
     96     auto future_result =
     97         std::async([&]() { fn(fq_name, instance_name, transport); });
     98     auto timeout = std::chrono::seconds(1);
     99     std::future_status status = future_result.wait_for(timeout);
    100     if (status != std::future_status::ready) {
    101       cout << "Timed out on: " << fq_name.string() << " " << instance_name
    102            << endl;
    103     }
    104     return true;  // continue to next instance
    105   });
    106 }
    107 
    108 sp<IBase> VtsTrebleVintfTestBase::GetHalService(const FQName &fq_name,
    109                                                 const string &instance_name,
    110                                                 Transport transport, bool log) {
    111   return GetHalService(fq_name.string(), instance_name, transport, log);
    112 }
    113 
    114 sp<IBase> VtsTrebleVintfTestBase::GetHalService(const string &fq_name,
    115                                                 const string &instance_name,
    116                                                 Transport transport, bool log) {
    117   using android::hardware::details::getRawServiceInternal;
    118 
    119   if (log) {
    120     cout << "Getting: " << fq_name << "/" << instance_name << endl;
    121   }
    122 
    123   // getService blocks until a service is available. In 100% of other cases
    124   // where getService is used, it should be called directly. However, this test
    125   // enforces that various services are actually available when they are
    126   // declared, it must make a couple of precautions in case the service isn't
    127   // actually available so that the proper failure can be reported.
    128 
    129   auto task = std::packaged_task<sp<IBase>()>([fq_name, instance_name]() {
    130     return getRawServiceInternal(fq_name, instance_name, true /* retry */,
    131                                  false /* getStub */);
    132   });
    133 
    134   std::future<sp<IBase>> future = task.get_future();
    135   std::thread(std::move(task)).detach();
    136   auto status = future.wait_for(std::chrono::milliseconds(500));
    137 
    138   if (status != std::future_status::ready) return nullptr;
    139 
    140   sp<IBase> base = future.get();
    141   if (base == nullptr) return nullptr;
    142 
    143   bool wantRemote = transport == Transport::HWBINDER;
    144   if (base->isRemote() != wantRemote) return nullptr;
    145 
    146   return base;
    147 }
    148 
    149 vector<string> VtsTrebleVintfTestBase::GetInstanceNames(
    150     const sp<IServiceManager> &manager, const FQName &fq_name) {
    151   vector<string> ret;
    152   auto status =
    153       manager->listByInterface(fq_name.string(), [&](const auto &out) {
    154         for (const auto &e : out) ret.push_back(e);
    155       });
    156   EXPECT_TRUE(status.isOk()) << status.description();
    157   return ret;
    158 }
    159 
    160 vector<string> VtsTrebleVintfTestBase::GetInterfaceChain(
    161     const sp<IBase> &service) {
    162   vector<string> iface_chain{};
    163   service->interfaceChain([&iface_chain](const hidl_vec<hidl_string> &chain) {
    164     for (const auto &iface_name : chain) {
    165       iface_chain.push_back(iface_name);
    166     }
    167   });
    168   return iface_chain;
    169 }
    170 
    171 Partition VtsTrebleVintfTestBase::GetPartition(sp<IBase> hal_service) {
    172   Partition partition = Partition::UNKNOWN;
    173   auto ret = hal_service->getDebugInfo(
    174       [&](const auto &info) { partition = PartitionOfProcess(info.pid); });
    175   EXPECT_TRUE(ret.isOk());
    176   return partition;
    177 }
    178 
    179 set<string> VtsTrebleVintfTestBase::GetPassthroughHals(
    180     HalManifestPtr manifest) {
    181   std::set<std::string> manifest_passthrough_hals_;
    182 
    183   auto add_manifest_hals = [&manifest_passthrough_hals_](
    184                                const FQName &fq_name,
    185                                const string &instance_name,
    186                                Transport transport) {
    187     if (transport == Transport::HWBINDER) {
    188       // ignore
    189     } else if (transport == Transport::PASSTHROUGH) {
    190       // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist)
    191       FQName fq = fq_name;
    192       while (true) {
    193         manifest_passthrough_hals_.insert(fq.string() + "/" + instance_name);
    194         if (fq.getPackageMinorVersion() <= 0) break;
    195         fq = fq.downRev();
    196       }
    197     } else {
    198       ADD_FAILURE() << "Unrecognized transport: " << transport;
    199     }
    200   };
    201   ForEachHalInstance(manifest, add_manifest_hals);
    202   return manifest_passthrough_hals_;
    203 }
    204 
    205 set<string> VtsTrebleVintfTestBase::GetHwbinderHals(HalManifestPtr manifest) {
    206   std::set<std::string> manifest_hwbinder_hals_;
    207 
    208   auto add_manifest_hals = [&manifest_hwbinder_hals_](
    209                                const FQName &fq_name,
    210                                const string &instance_name,
    211                                Transport transport) {
    212     if (transport == Transport::HWBINDER) {
    213       // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist)
    214       FQName fq = fq_name;
    215       while (true) {
    216         manifest_hwbinder_hals_.insert(fq.string() + "/" + instance_name);
    217         if (fq.getPackageMinorVersion() <= 0) break;
    218         fq = fq.downRev();
    219       }
    220     } else if (transport == Transport::PASSTHROUGH) {
    221       // ignore
    222     } else {
    223       ADD_FAILURE() << "Unrecognized transport: " << transport;
    224     }
    225   };
    226   ForEachHalInstance(manifest, add_manifest_hals);
    227   return manifest_hwbinder_hals_;
    228 }
    229 
    230 }  // namespace testing
    231 }  // namespace vintf
    232 }  // namespace android
    233