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