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.
IsExempt(const FQName & fq_iface_name)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 !IsAndroidPlatformInterface(fq_iface_name);
74 }
75
76 class VtsTrebleVintfTest : public ::testing::Test {
77 public:
SetUp()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
ForEachHalInstance(HalVerifyFn fn)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
GetHalService(const FQName & fq_name,const string & instance_name)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.
TEST_F(VtsTrebleVintfTest,HalsAreBinderized)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.
TEST_F(VtsTrebleVintfTest,VintfHalsAreServed)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.
TEST_F(VtsTrebleVintfTest,InterfacesAreReleased)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 (IsAndroidPlatformInterface(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