• 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 #define LOG_TAG "VtsTestabilityChecker"
17 
18 #include "VtsTestabilityChecker.h"
19 
20 #include <algorithm>
21 #include <iostream>
22 #include <set>
23 
24 #include <android-base/strings.h>
25 #include <vintf/parse_string.h>
26 
27 using android::base::Join;
28 using android::vintf::Arch;
29 using android::vintf::CompatibilityMatrix;
30 using android::vintf::gArchStrings;
31 using android::vintf::HalManifest;
32 using android::vintf::ManifestHal;
33 using android::vintf::ManifestInstance;
34 using android::vintf::MatrixHal;
35 using android::vintf::MatrixInstance;
36 using android::vintf::toFQNameString;
37 using android::vintf::Transport;
38 using android::vintf::Version;
39 using android::vintf::operator<<;
40 using std::set;
41 using std::string;
42 using std::vector;
43 
44 namespace android {
45 namespace vts {
46 
CheckHalForComplianceTest(const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,const Arch & arch,set<string> * instances)47 bool VtsTestabilityChecker::CheckHalForComplianceTest(
48     const string& hal_package_name, const Version& hal_version,
49     const string& hal_interface_name, const Arch& arch,
50     set<string>* instances) {
51   CHECK(instances) << "instances set should not be NULL.";
52   set<string> famework_hal_instances;
53   set<string> vendor_hal_instances;
54   bool check_framework_hal = CheckFrameworkManifestHal(
55       hal_package_name, hal_version, hal_interface_name, arch,
56       &famework_hal_instances);
57   bool check_vendor_hal =
58       CheckVendorManifestHal(hal_package_name, hal_version, hal_interface_name,
59                              arch, &vendor_hal_instances);
60   set_union(famework_hal_instances.begin(), famework_hal_instances.end(),
61             vendor_hal_instances.begin(), vendor_hal_instances.end(),
62             std::inserter(*instances, instances->begin()));
63   return check_framework_hal || check_vendor_hal;
64 }
65 
CheckHalForNonComplianceTest(const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,const Arch & arch,set<string> * instances)66 bool VtsTestabilityChecker::CheckHalForNonComplianceTest(
67     const string& hal_package_name, const Version& hal_version,
68     const string& hal_interface_name, const Arch& arch,
69     set<string>* instances) {
70   CHECK(instances) << "instances set should not be NULL.";
71   set<string> vendor_hal_instances;
72   set<string> test_hal_instances;
73   bool check_vendor_hal =
74       CheckVendorManifestHal(hal_package_name, hal_version, hal_interface_name,
75                              arch, &vendor_hal_instances);
76 
77   bool check_test_hal = CheckTestHalWithHwManager(
78       hal_package_name, hal_version, hal_interface_name, &test_hal_instances);
79 
80   set_union(vendor_hal_instances.begin(), vendor_hal_instances.end(),
81             test_hal_instances.begin(), test_hal_instances.end(),
82             std::inserter(*instances, instances->begin()));
83   return check_vendor_hal || check_test_hal;
84 }
85 
FindInstance(const vector<ManifestInstance> & manifest_instances,const MatrixInstance & matrix_instance)86 vector<const ManifestInstance*> VtsTestabilityChecker::FindInstance(
87     const vector<ManifestInstance>& manifest_instances,
88     const MatrixInstance& matrix_instance) {
89   vector<const ManifestInstance*> ret;
90   for (const auto& e : manifest_instances) {
91     if (matrix_instance.matchInstance(e.instance())) {
92       ret.push_back(&e);
93     }
94   }
95   return ret;
96 }
97 
FindInterface(const vector<ManifestInstance> & manifest_instances,const MatrixInstance & matrix_instance)98 vector<const ManifestInstance*> VtsTestabilityChecker::FindInterface(
99     const vector<ManifestInstance>& manifest_instances,
100     const MatrixInstance& matrix_instance) {
101   vector<const ManifestInstance*> ret;
102   for (const auto& e : manifest_instances) {
103     if (e.interface() == matrix_instance.interface()) {
104       ret.push_back(&e);
105     }
106   }
107   return ret;
108 }
109 
CheckFrameworkCompatibleHal(const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,const Arch & arch,set<string> * instances)110 bool VtsTestabilityChecker::CheckFrameworkCompatibleHal(
111     const string& hal_package_name, const Version& hal_version,
112     const string& hal_interface_name, const Arch& arch,
113     set<string>* instances) {
114   CHECK(instances) << "instances set should not be NULL.";
115 
116   auto matrix_instances = framework_comp_matrix_->getFqInstances(
117       hal_package_name, hal_version, hal_interface_name);
118   auto manifest_instances = device_hal_manifest_->getFqInstances(
119       hal_package_name, hal_version, hal_interface_name);
120 
121   bool testable = false;
122 
123   for (const auto& matrix_instance : matrix_instances) {
124     const auto& matched_instances =
125         FindInstance(manifest_instances, matrix_instance);
126     if (!matrix_instance.optional() && matched_instances.empty()) {
127       // In matrix but not in manifest.
128       // The test should still run, but expect the test
129       // to fail (due to incompatible vendor and framework HAL).
130       LOG(ERROR) << "Compatibility error. Hal " << hal_package_name
131                  << " is required by framework but not supported by vendor";
132       if (!hal_interface_name.empty()) {
133         if (!matrix_instance.isRegex()) {
134           instances->insert(matrix_instance.exactInstance());
135         } else {
136           LOG(ERROR) << "Ignore regex-instance '"
137                      << matrix_instance.regexPattern();
138         }
139       }
140       testable |= true;
141       continue;
142     }
143 
144     if (hal_interface_name.empty()) {
145       testable |= !matched_instances.empty();
146       continue;
147     }
148 
149     auto get_testable_instances =
150         [&](const vector<const vintf::ManifestInstance*>& manifest_instances) {
151           vector<string> ret;
152           for (const auto& manifest_instance : manifest_instances) {
153             if ((manifest_instance->transport() == Transport::PASSTHROUGH &&
154                  CheckPassthroughManifestArch(manifest_instance->arch(),
155                                               arch)) ||
156                 manifest_instance->transport() == Transport::HWBINDER) {
157               ret.push_back(manifest_instance->instance());
158             }
159           }
160           return ret;
161         };
162 
163     auto testable_instances = get_testable_instances(matched_instances);
164     if (!testable_instances.empty()) {
165       instances->insert(testable_instances.begin(), testable_instances.end());
166       testable |= true;
167       continue;
168     }
169 
170     // Special case: if a.h.foo@1.0::IFoo/default is in matrix but /custom
171     // is in manifest, the interface is still testable, but /default should
172     // not be added to instances.
173     const auto& matched_interface_instances =
174         FindInterface(manifest_instances, matrix_instance);
175     auto testable_interfaces =
176         get_testable_instances(matched_interface_instances);
177     if (!testable_interfaces.empty()) {
178       testable |= true;
179       continue;
180     }
181   }
182   if (instances->empty()) {
183     LOG(ERROR) << "Hal "
184                << toFQNameString(hal_package_name, hal_version,
185                                  hal_interface_name)
186                << " has no testable instance";
187   }
188   return testable;
189 }
190 
CheckPassthroughManifestArch(const Arch & manifest_arch,const Arch & arch)191 bool VtsTestabilityChecker::CheckPassthroughManifestArch(
192     const Arch& manifest_arch, const Arch& arch) {
193   switch (arch) {
194     case Arch::ARCH_32: {
195       if (android::vintf::has32(manifest_arch)) {
196         return true;
197       }
198       break;
199     }
200     case Arch::ARCH_64: {
201       if (android::vintf::has64(manifest_arch)) {
202         return true;
203       }
204       break;
205     }
206     default: {
207       LOG(ERROR) << "Unexpected arch to check: " << arch;
208       break;
209     }
210   }
211   return false;
212 }
213 
CheckFrameworkManifestHal(const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,const Arch & arch,set<string> * instances)214 bool VtsTestabilityChecker::CheckFrameworkManifestHal(
215     const string& hal_package_name, const Version& hal_version,
216     const string& hal_interface_name, const Arch& arch,
217     set<string>* instances) {
218   return CheckManifestHal(framework_hal_manifest_, hal_package_name,
219                           hal_version, hal_interface_name, arch, instances);
220 }
221 
CheckVendorManifestHal(const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,const Arch & arch,set<string> * instances)222 bool VtsTestabilityChecker::CheckVendorManifestHal(
223     const string& hal_package_name, const Version& hal_version,
224     const string& hal_interface_name, const Arch& arch,
225     set<string>* instances) {
226   return CheckManifestHal(device_hal_manifest_, hal_package_name, hal_version,
227                           hal_interface_name, arch, instances);
228 }
229 
CheckManifestHal(const HalManifest * hal_manifest,const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,const Arch & arch,set<string> * instances)230 bool VtsTestabilityChecker::CheckManifestHal(const HalManifest* hal_manifest,
231                                              const string& hal_package_name,
232                                              const Version& hal_version,
233                                              const string& hal_interface_name,
234                                              const Arch& arch,
235                                              set<string>* instances) {
236   CHECK(instances) << "instances set should not be NULL.";
237 
238   const auto& manifest_instances = hal_manifest->getFqInstances(
239       hal_package_name, hal_version, hal_interface_name);
240 
241   const auto& fq_instance_name =
242       toFQNameString(hal_package_name, hal_version, hal_interface_name);
243 
244   if (manifest_instances.empty()) {
245     LOG(DEBUG) << "Does not find instances for " << fq_instance_name
246                << " in manifest file";
247     return false;
248   }
249 
250   bool testable = false;
251   for (const auto& manifest_instance : manifest_instances) {
252     if (manifest_instance.transport() == Transport::PASSTHROUGH &&
253         !CheckPassthroughManifestArch(manifest_instance.arch(), arch)) {
254       LOG(DEBUG) << "Manifest HAL " << fq_instance_name
255                  << " is passthrough and does not support arch " << arch;
256       continue;  // skip this instance
257     }
258     if (!hal_interface_name.empty()) {
259       instances->insert(manifest_instance.instance());
260     }
261     testable = true;
262   }
263   return testable;
264 }
265 
CheckTestHalWithHwManager(const string & hal_package_name,const Version & hal_version,const string & hal_interface_name,set<string> * instances)266 bool VtsTestabilityChecker::CheckTestHalWithHwManager(
267     const string& hal_package_name, const Version& hal_version,
268     const string& hal_interface_name, set<string>* instances) {
269   CHECK(instances) << "instances set should not be NULL.";
270 
271   string fqName =
272       toFQNameString(hal_package_name, hal_version, hal_interface_name);
273   bool registered = false;
274   hardware::Return<void> res;
275   if (!hal_interface_name.empty()) {
276     res = sm_->listByInterface(fqName, [&](const auto& registered_instances) {
277       for (const string& instance : registered_instances) {
278         registered = true;
279         instances->insert(instance);
280       }
281     });
282   } else {  // handle legacy data without interface info.
283     res = sm_->list([&](const auto& services) {
284       for (const string& service : services) {
285         if (service.find(fqName) == 0) {
286           registered = true;
287           break;
288         }
289       }
290     });
291   }
292   if (!res.isOk()) {
293     LOG(ERROR) << "failed to check services: " << res.description();
294     return false;
295   }
296   return registered;
297 }
298 
299 }  // namespace vts
300 }  // namespace android
301