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 <chrono>
     18 #include <functional>
     19 #include <future>
     20 #include <iostream>
     21 #include <map>
     22 #include <set>
     23 #include <sstream>
     24 #include <string>
     25 #include <thread>
     26 #include <vector>
     27 
     28 #include <android/hidl/manager/1.0/IServiceManager.h>
     29 #include <gtest/gtest.h>
     30 #include <hidl-hash/Hash.h>
     31 #include <hidl-util/FQName.h>
     32 #include <hidl/ServiceManagement.h>
     33 #include <vintf/HalManifest.h>
     34 #include <vintf/VintfObject.h>
     35 #include <vintf/parse_string.h>
     36 
     37 #include "VtsTrebleVintfTestBase.h"
     38 
     39 namespace android {
     40 namespace vintf {
     41 namespace testing {
     42 namespace legacy {
     43 
     44 using android::FQName;
     45 using android::Hash;
     46 using android::sp;
     47 using android::hardware::hidl_array;
     48 using android::hardware::hidl_string;
     49 using android::hardware::hidl_vec;
     50 using android::hidl::manager::V1_0::IServiceManager;
     51 using android::vintf::HalManifest;
     52 using android::vintf::to_string;
     53 using android::vintf::Transport;
     54 using android::vintf::Version;
     55 using android::vintf::VintfObject;
     56 
     57 using std::cout;
     58 using std::endl;
     59 using std::map;
     60 using std::set;
     61 using std::string;
     62 using std::vector;
     63 using HalVerifyFn =
     64     std::function<void(const FQName &fq_name, const string &instance_name)>;
     65 
     66 // Returns true iff HAL interface is exempt from following rules:
     67 // 1. If an interface is declared in VINTF, it has to be served on the device.
     68 static bool IsExempt(const FQName &fq_iface_name) {
     69   static const set<string> exempt_hals_ = {};
     70   string hal_name = fq_iface_name.package();
     71   // Radio-releated and non-Google HAL interfaces are given exemptions.
     72   return exempt_hals_.find(hal_name) != exempt_hals_.end() ||
     73          !IsGoogleDefinedIface(fq_iface_name);
     74 }
     75 
     76 class VtsTrebleVintfTest : public ::testing::Test {
     77  public:
     78   virtual void SetUp() override {
     79     default_manager_ = ::android::hardware::defaultServiceManager();
     80     ASSERT_NE(default_manager_, nullptr)
     81         << "Failed to get default service manager." << endl;
     82 
     83     passthrough_manager_ = ::android::hardware::getPassthroughServiceManager();
     84     ASSERT_NE(passthrough_manager_, nullptr)
     85         << "Failed to get passthrough service manager." << endl;
     86 
     87     vendor_manifest_ = VintfObject::GetDeviceHalManifest();
     88     ASSERT_NE(vendor_manifest_, nullptr)
     89         << "Failed to get vendor HAL manifest." << endl;
     90   }
     91 
     92   // Applies given function to each HAL instance in VINTF.
     93   void ForEachHalInstance(HalVerifyFn);
     94   // Retrieves an existing HAL service.
     95   sp<android::hidl::base::V1_0::IBase> GetHalService(
     96       const FQName &fq_name, const string &instance_name);
     97 
     98   // Default service manager.
     99   sp<IServiceManager> default_manager_;
    100   // Passthrough service manager.
    101   sp<IServiceManager> passthrough_manager_;
    102   // Vendor hal manifest.
    103   std::shared_ptr<const HalManifest> vendor_manifest_;
    104 };
    105 
    106 void VtsTrebleVintfTest::ForEachHalInstance(HalVerifyFn fn) {
    107   vendor_manifest_->forEachInstance([fn](const auto &manifest_instance) {
    108     const FQName fq_name{manifest_instance.package(),
    109                          to_string(manifest_instance.version()),
    110                          manifest_instance.interface()};
    111     const std::string instance_name = manifest_instance.instance();
    112 
    113     auto future_result = std::async([&]() { fn(fq_name, instance_name); });
    114     auto timeout = std::chrono::milliseconds(500);
    115     std::future_status status = future_result.wait_for(timeout);
    116     if (status != std::future_status::ready) {
    117       cout << "Timed out on: " << fq_name.string() << " " << instance_name
    118            << endl;
    119     }
    120     return true;  // continue to next instance
    121   });
    122 }
    123 
    124 sp<android::hidl::base::V1_0::IBase> VtsTrebleVintfTest::GetHalService(
    125     const FQName &fq_name, const string &instance_name) {
    126   string hal_name = fq_name.package();
    127   Version version{fq_name.getPackageMajorVersion(),
    128                   fq_name.getPackageMinorVersion()};
    129   string iface_name = fq_name.name();
    130   string fq_iface_name = fq_name.string();
    131   cout << "Getting service of: " << fq_iface_name << endl;
    132 
    133   Transport transport = vendor_manifest_->getTransport(
    134       hal_name, version, iface_name, instance_name);
    135 
    136   return VtsTrebleVintfTestBase::GetHalService(fq_name, instance_name,
    137                                                transport);
    138 }
    139 
    140 // Tests that no HAL outside of the allowed set is specified as passthrough in
    141 // VINTF.
    142 TEST_F(VtsTrebleVintfTest, HalsAreBinderized) {
    143   // Verifies that HAL is binderized unless it's allowed to be passthrough.
    144   HalVerifyFn is_binderized = [this](const FQName &fq_name,
    145                                      const string &instance_name) {
    146     cout << "Verifying transport method of: " << fq_name.string() << endl;
    147     string hal_name = fq_name.package();
    148     Version version{fq_name.getPackageMajorVersion(),
    149                     fq_name.getPackageMinorVersion()};
    150     string iface_name = fq_name.name();
    151 
    152     Transport transport = vendor_manifest_->getTransport(
    153         hal_name, version, iface_name, instance_name);
    154 
    155     EXPECT_NE(transport, Transport::EMPTY)
    156         << hal_name << " has no transport specified in VINTF.";
    157 
    158     if (transport == Transport::PASSTHROUGH) {
    159       EXPECT_NE(kPassthroughHals.find(hal_name), kPassthroughHals.end())
    160           << hal_name << " can't be passthrough under Treble rules.";
    161     }
    162   };
    163 
    164   ForEachHalInstance(is_binderized);
    165 }
    166 
    167 // Tests that all HALs specified in the VINTF are available through service
    168 // manager.
    169 TEST_F(VtsTrebleVintfTest, VintfHalsAreServed) {
    170   // Verifies that HAL is available through service manager.
    171   HalVerifyFn is_available = [this](const FQName &fq_name,
    172                                     const string &instance_name) {
    173     if (IsExempt(fq_name)) {
    174       cout << fq_name.string() << " is exempt for O-MR1 vendor." << endl;
    175       return;
    176     }
    177 
    178     sp<android::hidl::base::V1_0::IBase> hal_service =
    179         GetHalService(fq_name, instance_name);
    180     EXPECT_NE(hal_service, nullptr)
    181         << fq_name.string() << " not available." << endl;
    182   };
    183 
    184   ForEachHalInstance(is_available);
    185 }
    186 
    187 // Tests that HAL interfaces are officially released.
    188 TEST_F(VtsTrebleVintfTest, InterfacesAreReleased) {
    189   // Verifies that HAL are released by fetching the hash of the interface and
    190   // comparing it to the set of known hashes of released interfaces.
    191   HalVerifyFn is_released = [this](const FQName &fq_name,
    192                                    const string &instance_name) {
    193     sp<android::hidl::base::V1_0::IBase> hal_service =
    194         GetHalService(fq_name, instance_name);
    195 
    196     if (hal_service == nullptr) {
    197       if (IsExempt(fq_name)) {
    198         cout << fq_name.string() << " is exempt for O-MR1 vendor." << endl;
    199       } else {
    200         ADD_FAILURE() << fq_name.package() << " not available." << endl;
    201       }
    202       return;
    203     }
    204 
    205     vector<string> iface_chain{};
    206     hal_service->interfaceChain(
    207         [&iface_chain](const hidl_vec<hidl_string> &chain) {
    208           for (const auto &iface_name : chain) {
    209             iface_chain.push_back(iface_name);
    210           }
    211         });
    212 
    213     vector<string> hash_chain{};
    214     hal_service->getHashChain(
    215         [&hash_chain](const hidl_vec<HashCharArray> &chain) {
    216           for (const HashCharArray &hash_array : chain) {
    217             vector<uint8_t> hash{hash_array.data(),
    218                                  hash_array.data() + hash_array.size()};
    219             hash_chain.push_back(Hash::hexString(hash));
    220           }
    221         });
    222 
    223     ASSERT_EQ(iface_chain.size(), hash_chain.size());
    224     for (size_t i = 0; i < iface_chain.size(); ++i) {
    225       FQName fq_iface_name;
    226       if (!FQName::parse(iface_chain[i], &fq_iface_name)) {
    227         ADD_FAILURE() << "Could not parse iface name " << iface_chain[i]
    228                       << " from interface chain of " << fq_name.string();
    229         return;
    230       }
    231       string hash = hash_chain[i];
    232 
    233       if (IsGoogleDefinedIface(fq_iface_name)) {
    234         set<string> released_hashes = ReleasedHashes(fq_iface_name);
    235         EXPECT_NE(released_hashes.find(hash), released_hashes.end())
    236             << "Hash not found. This interface was not released." << endl
    237             << "Interface name: " << fq_iface_name.string() << endl
    238             << "Hash: " << hash << endl;
    239       }
    240     }
    241   };
    242 
    243   ForEachHalInstance(is_released);
    244 }
    245 
    246 }  // namespace legacy
    247 }  // namespace testing
    248 }  // namespace vintf
    249 }  // namespace android
    250