Add <vndk> entry to framework manifest and device comp-mat.

Bug: 36400653

Test: libvintf_test
Change-Id: Ie727d4806ad74a72511354a901fca09ea9ae67c4
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 1d2acbd..1435c4e 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -316,6 +316,23 @@
         return true;
     }
 
+    template <typename T>
+    inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const {
+        std::vector<T> vec;
+        if (!parseChildren(root, conv, &vec)) {
+            return false;
+        }
+        s->clear();
+        s->insert(vec.begin(), vec.end());
+        if (s->size() != vec.size()) {
+            mLastError = "Duplicated elements <" + conv.elementName() + "> in element <"
+                    + this->elementName() + ">";
+            s->clear();
+            return false;
+        }
+        return true;
+    }
+
     inline bool parseText(NodeType *node, std::string *s) const {
         *s = getText(node);
         return true;
@@ -544,6 +561,26 @@
 };
 const SepolicyConverter sepolicyConverter{};
 
+const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
+const XmlTextConverter<std::string> vndkLibraryConverter{"library"};
+
+struct VndkConverter : public XmlNodeConverter<Vndk> {
+    std::string elementName() const override { return "vndk"; }
+    void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
+        appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
+        appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
+    }
+    bool buildObject(Vndk *object, NodeType *root) const override {
+        if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) ||
+            !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
+            return false;
+        }
+        return true;
+    }
+};
+
+const VndkConverter vndkConverter{};
+
 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
     std::string elementName() const override { return "sepolicy"; }
     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
@@ -563,6 +600,8 @@
         appendChildren(root, manifestHalConverter, m.getHals(), d);
         if (m.mType == SchemaType::DEVICE) {
             appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
+        } else if (m.mType == SchemaType::FRAMEWORK) {
+            appendChildren(root, vndkConverter, m.framework.mVndks, d);
         }
     }
     bool buildObject(HalManifest *object, NodeType *root) const override {
@@ -584,6 +623,17 @@
                     &object->device.mSepolicyVersion)) {
                 return false;
             }
+        } else if (object->mType == SchemaType::FRAMEWORK) {
+            if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) {
+                return false;
+            }
+            for (const auto &vndk : object->framework.mVndks) {
+                if (!vndk.mVersionRange.isSingleVersion()) {
+                    this->mLastError = "vndk.version " + to_string(vndk.mVersionRange)
+                            + " cannot be a range for manifests";
+                    return false;
+                }
+            }
         }
         for (auto &&hal : hals) {
             if (!object->add(std::move(hal))) {
@@ -622,6 +672,10 @@
                 !parseChild(root, sepolicyConverter, &object->framework.mSepolicy)) {
                 return false;
             }
+        } else if (object->mType == SchemaType::DEVICE) {
+            if (!parseChild(root, vndkConverter, &object->device.mVndk)) {
+                return false;
+            }
         }
 
         if (version != CompatibilityMatrix::kVersion) {