CompatibilityMatrix::combine handles multiple instances.
Fix an edge case:
1.xml states 1.0/default AND 1.0/custom
2.xml states 2.0/default AND 2.0/strong
The old code generates:
(1.0/default AND 1.0/custom) OR
(2.0/default AND 2.0/custom)
The new code correctly generates:
(1.0/default OR 2.0/default) AND
(1.0/custom) AND
(Optional 2.0/strong)
Test: libvintf_test
Test: vintf_object_test
Bug: 74341777
Change-Id: I07f0529b9bc1d046c269fc41f33be307f599422a
diff --git a/MatrixHal.cpp b/MatrixHal.cpp
index 504265e..62e0cd8 100644
--- a/MatrixHal.cpp
+++ b/MatrixHal.cpp
@@ -52,24 +52,6 @@
return ret;
}
-bool MatrixHal::containsInstances(const MatrixHal& other) const {
- for (const auto& pair : other.interfaces) {
- const std::string& interfaceName = pair.first;
- auto thisIt = interfaces.find(interfaceName);
- if (thisIt == interfaces.end()) {
- return false;
- }
-
- const std::set<std::string>& thisInstances = thisIt->second.instances;
- const std::set<std::string>& otherInstances = pair.second.instances;
- if (!std::includes(thisInstances.begin(), thisInstances.end(), otherInstances.begin(),
- otherInstances.end())) {
- return false;
- }
- }
- return true;
-}
-
bool MatrixHal::forEachInstance(const std::function<bool(const MatrixInstance&)>& func) const {
for (const auto& vr : versionRanges) {
if (!forEachInstance(vr, func)) {
@@ -95,6 +77,19 @@
return true;
}
+bool MatrixHal::forEachInstance(
+ const std::function<bool(const std::vector<VersionRange>&, const std::string&,
+ const std::string&)>& func) const {
+ for (const auto& intf : iterateValues(interfaces)) {
+ for (const auto& instance : intf.instances) {
+ if (!func(versionRanges, intf.name, instance)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
bool MatrixHal::isCompatible(const std::set<FqInstance>& providedInstances,
const std::set<Version>& providedVersions) const {
// <version>'s are related by OR.
@@ -136,8 +131,8 @@
this->optional = o;
}
-void MatrixHal::insertVersionRanges(const MatrixHal& other) {
- for (const VersionRange& otherVr : other.versionRanges) {
+void MatrixHal::insertVersionRanges(const std::vector<VersionRange>& other) {
+ for (const VersionRange& otherVr : other) {
auto existingVr = std::find_if(this->versionRanges.begin(), this->versionRanges.end(),
[&](const auto& e) { return e.overlaps(otherVr); });
@@ -150,5 +145,59 @@
}
}
+void MatrixHal::insertInstance(const std::string& interface, const std::string& instance) {
+ auto it = interfaces.find(interface);
+ if (it == interfaces.end())
+ it = interfaces.emplace(interface, HalInterface{interface, {}}).first;
+ it->second.instances.insert(instance);
+}
+
+bool MatrixHal::hasAnyInstance() const {
+ bool found = false;
+ forEachInstance([&](const auto&) {
+ found = true;
+ return false; // break if any instance
+ });
+ return found;
+}
+
+bool MatrixHal::hasInstance(const std::string& interface, const std::string& instance) const {
+ bool found = false;
+ forEachInstance([&](const auto& matrixInstance) {
+ found |= matrixInstance.interface() == interface && matrixInstance.instance() == instance;
+ return !found; // continue if not match
+ });
+ return found;
+}
+
+bool MatrixHal::hasOnlyInstance(const std::string& interface, const std::string& instance) const {
+ bool found = false;
+ bool foundOthers = false;
+
+ forEachInstance([&](const auto& matrixInstance) {
+ bool match =
+ matrixInstance.interface() == interface && matrixInstance.instance() == instance;
+
+ found |= match;
+ foundOthers |= (!match);
+
+ return !foundOthers;
+ });
+
+ return found && !foundOthers;
+}
+
+bool MatrixHal::removeInstance(const std::string& interface, const std::string& instance) {
+ auto it = interfaces.find(interface);
+ if (it == interfaces.end()) return false;
+ it->second.instances.erase(instance);
+ if (it->second.instances.empty()) interfaces.erase(it);
+ return true;
+}
+
+void MatrixHal::clearInstances() {
+ this->interfaces.clear();
+}
+
} // namespace vintf
} // namespace android