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 <functional>
18 #include <iostream>
19 #include <map>
20 #include <set>
21 #include <sstream>
22 #include <string>
23 #include <vector>
24
25 #include <android/hidl/manager/1.0/IServiceManager.h>
26 #include <gtest/gtest.h>
27 #include <hidl-hash/Hash.h>
28 #include <hidl-util/FQName.h>
29 #include <hidl/ServiceManagement.h>
30 #include <vintf/HalManifest.h>
31 #include <vintf/VintfObject.h>
32
33 using android::FQName;
34 using android::Hash;
35 using android::hardware::hidl_array;
36 using android::hardware::hidl_string;
37 using android::hardware::hidl_vec;
38 using android::hidl::manager::V1_0::IServiceManager;
39 using android::sp;
40 using android::vintf::HalManifest;
41 using android::vintf::Transport;
42 using android::vintf::Version;
43
44 using std::cout;
45 using std::endl;
46 using std::map;
47 using std::set;
48 using std::string;
49 using std::vector;
50 using HalVerifyFn =
51 std::function<void(const FQName &fq_name, const string &instance_name)>;
52 using HashCharArray = hidl_array<unsigned char, 32>;
53
54 // Path to directory on target containing test data.
55 static const string kDataDir = "/data/local/tmp/";
56
57 // Name of file containing HAL hashes.
58 static const string kHashFileName = "current.txt";
59
60 // Map from package name to package root.
61 static const map<string, string> kPackageRoot = {
62 {"android.frameworks", "frameworks/hardware/interfaces/"},
63 {"android.hardware", "hardware/interfaces/"},
64 {"android.hidl", "system/libhidl/transport/"},
65 {"android.system", "system/hardware/interfaces/"},
66 };
67
68 // HALs that are allowed to be passthrough under Treble rules.
69 static const set<string> kPassthroughHals = {
70 "android.hardware.graphics.mapper", "android.hardware.renderscript",
71 };
72
73 // For a given interface returns package root if known. Returns empty string
74 // otherwise.
PackageRoot(const FQName & fq_iface_name)75 static const string PackageRoot(const FQName &fq_iface_name) {
76 for (const auto &package_root : kPackageRoot) {
77 if (fq_iface_name.inPackage(package_root.first)) {
78 return package_root.second;
79 }
80 }
81 return "";
82 }
83
84 // Returns true iff HAL interface is Google-defined.
IsGoogleDefinedIface(const FQName & fq_iface_name)85 static bool IsGoogleDefinedIface(const FQName &fq_iface_name) {
86 // Package roots are only known for Google-defined packages.
87 return !PackageRoot(fq_iface_name).empty();
88 }
89
90 // Returns true iff HAL interface is exempt from following rules:
91 // 1. If an interface is declared in VINTF, it has to be served on the device.
92 // TODO(b/62547028): remove these exemptions in O-DR.
IsExempt(const FQName & fq_iface_name)93 static bool IsExempt(const FQName &fq_iface_name) {
94 static const set<string> exempt_hals_ = {
95 "android.hardware.radio", "android.hardware.radio.deprecated",
96 };
97 string hal_name = fq_iface_name.package();
98 // Radio-releated and non-Google HAL interfaces are given exemptions.
99 return exempt_hals_.find(hal_name) != exempt_hals_.end() ||
100 !IsGoogleDefinedIface(fq_iface_name);
101 }
102
103 // Returns the set of released hashes for a given HAL interface.
ReleasedHashes(const FQName & fq_iface_name)104 static set<string> ReleasedHashes(const FQName &fq_iface_name) {
105 set<string> released_hashes{};
106 string err = "";
107
108 string file_path = kDataDir + PackageRoot(fq_iface_name) + kHashFileName;
109 auto hashes = Hash::lookupHash(file_path, fq_iface_name.string(), &err);
110 released_hashes.insert(hashes.begin(), hashes.end());
111 return released_hashes;
112 }
113
114 class VtsTrebleVintfTest : public ::testing::Test {
115 public:
SetUp()116 virtual void SetUp() override {
117 default_manager_ = ::android::hardware::defaultServiceManager();
118 ASSERT_NE(default_manager_, nullptr)
119 << "Failed to get default service manager." << endl;
120
121 passthrough_manager_ = ::android::hardware::getPassthroughServiceManager();
122 ASSERT_NE(passthrough_manager_, nullptr)
123 << "Failed to get passthrough service manager." << endl;
124
125 vendor_manifest_ = ::android::vintf::VintfObject::GetDeviceHalManifest();
126 ASSERT_NE(passthrough_manager_, nullptr)
127 << "Failed to get vendor HAL manifest." << endl;
128 }
129
130 // Applies given function to each HAL instance in VINTF.
131 void ForEachHalInstance(HalVerifyFn);
132 // Retrieves an existing HAL service.
133 sp<android::hidl::base::V1_0::IBase> GetHalService(
134 const FQName &fq_name, const string &instance_name);
135
136 // Default service manager.
137 sp<IServiceManager> default_manager_;
138 // Passthrough service manager.
139 sp<IServiceManager> passthrough_manager_;
140 // Vendor hal manifest.
141 const HalManifest *vendor_manifest_;
142 };
143
ForEachHalInstance(HalVerifyFn fn)144 void VtsTrebleVintfTest::ForEachHalInstance(HalVerifyFn fn) {
145 auto hal_names = vendor_manifest_->getHalNames();
146 for (const auto &hal_name : hal_names) {
147 auto versions = vendor_manifest_->getSupportedVersions(hal_name);
148 auto iface_names = vendor_manifest_->getInterfaceNames(hal_name);
149 for (const auto &iface_name : iface_names) {
150 auto instance_names =
151 vendor_manifest_->getInstances(hal_name, iface_name);
152 for (const auto &version : versions) {
153 for (const auto &instance_name : instance_names) {
154 string major_ver = std::to_string(version.majorVer);
155 string minor_ver = std::to_string(version.minorVer);
156 string full_ver = major_ver + "." + minor_ver;
157 FQName fq_name{hal_name, full_ver, iface_name};
158 fn(fq_name, instance_name);
159 }
160 }
161 }
162 }
163 }
164
GetHalService(const FQName & fq_name,const string & instance_name)165 sp<android::hidl::base::V1_0::IBase> VtsTrebleVintfTest::GetHalService(
166 const FQName &fq_name, const string &instance_name) {
167 string hal_name = fq_name.package();
168 Version version{fq_name.getPackageMajorVersion(),
169 fq_name.getPackageMinorVersion()};
170 string iface_name = fq_name.name();
171 string fq_iface_name = fq_name.string();
172 cout << "Getting service of: " << fq_iface_name << endl;
173
174 Transport transport = vendor_manifest_->getTransport(
175 hal_name, version, iface_name, instance_name);
176
177 android::sp<android::hidl::base::V1_0::IBase> hal_service = nullptr;
178 if (transport == Transport::HWBINDER) {
179 hal_service = default_manager_->get(fq_iface_name, instance_name);
180 } else if (transport == Transport::PASSTHROUGH) {
181 hal_service = passthrough_manager_->get(fq_iface_name, instance_name);
182 }
183 return hal_service;
184 }
185
186 // Tests that all HAL entries in VINTF has all required fields filled out.
TEST_F(VtsTrebleVintfTest,HalEntriesAreComplete)187 TEST_F(VtsTrebleVintfTest, HalEntriesAreComplete) {
188 auto hal_names = vendor_manifest_->getHalNames();
189 for (const auto &hal_name : hal_names) {
190 auto versions = vendor_manifest_->getSupportedVersions(hal_name);
191 EXPECT_FALSE(versions.empty())
192 << hal_name << " has no version specified in VINTF.";
193 auto iface_names = vendor_manifest_->getInterfaceNames(hal_name);
194 EXPECT_FALSE(iface_names.empty())
195 << hal_name << " has no interface specified in VINTF.";
196 for (const auto &iface_name : iface_names) {
197 auto instances = vendor_manifest_->getInstances(hal_name, iface_name);
198 EXPECT_FALSE(instances.empty())
199 << hal_name << " has no instance specified in VINTF.";
200 }
201 }
202 }
203
204 // Tests that no HAL outside of the allowed set is specified as passthrough in
205 // VINTF.
TEST_F(VtsTrebleVintfTest,HalsAreBinderized)206 TEST_F(VtsTrebleVintfTest, HalsAreBinderized) {
207 // Verifies that HAL is binderized unless it's allowed to be passthrough.
208 HalVerifyFn is_binderized = [this](const FQName &fq_name,
209 const string &instance_name) {
210 cout << "Verifying transport method of: " << fq_name.string() << endl;
211 string hal_name = fq_name.package();
212 Version version{fq_name.getPackageMajorVersion(),
213 fq_name.getPackageMinorVersion()};
214 string iface_name = fq_name.name();
215
216 Transport transport = vendor_manifest_->getTransport(
217 hal_name, version, iface_name, instance_name);
218
219 EXPECT_NE(transport, Transport::EMPTY)
220 << hal_name << " has no transport specified in VINTF.";
221
222 if (transport == Transport::PASSTHROUGH) {
223 EXPECT_NE(kPassthroughHals.find(hal_name), kPassthroughHals.end())
224 << hal_name << " can't be passthrough under Treble rules.";
225 }
226 };
227
228 ForEachHalInstance(is_binderized);
229 }
230
231 // Tests that all HALs specified in the VINTF are available through service
232 // manager.
TEST_F(VtsTrebleVintfTest,VintfHalsAreServed)233 TEST_F(VtsTrebleVintfTest, VintfHalsAreServed) {
234 // Verifies that HAL is available through service manager.
235 HalVerifyFn is_available = [this](const FQName &fq_name,
236 const string &instance_name) {
237 if (IsExempt(fq_name)) {
238 cout << fq_name.string() << " is exempt." << endl;
239 return;
240 }
241
242 sp<android::hidl::base::V1_0::IBase> hal_service =
243 GetHalService(fq_name, instance_name);
244 EXPECT_NE(hal_service, nullptr)
245 << fq_name.package() << " not available." << endl;
246 };
247
248 ForEachHalInstance(is_available);
249 }
250
251 // Tests that HAL interfaces are officially released.
TEST_F(VtsTrebleVintfTest,InterfacesAreReleased)252 TEST_F(VtsTrebleVintfTest, InterfacesAreReleased) {
253 // Verifies that HAL are released by fetching the hash of the interface and
254 // comparing it to the set of known hashes of released interfaces.
255 HalVerifyFn is_released = [this](const FQName &fq_name,
256 const string &instance_name) {
257 sp<android::hidl::base::V1_0::IBase> hal_service =
258 GetHalService(fq_name, instance_name);
259
260 if (hal_service == nullptr) {
261 if (IsExempt(fq_name)) {
262 cout << fq_name.string() << " is exempt." << endl;
263 } else {
264 ADD_FAILURE() << fq_name.package() << " not available." << endl;
265 }
266 return;
267 }
268
269 vector<string> iface_chain{};
270 hal_service->interfaceChain(
271 [&iface_chain](const hidl_vec<hidl_string> &chain) {
272 for (const auto &iface_name : chain) {
273 iface_chain.push_back(iface_name);
274 }
275 });
276
277 vector<string> hash_chain{};
278 hal_service->getHashChain(
279 [&hash_chain](const hidl_vec<HashCharArray> &chain) {
280 for (const HashCharArray &hash_array : chain) {
281 vector<uint8_t> hash{hash_array.data(),
282 hash_array.data() + hash_array.size()};
283 hash_chain.push_back(Hash::hexString(hash));
284 }
285 });
286
287 ASSERT_EQ(iface_chain.size(), hash_chain.size());
288 for (size_t i = 0; i < iface_chain.size(); ++i) {
289 FQName fq_iface_name{iface_chain[i]};
290 string hash = hash_chain[i];
291
292 if (IsGoogleDefinedIface(fq_iface_name)) {
293 set<string> released_hashes = ReleasedHashes(fq_iface_name);
294 EXPECT_NE(released_hashes.find(hash), released_hashes.end())
295 << "Hash not found. This interface was not released." << endl
296 << "Interface name: " << fq_iface_name.string() << endl
297 << "Hash: " << hash << endl;
298 }
299 }
300 };
301
302 ForEachHalInstance(is_released);
303 }
304
main(int argc,char ** argv)305 int main(int argc, char **argv) {
306 ::testing::InitGoogleTest(&argc, argv);
307 return RUN_ALL_TESTS();
308 }
309