/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Convert objects from and to xml.

#define LOG_TAG "libvintf"
#include <android-base/logging.h>

#include "parse_xml.h"

#include <type_traits>

#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <tinyxml2.h>

#include "Regex.h"
#include "constants-private.h"
#include "constants.h"
#include "parse_string.h"
#include "parse_xml_for_test.h"
#include "utils.h"

using namespace std::string_literals;

#ifdef LIBVINTF_TARGET
static constexpr bool kDevice = true;
#else
static constexpr bool kDevice = false;
#endif

namespace android {
namespace vintf {

// --------------- tinyxml2 details

using NodeType = tinyxml2::XMLElement;
using DocType = tinyxml2::XMLDocument;

// caller is responsible for deleteDocument() call
inline DocType *createDocument() {
    return new tinyxml2::XMLDocument();
}

// caller is responsible for deleteDocument() call
inline DocType *createDocument(const std::string &xml) {
    DocType *doc = new tinyxml2::XMLDocument();
    if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
        return doc;
    }
    delete doc;
    return nullptr;
}

inline void deleteDocument(DocType *d) {
    delete d;
}

inline std::string printDocument(DocType *d) {
    tinyxml2::XMLPrinter p;
    d->Print(&p);
    return std::string{p.CStr()};
}

inline NodeType *createNode(const std::string &name, DocType *d) {
    return d->NewElement(name.c_str());
}

inline void appendChild(NodeType *parent, NodeType *child) {
    parent->InsertEndChild(child);
}

inline void appendChild(DocType *parent, NodeType *child) {
    parent->InsertEndChild(child);
}

inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
    e->SetAttribute(attrName.c_str(), attr.c_str());
}

// text -> text
inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
    parent->InsertEndChild(d->NewText(text.c_str()));
}

inline std::string nameOf(NodeType *root) {
    return root->Name() == NULL ? "" : root->Name();
}

inline std::string getText(NodeType *root) {
    return root->GetText() == NULL ? "" : root->GetText();
}

inline NodeType *getChild(NodeType *parent, const std::string &name) {
    return parent->FirstChildElement(name.c_str());
}

inline NodeType *getRootChild(DocType *parent) {
    return parent->FirstChildElement();
}

inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
    std::vector<NodeType *> v;
    for (NodeType *child = parent->FirstChildElement(name.c_str());
         child != nullptr;
         child = child->NextSiblingElement(name.c_str())) {
        v.push_back(child);
    }
    return v;
}

inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
    const char *c = root->Attribute(attrName.c_str());
    if (c == NULL)
        return false;
    *s = c;
    return true;
}

// --------------- tinyxml2 details end.

// Helper functions for XmlConverter
static bool parse(const std::string &attrText, bool *attr) {
    if (attrText == "true" || attrText == "1") {
        *attr = true;
        return true;
    }
    if (attrText == "false" || attrText == "0") {
        *attr = false;
        return true;
    }
    return false;
}

static bool parse(const std::string& attrText, std::optional<std::string>* attr) {
    *attr = attrText;
    return true;
}

static bool parse(const std::string& s, std::optional<uint64_t>* out) {
    uint64_t val;
    if (base::ParseUint(s, &val)) {
        *out = val;
        return true;
    }
    return false;
}

// ---------------------- XmlNodeConverter definitions

// When serializing an object to an XML document, these parameters don't change until
// the object is fully serialized.
// These parameters are also passed to converters of child nodes so they see the same
// serialization parameters.
struct MutateNodeParam {
    DocType* d;
    SerializeFlags::Type flags = SerializeFlags::EVERYTHING;
};

// When deserializing an XML document to an object, these parameters don't change until
// the XML document is fully deserialized.
// * Except metaVersion, which is immediately modified when parsing top-level <manifest>
//   or <compatibility-matrix>, and unchanged thereafter;
//   see HalManifestConverter::BuildObject and CompatibilityMatrixConverter::BuildObject)
// These parameters are also passed to converters of child nodes so they see the same
// deserialization parameters.
struct BuildObjectParam {
    std::string* error;
    Version metaVersion;
    std::string fileName;
};

template <typename Object>
struct XmlNodeConverter {
    XmlNodeConverter() {}
    virtual ~XmlNodeConverter() {}

   protected:
    virtual void mutateNode(const Object& object, NodeType* root, const MutateNodeParam&) const = 0;
    virtual bool buildObject(Object* object, NodeType* root, const BuildObjectParam&) const = 0;

   public:
    // Methods for other (usually parent) converters
    // Name of the XML element.
    virtual std::string elementName() const = 0;
    // Serialize |o| into an XML element.
    inline NodeType* operator()(const Object& o, const MutateNodeParam& param) const {
        NodeType* root = createNode(this->elementName(), param.d);
        this->mutateNode(o, root, param);
        return root;
    }
    // Deserialize XML element |root| into |object|.
    inline bool operator()(Object* object, NodeType* root, const BuildObjectParam& param) const {
        if (nameOf(root) != this->elementName()) {
            *param.error = "The root name(" + nameOf(root) + ") does not match the element name (" +
                           this->elementName() + ")";
            return false;
        }
        return this->buildObject(object, root, param);
    }

    // Public methods for android::vintf::fromXml / android::vintf::toXml.
    // Serialize |o| into an XML string.
    inline std::string toXml(const Object& o, SerializeFlags::Type flags) const {
        DocType* doc = createDocument();
        appendChild(doc, (*this)(o, MutateNodeParam{doc, flags}));
        std::string s = printDocument(doc);
        deleteDocument(doc);
        return s;
    }
    // Deserialize XML string |xml| into |o|.
    inline bool fromXml(Object* o, const std::string& xml, std::string* error) const {
        std::string errorBuffer;
        if (error == nullptr) error = &errorBuffer;

        auto doc = createDocument(xml);
        if (doc == nullptr) {
            *error = "Not a valid XML";
            return false;
        }
        // For top-level <manifest> and <compatibility-matrix>, HalManifestConverter and
        // CompatibilityMatrixConverter fills in metaversion and pass down to children.
        // For other nodes, we don't know metaversion of the original XML, so just leave empty
        // for maximum backwards compatibility.
        BuildObjectParam buildObjectParam{error, {}, {}};
        // Pass down filename for the current XML document.
        if constexpr (std::is_base_of_v<WithFileName, Object>) {
            // Get the last filename in case `o` keeps the list of filenames
            std::string_view fileName{o->fileName()};
            if (auto pos = fileName.rfind(':'); pos != fileName.npos) {
                fileName.remove_prefix(pos + 1);
            }
            buildObjectParam.fileName = std::string(fileName);
        }
        bool ret = (*this)(o, getRootChild(doc), buildObjectParam);
        deleteDocument(doc);
        return ret;
    }

