Home | History | Annotate | Download | only in libvintf
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // Convert objects from and to xml.
     18 
     19 #define LOG_TAG "libvintf"
     20 #include <android-base/logging.h>
     21 
     22 #include "parse_xml.h"
     23 
     24 #include <type_traits>
     25 
     26 #include <tinyxml2.h>
     27 
     28 #include "Regex.h"
     29 #include "constants.h"
     30 #include "parse_string.h"
     31 
     32 namespace android {
     33 namespace vintf {
     34 
     35 // --------------- tinyxml2 details
     36 
     37 using NodeType = tinyxml2::XMLElement;
     38 using DocType = tinyxml2::XMLDocument;
     39 
     40 // caller is responsible for deleteDocument() call
     41 inline DocType *createDocument() {
     42     return new tinyxml2::XMLDocument();
     43 }
     44 
     45 // caller is responsible for deleteDocument() call
     46 inline DocType *createDocument(const std::string &xml) {
     47     DocType *doc = new tinyxml2::XMLDocument();
     48     if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
     49         return doc;
     50     }
     51     delete doc;
     52     return nullptr;
     53 }
     54 
     55 inline void deleteDocument(DocType *d) {
     56     delete d;
     57 }
     58 
     59 inline std::string printDocument(DocType *d) {
     60     tinyxml2::XMLPrinter p;
     61     d->Print(&p);
     62     return std::string{p.CStr()};
     63 }
     64 
     65 inline NodeType *createNode(const std::string &name, DocType *d) {
     66     return d->NewElement(name.c_str());
     67 }
     68 
     69 inline void appendChild(NodeType *parent, NodeType *child) {
     70     parent->InsertEndChild(child);
     71 }
     72 
     73 inline void appendChild(DocType *parent, NodeType *child) {
     74     parent->InsertEndChild(child);
     75 }
     76 
     77 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
     78     e->SetAttribute(attrName.c_str(), attr.c_str());
     79 }
     80 
     81 // text -> text
     82 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
     83     parent->InsertEndChild(d->NewText(text.c_str()));
     84 }
     85 
     86 inline std::string nameOf(NodeType *root) {
     87     return root->Name() == NULL ? "" : root->Name();
     88 }
     89 
     90 inline std::string getText(NodeType *root) {
     91     return root->GetText() == NULL ? "" : root->GetText();
     92 }
     93 
     94 inline NodeType *getChild(NodeType *parent, const std::string &name) {
     95     return parent->FirstChildElement(name.c_str());
     96 }
     97 
     98 inline NodeType *getRootChild(DocType *parent) {
     99     return parent->FirstChildElement();
    100 }
    101 
    102 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
    103     std::vector<NodeType *> v;
    104     for (NodeType *child = parent->FirstChildElement(name.c_str());
    105          child != nullptr;
    106          child = child->NextSiblingElement(name.c_str())) {
    107         v.push_back(child);
    108     }
    109     return v;
    110 }
    111 
    112 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
    113     const char *c = root->Attribute(attrName.c_str());
    114     if (c == NULL)
    115         return false;
    116     *s = c;
    117     return true;
    118 }
    119 
    120 // --------------- tinyxml2 details end.
    121 
    122 // Helper functions for XmlConverter
    123 static bool parse(const std::string &attrText, bool *attr) {
    124     if (attrText == "true" || attrText == "1") {
    125         *attr = true;
    126         return true;
    127     }
    128     if (attrText == "false" || attrText == "0") {
    129         *attr = false;
    130         return true;
    131     }
    132     return false;
    133 }
    134 
    135 // ---------------------- XmlNodeConverter definitions
    136 
    137 template<typename Object>
    138 struct XmlNodeConverter : public XmlConverter<Object> {
    139     XmlNodeConverter() {}
    140     virtual ~XmlNodeConverter() {}
    141 
    142     // sub-types should implement these.
    143     virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
    144     virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const {
    145         mutateNode(o, n, d);
    146     }
    147     virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
    148     virtual std::string elementName() const = 0;
    149 
    150     // convenience methods for user
    151     inline const std::string& lastError() const override { return mLastError; }
    152     inline NodeType* serialize(const Object& o, DocType* d,
    153                                SerializeFlags flags = EVERYTHING) const {
    154         NodeType *root = createNode(this->elementName(), d);
    155         this->mutateNode(o, root, d, flags);
    156         return root;
    157     }
    158     inline std::string serialize(const Object& o, SerializeFlags flags) const override {
    159         DocType *doc = createDocument();
    160         appendChild(doc, serialize(o, doc, flags));
    161         std::string s = printDocument(doc);
    162         deleteDocument(doc);
    163         return s;
    164     }
    165     inline bool deserialize(Object* object, NodeType* root) {
    166         bool ret = deserialize(object, root, &mLastError);
    167         return ret;
    168     }
    169     inline bool deserialize(Object* o, const std::string& xml) override {
    170         bool ret = (*this)(o, xml, &mLastError);
    171         return ret;
    172     }
    173     inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
    174         if (nameOf(root) != this->elementName()) {
    175             return false;
    176         }
    177         return this->buildObject(object, root, error);
    178     }
    179     inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
    180         std::string errorBuffer;
    181         if (error == nullptr) error = &errorBuffer;
    182 
    183         auto doc = createDocument(xml);
    184         if (doc == nullptr) {
    185             *error = "Not a valid XML";
    186             return false;
    187         }
    188         bool ret = deserialize(o, getRootChild(doc), error);
    189         deleteDocument(doc);
    190         return ret;
    191     }
    192     inline NodeType *operator()(const Object &o, DocType *d) const {
    193         return serialize(o, d);
    194     }
    195     inline std::string operator()(const Object& o, SerializeFlags flags) const override {
    196         return serialize(o, flags);
    197     }
    198     inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
    199     inline bool operator()(Object* o, const std::string& xml) override {
    200         return deserialize(o, xml);
    201     }
    202 
    203     // convenience methods for implementor.
    204 
    205     // All append* functions helps mutateNode() to serialize the object into XML.
    206     template <typename T>
    207     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
    208         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
    209     }
    210 
    211     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
    212         return appendStrAttr(e, attrName, attr ? "true" : "false");
    213     }
    214 
    215     // text -> <name>text</name>
    216     inline void appendTextElement(NodeType *parent, const std::string &name,
    217                 const std::string &text, DocType *d) const {
    218         NodeType *c = createNode(name, d);
    219         appendText(c, text, d);
    220         appendChild(parent, c);
    221     }
    222 
    223     // text -> <name>text</name>
    224     template<typename Array>
    225     inline void appendTextElements(NodeType *parent, const std::string &name,
    226                 const Array &array, DocType *d) const {
    227         for (const std::string &text : array) {
    228             NodeType *c = createNode(name, d);
    229             appendText(c, text, d);
    230             appendChild(parent, c);
    231         }
    232     }
    233 
    234     template <typename T, typename Array>
    235     inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
    236                                const Array& array, DocType* d,
    237                                SerializeFlags flags = SerializeFlag::EVERYTHING) const {
    238         for (const T &t : array) {
    239             appendChild(parent, conv.serialize(t, d, flags));
    240         }
    241     }
    242 
    243     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
    244     // true if deserialization is successful, false if any error, and "error" will be
    245     // set to error message.
    246     template <typename T>
    247     inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
    248                                   T* attr, std::string* /* error */) const {
    249         std::string attrText;
    250         bool success = getAttr(root, attrName, &attrText) &&
    251                        ::android::vintf::parse(attrText, attr);
    252         if (!success) {
    253             *attr = std::move(defaultValue);
    254         }
    255         return true;
    256     }
    257 
    258     template <typename T>
    259     inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
    260                           std::string* error) const {
    261         std::string attrText;
    262         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
    263         if (!ret) {
    264             *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
    265                      attrText + "\" for element <" + elementName() + ">";
    266         }
    267         return ret;
    268     }
    269 
    270     inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
    271                           std::string* error) const {
    272         bool ret = getAttr(root, attrName, attr);
    273         if (!ret) {
    274             *error = "Could not find attr with name \"" + attrName + "\" for element <" +
    275                      elementName() + ">";
    276         }
    277         return ret;
    278     }
    279 
    280     inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
    281                                  std::string* error) const {
    282         NodeType *child = getChild(root, elementName);
    283         if (child == nullptr) {
    284             *error = "Could not find element with name <" + elementName + "> in element <" +
    285                      this->elementName() + ">";
    286             return false;
    287         }
    288         *s = getText(child);
    289         return true;
    290     }
    291 
    292     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
    293                                          std::string&& defaultValue, std::string* s,
    294                                          std::string* /* error */) const {
    295         NodeType* child = getChild(root, elementName);
    296         *s = child == nullptr ? std::move(defaultValue) : getText(child);
    297         return true;
    298     }
    299 
    300     inline bool parseTextElements(NodeType* root, const std::string& elementName,
    301                                   std::vector<std::string>* v, std::string* /* error */) const {
    302         auto nodes = getChildren(root, elementName);
    303         v->resize(nodes.size());
    304         for (size_t i = 0; i < nodes.size(); ++i) {
    305             v->at(i) = getText(nodes[i]);
    306         }
    307         return true;
    308     }
    309 
    310     template <typename T>
    311     inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
    312                            std::string* error) const {
    313         NodeType *child = getChild(root, conv.elementName());
    314         if (child == nullptr) {
    315             *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
    316                      this->elementName() + ">";
    317             return false;
    318         }
    319         return conv.deserialize(t, child, error);
    320     }
    321 
    322     template <typename T>
    323     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
    324                                    T&& defaultValue, T* t, std::string* error) const {
    325         NodeType *child = getChild(root, conv.elementName());
    326         if (child == nullptr) {
    327             *t = std::move(defaultValue);
    328             return true;
    329         }
    330         return conv.deserialize(t, child, error);
    331     }
    332 
    333     template <typename T>
    334     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
    335                               std::string* error) const {
    336         auto nodes = getChildren(root, conv.elementName());
    337         v->resize(nodes.size());
    338         for (size_t i = 0; i < nodes.size(); ++i) {
    339             if (!conv.deserialize(&v->at(i), nodes[i], error)) {
    340                 *error = "Could not parse element with name <" + conv.elementName() +
    341                          "> in element <" + this->elementName() + ">: " + *error;
    342                 return false;
    343             }
    344         }
    345         return true;
    346     }
    347 
    348     template <typename T>
    349     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::set<T>* s,
    350                               std::string* error) const {
    351         std::vector<T> vec;
    352         if (!parseChildren(root, conv, &vec, error)) {
    353             return false;
    354         }
    355         s->clear();
    356         s->insert(vec.begin(), vec.end());
    357         if (s->size() != vec.size()) {
    358             *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
    359                      this->elementName() + ">";
    360             s->clear();
    361             return false;
    362         }
    363         return true;
    364     }
    365 
    366     inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
    367         *s = getText(node);
    368         return true;
    369     }
    370 
    371     template <typename T>
    372     inline bool parseText(NodeType* node, T* s, std::string* error) const {
    373         std::string text = getText(node);
    374         bool ret = ::android::vintf::parse(text, s);
    375         if (!ret) {
    376             *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
    377         }
    378         return ret;
    379     }
    380 
    381    private:
    382     mutable std::string mLastError;
    383 };
    384 
    385 template<typename Object>
    386 struct XmlTextConverter : public XmlNodeConverter<Object> {
    387     XmlTextConverter(const std::string &elementName)
    388         : mElementName(elementName) {}
    389 
    390     virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
    391         appendText(root, ::android::vintf::to_string(object), d);
    392     }
    393     virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
    394         return this->parseText(root, object, error);
    395     }
    396     virtual std::string elementName() const { return mElementName; };
    397 private:
    398     std::string mElementName;
    399 };
    400 
    401 // ---------------------- XmlNodeConverter definitions end
    402 
    403 XmlTextConverter<Version> versionConverter{"version"};
    404 
    405 XmlTextConverter<VersionRange> versionRangeConverter{"version"};
    406 
    407 XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
    408 
    409 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
    410     std::string elementName() const override { return "transport"; }
    411     void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
    412         if (object.arch != Arch::ARCH_EMPTY) {
    413             appendAttr(root, "arch", object.arch);
    414         }
    415         appendText(root, ::android::vintf::to_string(object.transport), d);
    416     }
    417     bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
    418         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
    419             !parseText(root, &object->transport, error)) {
    420             return false;
    421         }
    422         if (!object->isValid()) {
    423             *error = "transport == " + ::android::vintf::to_string(object->transport) +
    424                      " and arch == " + ::android::vintf::to_string(object->arch) +
    425                      " is not a valid combination.";
    426             return false;
    427         }
    428         return true;
    429     }
    430 };
    431 
    432 TransportArchConverter transportArchConverter{};
    433 
    434 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
    435     std::string elementName() const override { return "value"; }
    436     void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
    437         appendAttr(root, "type", object.mType);
    438         appendText(root, ::android::vintf::to_string(object), d);
    439     }
    440     bool buildObject(KernelConfigTypedValue* object, NodeType* root,
    441                      std::string* error) const override {
    442         std::string stringValue;
    443         if (!parseAttr(root, "type", &object->mType, error) ||
    444             !parseText(root, &stringValue, error)) {
    445             return false;
    446         }
    447         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
    448             *error = "Could not parse kernel config value \"" + stringValue + "\"";
    449             return false;
    450         }
    451         return true;
    452     }
    453 };
    454 
    455 KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
    456 
    457 struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
    458     std::string elementName() const override { return "config"; }
    459     void mutateNode(const KernelConfig &object, NodeType *root, DocType *d) const override {
    460         appendChild(root, kernelConfigKeyConverter(object.first, d));
    461         appendChild(root, kernelConfigTypedValueConverter(object.second, d));
    462     }
    463     bool buildObject(KernelConfig* object, NodeType* root, std::string* error) const override {
    464         if (!parseChild(root, kernelConfigKeyConverter, &object->first, error) ||
    465             !parseChild(root, kernelConfigTypedValueConverter, &object->second, error)) {
    466             return false;
    467         }
    468         return true;
    469     }
    470 };
    471 
    472 KernelConfigConverter kernelConfigConverter{};
    473 
    474 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
    475     std::string elementName() const override { return "interface"; }
    476     void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
    477         appendTextElement(root, "name", intf.name(), d);
    478         appendTextElements(root, "instance", intf.mInstances, d);
    479         appendTextElements(root, "regex-instance", intf.mRegexes, d);
    480     }
    481     bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
    482         std::vector<std::string> instances;
    483         std::vector<std::string> regexes;
    484         if (!parseTextElement(root, "name", &intf->mName, error) ||
    485             !parseTextElements(root, "instance", &instances, error) ||
    486             !parseTextElements(root, "regex-instance", &regexes, error)) {
    487             return false;
    488         }
    489         bool success = true;
    490         for (const auto& e : instances) {
    491             if (!intf->insertInstance(e, false /* isRegex */)) {
    492                 if (!error->empty()) *error += "\n";
    493                 *error += "Duplicated instance '" + e + "' in " + intf->name();
    494                 success = false;
    495             }
    496         }
    497         for (const auto& e : regexes) {
    498             details::Regex regex;
    499             if (!regex.compile(e)) {
    500                 if (!error->empty()) *error += "\n";
    501                 *error += "Invalid regular expression '" + e + "' in " + intf->name();
    502                 success = false;
    503             }
    504             if (!intf->insertInstance(e, true /* isRegex */)) {
    505                 if (!error->empty()) *error += "\n";
    506                 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
    507                 success = false;
    508             }
    509         }
    510         return success;
    511     }
    512 };
    513 
    514 HalInterfaceConverter halInterfaceConverter{};
    515 
    516 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
    517     std::string elementName() const override { return "hal"; }
    518     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
    519         appendAttr(root, "format", hal.format);
    520         appendAttr(root, "optional", hal.optional);
    521         appendTextElement(root, "name", hal.name, d);
    522         appendChildren(root, versionRangeConverter, hal.versionRanges, d);
    523         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
    524     }
    525     bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
    526         std::vector<HalInterface> interfaces;
    527         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
    528             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
    529                                error) ||
    530             !parseTextElement(root, "name", &object->name, error) ||
    531             !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
    532             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
    533             return false;
    534         }
    535         for (auto&& interface : interfaces) {
    536             std::string name{interface.name()};
    537             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
    538             if (!res.second) {
    539                 *error = "Duplicated interface entry \"" + res.first->first +
    540                          "\"; if additional instances are needed, add them to the "
    541                          "existing <interface> node.";
    542                 return false;
    543             }
    544         }
    545 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
    546 #ifndef LIBVINTF_TARGET
    547         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
    548             return false;
    549         }
    550 #endif
    551         return true;
    552     }
    553 
    554 #ifndef LIBVINTF_TARGET
    555    private:
    556     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
    557         if (hal.getName() == "netutils-wrapper") {
    558             if (hal.versionRanges.size() != 1) {
    559                 *error =
    560                     "netutils-wrapper HAL must specify exactly one version x.0, "
    561                     "but multiple <version> element is specified.";
    562                 return false;
    563             }
    564             const VersionRange& v = hal.versionRanges.at(0);
    565             if (!v.isSingleVersion()) {
    566                 *error =
    567                     "netutils-wrapper HAL must specify exactly one version x.0, "
    568                     "but a range is provided. Perhaps you mean '" +
    569                     to_string(Version{v.majorVer, 0}) + "'?";
    570                 return false;
    571             }
    572             if (v.minMinor != 0) {
    573                 *error =
    574                     "netutils-wrapper HAL must specify exactly one version x.0, "
    575                     "but minor version is not 0. Perhaps you mean '" +
    576                     to_string(Version{v.majorVer, 0}) + "'?";
    577                 return false;
    578             }
    579         }
    580         return true;
    581     }
    582 #endif
    583 };
    584 
    585 MatrixHalConverter matrixHalConverter{};
    586 
    587 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
    588     std::string elementName() const override { return "conditions"; }
    589     void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
    590                     DocType* d) const override {
    591         appendChildren(root, kernelConfigConverter, conds, d);
    592     }
    593     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
    594                      std::string* error) const override {
    595         return parseChildren(root, kernelConfigConverter, object, error);
    596     }
    597 };
    598 
    599 MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
    600 
    601 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
    602     std::string elementName() const override { return "kernel"; }
    603     void mutateNode(const MatrixKernel &kernel, NodeType *root, DocType *d) const override {
    604         appendAttr(root, "version", kernel.mMinLts);
    605         if (!kernel.mConditions.empty()) {
    606             appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
    607         }
    608         appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
    609     }
    610     bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
    611         if (!parseAttr(root, "version", &object->mMinLts, error) ||
    612             !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
    613                                 error) ||
    614             !parseChildren(root, kernelConfigConverter, &object->mConfigs, error)) {
    615             return false;
    616         }
    617         return true;
    618     }
    619 };
    620 
    621 MatrixKernelConverter matrixKernelConverter{};
    622 
    623 XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
    624 
    625 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
    626     std::string elementName() const override { return "hal"; }
    627     void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
    628         mutateNode(m, root, d, SerializeFlag::EVERYTHING);
    629     }
    630     void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
    631                     SerializeFlags flags) const override {
    632         appendAttr(root, "format", hal.format);
    633         appendTextElement(root, "name", hal.name, d);
    634         appendChild(root, transportArchConverter(hal.transportArch, d));
    635         appendChildren(root, versionConverter, hal.versions, d);
    636         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
    637         if (hal.isOverride()) {
    638             appendAttr(root, "override", hal.isOverride());
    639         }
    640 
    641         if (!(flags & SerializeFlag::NO_FQNAME)) {
    642             std::set<FqInstance> fqInstances;
    643             hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
    644                 fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
    645                 return true;
    646             });
    647             appendChildren(root, fqInstanceConverter, fqInstances, d);
    648         }
    649     }
    650     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
    651         std::vector<HalInterface> interfaces;
    652         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
    653             !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
    654             !parseTextElement(root, "name", &object->name, error) ||
    655             !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
    656             !parseChildren(root, versionConverter, &object->versions, error) ||
    657             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
    658             return false;
    659         }
    660 
    661         switch (object->format) {
    662             case HalFormat::HIDL: {
    663                 if (object->transportArch.empty()) {
    664                     *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
    665                     return false;
    666                 }
    667             } break;
    668             case HalFormat::NATIVE: {
    669                 if (!object->transportArch.empty()) {
    670                     *error =
    671                         "Native HAL '" + object->name + "' should not have <transport> defined.";
    672                     return false;
    673                 }
    674             } break;
    675             default: {
    676                 LOG(FATAL) << "Unhandled HalFormat "
    677                            << static_cast<typename std::underlying_type<HalFormat>::type>(
    678                                   object->format);
    679             } break;
    680         }
    681         if (!object->transportArch.isValid()) return false;
    682 
    683         object->interfaces.clear();
    684         for (auto &&interface : interfaces) {
    685             auto res = object->interfaces.emplace(interface.name(), std::move(interface));
    686             if (!res.second) {
    687                 *error = "Duplicated interface entry \"" + res.first->first +
    688                          "\"; if additional instances are needed, add them to the "
    689                          "existing <interface> node.";
    690                 return false;
    691             }
    692         }
    693         if (!object->isValid()) {
    694             *error = "'" + object->name + "' is not a valid Manifest HAL.";
    695             return false;
    696         }
    697 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
    698 #ifndef LIBVINTF_TARGET
    699         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
    700             return false;
    701         }
    702 #endif
    703 
    704         std::set<FqInstance> fqInstances;
    705         if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
    706             return false;
    707         }
    708         if (!object->insertInstances(fqInstances, error)) {
    709             return false;
    710         }
    711 
    712         return true;
    713     }
    714 
    715 #ifndef LIBVINTF_TARGET
    716    private:
    717     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
    718         if (hal.getName() == "netutils-wrapper") {
    719             for (const Version& v : hal.versions) {
    720                 if (v.minorVer != 0) {
    721                     *error =
    722                         "netutils-wrapper HAL must specify exactly one version x.0, "
    723                         "but minor version is not 0. Perhaps you mean '" +
    724                         to_string(Version{v.majorVer, 0}) + "'?";
    725                     return false;
    726                 }
    727             }
    728         }
    729         return true;
    730     }
    731 #endif
    732 };
    733 
    734 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
    735 // .isValid() == true.
    736 ManifestHalConverter manifestHalConverter{};
    737 
    738 XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
    739 XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
    740 
    741 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
    742     std::string elementName() const override { return "sepolicy"; }
    743     void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
    744         appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
    745         appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
    746     }
    747     bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
    748         if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
    749                         error) ||
    750             !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
    751                            error)) {
    752             return false;
    753         }
    754         return true;
    755     }
    756 };
    757 SepolicyConverter sepolicyConverter{};
    758 
    759 [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
    760 
    761 XmlTextConverter<std::string> vndkVersionConverter{"version"};
    762 XmlTextConverter<std::string> vndkLibraryConverter{"library"};
    763 
    764 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
    765     std::string elementName() const override { return "vndk"; }
    766     void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
    767         appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
    768         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
    769     }
    770     bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
    771         if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
    772             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
    773             return false;
    774         }
    775         return true;
    776     }
    777 };
    778 
    779 [[deprecated]] VndkConverter vndkConverter{};
    780 
    781 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
    782     std::string elementName() const override { return "vendor-ndk"; }
    783     void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
    784         appendChild(root, vndkVersionConverter(object.mVersion, d));
    785         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
    786     }
    787     bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
    788         if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
    789             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
    790             return false;
    791         }
    792         return true;
    793     }
    794 };
    795 
    796 VendorNdkConverter vendorNdkConverter{};
    797 
    798 XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
    799 
    800 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
    801     std::string elementName() const override { return "system-sdk"; }
    802     void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
    803         appendChildren(root, systemSdkVersionConverter, object.versions(), d);
    804     }
    805     bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
    806         return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
    807     }
    808 };
    809 
    810 SystemSdkConverter systemSdkConverter{};
    811 
    812 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
    813     std::string elementName() const override { return "sepolicy"; }
    814     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
    815         appendChild(root, versionConverter(m, d));
    816     }
    817     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
    818         return parseChild(root, versionConverter, object, error);
    819     }
    820 };
    821 HalManifestSepolicyConverter halManifestSepolicyConverter{};
    822 
    823 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
    824     std::string elementName() const override { return "xmlfile"; }
    825     void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
    826         appendTextElement(root, "name", f.name(), d);
    827         appendChild(root, versionConverter(f.version(), d));
    828         if (!f.overriddenPath().empty()) {
    829             appendTextElement(root, "path", f.overriddenPath(), d);
    830         }
    831     }
    832     bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
    833         if (!parseTextElement(root, "name", &object->mName, error) ||
    834             !parseChild(root, versionConverter, &object->mVersion, error) ||
    835             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
    836             return false;
    837         }
    838         return true;
    839     }
    840 };
    841 ManifestXmlFileConverter manifestXmlFileConverter{};
    842 
    843 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
    844     std::string elementName() const override { return "manifest"; }
    845     void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
    846         mutateNode(m, root, d, SerializeFlag::EVERYTHING);
    847     }
    848     void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
    849                     SerializeFlags flags) const override {
    850         appendAttr(root, "version", m.getMetaVersion());
    851         appendAttr(root, "type", m.mType);
    852 
    853         if (!(flags & SerializeFlag::NO_HALS)) {
    854             appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
    855         }
    856         if (m.mType == SchemaType::DEVICE) {
    857             if (!(flags & SerializeFlag::NO_SEPOLICY)) {
    858                 appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
    859             }
    860             if (m.mLevel != Level::UNSPECIFIED) {
    861                 this->appendAttr(root, "target-level", m.mLevel);
    862             }
    863         } else if (m.mType == SchemaType::FRAMEWORK) {
    864             if (!(flags & SerializeFlag::NO_VNDK)) {
    865 #pragma clang diagnostic push
    866 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    867                 appendChildren(root, vndkConverter, m.framework.mVndks, d);
    868 #pragma clang diagnostic pop
    869 
    870                 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
    871             }
    872             if (!(flags & SerializeFlag::NO_SSDK)) {
    873                 if (!m.framework.mSystemSdk.empty()) {
    874                     appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
    875                 }
    876             }
    877         }
    878 
    879         if (!(flags & SerializeFlag::NO_XMLFILES)) {
    880             appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
    881         }
    882     }
    883     bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
    884         std::vector<ManifestHal> hals;
    885         if (!parseAttr(root, "version", &object->mMetaVersion, error) ||
    886             !parseAttr(root, "type", &object->mType, error) ||
    887             !parseChildren(root, manifestHalConverter, &hals, error)) {
    888             return false;
    889         }
    890         if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) {
    891             *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
    892                      " (libvintf@" + to_string(kMetaVersion) + ")";
    893             return false;
    894         }
    895         if (object->mType == SchemaType::DEVICE) {
    896             // tags for device hal manifest only.
    897             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
    898             // in the XML file.
    899             if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
    900                                     &object->device.mSepolicyVersion, error)) {
    901                 return false;
    902             }
    903 
    904             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
    905                                    error)) {
    906                 return false;
    907             }
    908         } else if (object->mType == SchemaType::FRAMEWORK) {
    909 #pragma clang diagnostic push
    910 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    911             if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
    912                 return false;
    913             }
    914             for (const auto &vndk : object->framework.mVndks) {
    915                 if (!vndk.mVersionRange.isSingleVersion()) {
    916                     *error = "vndk.version " + to_string(vndk.mVersionRange) +
    917                              " cannot be a range for manifests";
    918                     return false;
    919                 }
    920             }
    921 #pragma clang diagnostic pop
    922 
    923             if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
    924                 return false;
    925             }
    926 
    927             std::set<std::string> vendorNdkVersions;
    928             for (const auto& vendorNdk : object->framework.mVendorNdks) {
    929                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
    930                     *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
    931                     return false;
    932                 }
    933                 vendorNdkVersions.insert(vendorNdk.version());
    934             }
    935 
    936             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
    937                                     error)) {
    938                 return false;
    939             }
    940         }
    941         for (auto &&hal : hals) {
    942             std::string description{hal.name};
    943             if (!object->add(std::move(hal))) {
    944                 *error = "Duplicated manifest.hal entry " + description;
    945                 return false;
    946             }
    947         }
    948 
    949         std::vector<ManifestXmlFile> xmlFiles;
    950         if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
    951             return false;
    952         }
    953         for (auto&& xmlFile : xmlFiles) {
    954             std::string description{xmlFile.name()};
    955             if (!object->addXmlFile(std::move(xmlFile))) {
    956                 *error = "Duplicated manifest.xmlfile entry " + description +
    957                          "; entries cannot have duplicated name and version";
    958                 return false;
    959             }
    960         }
    961 
    962         return true;
    963     }
    964 };
    965 
    966 HalManifestConverter halManifestConverter{};
    967 
    968 XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
    969 struct AvbConverter : public XmlNodeConverter<Version> {
    970     std::string elementName() const override { return "avb"; }
    971     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
    972         appendChild(root, avbVersionConverter(m, d));
    973     }
    974     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
    975         return parseChild(root, avbVersionConverter, object, error);
    976     }
    977 };
    978 AvbConverter avbConverter{};
    979 
    980 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
    981     std::string elementName() const override { return "xmlfile"; }
    982     void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
    983         appendTextElement(root, "name", f.name(), d);
    984         appendAttr(root, "format", f.format());
    985         appendAttr(root, "optional", f.optional());
    986         appendChild(root, versionRangeConverter(f.versionRange(), d));
    987         if (!f.overriddenPath().empty()) {
    988             appendTextElement(root, "path", f.overriddenPath(), d);
    989         }
    990     }
    991     bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
    992         if (!parseTextElement(root, "name", &object->mName, error) ||
    993             !parseAttr(root, "format", &object->mFormat, error) ||
    994             !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
    995             !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
    996             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
    997             return false;
    998         }
    999         return true;
   1000     }
   1001 };
   1002 MatrixXmlFileConverter matrixXmlFileConverter{};
   1003 
   1004 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
   1005     std::string elementName() const override { return "compatibility-matrix"; }
   1006     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
   1007         mutateNode(m, root, d, SerializeFlag::EVERYTHING);
   1008     }
   1009     void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
   1010                     SerializeFlags flags) const override {
   1011         appendAttr(root, "version", m.getMinimumMetaVersion());
   1012         appendAttr(root, "type", m.mType);
   1013 
   1014         if (!(flags & SerializeFlag::NO_HALS)) {
   1015             appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
   1016         }
   1017         if (m.mType == SchemaType::FRAMEWORK) {
   1018             if (!(flags & SerializeFlag::NO_KERNEL)) {
   1019                 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
   1020             }
   1021             if (!(flags & SerializeFlag::NO_SEPOLICY)) {
   1022                 if (!(m.framework.mSepolicy == Sepolicy{})) {
   1023                     appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
   1024                 }
   1025             }
   1026             if (!(flags & SerializeFlag::NO_AVB)) {
   1027                 if (!(m.framework.mAvbMetaVersion == Version{})) {
   1028                     appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
   1029                 }
   1030             }
   1031             if (m.mLevel != Level::UNSPECIFIED) {
   1032                 this->appendAttr(root, "level", m.mLevel);
   1033             }
   1034         } else if (m.mType == SchemaType::DEVICE) {
   1035             if (!(flags & SerializeFlag::NO_VNDK)) {
   1036 #pragma clang diagnostic push
   1037 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
   1038                 if (!(m.device.mVndk == Vndk{})) {
   1039                     appendChild(root, vndkConverter(m.device.mVndk, d));
   1040                 }
   1041 #pragma clang diagnostic pop
   1042 
   1043                 if (!(m.device.mVendorNdk == VendorNdk{})) {
   1044                     appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
   1045                 }
   1046             }
   1047 
   1048             if (!(flags & SerializeFlag::NO_SSDK)) {
   1049                 if (!m.device.mSystemSdk.empty()) {
   1050                     appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
   1051                 }
   1052             }
   1053         }
   1054 
   1055         if (!(flags & SerializeFlag::NO_XMLFILES)) {
   1056             appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
   1057         }
   1058     }
   1059     bool buildObject(CompatibilityMatrix* object, NodeType* root,
   1060                      std::string* error) const override {
   1061         Version version;
   1062         std::vector<MatrixHal> hals;
   1063         if (!parseAttr(root, "version", &version, error) ||
   1064             !parseAttr(root, "type", &object->mType, error) ||
   1065             !parseChildren(root, matrixHalConverter, &hals, error)) {
   1066             return false;
   1067         }
   1068 
   1069         if (object->mType == SchemaType::FRAMEWORK) {
   1070             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
   1071             // hard-coded in the XML file.
   1072             if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
   1073                 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
   1074                                     error) ||
   1075                 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
   1076                                     error)) {
   1077                 return false;
   1078             }
   1079 
   1080             std::set<Version> seenKernelVersions;
   1081             for (const auto& kernel : object->framework.mKernels) {
   1082                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
   1083                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
   1084                     continue;
   1085                 }
   1086                 if (!kernel.conditions().empty()) {
   1087                     *error = "First <kernel> for version " + to_string(minLts) +
   1088                              " must have empty <conditions> for backwards compatibility.";
   1089                     return false;
   1090                 }
   1091                 seenKernelVersions.insert(minLts);
   1092             }
   1093 
   1094             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
   1095                 return false;
   1096             }
   1097 
   1098         } else if (object->mType == SchemaType::DEVICE) {
   1099             // <vndk> can be missing because it can be determined at build time, not hard-coded
   1100             // in the XML file.
   1101 #pragma clang diagnostic push
   1102 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
   1103             if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
   1104                 return false;
   1105             }
   1106 #pragma clang diagnostic pop
   1107 
   1108             if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
   1109                                     error)) {
   1110                 return false;
   1111             }
   1112 
   1113             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
   1114                                     error)) {
   1115                 return false;
   1116             }
   1117         }
   1118 
   1119         if (!kMetaVersion.minorAtLeast(version)) {
   1120             *error = "Unrecognized compatibility-matrix.version " + to_string(version) +
   1121                      " (libvintf@" + to_string(kMetaVersion) + ")";
   1122             return false;
   1123         }
   1124         for (auto &&hal : hals) {
   1125             if (!object->add(std::move(hal))) {
   1126                 *error = "Duplicated compatibility-matrix.hal entry";
   1127                 return false;
   1128             }
   1129         }
   1130 
   1131         std::vector<MatrixXmlFile> xmlFiles;
   1132         if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
   1133             return false;
   1134         }
   1135         for (auto&& xmlFile : xmlFiles) {
   1136             if (!xmlFile.optional()) {
   1137                 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
   1138                          " has to be optional for compatibility matrix version 1.0";
   1139                 return false;
   1140             }
   1141             std::string description{xmlFile.name()};
   1142             if (!object->addXmlFile(std::move(xmlFile))) {
   1143                 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
   1144                 return false;
   1145             }
   1146         }
   1147 
   1148         return true;
   1149     }
   1150 };
   1151 
   1152 CompatibilityMatrixConverter compatibilityMatrixConverter{};
   1153 
   1154 // Publicly available as in parse_xml.h
   1155 XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
   1156 XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
   1157 
   1158 // For testing in LibVintfTest
   1159 XmlConverter<Version>& gVersionConverter = versionConverter;
   1160 XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
   1161     kernelConfigTypedValueConverter;
   1162 XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
   1163 XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
   1164 
   1165 } // namespace vintf
   1166 } // namespace android
   1167