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