    // convenience methods for subclasses to implement virtual functions.

    // All append* functions helps mutateNode() to serialize the object into XML.
    template <typename T>
    inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
        return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
    }

    inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
        return appendStrAttr(e, attrName, attr ? "true" : "false");
    }

    // text -> <name>text</name>
    inline void appendTextElement(NodeType *parent, const std::string &name,
                const std::string &text, DocType *d) const {
        NodeType *c = createNode(name, d);
        appendText(c, text, d);
        appendChild(parent, c);
    }

    // text -> <name>text</name>
    template<typename Array>
    inline void appendTextElements(NodeType *parent, const std::string &name,
                const Array &array, DocType *d) const {
        for (const std::string &text : array) {
            NodeType *c = createNode(name, d);
            appendText(c, text, d);
            appendChild(parent, c);
        }
    }

    template <typename T, typename Array>
    inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
                               const Array& array, const MutateNodeParam& param) const {
        for (const T &t : array) {
            appendChild(parent, conv(t, param));
        }
    }

    // All parse* functions helps buildObject() to deserialize XML to the object. Returns
    // true if deserialization is successful, false if any error, and "error" will be
    // set to error message.
    template <typename T>
    inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
                                  T* attr, const BuildObjectParam& param) const {
        std::string attrText;
        bool success = getAttr(root, attrName, &attrText);
        bool parseSuccess = true;
        if (success) {
            parseSuccess = ::android::vintf::parse(attrText, attr);
        } else {
            *attr = std::move(defaultValue);
        }
        if (param.metaVersion >= kMetaVersionStrictAttributeValues) {
            if (!parseSuccess && param.error) {
                *param.error += "Unknown value (\"" + attrText + "\") for attribute '" + attrName +
                                "' is considered a failure.";
            }
            return parseSuccess;
        } else {
            return true;
        }
    }

    template <typename T>
    inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
                          std::string* error) const {
        std::string attrText;
        bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
        if (!ret) {
            *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
                     attrText + "\" for element <" + elementName() + ">";
        }
        return ret;
    }

    inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
                          std::string* error) const {
        bool ret = getAttr(root, attrName, attr);
        if (!ret) {
            *error = "Could not find attr with name \"" + attrName + "\" for element <" +
                     elementName() + ">";
        }
        return ret;
    }

    inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
                                 std::string* error) const {
        NodeType *child = getChild(root, elementName);
        if (child == nullptr) {
            *error = "Could not find element with name <" + elementName + "> in element <" +
                     this->elementName() + ">";
            return false;
        }
        *s = getText(child);
        return true;
    }

    template <typename T>
    inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
                                         T&& defaultValue, T* s, std::string* /* error */) const {
        NodeType* child = getChild(root, elementName);
        *s = child == nullptr ? std::move(defaultValue) : getText(child);
        return true;
    }

    inline bool parseTextElements(NodeType* root, const std::string& elementName,
                                  std::vector<std::string>* v, std::string* /* error */) const {
        auto nodes = getChildren(root, elementName);
        v->resize(nodes.size());
        for (size_t i = 0; i < nodes.size(); ++i) {
            v->at(i) = getText(nodes[i]);
        }
        return true;
    }

    template <typename T>
    inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
                           const BuildObjectParam& param) const {
        NodeType *child = getChild(root, conv.elementName());
        if (child == nullptr) {
            *param.error = "Could not find element with name <" + conv.elementName() +
                           "> in element <" + this->elementName() + ">";
            return false;
        }
        return conv(t, child, param);
    }

    template <typename T>
    inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
                                   T&& defaultValue, T* t, const BuildObjectParam& param) const {
        NodeType *child = getChild(root, conv.elementName());
        if (child == nullptr) {
            *t = std::move(defaultValue);
            return true;
        }
        return conv(t, child, param);
    }

    template <typename T>
    inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
                                   std::optional<T>* t, const BuildObjectParam& param) const {
        NodeType* child = getChild(root, conv.elementName());
        if (child == nullptr) {
            *t = std::nullopt;
            return true;
        }
        *t = std::make_optional<T>();
        return conv(&**t, child, param);
    }

    template <typename T>
    inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
                              const BuildObjectParam& param) const {
        auto nodes = getChildren(root, conv.elementName());
        v->resize(nodes.size());
        for (size_t i = 0; i < nodes.size(); ++i) {
            if (!conv(&v->at(i), nodes[i], param)) {
                *param.error = "Could not parse element with name <" + conv.elementName() +
                               "> in element <" + this->elementName() + ">: " + *param.error;
                return false;
            }
        }
        return true;
    }

    template <typename Container, typename T = typename Container::value_type,
              typename = typename Container::key_compare>
    inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
                              const BuildObjectParam& param) const {
        std::vector<T> vec;
        if (!parseChildren(root, conv, &vec, param)) {
            return false;
        }
        s->clear();
        s->insert(vec.begin(), vec.end());
        if (s->size() != vec.size()) {
            *param.error = "Duplicated elements <" + conv.elementName() + "> in element <" +
                           this->elementName() + ">";
            s->clear();
            return false;
        }
        return true;
    }

    template <typename K, typename V>
    inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
                              std::map<K, V>* s, const BuildObjectParam& param) const {
        return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, param);
    }

    inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
        *s = getText(node);
        return true;
    }

    template <typename T>
    inline bool parseText(NodeType* node, T* s, std::string* error) const {
        bool (*parser)(const std::string&, T*) = ::android::vintf::parse;
        return parseText(node, s, {parser}, error);
    }

    template <typename T>
    inline bool parseText(NodeType* node, T* s,
                          const std::function<bool(const std::string&, T*)>& parse,
                          std::string* error) const {
        std::string text = getText(node);
        bool ret = parse(text, s);
        if (!ret) {
            *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
        }
        return ret;
    }
};

