summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'HalManifest.cpp')
-rw-r--r--HalManifest.cpp127
1 files changed, 37 insertions, 90 deletions
diff --git a/HalManifest.cpp b/HalManifest.cpp
index a27e935..aee4462 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -177,13 +177,6 @@ std::set<Version> HalManifest::getSupportedVersions(const std::string &name) con
177 return ret; 177 return ret;
178} 178}
179 179
180bool HalManifest::hasInstance(const std::string& halName, const Version& version,
181 const std::string& interfaceName,
182 const std::string& instanceName) const {
183 const auto& instances = getInstances(halName, version, interfaceName);
184 return instances.find(instanceName) != instances.end();
185}
186
187bool HalManifest::forEachInstanceOfVersion( 180bool HalManifest::forEachInstanceOfVersion(
188 const std::string& package, const Version& expectVersion, 181 const std::string& package, const Version& expectVersion,
189 const std::function<bool(const ManifestInstance&)>& func) const { 182 const std::function<bool(const ManifestInstance&)>& func) const {
@@ -199,89 +192,12 @@ bool HalManifest::forEachInstanceOfVersion(
199 return true; 192 return true;
200} 193}
201 194
202static bool satisfyVersion(const MatrixHal& matrixHal, const Version& manifestHalVersion) {
203 for (const VersionRange &matrixVersionRange : matrixHal.versionRanges) {
204 // If Compatibility Matrix says 2.5-2.7, the "2.7" is purely informational;
205 // the framework can work with all 2.5-2.infinity.
206 if (matrixVersionRange.supportedBy(manifestHalVersion)) {
207 return true;
208 }
209 }
210 return false;
211}
212
213// Check if matrixHal.interfaces is a subset of instancesOfVersion
214static bool satisfyAllInstances(const MatrixHal& matrixHal,
215 const InstancesOfVersion &instancesOfVersion) {
216 for (const auto& matrixHalInterfacePair : matrixHal.interfaces) {
217 const std::string& interface = matrixHalInterfacePair.first;
218 auto it = instancesOfVersion.find(interface);
219 if (it == instancesOfVersion.end()) {
220 return false;
221 }
222 const std::set<std::string>& manifestInterfaceInstances = it->second;
223 const std::set<std::string>& matrixInterfaceInstances =
224 matrixHalInterfacePair.second.instances;
225 if (!std::includes(manifestInterfaceInstances.begin(), manifestInterfaceInstances.end(),
226 matrixInterfaceInstances.begin(), matrixInterfaceInstances.end())) {
227 return false;
228 }
229 }
230 return true;
231}
232
233Instances HalManifest::expandInstances(const std::string& name) const {
234 Instances instances;
235 // Do the cross product version x interface x instance and sort them,
236 // because interfaces / instances can span in multiple HALs.
237 // This is efficient for small <hal> entries.
238 for (const ManifestHal* manifestHal : getHals(name)) {
239 for (const Version& manifestHalVersion : manifestHal->versions) {
240 instances[manifestHalVersion] = {};
241 for (const auto& halInterfacePair : manifestHal->interfaces) {
242 const std::string& interface = halInterfacePair.first;
243 const auto& toAdd = halInterfacePair.second.instances;
244 instances[manifestHalVersion][interface].insert(toAdd.begin(), toAdd.end());
245 }
246 }
247 }
248 return instances;
249}
250
251bool HalManifest::isCompatible(const Instances& instances, const MatrixHal& matrixHal) const {
252 for (const auto& instanceMapPair : instances) {
253 const Version& manifestHalVersion = instanceMapPair.first;
254 const InstancesOfVersion& instancesOfVersion = instanceMapPair.second;
255 if (!satisfyVersion(matrixHal, manifestHalVersion)) {
256 continue;
257 }
258 if (!satisfyAllInstances(matrixHal, instancesOfVersion)) {
259 continue;
260 }
261 return true; // match!
262 }
263 return false;
264}
265
266static std::vector<std::string> toLines(const Instances& allInstances) {
267 std::vector<std::string> lines;
268 for (const auto& pair : allInstances) {
269 const auto& version = pair.first;
270 for (const auto& ifacePair : pair.second) {
271 const auto& interface = ifacePair.first;
272 for (const auto& instance : ifacePair.second) {
273 lines.push_back(toFQNameString(version, interface, instance));
274 }
275 }
276 }
277 return lines;
278}
279
280// indent = 2, {"foo"} => "foo" 195// indent = 2, {"foo"} => "foo"
281// indent = 2, {"foo", "bar"} => "\n foo\n bar"; 196// indent = 2, {"foo", "bar"} => "\n foo\n bar";
282void multilineIndent(std::ostream& os, size_t indent, const std::vector<std::string>& lines) { 197template <typename Container>
198void multilineIndent(std::ostream& os, size_t indent, const Container& lines) {
283 if (lines.size() == 1) { 199 if (lines.size() == 1) {
284 os << lines.front(); 200 os << *lines.begin();
285 return; 201 return;
286 } 202 }
287 for (const auto& line : lines) { 203 for (const auto& line : lines) {
@@ -298,13 +214,29 @@ std::vector<std::string> HalManifest::checkIncompatibleHals(const CompatibilityM
298 if (matrixHal.optional) { 214 if (matrixHal.optional) {
299 continue; 215 continue;
300 } 216 }
301 auto manifestInstances = expandInstances(matrixHal.name); 217
302 if (!isCompatible(manifestInstances, matrixHal)) { 218 std::set<FqInstance> manifestInstances;
219 std::set<FqInstance> manifestInstancesNoPackage;
220 std::set<Version> versions;
221 for (const ManifestHal* manifestHal : getHals(matrixHal.name)) {
222 manifestHal->forEachInstance([&](const auto& manifestInstance) {
223 manifestInstances.insert(manifestInstance.getFqInstance());
224 manifestInstancesNoPackage.insert(manifestInstance.getFqInstanceNoPackage());
225 return true;
226 });
227 manifestHal->appendAllVersions(&versions);
228 }
229
230 if (!matrixHal.isCompatible(manifestInstances, versions)) {
303 std::ostringstream oss; 231 std::ostringstream oss;
304 oss << matrixHal.name << ":\n required: "; 232 oss << matrixHal.name << ":\n required: ";
305 multilineIndent(oss, 8, android::vintf::expandInstances(matrixHal)); 233 multilineIndent(oss, 8, android::vintf::expandInstances(matrixHal));
306 oss << "\n provided: "; 234 oss << "\n provided: ";
307 multilineIndent(oss, 8, toLines(manifestInstances)); 235 if (manifestInstances.empty()) {
236 multilineIndent(oss, 8, versions);
237 } else {
238 multilineIndent(oss, 8, manifestInstancesNoPackage);
239 }
308 240
309 ret.insert(ret.end(), oss.str()); 241 ret.insert(ret.end(), oss.str());
310 } 242 }
@@ -312,6 +244,21 @@ std::vector<std::string> HalManifest::checkIncompatibleHals(const CompatibilityM
312 return ret; 244 return ret;
313} 245}
314 246
247std::set<std::string> HalManifest::checkUnusedHals(const CompatibilityMatrix& mat) const {
248 std::set<std::string> ret;
249
250 forEachInstance([&ret, &mat](const auto& manifestInstance) {
251 const auto& fqInstance = manifestInstance.getFqInstance();
252 if (!mat.hasInstance(fqInstance.getPackage(), fqInstance.getVersion(),
253 fqInstance.getInterface(), fqInstance.getInstance())) {
254 ret.insert(fqInstance.string());
255 }
256 return true;
257 });
258
259 return ret;
260}
261
315static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk, 262static bool checkVendorNdkCompatibility(const VendorNdk& matVendorNdk,
316 const std::vector<VendorNdk>& manifestVendorNdk, 263 const std::vector<VendorNdk>& manifestVendorNdk,
317 std::string* error) { 264 std::string* error) {