Add <fqname> to manifests.

The format of <fqname> is:
<hal>
    <name>android.hardware.foo</name>
    <!-- transport, etc. -->
    <fqname>@1.0::IFoo/default</fqname>
</hal>

It is possible to mix <fqname> and <version>
x <interface> x <instance> ; see tests for details.

This allows instances at different versions. For example,
it is now allowed to serve @1.0::IFoo/default, @1.1::IFoo/custom
simultaneously without serving @1.1::IFoo/default.

If override="true" and no <version>x<interface>x<instance> nor
<fqname>, the HAL tag is disabled. (Previously, the HAL tag
is disabled iff no <version> exists).

Bug: 73556059
Test: libvintf_test
Test: vintf_object_test

Change-Id: I80cb9ccdeec708c2c5530812913b37f8b3cc3ffa
diff --git a/ManifestHal.cpp b/ManifestHal.cpp
index cd30f16..1576c80 100644
--- a/ManifestHal.cpp
+++ b/ManifestHal.cpp
@@ -18,6 +18,7 @@
 #include <unordered_set>
 
 #include "MapValueIterator.h"
+#include "parse_string.h"
 
 namespace android {
 namespace vintf {
@@ -43,11 +44,11 @@
     if (!(transportArch == other.transportArch)) return false;
     if (interfaces != other.interfaces) return false;
     if (isOverride() != other.isOverride()) return false;
+    if (mAdditionalInstances != other.mAdditionalInstances) return false;
     return true;
 }
 
 bool ManifestHal::forEachInstance(const std::function<bool(const ManifestInstance&)>& func) const {
-    // TODO(b/73556059): support <fqname> as well.
     for (const auto& v : versions) {
         for (const auto& intf : iterateValues(interfaces)) {
             for (const auto& instance : intf.instances) {
@@ -62,6 +63,13 @@
             }
         }
     }
+
+    for (const auto& manifestInstance : mAdditionalInstances) {
+        if (!func(manifestInstance)) {
+            return false;
+        }
+    }
+
     return true;
 }
 
@@ -83,5 +91,49 @@
     });
 }
 
+static bool verifyInstances(const std::set<FqInstance>& fqInstances, std::string* error) {
+    for (const FqInstance& fqInstance : fqInstances) {
+        if (fqInstance.hasPackage()) {
+            if (error) *error = "Should not specify package: \"" + fqInstance.string() + "\"";
+            return false;
+        }
+        if (!fqInstance.hasVersion()) {
+            if (error) *error = "Should specify version: \"" + fqInstance.string() + "\"";
+            return false;
+        }
+        if (!fqInstance.hasInterface()) {
+            if (error) *error = "Should specify interface: \"" + fqInstance.string() + "\"";
+            return false;
+        }
+        if (!fqInstance.hasInstance()) {
+            if (error) *error = "Should specify instance: \"" + fqInstance.string() + "\"";
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ManifestHal::insertInstances(const std::set<FqInstance>& fqInstances, std::string* error) {
+    if (!verifyInstances(fqInstances, error)) {
+        return false;
+    }
+
+    for (const FqInstance& e : fqInstances) {
+        FqInstance withPackage;
+        if (!withPackage.setTo(this->getName(), e.getMajorVersion(), e.getMinorVersion(),
+                               e.getInterface(), e.getInstance())) {
+            if (error) {
+                *error = "Cannot create FqInstance with package='" + this->getName() +
+                         "', version='" + to_string(Version(e.getVersion())) + "', interface='" +
+                         e.getInterface() + "', instance='" + e.getInstance() + "'";
+            }
+            return false;
+        }
+        mAdditionalInstances.emplace(std::move(withPackage), this->transportArch);
+    }
+
+    return true;
+}
+
 } // namespace vintf
 } // namespace android