• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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