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 "parse_string.h"
     29 
     30 namespace android {
     31 namespace vintf {
     32 
     33 // --------------- tinyxml2 details
     34 
     35 using NodeType = tinyxml2::XMLElement;
     36 using DocType = tinyxml2::XMLDocument;
     37 
     38 // caller is responsible for deleteDocument() call
     39 inline DocType *createDocument() {
     40     return new tinyxml2::XMLDocument();
     41 }
     42 
     43 // caller is responsible for deleteDocument() call
     44 inline DocType *createDocument(const std::string &xml) {
     45     DocType *doc = new tinyxml2::XMLDocument();
     46     if (doc->Parse(xml.c_str()) == tinyxml2::XML_NO_ERROR) {
     47         return doc;
     48     }
     49     delete doc;
     50     return nullptr;
     51 }
     52 
     53 inline void deleteDocument(DocType *d) {
     54     delete d;
     55 }
     56 
     57 inline std::string printDocument(DocType *d) {
     58     tinyxml2::XMLPrinter p;
     59     d->Print(&p);
     60     return std::string{p.CStr()};
     61 }
     62 
     63 inline NodeType *createNode(const std::string &name, DocType *d) {
     64     return d->NewElement(name.c_str());
     65 }
     66 
     67 inline void appendChild(NodeType *parent, NodeType *child) {
     68     parent->InsertEndChild(child);
     69 }
     70 
     71 inline void appendChild(DocType *parent, NodeType *child) {
     72     parent->InsertEndChild(child);
     73 }
     74 
     75 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
     76     e->SetAttribute(attrName.c_str(), attr.c_str());
     77 }
     78 
     79 // text -> text
     80 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
     81     parent->InsertEndChild(d->NewText(text.c_str()));
     82 }
     83 
     84 inline std::string nameOf(NodeType *root) {
     85     return root->Name() == NULL ? "" : root->Name();
     86 }
     87 
     88 inline std::string getText(NodeType *root) {
     89     return root->GetText() == NULL ? "" : root->GetText();
     90 }
     91 
     92 inline NodeType *getChild(NodeType *parent, const std::string &name) {
     93     return parent->FirstChildElement(name.c_str());
     94 }
     95 
     96 inline NodeType *getRootChild(DocType *parent) {
     97     return parent->FirstChildElement();
     98 }
     99 
    100 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
    101     std::vector<NodeType *> v;
    102     for (NodeType *child = parent->FirstChildElement(name.c_str());
    103          child != nullptr;
    104          child = child->NextSiblingElement(name.c_str())) {
    105         v.push_back(child);
    106     }
    107     return v;
    108 }
    109 
    110 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
    111     const char *c = root->Attribute(attrName.c_str());
    112     if (c == NULL)
    113         return false;
    114     *s = c;
    115     return true;
    116 }
    117 
    118 // --------------- tinyxml2 details end.
    119 
    120 // Helper functions for XmlConverter
    121 static bool parse(const std::string &attrText, bool *attr) {
    122     if (attrText == "true" || attrText == "1") {
    123         *attr = true;
    124         return true;
    125     }
    126     if (attrText == "false" || attrText == "0") {
    127         *attr = false;
    128         return true;
    129     }
    130     return false;
    131 }
    132 
    133 // ---------------------- XmlNodeConverter definitions
    134 
    135 template<typename Object>
    136 struct XmlNodeConverter : public XmlConverter<Object> {
    137     XmlNodeConverter() {}
    138     virtual ~XmlNodeConverter() {}
    139 
    140     // sub-types should implement these.
    141     virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
    142     virtual bool buildObject(Object *o, NodeType *n) const = 0;
    143     virtual std::string elementName() const = 0;
    144 
    145     // convenience methods for user
    146     inline const std::string &lastError() const { return mLastError; }
    147     inline NodeType *serialize(const Object &o, DocType *d) const {
    148         NodeType *root = createNode(this->elementName(), d);
    149         this->mutateNode(o, root, d);
    150         return root;
    151     }
    152     inline std::string serialize(const Object &o) const {
    153         DocType *doc = createDocument();
    154         appendChild(doc, serialize(o, doc));
    155         std::string s = printDocument(doc);
    156         deleteDocument(doc);
    157         return s;
    158     }
    159     inline bool deserialize(Object *object, NodeType *root) const {
    160         if (nameOf(root) != this->elementName()) {
    161             return false;
    162         }
    163         return this->buildObject(object, root);
    164     }
    165     inline bool deserialize(Object *o, const std::string &xml) const {
    166         DocType *doc = createDocument(xml);
    167         if (doc == nullptr) {
    168             this->mLastError = "Not a valid XML";
    169             return false;
    170         }
    171         bool ret = deserialize(o, getRootChild(doc));
    172         deleteDocument(doc);
    173         return ret;
    174     }
    175     inline NodeType *operator()(const Object &o, DocType *d) const {
    176         return serialize(o, d);
    177     }
    178     inline std::string operator()(const Object &o) const {
    179         return serialize(o);
    180     }
    181     inline bool operator()(Object *o, NodeType *node) const {
    182         return deserialize(o, node);
    183     }
    184     inline bool operator()(Object *o, const std::string &xml) const {
    185         return deserialize(o, xml);
    186     }
    187 
    188     // convenience methods for implementor.
    189 
    190     // All append* functions helps mutateNode() to serialize the object into XML.
    191     template <typename T>
    192     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
    193         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
    194     }
    195 
    196     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
    197         return appendStrAttr(e, attrName, attr ? "true" : "false");
    198     }
    199 
    200     // text -> <name>text</name>
    201     inline void appendTextElement(NodeType *parent, const std::string &name,
    202                 const std::string &text, DocType *d) const {
    203         NodeType *c = createNode(name, d);
    204         appendText(c, text, d);
    205         appendChild(parent, c);
    206     }
    207 
    208     // text -> <name>text</name>
    209     template<typename Array>
    210     inline void appendTextElements(NodeType *parent, const std::string &name,
    211                 const Array &array, DocType *d) const {
    212         for (const std::string &text : array) {
    213             NodeType *c = createNode(name, d);
    214             appendText(c, text, d);
    215             appendChild(parent, c);
    216         }
    217     }
    218 
    219     template<typename T, typename Array>
    220     inline void appendChildren(NodeType *parent, const XmlNodeConverter<T> &conv,
    221             const Array &array, DocType *d) const {
    222         for (const T &t : array) {
    223             appendChild(parent, conv(t, d));
    224         }
    225     }
    226 
    227     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
    228     // true if deserialization is successful, false if any error, and mLastError will be
    229     // set to error message.
    230     template <typename T>
    231     inline bool parseOptionalAttr(NodeType *root, const std::string &attrName,
    232             T &&defaultValue, T *attr) const {
    233         std::string attrText;
    234         bool success = getAttr(root, attrName, &attrText) &&
    235                        ::android::vintf::parse(attrText, attr);
    236         if (!success) {
    237             *attr = std::move(defaultValue);
    238         }
    239         return true;
    240     }
    241 
    242     template <typename T>
    243     inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const {
    244         std::string attrText;
    245         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
    246         if (!ret) {
    247             mLastError = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
    248                          attrText + "\" for element <" + elementName() + ">";
    249         }
    250         return ret;
    251     }
    252 
    253     inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const {
    254         bool ret = getAttr(root, attrName, attr);
    255         if (!ret) {
    256             mLastError = "Could not find attr with name \"" + attrName + "\" for element <"
    257                     + elementName() + ">";
    258         }
    259         return ret;
    260     }
    261 
    262     inline bool parseTextElement(NodeType *root,
    263             const std::string &elementName, std::string *s) const {
    264         NodeType *child = getChild(root, elementName);
    265         if (child == nullptr) {
    266             mLastError = "Could not find element with name <" + elementName + "> in element <"
    267                     + this->elementName() + ">";
    268             return false;
    269         }
    270         *s = getText(child);
    271         return true;
    272     }
    273 
    274     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
    275                                          std::string&& defaultValue, std::string* s) const {
    276         NodeType* child = getChild(root, elementName);
    277         *s = child == nullptr ? std::move(defaultValue) : getText(child);
    278         return true;
    279     }
    280 
    281     inline bool parseTextElements(NodeType *root, const std::string &elementName,
    282             std::vector<std::string> *v) const {
    283         auto nodes = getChildren(root, elementName);
    284         v->resize(nodes.size());
    285         for (size_t i = 0; i < nodes.size(); ++i) {
    286             v->at(i) = getText(nodes[i]);
    287         }
    288         return true;
    289     }
    290 
    291     template <typename T>
    292     inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const {
    293         NodeType *child = getChild(root, conv.elementName());
    294         if (child == nullptr) {
    295             mLastError = "Could not find element with name <" + conv.elementName() + "> in element <"
    296                     + this->elementName() + ">";
    297             return false;
    298         }
    299         bool success = conv.deserialize(t, child);
    300         if (!success) {
    301             mLastError = conv.lastError();
    302         }
    303         return success;
    304     }
    305 
    306     template <typename T>
    307     inline bool parseOptionalChild(NodeType *root, const XmlNodeConverter<T> &conv,
    308             T &&defaultValue, T *t) const {
    309         NodeType *child = getChild(root, conv.elementName());
    310         if (child == nullptr) {
    311             *t = std::move(defaultValue);
    312             return true;
    313         }
    314         bool success = conv.deserialize(t, child);
    315         if (!success) {
    316             mLastError = conv.lastError();
    317         }
    318         return success;
    319     }
    320 
    321     template <typename T>
    322     inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const {
    323         auto nodes = getChildren(root, conv.elementName());
    324         v->resize(nodes.size());
    325         for (size_t i = 0; i < nodes.size(); ++i) {
    326             if (!conv.deserialize(&v->at(i), nodes[i])) {
    327                 mLastError = "Could not parse element with name <" + conv.elementName()
    328                         + "> in element <" + this->elementName() + ">: " + conv.lastError();
    329                 return false;
    330             }
    331         }
    332         return true;
    333     }
    334 
    335     template <typename T>
    336     inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const {
    337         std::vector<T> vec;
    338         if (!parseChildren(root, conv, &vec)) {
    339             return false;
    340         }
    341         s->clear();
    342         s->insert(vec.begin(), vec.end());
    343         if (s->size() != vec.size()) {
    344             mLastError = "Duplicated elements <" + conv.elementName() + "> in element <"
    345                     + this->elementName() + ">";
    346             s->clear();
    347             return false;
    348         }
    349         return true;
    350     }
    351 
    352     inline bool parseText(NodeType *node, std::string *s) const {
    353         *s = getText(node);
    354         return true;
    355     }
    356 
    357     template <typename T>
    358     inline bool parseText(NodeType *node, T *s) const {
    359         std::string text = getText(node);
    360         bool ret = ::android::vintf::parse(text, s);
    361         if (!ret) {
    362             mLastError = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
    363         }
    364         return ret;
    365     }
    366 protected:
    367     mutable std::string mLastError;
    368 };
    369 
    370 template<typename Object>
    371 struct XmlTextConverter : public XmlNodeConverter<Object> {
    372     XmlTextConverter(const std::string &elementName)
    373         : mElementName(elementName) {}
    374 
    375     virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
    376         appendText(root, ::android::vintf::to_string(object), d);
    377     }
    378     virtual bool buildObject(Object *object, NodeType *root) const override {
    379         return this->parseText(root, object);
    380     }
    381     virtual std::string elementName() const { return mElementName; };
    382 private:
    383     std::string mElementName;
    384 };
    385 
    386 // ---------------------- XmlNodeConverter definitions end
    387 
    388 const XmlTextConverter<Version> versionConverter{"version"};
    389 
    390 const XmlTextConverter<VersionRange> versionRangeConverter{"version"};
    391 
    392 const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
    393 
    394 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
    395     std::string elementName() const override { return "transport"; }
    396     void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
    397         if (object.arch != Arch::ARCH_EMPTY) {
    398             appendAttr(root, "arch", object.arch);
    399         }
    400         appendText(root, ::android::vintf::to_string(object.transport), d);
    401     }
    402     bool buildObject(TransportArch *object, NodeType *root) const override {
    403         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch) ||
    404             !parseText(root, &object->transport)) {
    405             return false;
    406         }
    407         if (!object->isValid()) {
    408             this->mLastError = "transport == " + ::android::vintf::to_string(object->transport) +
    409                     " and arch == " + ::android::vintf::to_string(object->arch) +
    410                     " is not a valid combination.";
    411             return false;
    412         }
    413         return true;
    414     }
    415 };
    416 
    417 const TransportArchConverter transportArchConverter{};
    418 
    419 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
    420     std::string elementName() const override { return "value"; }
    421     void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
    422         appendAttr(root, "type", object.mType);
    423         appendText(root, ::android::vintf::to_string(object), d);
    424     }
    425     bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override {
    426         std::string stringValue;
    427         if (!parseAttr(root, "type", &object->mType) ||
    428             !parseText(root, &stringValue)) {
    429             return false;
    430         }
    431         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
    432             this->mLastError = "Could not parse kernel config value \"" + stringValue + "\"";
    433             return false;
    434         }
    435         return true;
    436     }
    437 };
    438 
    439 const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
    440 
    441 struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
    442     std::string elementName() const override { return "config"; }
    443     void mutateNode(const KernelConfig &object, NodeType *root, DocType *d) const override {
    444         appendChild(root, kernelConfigKeyConverter(object.first, d));
    445         appendChild(root, kernelConfigTypedValueConverter(object.second, d));
    446     }
    447     bool buildObject(KernelConfig *object, NodeType *root) const override {
    448         if (   !parseChild(root, kernelConfigKeyConverter, &object->first)
    449             || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) {
    450             return false;
    451         }
    452         return true;
    453     }
    454 };
    455 
    456 const KernelConfigConverter kernelConfigConverter{};
    457 
    458 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
    459     std::string elementName() const override { return "interface"; }
    460     void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
    461         appendTextElement(root, "name", intf.name, d);
    462         appendTextElements(root, "instance", intf.instances, d);
    463     }
    464     bool buildObject(HalInterface *intf, NodeType *root) const override {
    465         std::vector<std::string> instances;
    466         if (!parseTextElement(root, "name", &intf->name) ||
    467             !parseTextElements(root, "instance", &instances)) {
    468             return false;
    469         }
    470         intf->instances.clear();
    471         intf->instances.insert(instances.begin(), instances.end());
    472         if (intf->instances.size() != instances.size()) {
    473             this->mLastError = "Duplicated instances in " + intf->name;
    474             return false;
    475         }
    476         return true;
    477     }
    478 };
    479 
    480 const HalInterfaceConverter halInterfaceConverter{};
    481 
    482 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
    483     std::string elementName() const override { return "hal"; }
    484     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
    485         appendAttr(root, "format", hal.format);
    486         appendAttr(root, "optional", hal.optional);
    487         appendTextElement(root, "name", hal.name, d);
    488         appendChildren(root, versionRangeConverter, hal.versionRanges, d);
    489         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
    490     }
    491     bool buildObject(MatrixHal *object, NodeType *root) const override {
    492         std::vector<HalInterface> interfaces;
    493         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
    494             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional) ||
    495             !parseTextElement(root, "name", &object->name) ||
    496             !parseChildren(root, versionRangeConverter, &object->versionRanges) ||
    497             !parseChildren(root, halInterfaceConverter, &interfaces)) {
    498             return false;
    499         }
    500         for (auto&& interface : interfaces) {
    501             std::string name{interface.name};
    502             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
    503             if (!res.second) {
    504                 this->mLastError = "Duplicated interface entry \"" + res.first->first +
    505                                    "\"; if additional instances are needed, add them to the "
    506                                    "existing <interface> node.";
    507                 return false;
    508             }
    509         }
    510 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
    511 #ifdef LIBVINTF_HOST
    512         if (!checkAdditionalRestrictionsOnHal(*object)) {
    513             return false;
    514         }
    515 #endif
    516         return true;
    517     }
    518 
    519 #ifdef LIBVINTF_HOST
    520    private:
    521     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal) const {
    522         if (hal.getName() == "netutils-wrapper") {
    523             if (hal.versionRanges.size() != 1) {
    524                 this->mLastError =
    525                     "netutils-wrapper HAL must specify exactly one version x.0, "
    526                     "but multiple <version> element is specified.";
    527                 return false;
    528             }
    529             const VersionRange& v = hal.versionRanges.at(0);
    530             if (!v.isSingleVersion()) {
    531                 this->mLastError =
    532                     "netutils-wrapper HAL must specify exactly one version x.0, "
    533                     "but a range is provided. Perhaps you mean '" +
    534                     to_string(Version{v.majorVer, 0}) + "'?";
    535                 return false;
    536             }
    537             if (v.minMinor != 0) {
    538                 this->mLastError =
    539                     "netutils-wrapper HAL must specify exactly one version x.0, "
    540                     "but minor version is not 0. Perhaps you mean '" +
    541                     to_string(Version{v.majorVer, 0}) + "'?";
    542                 return false;
    543             }
    544         }
    545         return true;
    546     }
    547 #endif
    548 };
    549 
    550 const MatrixHalConverter matrixHalConverter{};
    551 
    552 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
    553     std::string elementName() const override { return "conditions"; }
    554     void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
    555                     DocType* d) const override {
    556         appendChildren(root, kernelConfigConverter, conds, d);
    557     }
    558     bool buildObject(std::vector<KernelConfig>* object, NodeType* root) const override {
    559         return parseChildren(root, kernelConfigConverter, object);
    560     }
    561 };
    562 
    563 const MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
    564 
    565 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
    566     std::string elementName() const override { return "kernel"; }
    567     void mutateNode(const MatrixKernel &kernel, NodeType *root, DocType *d) const override {
    568         appendAttr(root, "version", kernel.mMinLts);
    569         if (!kernel.mConditions.empty()) {
    570             appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
    571         }
    572         appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
    573     }
    574     bool buildObject(MatrixKernel *object, NodeType *root) const override {
    575         if (!parseAttr(root, "version", &object->mMinLts) ||
    576             !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions) ||
    577             !parseChildren(root, kernelConfigConverter, &object->mConfigs)) {
    578             return false;
    579         }
    580         return true;
    581     }
    582 };
    583 
    584 const MatrixKernelConverter matrixKernelConverter{};
    585 
    586 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
    587     std::string elementName() const override { return "hal"; }
    588     void mutateNode(const ManifestHal &hal, NodeType *root, DocType *d) const override {
    589         appendAttr(root, "format", hal.format);
    590         appendTextElement(root, "name", hal.name, d);
    591         appendChild(root, transportArchConverter(hal.transportArch, d));
    592         appendChildren(root, versionConverter, hal.versions, d);
    593         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
    594     }
    595     bool buildObject(ManifestHal *object, NodeType *root) const override {
    596         std::vector<HalInterface> interfaces;
    597         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) ||
    598             !parseTextElement(root, "name", &object->name) ||
    599             !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch) ||
    600             !parseChildren(root, versionConverter, &object->versions) ||
    601             !parseChildren(root, halInterfaceConverter, &interfaces)) {
    602             return false;
    603         }
    604 
    605         switch (object->format) {
    606             case HalFormat::HIDL: {
    607                 if (object->transportArch.empty()) {
    608                     this->mLastError =
    609                         "HIDL HAL '" + object->name + "' should have <transport> defined.";
    610                     return false;
    611                 }
    612             } break;
    613             case HalFormat::NATIVE: {
    614                 if (!object->transportArch.empty()) {
    615                     this->mLastError =
    616                         "Native HAL '" + object->name + "' should not have <transport> defined.";
    617                     return false;
    618                 }
    619             } break;
    620             default: {
    621                 LOG(FATAL) << "Unhandled HalFormat "
    622                            << static_cast<typename std::underlying_type<HalFormat>::type>(
    623                                   object->format);
    624             } break;
    625         }
    626         if (!object->transportArch.isValid()) return false;
    627 
    628         object->interfaces.clear();
    629         for (auto &&interface : interfaces) {
    630             auto res = object->interfaces.emplace(interface.name,
    631                                                   std::move(interface));
    632             if (!res.second) {
    633                 this->mLastError = "Duplicated interface entry \"" + res.first->first +
    634                                    "\"; if additional instances are needed, add them to the "
    635                                    "existing <interface> node.";
    636                 return false;
    637             }
    638         }
    639         if (!object->isValid()) {
    640             this->mLastError = "'" + object->name + "' is not a valid Manifest HAL.";
    641             return false;
    642         }
    643 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
    644 #ifdef LIBVINTF_HOST
    645         if (!checkAdditionalRestrictionsOnHal(*object)) {
    646             return false;
    647         }
    648 #endif
    649         return true;
    650     }
    651 
    652 #ifdef LIBVINTF_HOST
    653    private:
    654     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal) const {
    655         if (hal.getName() == "netutils-wrapper") {
    656             for (const Version& v : hal.versions) {
    657                 if (v.minorVer != 0) {
    658                     this->mLastError =
    659                         "netutils-wrapper HAL must specify exactly one version x.0, "
    660                         "but minor version is not 0. Perhaps you mean '" +
    661                         to_string(Version{v.majorVer, 0}) + "'?";
    662                     return false;
    663                 }
    664             }
    665         }
    666         return true;
    667     }
    668 #endif
    669 };
    670 
    671 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
    672 // .isValid() == true.
    673 const ManifestHalConverter manifestHalConverter{};
    674 
    675 const XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
    676 const XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
    677 
    678 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
    679     std::string elementName() const override { return "sepolicy"; }
    680     void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
    681         appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
    682         appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
    683     }
    684     bool buildObject(Sepolicy *object, NodeType *root) const override {
    685         if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) ||
    686             !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges)) {
    687             return false;
    688         }
    689         return true;
    690     }
    691 };
    692 const SepolicyConverter sepolicyConverter{};
    693 
    694 const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
    695 const XmlTextConverter<std::string> vndkLibraryConverter{"library"};
    696 
    697 struct VndkConverter : public XmlNodeConverter<Vndk> {
    698     std::string elementName() const override { return "vndk"; }
    699     void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
    700         appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
    701         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
    702     }
    703     bool buildObject(Vndk *object, NodeType *root) const override {
    704         if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) ||
    705             !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) {
    706             return false;
    707         }
    708         return true;
    709     }
    710 };
    711 
    712 const VndkConverter vndkConverter{};
    713 
    714 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
    715     std::string elementName() const override { return "sepolicy"; }
    716     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
    717         appendChild(root, versionConverter(m, d));
    718     }
    719     bool buildObject(Version *object, NodeType *root) const override {
    720         return parseChild(root, versionConverter, object);
    721     }
    722 };
    723 const HalManifestSepolicyConverter halManifestSepolicyConverter{};
    724 
    725 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
    726     std::string elementName() const override { return "xmlfile"; }
    727     void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
    728         appendTextElement(root, "name", f.name(), d);
    729         appendChild(root, versionConverter(f.version(), d));
    730         if (!f.overriddenPath().empty()) {
    731             appendTextElement(root, "path", f.overriddenPath(), d);
    732         }
    733     }
    734     bool buildObject(ManifestXmlFile* object, NodeType* root) const override {
    735         if (!parseTextElement(root, "name", &object->mName) ||
    736             !parseChild(root, versionConverter, &object->mVersion) ||
    737             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
    738             return false;
    739         }
    740         return true;
    741     }
    742 };
    743 const ManifestXmlFileConverter manifestXmlFileConverter{};
    744 
    745 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
    746     std::string elementName() const override { return "manifest"; }
    747     void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
    748         appendAttr(root, "version", HalManifest::kVersion);
    749         appendAttr(root, "type", m.mType);
    750 
    751         appendChildren(root, manifestHalConverter, m.getHals(), d);
    752         if (m.mType == SchemaType::DEVICE) {
    753             appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
    754         } else if (m.mType == SchemaType::FRAMEWORK) {
    755             appendChildren(root, vndkConverter, m.framework.mVndks, d);
    756         }
    757 
    758         appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
    759     }
    760     bool buildObject(HalManifest *object, NodeType *root) const override {
    761         Version version;
    762         std::vector<ManifestHal> hals;
    763         if (!parseAttr(root, "version", &version) ||
    764             !parseAttr(root, "type", &object->mType) ||
    765             !parseChildren(root, manifestHalConverter, &hals)) {
    766             return false;
    767         }
    768         if (version != HalManifest::kVersion) {
    769             this->mLastError = "Unrecognized manifest.version";
    770             return false;
    771         }
    772         if (object->mType == SchemaType::DEVICE) {
    773             // tags for device hal manifest only.
    774             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
    775             // in the XML file.
    776             if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
    777                     &object->device.mSepolicyVersion)) {
    778                 return false;
    779             }
    780         } else if (object->mType == SchemaType::FRAMEWORK) {
    781             if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) {
    782                 return false;
    783             }
    784             for (const auto &vndk : object->framework.mVndks) {
    785                 if (!vndk.mVersionRange.isSingleVersion()) {
    786                     this->mLastError = "vndk.version " + to_string(vndk.mVersionRange)
    787                             + " cannot be a range for manifests";
    788                     return false;
    789                 }
    790             }
    791         }
    792         for (auto &&hal : hals) {
    793             std::string description{hal.name};
    794             if (!object->add(std::move(hal))) {
    795                 this->mLastError = "Duplicated manifest.hal entry " + description;
    796                 return false;
    797             }
    798         }
    799 
    800         std::vector<ManifestXmlFile> xmlFiles;
    801         if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles)) {
    802             return false;
    803         }
    804         for (auto&& xmlFile : xmlFiles) {
    805             std::string description{xmlFile.name()};
    806             if (!object->addXmlFile(std::move(xmlFile))) {
    807                 this->mLastError = "Duplicated manifest.xmlfile entry " + description +
    808                                    "; entries cannot have duplicated name and version";
    809                 return false;
    810             }
    811         }
    812 
    813         return true;
    814     }
    815 };
    816 
    817 const HalManifestConverter halManifestConverter{};
    818 
    819 const XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
    820 struct AvbConverter : public XmlNodeConverter<Version> {
    821     std::string elementName() const override { return "avb"; }
    822     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
    823         appendChild(root, avbVersionConverter(m, d));
    824     }
    825     bool buildObject(Version *object, NodeType *root) const override {
    826         return parseChild(root, avbVersionConverter, object);
    827     }
    828 };
    829 const AvbConverter avbConverter{};
    830 
    831 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
    832     std::string elementName() const override { return "xmlfile"; }
    833     void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
    834         appendTextElement(root, "name", f.name(), d);
    835         appendAttr(root, "format", f.format());
    836         appendAttr(root, "optional", f.optional());
    837         appendChild(root, versionRangeConverter(f.versionRange(), d));
    838         if (!f.overriddenPath().empty()) {
    839             appendTextElement(root, "path", f.overriddenPath(), d);
    840         }
    841     }
    842     bool buildObject(MatrixXmlFile* object, NodeType* root) const override {
    843         if (!parseTextElement(root, "name", &object->mName) ||
    844             !parseAttr(root, "format", &object->mFormat) ||
    845             !parseOptionalAttr(root, "optional", false, &object->mOptional) ||
    846             !parseChild(root, versionRangeConverter, &object->mVersionRange) ||
    847             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) {
    848             return false;
    849         }
    850         return true;
    851     }
    852 };
    853 const MatrixXmlFileConverter matrixXmlFileConverter{};
    854 
    855 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
    856     std::string elementName() const override { return "compatibility-matrix"; }
    857     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
    858         appendAttr(root, "version", CompatibilityMatrix::kVersion);
    859         appendAttr(root, "type", m.mType);
    860         appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
    861         if (m.mType == SchemaType::FRAMEWORK) {
    862             appendChildren(root, matrixKernelConverter, m.framework.mKernels, d);
    863             appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
    864             appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
    865         } else if (m.mType == SchemaType::DEVICE) {
    866             appendChild(root, vndkConverter(m.device.mVndk, d));
    867         }
    868 
    869         appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
    870     }
    871     bool buildObject(CompatibilityMatrix *object, NodeType *root) const override {
    872         Version version;
    873         std::vector<MatrixHal> hals;
    874         if (!parseAttr(root, "version", &version) ||
    875             !parseAttr(root, "type", &object->mType) ||
    876             !parseChildren(root, matrixHalConverter, &hals)) {
    877             return false;
    878         }
    879 
    880         if (object->mType == SchemaType::FRAMEWORK) {
    881             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
    882             // hard-coded in the XML file.
    883             if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) ||
    884                 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy) ||
    885                 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion)) {
    886                 return false;
    887             }
    888 
    889             std::set<Version> seenKernelVersions;
    890             for (const auto& kernel : object->framework.mKernels) {
    891                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
    892                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
    893                     continue;
    894                 }
    895                 if (!kernel.conditions().empty()) {
    896                     this->mLastError = "First <kernel> for version " + to_string(minLts) +
    897                                        " must have empty <conditions> for backwards compatibility.";
    898                     return false;
    899                 }
    900                 seenKernelVersions.insert(minLts);
    901             }
    902 
    903         } else if (object->mType == SchemaType::DEVICE) {
    904             // <vndk> can be missing because it can be determined at build time, not hard-coded
    905             // in the XML file.
    906             if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) {
    907                 return false;
    908             }
    909         }
    910 
    911         if (version != CompatibilityMatrix::kVersion) {
    912             this->mLastError = "Unrecognized compatibility-matrix.version";
    913             return false;
    914         }
    915         for (auto &&hal : hals) {
    916             if (!object->add(std::move(hal))) {
    917                 this->mLastError = "Duplicated compatibility-matrix.hal entry";
    918                 return false;
    919             }
    920         }
    921 
    922         std::vector<MatrixXmlFile> xmlFiles;
    923         if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles)) {
    924             return false;
    925         }
    926         for (auto&& xmlFile : xmlFiles) {
    927             if (!xmlFile.optional()) {
    928                 this->mLastError = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
    929                                    " has to be optional for compatibility matrix version 1.0";
    930                 return false;
    931             }
    932             std::string description{xmlFile.name()};
    933             if (!object->addXmlFile(std::move(xmlFile))) {
    934                 this->mLastError = "Duplicated compatibility-matrix.xmlfile entry " + description;
    935                 return false;
    936             }
    937         }
    938 
    939         return true;
    940     }
    941 };
    942 
    943 const CompatibilityMatrixConverter compatibilityMatrixConverter{};
    944 
    945 // Publicly available as in parse_xml.h
    946 const XmlConverter<HalManifest> &gHalManifestConverter = halManifestConverter;
    947 const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter
    948         = compatibilityMatrixConverter;
    949 
    950 // For testing in LibVintfTest
    951 const XmlConverter<Version> &gVersionConverter = versionConverter;
    952 const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter
    953         = kernelConfigTypedValueConverter;
    954 const XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter;
    955 const XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter;
    956 
    957 } // namespace vintf
    958 } // namespace android
    959