template<typename Object>
struct XmlTextConverter : public XmlNodeConverter<Object> {
    void mutateNode(const Object& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendText(root, ::android::vintf::to_string(object), param.d);
    }
    bool buildObject(Object* object, NodeType* root, const BuildObjectParam& param) const override {
        return this->parseText(root, object, param.error);
    }
};

template <typename Pair, typename FirstConverter, typename SecondConverter>
struct XmlPairConverter : public XmlNodeConverter<Pair> {
    void mutateNode(const Pair& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChild(root, FirstConverter{}(object.first, param));
        appendChild(root, SecondConverter{}(object.second, param));
    }
    bool buildObject(Pair* object, NodeType* root, const BuildObjectParam& param) const override {
        return this->parseChild(root, FirstConverter{}, &object->first, param) &&
               this->parseChild(root, SecondConverter{}, &object->second, param);
    }
};

// ---------------------- XmlNodeConverter definitions end

struct VersionConverter : public XmlTextConverter<Version> {
    std::string elementName() const override { return "version"; }
};

struct SepolicyVersionConverter : public XmlTextConverter<SepolicyVersion> {
    std::string elementName() const override { return "version"; }
};

struct VersionRangeConverter : public XmlTextConverter<VersionRange> {
    std::string elementName() const override { return "version"; }
};

struct SepolicyVersionRangeConverter : public XmlTextConverter<SepolicyVersionRange> {
    std::string elementName() const override { return "sepolicy-version"; }
};

// <version>100</version> <=> Version{kFakeAidlMajorVersion, 100}
struct AidlVersionConverter : public XmlNodeConverter<Version> {
    std::string elementName() const override { return "version"; }
    void mutateNode(const Version& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendText(root, aidlVersionToString(object), param.d);
    }
    bool buildObject(Version* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseText(root, object, {parseAidlVersion}, param.error);
    }
};

// <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100}
// <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105}
struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> {
    std::string elementName() const override { return "version"; }
    void mutateNode(const VersionRange& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendText(root, aidlVersionRangeToString(object), param.d);
    }
    bool buildObject(VersionRange* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseText(root, object, {parseAidlVersionRange}, param.error);
    }
};

struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
    std::string elementName() const override { return "transport"; }
    void mutateNode(const TransportArch& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        if (object.arch != Arch::ARCH_EMPTY) {
            appendAttr(root, "arch", object.arch);
        }
        if (object.ip.has_value()) {
            appendAttr(root, "ip", *object.ip);
        }
        if (object.port.has_value()) {
            appendAttr(root, "port", *object.port);
        }
        appendText(root, ::android::vintf::to_string(object.transport), param.d);
    }
    bool buildObject(TransportArch* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, param) ||
            !parseOptionalAttr(root, "ip", {}, &object->ip, param) ||
            !parseOptionalAttr(root, "port", {}, &object->port, param) ||
            !parseText(root, &object->transport, param.error)) {
            return false;
        }
        if (!object->isValid(param.error)) {
            return false;
        }
        return true;
    }
};

struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
    std::string elementName() const override { return "value"; }
    void mutateNode(const KernelConfigTypedValue& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendAttr(root, "type", object.mType);
        appendText(root, ::android::vintf::to_string(object), param.d);
    }
    bool buildObject(KernelConfigTypedValue* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        std::string stringValue;
        if (!parseAttr(root, "type", &object->mType, param.error) ||
            !parseText(root, &stringValue, param.error)) {
            return false;
        }
        if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
            *param.error = "Could not parse kernel config value \"" + stringValue + "\"";
            return false;
        }
        return true;
    }
};

struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> {
    std::string elementName() const override { return "key"; }
};

struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter,
                                                             KernelConfigTypedValueConverter> {
    std::string elementName() const override { return "config"; }
};

struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
    std::string elementName() const override { return "interface"; }
    void mutateNode(const HalInterface& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        if (!object.name().empty()) {
            appendTextElement(root, "name", object.name(), param.d);
        }
        appendTextElements(root, "instance", object.mInstances, param.d);
        appendTextElements(root, "regex-instance", object.mRegexes, param.d);
    }
    bool buildObject(HalInterface* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        std::vector<std::string> instances;
        std::vector<std::string> regexes;
        if (!parseOptionalTextElement(root, "name", {}, &object->mName, param.error) ||
            !parseTextElements(root, "instance", &instances, param.error) ||
            !parseTextElements(root, "regex-instance", &regexes, param.error)) {
            return false;
        }
        bool success = true;
        for (const auto& e : instances) {
            if (!object->insertInstance(e, false /* isRegex */)) {
                if (!param.error->empty()) *param.error += "\n";
                *param.error += "Duplicated instance '" + e + "' in " + object->name();
                success = false;
            }
        }
        for (const auto& e : regexes) {
            details::Regex regex;
            if (!regex.compile(e)) {
                if (!param.error->empty()) *param.error += "\n";
                *param.error += "Invalid regular expression '" + e + "' in " + object->name();
                success = false;
            }
            if (!object->insertInstance(e, true /* isRegex */)) {
                if (!param.error->empty()) *param.error += "\n";
                *param.error += "Duplicated regex-instance '" + e + "' in " + object->name();
                success = false;
            }
        }
        return success;
    }
};

struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
    std::string elementName() const override { return "hal"; }
    void mutateNode(const MatrixHal& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendAttr(root, "format", object.format);
        // Only include if it is not the default empty value
        if (object.exclusiveTo != ExclusiveTo::EMPTY) {
            appendAttr(root, "exclusive-to", object.exclusiveTo);
        }
        // Only include update-via-apex if enabled
        if (object.updatableViaApex) {
            appendAttr(root, "updatable-via-apex", object.updatableViaApex);
        }
        appendTextElement(root, "name", object.name, param.d);
        if (object.format == HalFormat::AIDL) {
            // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
            // is specified. Don't output any <version> tag if there's only one <version>0</version>
            // tag.
            if (object.versionRanges.size() != 1 ||
                object.versionRanges[0] != details::kDefaultAidlVersionRange) {
                appendChildren(root, AidlVersionRangeConverter{}, object.versionRanges, param);
            }
        } else {
            appendChildren(root, VersionRangeConverter{}, object.versionRanges, param);
        }
        appendChildren(root, HalInterfaceConverter{}, iterateValues(object.interfaces), param);
    }
    bool buildObject(MatrixHal* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        std::vector<HalInterface> interfaces;
        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param) ||
            !parseOptionalAttr(root, "exclusive-to", ExclusiveTo::EMPTY, &object->exclusiveTo,
                               param) ||
            !parseOptionalAttr(root, "updatable-via-apex", false /* defaultValue */,
                               &object->updatableViaApex, param) ||
            !parseTextElement(root, "name", &object->name, param.error) ||
            !parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
            return false;
        }
        if (object->format == HalFormat::AIDL) {
            if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, param)) {
                return false;
            }
            // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
            // HAL formats can be unified.
            if (object->versionRanges.empty()) {
                object->versionRanges.push_back(details::kDefaultAidlVersionRange);
            }
        } else {
            if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, param)) {
                return false;
            }
        }
        for (auto&& interface : interfaces) {
            std::string name{interface.name()};
            auto res = object->interfaces.emplace(std::move(name), std::move(interface));
            if (!res.second) {
                *param.error = "Duplicated interface entry \"" + res.first->first +
                               "\"; if additional instances are needed, add them to the "
                               "existing <interface> node.";
                return false;
            }
        }
        if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
            return false;
        }

        if (!object->isValid(param.error)) {
            param.error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: ");
            return false;
        }
        return true;
    }

   private:
    bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
        // Do not check for target-side libvintf to avoid restricting ability for upgrade
        // accidentally.
        if constexpr (kDevice) {
            return true;
        }
        if (hal.getName() == "netutils-wrapper") {
            if (hal.versionRanges.size() != 1) {
                *error =
                    "netutils-wrapper HAL must specify exactly one version x.0, "
                    "but multiple <version> element is specified.";
                return false;
            }
            const VersionRange& v = hal.versionRanges.at(0);
            if (!v.isSingleVersion()) {
                *error =
                    "netutils-wrapper HAL must specify exactly one version x.0, "
                    "but a range is provided. Perhaps you mean '" +
                    to_string(Version{v.majorVer, 0}) + "'?";
                return false;
            }
            if (v.minMinor != 0) {
                *error =
                    "netutils-wrapper HAL must specify exactly one version x.0, "
                    "but minor version is not 0. Perhaps you mean '" +
                    to_string(Version{v.majorVer, 0}) + "'?";
                return false;
            }
        }
        return true;
    }
};

struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
    std::string elementName() const override { return "conditions"; }
    void mutateNode(const std::vector<KernelConfig>& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChildren(root, MatrixKernelConfigConverter{}, object, param);
    }
    bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseChildren(root, MatrixKernelConfigConverter{}, object, param);
    }
};

struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
    std::string elementName() const override { return "kernel"; }
    void mutateNode(const MatrixKernel& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        KernelVersion kv = object.mMinLts;
        if (!param.flags.isKernelMinorRevisionEnabled()) {
            kv.minorRev = 0u;
        }
        appendAttr(root, "version", kv);

        if (object.getSourceMatrixLevel() != Level::UNSPECIFIED) {
            appendAttr(root, "level", object.getSourceMatrixLevel());
        }

        if (!object.mConditions.empty()) {
            appendChild(root, MatrixKernelConditionsConverter{}(object.mConditions, param));
        }
        if (param.flags.isKernelConfigsEnabled()) {
            appendChildren(root, MatrixKernelConfigConverter{}, object.mConfigs, param);
        }
    }
    bool buildObject(MatrixKernel* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        Level sourceMatrixLevel = Level::UNSPECIFIED;
        if (!parseAttr(root, "version", &object->mMinLts, param.error) ||
            !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, param) ||
            !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions,
                                param) ||
            !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, param)) {
            return false;
        }
        object->setSourceMatrixLevel(sourceMatrixLevel);
        return true;
    }
};

struct FqInstanceConverter : public XmlTextConverter<FqInstance> {
    std::string elementName() const override { return "fqname"; }
};

