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/parse_xml.cpp b/parse_xml.cpp
index bf8889f..38a09b4 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -230,11 +230,12 @@
         }
     }
 
-    template<typename T, typename Array>
-    inline void appendChildren(NodeType *parent, const XmlNodeConverter<T> &conv,
-            const Array &array, DocType *d) const {
+    template <typename T, typename Array>
+    inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
+                               const Array& array, DocType* d,
+                               SerializeFlags flags = SerializeFlag::EVERYTHING) const {
         for (const T &t : array) {
-            appendChild(parent, conv(t, d));
+            appendChild(parent, conv.serialize(t, d, flags));
         }
     }
 
@@ -600,9 +601,15 @@
 
 MatrixKernelConverter matrixKernelConverter{};
 
+XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
+
 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
     std::string elementName() const override { return "hal"; }
-    void mutateNode(const ManifestHal &hal, NodeType *root, DocType *d) const override {
+    void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
+        mutateNode(m, root, d, SerializeFlag::EVERYTHING);
+    }
+    void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
+                    SerializeFlags flags) const override {
         appendAttr(root, "format", hal.format);
         appendTextElement(root, "name", hal.name, d);
         appendChild(root, transportArchConverter(hal.transportArch, d));
@@ -611,6 +618,15 @@
         if (hal.isOverride()) {
             appendAttr(root, "override", hal.isOverride());
         }
+
+        if (!(flags & SerializeFlag::NO_FQNAME)) {
+            std::set<FqInstance> fqInstances;
+            hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
+                fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
+                return true;
+            });
+            appendChildren(root, fqInstanceConverter, fqInstances, d);
+        }
     }
     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
         std::vector<HalInterface> interfaces;
@@ -666,6 +682,15 @@
             return false;
         }
 #endif
+
+        std::set<FqInstance> fqInstances;
+        if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
+            return false;
+        }
+        if (!object->insertInstances(fqInstances, error)) {
+            return false;
+        }
+
         return true;
     }
 
@@ -808,7 +833,7 @@
         appendAttr(root, "type", m.mType);
 
         if (!(flags & SerializeFlag::NO_HALS)) {
-            appendChildren(root, manifestHalConverter, m.getHals(), d);
+            appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
         }
         if (m.mType == SchemaType::DEVICE) {
             if (!(flags & SerializeFlag::NO_SEPOLICY)) {