// Convert ManifestHal from and to XML. Returned object is guaranteed to have
// .isValid() == true.
struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
    std::string elementName() const override { return "hal"; }
    void mutateNode(const ManifestHal& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendAttr(root, "format", object.format);
        // Only include if it is not the default empty value
        if (object.exclusiveTo != ExclusiveTo::EMPTY) {
            appendAttr(root, "exclusive-to", object.exclusiveTo);
        }
        appendTextElement(root, "name", object.name, param.d);
        if (!object.transportArch.empty()) {
            appendChild(root, TransportArchConverter{}(object.transportArch, param));
        }
        if (object.format == HalFormat::AIDL) {
            // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
            // is specified. Don't output any <version> tag if there's only one <version>0</version>
            // tag.
            if (object.versions.size() != 1 || object.versions[0] != details::kDefaultAidlVersion) {
                appendChildren(root, AidlVersionConverter{}, object.versions, param);
            }
        } else {
            appendChildren(root, VersionConverter{}, object.versions, param);
        }
        if (object.isOverride()) {
            appendAttr(root, "override", object.isOverride());
        }
        if (const auto& apex = object.updatableViaApex(); apex.has_value()) {
            appendAttr(root, "updatable-via-apex", apex.value());
        }
        // Only include update-via-system if enabled
        if (object.updatableViaSystem()) {
            appendAttr(root, "updatable-via-system", object.updatableViaSystem());
        }
        if (const auto& accessor = object.accessor(); accessor.has_value()) {
            appendTextElement(root, "accessor", accessor.value(), param.d);
        }
        if (param.flags.isFqnameEnabled()) {
            std::set<std::string> simpleFqInstances;
            object.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
                simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
                return true;
            });
            appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances,
                               param.d);
        }
        if (object.getMaxLevel() != Level::UNSPECIFIED) {
            appendAttr(root, "max-level", object.getMaxLevel());
        }
        if (object.getMinLevel() != Level::UNSPECIFIED) {
            appendAttr(root, "min-level", object.getMinLevel());
        }
    }
    bool buildObject(ManifestHal* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        std::vector<HalInterface> interfaces;
        if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param) ||
            !parseOptionalAttr(root, "override", false, &object->mIsOverride, param) ||
            !parseOptionalAttr(root, "exclusive-to", ExclusiveTo::EMPTY, &object->exclusiveTo,
                               param) ||
            !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex, param) ||
            !parseOptionalAttr(root, "updatable-via-system", false /* defaultValue */,
                               &object->mUpdatableViaSystem, param) ||
            !parseOptionalTextElement(root, "accessor", {}, &object->mAccessor, param.error) ||
            !parseTextElement(root, "name", &object->name, param.error) ||
            !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch,
                                param) ||
            !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel, param) ||
            !parseOptionalAttr(root, "min-level", Level::UNSPECIFIED, &object->mMinLevel, param)) {
            return false;
        }
        if (getChildren(root, "accessor").size() > 1) {
            *param.error = "No more than one <accessor> is allowed in <hal>";
            return false;
        }

        std::string_view apexName = parseApexName(param.fileName);
        if (!apexName.empty()) {
            if (object->mUpdatableViaApex.has_value()) {
                // When defined in APEX, updatable-via-apex can be either
                // - ""(empty)  : the HAL isn't updatable even if it's in APEX
                // - {apex name}: the HAL is updtable via the current APEX
                const std::string& updatableViaApex = object->mUpdatableViaApex.value();
                if (!updatableViaApex.empty() && apexName.compare(updatableViaApex) != 0) {
                    *param.error = "Invalid APEX HAL " + object->name + ": updatable-via-apex " +
                                   updatableViaApex + " doesn't match with the defining APEX " +
                                   std::string(apexName) + "\n";
                    return false;
                }
            } else {
                // Set updatable-via-apex to the defining APEX when it's not set explicitly.
                // This should be set before calling insertInstances() which copies the current
                // value to ManifestInstance.
                object->mUpdatableViaApex = apexName;
            }
        }

        switch (object->format) {
            case HalFormat::HIDL: {
                if (!parseChildren(root, VersionConverter{}, &object->versions, param))
                    return false;
                if (object->transportArch.empty()) {
                    *param.error =
                        "HIDL HAL '" + object->name + "' should have <transport> defined.";
                    return false;
                }
                if (object->transportArch.transport == Transport::INET ||
                    object->transportArch.ip.has_value() ||
                    object->transportArch.port.has_value()) {
                    *param.error = "HIDL HAL '" + object->name +
                                   "' should not have <transport> \"inet\" " +
                                   "or ip or port attributes defined.";
                    return false;
                }
            } break;
            case HalFormat::NATIVE: {
                if (!parseChildren(root, VersionConverter{}, &object->versions, param))
                    return false;
                if (!object->transportArch.empty()) {
                    *param.error =
                        "Native HAL '" + object->name + "' should not have <transport> defined.";
                    return false;
                }
            } break;
            case HalFormat::AIDL: {
                if (!object->transportArch.empty() &&
                    object->transportArch.transport != Transport::INET) {
                    if (param.metaVersion >= kMetaVersionAidlInet) {
                        *param.error = "AIDL HAL '" + object->name +
                                       R"(' only supports "inet" or empty <transport>, found ")" +
                                       to_string(object->transportArch) + "\"";
                        return false;
                    }
                    LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
                                 << object->name << ". Only \"inet\" supported.";
                    object->transportArch = {};
                }
                if (!parseChildren(root, AidlVersionConverter{}, &object->versions, param)) {
                    return false;
                }
                // Insert fake version for AIDL HALs so that forEachInstance works.
                if (object->versions.empty()) {
                    object->versions.push_back(details::kDefaultAidlVersion);
                }
            } break;
            default: {
                LOG(FATAL) << "Unhandled HalFormat "
                           << static_cast<typename std::underlying_type<HalFormat>::type>(
                                  object->format);
            } break;
        }
        if (!object->transportArch.isValid(param.error)) return false;

        // Parse <fqname> into fqInstances list
        std::set<FqInstance> fqInstances;
        if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, param)) {
            return false;
        }

        // Handle deprecated <interface> x <instance>
        if (!parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
            return false;
        }
        // Check duplicated <interface><name>
        std::set<std::string> interface_names;
        for (auto &&interface : interfaces) {
            auto res = interface_names.emplace(interface.name());
            if (!res.second) {
                *param.error = "Duplicated interface entry \"" + *res.first +
                               "\"; if additional instances are needed, add them to the "
                               "existing <interface> node.";
                return false;
            }
        }
        // Turn <version> x <interface> x <instance> into <fqname>s; insert into
        // fqInstances list.
        bool convertedInstancesIntoFqnames = false;
        for (const auto& v : object->versions) {
            for (const auto& intf : interfaces) {
                if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance &&
                    (object->format == HalFormat::HIDL || object->format == HalFormat::AIDL) &&
                    !intf.hasAnyInstance()) {
                    *param.error +=
                        "<hal> " + object->name + " <interface> " + intf.name() +
                        " has no <instance>. Either specify <instance> or, "
                        "preferably, specify <fqname> and delete <version> and <interface>.";
                    return false;
                }
                bool cont = intf.forEachInstance(
                    [&v, &fqInstances, &convertedInstancesIntoFqnames, &object, &param](
                        const auto& interface, const auto& instance, bool /* isRegex */) {
                        auto fqInstance = details::convertLegacyInstanceIntoFqInstance(
                            object->name, v, interface, instance, object->format, param.error);

                        if (!fqInstance.has_value()) {
                            return false;
                        }

                        // Check for duplication in fqInstances.
                        // Before kMetaVersionNoHalInterfaceInstance: It is okay to have duplication
                        // between <interface> and <fqname>.
                        // After kMetaVersionNoHalInterfaceInstance: Duplication between
                        // <interface> and <fqname> is not allowed.
                        auto&& [it, inserted] = fqInstances.emplace(std::move(fqInstance.value()));
                        if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance && !inserted) {
                            std::string debugString =
                                object->format == HalFormat::AIDL
                                    ? toAidlFqnameString(object->name, interface, instance)
                                    : toFQNameString(object->name, v, interface, instance);
                            *param.error = "Duplicated " + debugString +
                                           " in <interface><instance> and <fqname>. ";
                            if constexpr (kDevice) {
                                *param.error +=
                                    "(Did you copy source manifests to the device directly "
                                    "without going through assemble_vintf, e.g. not using "
                                    "DEVICE_MANIFEST_FILE or ODM_MANIFEST_FILES?)";
                            } else {
                                *param.error += "Remove deprecated <interface>.";
                            }
                            return false;
                        }

                        convertedInstancesIntoFqnames = true;
                        return true;  // continue
                    });
                if (!cont) {
                    return false;
                }
            }
        }

        if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
            return false;
        }

        // For HIDL, if any <version> x <interface> x <instance> tuple, all <version>
        // tags can be cleared. <version> information is already in <fqname>'s.
        // For AIDL, <version> information is not in <fqname>, so don't clear them.
        // For HALs with only <version> but no <interface>
        // (e.g. native HALs like netutils-wrapper), <version> is kept.
        if (convertedInstancesIntoFqnames && object->format != HalFormat::AIDL) {
            object->versions.clear();
        }

        std::set<FqInstance> fqInstancesToInsert;
        for (auto& e : fqInstances) {
            if (e.hasPackage()) {
                *param.error = "Should not specify package: \"" + e.string() + "\"";
                return false;
            }
            if (object->format == HalFormat::AIDL) {
                // <fqname> in AIDL HALs should not contain version.
                if (e.hasVersion()) {
                    *param.error = "Should not specify version in <fqname> for AIDL HAL: \"" +
                                   e.string() + "\"";
                    return false;
                }
                // Put in the fake kDefaultAidlVersion so that HalManifest can
                // store it in an FqInstance object with a non-empty package.
                FqInstance withFakeVersion;
                if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer,
                                           details::kDefaultAidlVersion.minorVer, e.getInterface(),
                                           e.getInstance())) {
                    return false;
                }
                fqInstancesToInsert.emplace(std::move(withFakeVersion));
            } else {
                fqInstancesToInsert.emplace(std::move(e));
            }
        }

        if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance &&
            (object->format == HalFormat::HIDL || object->format == HalFormat::AIDL) &&
            fqInstancesToInsert.empty() && !object->isOverride()) {
            *param.error = "<hal> " + object->name + " has no instance. Fix by adding <fqname>.";
            return false;
        }

        bool allowMajorVersionDup = param.metaVersion < kMetaVersionNoHalInterfaceInstance;
        if (!object->insertInstances(fqInstancesToInsert, allowMajorVersionDup, param.error)) {
            return false;
        }

        if (!object->isValid(param.error)) {
            param.error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
            return false;
        }

        return true;
    }

   private:
    bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
        // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
        if constexpr (kDevice) {
            return true;
        }
        if (hal.getName() == "netutils-wrapper") {
            for (const Version& v : hal.versions) {
                if (v.minorVer != 0) {
                    *error =
                        "netutils-wrapper HAL must specify exactly one version x.0, "
                        "but minor version is not 0. Perhaps you mean '" +
                        to_string(Version{v.majorVer, 0}) + "'?";
                    return false;
                }
            }
        }
        return true;
    }
};

struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> {
    std::string elementName() const override { return "kernel-sepolicy-version"; }
};

struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
    std::string elementName() const override { return "sepolicy"; }
    void mutateNode(const Sepolicy& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), param));
        appendChildren(root, SepolicyVersionRangeConverter{}, object.sepolicyVersions(), param);
    }
    bool buildObject(Sepolicy* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion,
                        param) ||
            !parseChildren(root, SepolicyVersionRangeConverter{}, &object->mSepolicyVersionRanges,
                           param)) {
            return false;
        }
        return true;
    }
};

struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> {
    std::string elementName() const override { return "version"; }
};

struct VndkVersionConverter : public XmlTextConverter<std::string> {
    std::string elementName() const override { return "version"; }
};

struct VndkLibraryConverter : public XmlTextConverter<std::string> {
    std::string elementName() const override { return "library"; }
};

struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
    std::string elementName() const override { return "vndk"; }
    void mutateNode(const Vndk& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, param));
        appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
    }
    bool buildObject(Vndk* object, NodeType* root, const BuildObjectParam& param) const override {
        if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, param) ||
            !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
            return false;
        }
        return true;
    }
};

struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
    std::string elementName() const override { return "vendor-ndk"; }
    void mutateNode(const VendorNdk& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChild(root, VndkVersionConverter{}(object.mVersion, param));
        appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
    }
    bool buildObject(VendorNdk* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, param) ||
            !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
            return false;
        }
        return true;
    }
};

struct SystemSdkVersionConverter : public XmlTextConverter<std::string> {
    std::string elementName() const override { return "version"; }
};

struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
    std::string elementName() const override { return "system-sdk"; }
    void mutateNode(const SystemSdk& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChildren(root, SystemSdkVersionConverter{}, object.versions(), param);
    }
    bool buildObject(SystemSdk* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, param);
    }
};

struct HalManifestSepolicyConverter : public XmlNodeConverter<SepolicyVersion> {
    std::string elementName() const override { return "sepolicy"; }
    void mutateNode(const SepolicyVersion& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChild(root, SepolicyVersionConverter{}(object, param));
    }
    bool buildObject(SepolicyVersion* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseChild(root, SepolicyVersionConverter{}, object, param);
    }
};

struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
    std::string elementName() const override { return "xmlfile"; }
    void mutateNode(const ManifestXmlFile& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendTextElement(root, "name", object.name(), param.d);
        appendChild(root, VersionConverter{}(object.version(), param));
        if (!object.overriddenPath().empty()) {
            appendTextElement(root, "path", object.overriddenPath(), param.d);
        }
    }
    bool buildObject(ManifestXmlFile* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        if (!parseTextElement(root, "name", &object->mName, param.error) ||
            !parseChild(root, VersionConverter{}, &object->mVersion, param) ||
            !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
            return false;
        }
        return true;
    }
};

struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> {
    std::string elementName() const override { return "key"; }
};

struct KernelConfigValueConverter : public XmlTextConverter<std::string> {
    std::string elementName() const override { return "value"; }
};

struct StringKernelConfigConverter
    : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter,
                              KernelConfigValueConverter> {
    std::string elementName() const override { return "config"; }
};

struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
    std::string elementName() const override { return "kernel"; }
    void mutateNode(const KernelInfo& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        if (object.version() != KernelVersion{}) {
            appendAttr(root, "version", object.version());
        }
        if (object.level() != Level::UNSPECIFIED) {
            appendAttr(root, "target-level", object.level());
        }
        if (param.flags.isKernelConfigsEnabled()) {
            appendChildren(root, StringKernelConfigConverter{}, object.configs(), param);
        }
    }
    bool buildObject(KernelInfo* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseOptionalAttr(root, "version", {}, &object->mVersion, param) &&
               parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
                                 param) &&
               parseChildren(root, StringKernelConfigConverter{}, &object->mConfigs, param);
    }
};

struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
    std::string elementName() const override { return "manifest"; }
    void mutateNode(const HalManifest& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        if (param.flags.isMetaVersionEnabled()) {
            // Append the current metaversion of libvintf because the XML file
            // is generated with libvintf @ current meta version.
            appendAttr(root, "version", kMetaVersion);
        }
        if (param.flags.isSchemaTypeEnabled()) {
            appendAttr(root, "type", object.mType);
        }

        if (param.flags.isHalsEnabled()) {
            appendChildren(root, ManifestHalConverter{}, object.getHals(), param);
        }
        if (object.mType == SchemaType::DEVICE) {
            if (param.flags.isSepolicyEnabled()) {
                if (object.device.mSepolicyVersion != SepolicyVersion{}) {
                    appendChild(root, HalManifestSepolicyConverter{}(object.device.mSepolicyVersion,
                                                                     param));
                }
            }
            if (object.mLevel != Level::UNSPECIFIED) {
                this->appendAttr(root, "target-level", object.mLevel);
            }

            if (param.flags.isKernelEnabled()) {
                if (!!object.kernel()) {
                    appendChild(root, KernelInfoConverter{}(*object.kernel(), param));
                }
            }
        } else if (object.mType == SchemaType::FRAMEWORK) {
            if (param.flags.isVndkEnabled()) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
                appendChildren(root, VndkConverter{}, object.framework.mVndks, param);
#pragma clang diagnostic pop

                appendChildren(root, VendorNdkConverter{}, object.framework.mVendorNdks, param);
            }
            if (param.flags.isSsdkEnabled()) {
                if (!object.framework.mSystemSdk.empty()) {
                    appendChild(root, SystemSdkConverter{}(object.framework.mSystemSdk, param));
                }
            }
        }

        if (param.flags.isXmlFilesEnabled()) {
            appendChildren(root, ManifestXmlFileConverter{}, object.getXmlFiles(), param);
        }
    }
    bool buildObject(HalManifest* object, NodeType* root,
                     const BuildObjectParam& constParam) const override {
        BuildObjectParam param = constParam;
        if (!parseAttr(root, "version", &param.metaVersion, param.error)) return false;
        if (param.metaVersion > kMetaVersion) {
            *param.error = "Unrecognized manifest.version " + to_string(param.metaVersion) +
                           " (libvintf@" + to_string(kMetaVersion) + ")";
            return false;
        }
        object->mSourceMetaVersion = param.metaVersion;

        if (!parseAttr(root, "type", &object->mType, param.error)) {
            return false;
        }

        std::vector<ManifestHal> hals;
        if (!parseChildren(root, ManifestHalConverter{}, &hals, param)) {
            return false;
        }
        for (auto&& hal : hals) {
            hal.setFileName(object->fileName());
        }

        if (object->mType == SchemaType::DEVICE) {
            // tags for device hal manifest only.
            // <sepolicy> can be missing because it can be determined at build time, not hard-coded
            // in the XML file.
            if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {},
                                    &object->device.mSepolicyVersion, param)) {
                return false;
            }

            if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
                                   param)) {
                return false;
            }

            if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, param)) {
                return false;
            }
        } else if (object->mType == SchemaType::FRAMEWORK) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, param)) {
                return false;
            }
            for (const auto& vndk : object->framework.mVndks) {
                if (!vndk.mVersionRange.isSingleVersion()) {
                    *param.error = "vndk.version " + to_string(vndk.mVersionRange) +
                                   " cannot be a range for manifests";
                    return false;
                }
            }
#pragma clang diagnostic pop

            if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, param)) {
                return false;
            }

            std::set<std::string> vendorNdkVersions;
            for (const auto& vendorNdk : object->framework.mVendorNdks) {
                if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
                    *param.error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
                    return false;
                }
                vendorNdkVersions.insert(vendorNdk.version());
            }

            if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk,
                                    param)) {
                return false;
            }
        }
        for (auto &&hal : hals) {
            std::string description{hal.name};
            if (!object->add(std::move(hal), param.error)) {
                param.error->insert(0, "Duplicated manifest.hal entry " + description + ": ");
                return false;
            }
        }

        std::vector<ManifestXmlFile> xmlFiles;
        if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, param)) {
            return false;
        }
        for (auto&& xmlFile : xmlFiles) {
            std::string description{xmlFile.name()};
            if (!object->addXmlFile(std::move(xmlFile))) {
                *param.error = "Duplicated manifest.xmlfile entry " + description +
                               "; entries cannot have duplicated name and version";
                return false;
            }
        }

        return true;
    }
};

struct AvbVersionConverter : public XmlTextConverter<Version> {
    std::string elementName() const override { return "vbmeta-version"; }
};

struct AvbConverter : public XmlNodeConverter<Version> {
    std::string elementName() const override { return "avb"; }
    void mutateNode(const Version& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendChild(root, AvbVersionConverter{}(object, param));
    }
    bool buildObject(Version* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        return parseChild(root, AvbVersionConverter{}, object, param);
    }
};

struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
    std::string elementName() const override { return "xmlfile"; }
    void mutateNode(const MatrixXmlFile& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        appendTextElement(root, "name", object.name(), param.d);
        appendAttr(root, "format", object.format());
        appendChild(root, VersionRangeConverter{}(object.versionRange(), param));
        if (!object.overriddenPath().empty()) {
            appendTextElement(root, "path", object.overriddenPath(), param.d);
        }
    }
    bool buildObject(MatrixXmlFile* object, NodeType* root,
                     const BuildObjectParam& param) const override {
        if (!parseTextElement(root, "name", &object->mName, param.error) ||
            !parseAttr(root, "format", &object->mFormat, param.error) ||
            !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, param) ||
            !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
            return false;
        }
        return true;
    }
};

struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
    std::string elementName() const override { return "compatibility-matrix"; }
    void mutateNode(const CompatibilityMatrix& object, NodeType* root,
                    const MutateNodeParam& param) const override {
        if (param.flags.isMetaVersionEnabled()) {
            appendAttr(root, "version", kMetaVersion);
        }
        if (param.flags.isSchemaTypeEnabled()) {
            appendAttr(root, "type", object.mType);
        }

        if (param.flags.isHalsEnabled()) {
            appendChildren(root, MatrixHalConverter{}, iterateValues(object.mHals), param);
        }
        if (object.mType == SchemaType::FRAMEWORK) {
            if (param.flags.isKernelEnabled()) {
                appendChildren(root, MatrixKernelConverter{}, object.framework.mKernels, param);
            }
            if (param.flags.isSepolicyEnabled()) {
                if (!(object.framework.mSepolicy == Sepolicy{})) {
                    appendChild(root, SepolicyConverter{}(object.framework.mSepolicy, param));
                }
            }
            if (param.flags.isAvbEnabled()) {
                if (!(object.framework.mAvbMetaVersion == Version{})) {
                    appendChild(root, AvbConverter{}(object.framework.mAvbMetaVersion, param));
                }
            }
            if (object.mLevel != Level::UNSPECIFIED) {
                this->appendAttr(root, "level", object.mLevel);
            }
        } else if (object.mType == SchemaType::DEVICE) {
            if (param.flags.isVndkEnabled()) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
                if (!(object.device.mVndk == Vndk{})) {
                    appendChild(root, VndkConverter{}(object.device.mVndk, param));
                }
#pragma clang diagnostic pop

                if (!(object.device.mVendorNdk == VendorNdk{})) {
                    appendChild(root, VendorNdkConverter{}(object.device.mVendorNdk, param));
                }
            }

            if (param.flags.isSsdkEnabled()) {
                if (!object.device.mSystemSdk.empty()) {
                    appendChild(root, SystemSdkConverter{}(object.device.mSystemSdk, param));
                }
            }
        }

        if (param.flags.isXmlFilesEnabled()) {
            appendChildren(root, MatrixXmlFileConverter{}, object.getXmlFiles(), param);
        }
    }
    bool buildObject(CompatibilityMatrix* object, NodeType* root,
                     const BuildObjectParam& constParam) const override {
        BuildObjectParam param = constParam;
        if (!parseAttr(root, "version", &param.metaVersion, param.error)) return false;
        if (param.metaVersion > kMetaVersion) {
            *param.error = "Unrecognized compatibility-matrix.version " +
                           to_string(param.metaVersion) + " (libvintf@" + to_string(kMetaVersion) +
                           ")";
            return false;
        }

        std::vector<MatrixHal> hals;
        if (!parseAttr(root, "type", &object->mType, param.error) ||
            !parseChildren(root, MatrixHalConverter{}, &hals, param)) {
            return false;
        }

        if (object->mType == SchemaType::FRAMEWORK) {
            // <avb> and <sepolicy> can be missing because it can be determined at build time, not
            // hard-coded in the XML file.
            if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, param) ||
                !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy,
                                    param) ||
                !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion,
                                    param)) {
                return false;
            }

            std::set<Version> seenKernelVersions;
            for (const auto& kernel : object->framework.mKernels) {
                Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
                if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
                    continue;
                }
                if (!kernel.conditions().empty()) {
                    *param.error = "First <kernel> for version " + to_string(minLts) +
                                   " must have empty <conditions> for backwards compatibility.";
                    return false;
                }
                seenKernelVersions.insert(minLts);
            }

            if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, param)) {
                return false;
            }

        } else if (object->mType == SchemaType::DEVICE) {
            // <vndk> can be missing because it can be determined at build time, not hard-coded
            // in the XML file.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, param)) {
                return false;
            }
#pragma clang diagnostic pop

            if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk,
                                    param)) {
                return false;
            }

            if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk,
                                    param)) {
                return false;
            }
        }

        for (auto &&hal : hals) {
            if (!object->add(std::move(hal))) {
                *param.error = "Duplicated compatibility-matrix.hal entry";
                return false;
            }
        }

        std::vector<MatrixXmlFile> xmlFiles;
        if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, param)) {
            return false;
        }
        for (auto&& xmlFile : xmlFiles) {
            std::string description{xmlFile.name()};
            if (!object->addXmlFile(std::move(xmlFile))) {
                *param.error = "Duplicated compatibility-matrix.xmlfile entry " + description;
                return false;
            }
        }

        return true;
    }
};

#define CREATE_CONVERT_FN(type)                                         \
    std::string toXml(const type& o, SerializeFlags::Type flags) {      \
        return type##Converter{}.toXml(o, flags);                       \
    }                                                                   \
    bool fromXml(type* o, const std::string& xml, std::string* error) { \
        return type##Converter{}.fromXml(o, xml, error);                \
    }

// Create convert functions for public usage.
CREATE_CONVERT_FN(HalManifest)
CREATE_CONVERT_FN(CompatibilityMatrix)

// Create convert functions for internal usage.
CREATE_CONVERT_FN(KernelInfo)

// Create convert functions for testing.
CREATE_CONVERT_FN(Version)
CREATE_CONVERT_FN(SepolicyVersion)
CREATE_CONVERT_FN(KernelConfigTypedValue)
CREATE_CONVERT_FN(MatrixHal)
CREATE_CONVERT_FN(ManifestHal)

#undef CREATE_CONVERT_FN

} // namespace vintf
} // namespace android
