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-private.h"
30 #include "constants.h"
31 #include "parse_string.h"
32 
33 namespace android {
34 namespace vintf {
35 
36 // --------------- tinyxml2 details
37 
38 using NodeType = tinyxml2::XMLElement;
39 using DocType = tinyxml2::XMLDocument;
40 
41 // caller is responsible for deleteDocument() call
createDocument()42 inline DocType *createDocument() {
43     return new tinyxml2::XMLDocument();
44 }
45 
46 // caller is responsible for deleteDocument() call
createDocument(const std::string & xml)47 inline DocType *createDocument(const std::string &xml) {
48     DocType *doc = new tinyxml2::XMLDocument();
49     if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
50         return doc;
51     }
52     delete doc;
53     return nullptr;
54 }
55 
deleteDocument(DocType * d)56 inline void deleteDocument(DocType *d) {
57     delete d;
58 }
59 
printDocument(DocType * d)60 inline std::string printDocument(DocType *d) {
61     tinyxml2::XMLPrinter p;
62     d->Print(&p);
63     return std::string{p.CStr()};
64 }
65 
createNode(const std::string & name,DocType * d)66 inline NodeType *createNode(const std::string &name, DocType *d) {
67     return d->NewElement(name.c_str());
68 }
69 
appendChild(NodeType * parent,NodeType * child)70 inline void appendChild(NodeType *parent, NodeType *child) {
71     parent->InsertEndChild(child);
72 }
73 
appendChild(DocType * parent,NodeType * child)74 inline void appendChild(DocType *parent, NodeType *child) {
75     parent->InsertEndChild(child);
76 }
77 
appendStrAttr(NodeType * e,const std::string & attrName,const std::string & attr)78 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
79     e->SetAttribute(attrName.c_str(), attr.c_str());
80 }
81 
82 // text -> text
appendText(NodeType * parent,const std::string & text,DocType * d)83 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
84     parent->InsertEndChild(d->NewText(text.c_str()));
85 }
86 
nameOf(NodeType * root)87 inline std::string nameOf(NodeType *root) {
88     return root->Name() == NULL ? "" : root->Name();
89 }
90 
getText(NodeType * root)91 inline std::string getText(NodeType *root) {
92     return root->GetText() == NULL ? "" : root->GetText();
93 }
94 
getChild(NodeType * parent,const std::string & name)95 inline NodeType *getChild(NodeType *parent, const std::string &name) {
96     return parent->FirstChildElement(name.c_str());
97 }
98 
getRootChild(DocType * parent)99 inline NodeType *getRootChild(DocType *parent) {
100     return parent->FirstChildElement();
101 }
102 
getChildren(NodeType * parent,const std::string & name)103 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
104     std::vector<NodeType *> v;
105     for (NodeType *child = parent->FirstChildElement(name.c_str());
106          child != nullptr;
107          child = child->NextSiblingElement(name.c_str())) {
108         v.push_back(child);
109     }
110     return v;
111 }
112 
getAttr(NodeType * root,const std::string & attrName,std::string * s)113 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
114     const char *c = root->Attribute(attrName.c_str());
115     if (c == NULL)
116         return false;
117     *s = c;
118     return true;
119 }
120 
121 // --------------- tinyxml2 details end.
122 
123 // Helper functions for XmlConverter
parse(const std::string & attrText,bool * attr)124 static bool parse(const std::string &attrText, bool *attr) {
125     if (attrText == "true" || attrText == "1") {
126         *attr = true;
127         return true;
128     }
129     if (attrText == "false" || attrText == "0") {
130         *attr = false;
131         return true;
132     }
133     return false;
134 }
135 
136 // ---------------------- XmlNodeConverter definitions
137 
138 template<typename Object>
139 struct XmlNodeConverter : public XmlConverter<Object> {
XmlNodeConverterandroid::vintf::XmlNodeConverter140     XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter141     virtual ~XmlNodeConverter() {}
142 
143     // sub-types should implement these.
144     virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
mutateNodeandroid::vintf::XmlNodeConverter145     virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
146         mutateNode(o, n, d);
147     }
148     virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
149     virtual std::string elementName() const = 0;
150 
151     // convenience methods for user
lastErrorandroid::vintf::XmlNodeConverter152     inline const std::string& lastError() const override { return mLastError; }
serializeandroid::vintf::XmlNodeConverter153     inline NodeType* serialize(const Object& o, DocType* d,
154                                SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
155         NodeType *root = createNode(this->elementName(), d);
156         this->mutateNode(o, root, d, flags);
157         return root;
158     }
serializeandroid::vintf::XmlNodeConverter159     inline std::string serialize(const Object& o, SerializeFlags::Type flags) const override {
160         DocType *doc = createDocument();
161         appendChild(doc, serialize(o, doc, flags));
162         std::string s = printDocument(doc);
163         deleteDocument(doc);
164         return s;
165     }
deserializeandroid::vintf::XmlNodeConverter166     inline bool deserialize(Object* object, NodeType* root) {
167         bool ret = deserialize(object, root, &mLastError);
168         return ret;
169     }
deserializeandroid::vintf::XmlNodeConverter170     inline bool deserialize(Object* o, const std::string& xml) override {
171         bool ret = (*this)(o, xml, &mLastError);
172         return ret;
173     }
deserializeandroid::vintf::XmlNodeConverter174     inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
175         if (nameOf(root) != this->elementName()) {
176             return false;
177         }
178         return this->buildObject(object, root, error);
179     }
operator ()android::vintf::XmlNodeConverter180     inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
181         std::string errorBuffer;
182         if (error == nullptr) error = &errorBuffer;
183 
184         auto doc = createDocument(xml);
185         if (doc == nullptr) {
186             *error = "Not a valid XML";
187             return false;
188         }
189         bool ret = deserialize(o, getRootChild(doc), error);
190         deleteDocument(doc);
191         return ret;
192     }
operator ()android::vintf::XmlNodeConverter193     inline NodeType *operator()(const Object &o, DocType *d) const {
194         return serialize(o, d);
195     }
operator ()android::vintf::XmlNodeConverter196     inline std::string operator()(const Object& o, SerializeFlags::Type flags) const override {
197         return serialize(o, flags);
198     }
operator ()android::vintf::XmlNodeConverter199     inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
operator ()android::vintf::XmlNodeConverter200     inline bool operator()(Object* o, const std::string& xml) override {
201         return deserialize(o, xml);
202     }
203 
204     // convenience methods for implementor.
205 
206     // All append* functions helps mutateNode() to serialize the object into XML.
207     template <typename T>
appendAttrandroid::vintf::XmlNodeConverter208     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
209         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
210     }
211 
appendAttrandroid::vintf::XmlNodeConverter212     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
213         return appendStrAttr(e, attrName, attr ? "true" : "false");
214     }
215 
216     // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter217     inline void appendTextElement(NodeType *parent, const std::string &name,
218                 const std::string &text, DocType *d) const {
219         NodeType *c = createNode(name, d);
220         appendText(c, text, d);
221         appendChild(parent, c);
222     }
223 
224     // text -> <name>text</name>
225     template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter226     inline void appendTextElements(NodeType *parent, const std::string &name,
227                 const Array &array, DocType *d) const {
228         for (const std::string &text : array) {
229             NodeType *c = createNode(name, d);
230             appendText(c, text, d);
231             appendChild(parent, c);
232         }
233     }
234 
235     template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter236     inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
237                                const Array& array, DocType* d,
238                                SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
239         for (const T &t : array) {
240             appendChild(parent, conv.serialize(t, d, flags));
241         }
242     }
243 
244     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
245     // true if deserialization is successful, false if any error, and "error" will be
246     // set to error message.
247     template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter248     inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
249                                   T* attr, std::string* /* error */) const {
250         std::string attrText;
251         bool success = getAttr(root, attrName, &attrText) &&
252                        ::android::vintf::parse(attrText, attr);
253         if (!success) {
254             *attr = std::move(defaultValue);
255         }
256         return true;
257     }
258 
259     template <typename T>
parseAttrandroid::vintf::XmlNodeConverter260     inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
261                           std::string* error) const {
262         std::string attrText;
263         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
264         if (!ret) {
265             *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
266                      attrText + "\" for element <" + elementName() + ">";
267         }
268         return ret;
269     }
270 
parseAttrandroid::vintf::XmlNodeConverter271     inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
272                           std::string* error) const {
273         bool ret = getAttr(root, attrName, attr);
274         if (!ret) {
275             *error = "Could not find attr with name \"" + attrName + "\" for element <" +
276                      elementName() + ">";
277         }
278         return ret;
279     }
280 
parseTextElementandroid::vintf::XmlNodeConverter281     inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
282                                  std::string* error) const {
283         NodeType *child = getChild(root, elementName);
284         if (child == nullptr) {
285             *error = "Could not find element with name <" + elementName + "> in element <" +
286                      this->elementName() + ">";
287             return false;
288         }
289         *s = getText(child);
290         return true;
291     }
292 
parseOptionalTextElementandroid::vintf::XmlNodeConverter293     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
294                                          std::string&& defaultValue, std::string* s,
295                                          std::string* /* error */) const {
296         NodeType* child = getChild(root, elementName);
297         *s = child == nullptr ? std::move(defaultValue) : getText(child);
298         return true;
299     }
300 
parseTextElementsandroid::vintf::XmlNodeConverter301     inline bool parseTextElements(NodeType* root, const std::string& elementName,
302                                   std::vector<std::string>* v, std::string* /* error */) const {
303         auto nodes = getChildren(root, elementName);
304         v->resize(nodes.size());
305         for (size_t i = 0; i < nodes.size(); ++i) {
306             v->at(i) = getText(nodes[i]);
307         }
308         return true;
309     }
310 
311     template <typename T>
parseChildandroid::vintf::XmlNodeConverter312     inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
313                            std::string* error) const {
314         NodeType *child = getChild(root, conv.elementName());
315         if (child == nullptr) {
316             *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
317                      this->elementName() + ">";
318             return false;
319         }
320         return conv.deserialize(t, child, error);
321     }
322 
323     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter324     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
325                                    T&& defaultValue, T* t, std::string* error) const {
326         NodeType *child = getChild(root, conv.elementName());
327         if (child == nullptr) {
328             *t = std::move(defaultValue);
329             return true;
330         }
331         return conv.deserialize(t, child, error);
332     }
333 
334     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter335     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
336                                    std::optional<T>* t, std::string* error) const {
337         NodeType* child = getChild(root, conv.elementName());
338         if (child == nullptr) {
339             *t = std::nullopt;
340             return true;
341         }
342         *t = std::make_optional<T>();
343         return conv.deserialize(&**t, child, error);
344     }
345 
346     template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter347     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
348                               std::string* error) const {
349         auto nodes = getChildren(root, conv.elementName());
350         v->resize(nodes.size());
351         for (size_t i = 0; i < nodes.size(); ++i) {
352             if (!conv.deserialize(&v->at(i), nodes[i], error)) {
353                 *error = "Could not parse element with name <" + conv.elementName() +
354                          "> in element <" + this->elementName() + ">: " + *error;
355                 return false;
356             }
357         }
358         return true;
359     }
360 
361     template <typename Container, typename T = typename Container::value_type,
362               typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter363     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
364                               std::string* error) const {
365         std::vector<T> vec;
366         if (!parseChildren(root, conv, &vec, error)) {
367             return false;
368         }
369         s->clear();
370         s->insert(vec.begin(), vec.end());
371         if (s->size() != vec.size()) {
372             *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
373                      this->elementName() + ">";
374             s->clear();
375             return false;
376         }
377         return true;
378     }
379 
380     template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter381     inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
382                               std::map<K, V>* s, std::string* error) const {
383         return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
384     }
385 
parseTextandroid::vintf::XmlNodeConverter386     inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
387         *s = getText(node);
388         return true;
389     }
390 
391     template <typename T>
parseTextandroid::vintf::XmlNodeConverter392     inline bool parseText(NodeType* node, T* s, std::string* error) const {
393         std::string text = getText(node);
394         bool ret = ::android::vintf::parse(text, s);
395         if (!ret) {
396             *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
397         }
398         return ret;
399     }
400 
401    private:
402     mutable std::string mLastError;
403 };
404 
405 template<typename Object>
406 struct XmlTextConverter : public XmlNodeConverter<Object> {
XmlTextConverterandroid::vintf::XmlTextConverter407     XmlTextConverter(const std::string &elementName)
408         : mElementName(elementName) {}
409 
mutateNodeandroid::vintf::XmlTextConverter410     virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
411         appendText(root, ::android::vintf::to_string(object), d);
412     }
buildObjectandroid::vintf::XmlTextConverter413     virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
414         return this->parseText(root, object, error);
415     }
elementNameandroid::vintf::XmlTextConverter416     virtual std::string elementName() const { return mElementName; }
417 
418    private:
419     std::string mElementName;
420 };
421 
422 template <typename Pair>
423 struct XmlPairConverter : public XmlNodeConverter<Pair> {
XmlPairConverterandroid::vintf::XmlPairConverter424     XmlPairConverter(
425         const std::string& elementName,
426         std::unique_ptr<XmlNodeConverter<typename Pair::first_type>>&& firstConverter,
427         std::unique_ptr<XmlNodeConverter<typename Pair::second_type>>&& secondConverter)
428         : mElementName(elementName),
429           mFirstConverter(std::move(firstConverter)),
430           mSecondConverter(std::move(secondConverter)) {}
431 
mutateNodeandroid::vintf::XmlPairConverter432     virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
433         appendChild(root, mFirstConverter->serialize(pair.first, d));
434         appendChild(root, mSecondConverter->serialize(pair.second, d));
435     }
buildObjectandroid::vintf::XmlPairConverter436     virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
437         return this->parseChild(root, *mFirstConverter, &pair->first, error) &&
438                this->parseChild(root, *mSecondConverter, &pair->second, error);
439     }
elementNameandroid::vintf::XmlPairConverter440     virtual std::string elementName() const { return mElementName; }
441 
442    private:
443     std::string mElementName;
444     std::unique_ptr<XmlNodeConverter<typename Pair::first_type>> mFirstConverter;
445     std::unique_ptr<XmlNodeConverter<typename Pair::second_type>> mSecondConverter;
446 };
447 
448 // ---------------------- XmlNodeConverter definitions end
449 
450 XmlTextConverter<Version> versionConverter{"version"};
451 
452 XmlTextConverter<VersionRange> versionRangeConverter{"version"};
453 
454 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter455     std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter456     void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
457         if (object.arch != Arch::ARCH_EMPTY) {
458             appendAttr(root, "arch", object.arch);
459         }
460         appendText(root, ::android::vintf::to_string(object.transport), d);
461     }
buildObjectandroid::vintf::TransportArchConverter462     bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
463         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
464             !parseText(root, &object->transport, error)) {
465             return false;
466         }
467         if (!object->isValid(error)) {
468             return false;
469         }
470         return true;
471     }
472 };
473 
474 TransportArchConverter transportArchConverter{};
475 
476 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter477     std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter478     void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
479         appendAttr(root, "type", object.mType);
480         appendText(root, ::android::vintf::to_string(object), d);
481     }
buildObjectandroid::vintf::KernelConfigTypedValueConverter482     bool buildObject(KernelConfigTypedValue* object, NodeType* root,
483                      std::string* error) const override {
484         std::string stringValue;
485         if (!parseAttr(root, "type", &object->mType, error) ||
486             !parseText(root, &stringValue, error)) {
487             return false;
488         }
489         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
490             *error = "Could not parse kernel config value \"" + stringValue + "\"";
491             return false;
492         }
493         return true;
494     }
495 };
496 
497 KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
498 
499 XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
500     "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
501     std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
502 
503 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter504     std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter505     void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
506         appendTextElement(root, "name", intf.name(), d);
507         appendTextElements(root, "instance", intf.mInstances, d);
508         appendTextElements(root, "regex-instance", intf.mRegexes, d);
509     }
buildObjectandroid::vintf::HalInterfaceConverter510     bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
511         std::vector<std::string> instances;
512         std::vector<std::string> regexes;
513         if (!parseTextElement(root, "name", &intf->mName, error) ||
514             !parseTextElements(root, "instance", &instances, error) ||
515             !parseTextElements(root, "regex-instance", &regexes, error)) {
516             return false;
517         }
518         bool success = true;
519         for (const auto& e : instances) {
520             if (!intf->insertInstance(e, false /* isRegex */)) {
521                 if (!error->empty()) *error += "\n";
522                 *error += "Duplicated instance '" + e + "' in " + intf->name();
523                 success = false;
524             }
525         }
526         for (const auto& e : regexes) {
527             details::Regex regex;
528             if (!regex.compile(e)) {
529                 if (!error->empty()) *error += "\n";
530                 *error += "Invalid regular expression '" + e + "' in " + intf->name();
531                 success = false;
532             }
533             if (!intf->insertInstance(e, true /* isRegex */)) {
534                 if (!error->empty()) *error += "\n";
535                 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
536                 success = false;
537             }
538         }
539         return success;
540     }
541 };
542 
543 HalInterfaceConverter halInterfaceConverter{};
544 
545 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter546     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter547     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
548         appendAttr(root, "format", hal.format);
549         appendAttr(root, "optional", hal.optional);
550         appendTextElement(root, "name", hal.name, d);
551         // Don't write <version> for format="aidl"
552         if (hal.format != HalFormat::AIDL) {
553             appendChildren(root, versionRangeConverter, hal.versionRanges, d);
554         }
555         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
556     }
buildObjectandroid::vintf::MatrixHalConverter557     bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
558         std::vector<HalInterface> interfaces;
559         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
560             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
561                                error) ||
562             !parseTextElement(root, "name", &object->name, error) ||
563             !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
564             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
565             return false;
566         }
567         if (object->format == HalFormat::AIDL) {
568             if (!object->versionRanges.empty()) {
569                 LOG(WARNING) << "Ignoring <version> on matrix <hal format=\"aidl\"> "
570                              << object->name;
571                 object->versionRanges.clear();
572             }
573             // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
574             // HAL formats can be unified.
575             object->versionRanges.push_back(details::kFakeAidlVersionRange);
576         }
577         for (auto&& interface : interfaces) {
578             std::string name{interface.name()};
579             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
580             if (!res.second) {
581                 *error = "Duplicated interface entry \"" + res.first->first +
582                          "\"; if additional instances are needed, add them to the "
583                          "existing <interface> node.";
584                 return false;
585             }
586         }
587 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
588 #ifndef LIBVINTF_TARGET
589         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
590             return false;
591         }
592 #endif
593         return true;
594     }
595 
596 #ifndef LIBVINTF_TARGET
597    private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter598     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
599         if (hal.getName() == "netutils-wrapper") {
600             if (hal.versionRanges.size() != 1) {
601                 *error =
602                     "netutils-wrapper HAL must specify exactly one version x.0, "
603                     "but multiple <version> element is specified.";
604                 return false;
605             }
606             const VersionRange& v = hal.versionRanges.at(0);
607             if (!v.isSingleVersion()) {
608                 *error =
609                     "netutils-wrapper HAL must specify exactly one version x.0, "
610                     "but a range is provided. Perhaps you mean '" +
611                     to_string(Version{v.majorVer, 0}) + "'?";
612                 return false;
613             }
614             if (v.minMinor != 0) {
615                 *error =
616                     "netutils-wrapper HAL must specify exactly one version x.0, "
617                     "but minor version is not 0. Perhaps you mean '" +
618                     to_string(Version{v.majorVer, 0}) + "'?";
619                 return false;
620             }
621         }
622         return true;
623     }
624 #endif
625 };
626 
627 MatrixHalConverter matrixHalConverter{};
628 
629 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter630     std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter631     void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
632                     DocType* d) const override {
633         appendChildren(root, matrixKernelConfigConverter, conds, d);
634     }
buildObjectandroid::vintf::MatrixKernelConditionsConverter635     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
636                      std::string* error) const override {
637         return parseChildren(root, matrixKernelConfigConverter, object, error);
638     }
639 };
640 
641 MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
642 
643 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter644     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter645     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
646         mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
647     }
mutateNodeandroid::vintf::MatrixKernelConverter648     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
649                     SerializeFlags::Type flags) const override {
650         KernelVersion kv = kernel.mMinLts;
651         if (!flags.isKernelMinorRevisionEnabled()) {
652             kv.minorRev = 0u;
653         }
654         appendAttr(root, "version", kv);
655 
656         if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
657             appendAttr(root, "level", kernel.getSourceMatrixLevel());
658         }
659 
660         if (!kernel.mConditions.empty()) {
661             appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
662         }
663         if (flags.isKernelConfigsEnabled()) {
664             appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
665         }
666     }
buildObjectandroid::vintf::MatrixKernelConverter667     bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
668         Level sourceMatrixLevel = Level::UNSPECIFIED;
669         if (!parseAttr(root, "version", &object->mMinLts, error) ||
670             !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
671             !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
672                                 error) ||
673             !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
674             return false;
675         }
676         object->setSourceMatrixLevel(sourceMatrixLevel);
677         return true;
678     }
679 };
680 
681 MatrixKernelConverter matrixKernelConverter{};
682 
683 XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
684 
685 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter686     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter687     void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
688         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
689     }
mutateNodeandroid::vintf::ManifestHalConverter690     void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
691                     SerializeFlags::Type flags) const override {
692         appendAttr(root, "format", hal.format);
693         appendTextElement(root, "name", hal.name, d);
694         if (!hal.transportArch.empty()) {
695             appendChild(root, transportArchConverter(hal.transportArch, d));
696         }
697         // Don't output <version> for format="aidl"
698         if (hal.format != HalFormat::AIDL) {
699             appendChildren(root, versionConverter, hal.versions, d);
700         }
701         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
702         if (hal.isOverride()) {
703             appendAttr(root, "override", hal.isOverride());
704         }
705 
706         if (flags.isFqnameEnabled()) {
707             std::set<std::string> simpleFqInstances;
708             hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
709                 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
710                 return true;
711             });
712             appendTextElements(root, fqInstanceConverter.elementName(), simpleFqInstances, d);
713         }
714     }
buildObjectandroid::vintf::ManifestHalConverter715     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
716         std::vector<HalInterface> interfaces;
717         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
718             !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
719             !parseTextElement(root, "name", &object->name, error) ||
720             !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
721             !parseChildren(root, versionConverter, &object->versions, error) ||
722             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
723             return false;
724         }
725 
726         switch (object->format) {
727             case HalFormat::HIDL: {
728                 if (object->transportArch.empty()) {
729                     *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
730                     return false;
731                 }
732             } break;
733             case HalFormat::NATIVE: {
734                 if (!object->transportArch.empty()) {
735                     *error =
736                         "Native HAL '" + object->name + "' should not have <transport> defined.";
737                     return false;
738                 }
739             } break;
740             case HalFormat::AIDL: {
741                 if (!object->transportArch.empty()) {
742                     LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
743                                  << object->name;
744                     object->transportArch = {};
745                 }
746                 if (!object->versions.empty()) {
747                     LOG(WARNING) << "Ignoring <version> on manifest <hal format=\"aidl\"> "
748                                  << object->name;
749                     object->versions.clear();
750                 }
751                 // Insert fake version for AIDL HALs so that forEachInstance works.
752                 object->versions.push_back(details::kFakeAidlVersion);
753             } break;
754             default: {
755                 LOG(FATAL) << "Unhandled HalFormat "
756                            << static_cast<typename std::underlying_type<HalFormat>::type>(
757                                   object->format);
758             } break;
759         }
760         if (!object->transportArch.isValid(error)) return false;
761 
762         object->interfaces.clear();
763         for (auto &&interface : interfaces) {
764             auto res = object->interfaces.emplace(interface.name(), std::move(interface));
765             if (!res.second) {
766                 *error = "Duplicated interface entry \"" + res.first->first +
767                          "\"; if additional instances are needed, add them to the "
768                          "existing <interface> node.";
769                 return false;
770             }
771         }
772         if (!object->isValid(error)) {
773             error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
774             return false;
775         }
776 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
777 #ifndef LIBVINTF_TARGET
778         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
779             return false;
780         }
781 #endif
782 
783         std::set<FqInstance> fqInstances;
784         if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
785             return false;
786         }
787         std::set<FqInstance> fqInstancesToInsert;
788         for (auto& e : fqInstances) {
789             if (e.hasPackage()) {
790                 *error = "Should not specify package: \"" + e.string() + "\"";
791                 return false;
792             }
793             if (object->format == HalFormat::AIDL) {
794                 // <fqname> in AIDL HALs should not contain version. Put in the fake
795                 // kFakeAidlVersion so that compatibility check works.
796                 FqInstance withFakeVersion;
797                 if (!withFakeVersion.setTo(details::kFakeAidlVersion.majorVer,
798                                            details::kFakeAidlVersion.minorVer, e.getInterface(),
799                                            e.getInstance())) {
800                     return false;
801                 }
802                 fqInstancesToInsert.emplace(std::move(withFakeVersion));
803             } else {
804                 fqInstancesToInsert.emplace(std::move(e));
805             }
806         }
807         if (!object->insertInstances(fqInstancesToInsert, error)) {
808             return false;
809         }
810 
811         return true;
812     }
813 
814 #ifndef LIBVINTF_TARGET
815    private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter816     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
817         if (hal.getName() == "netutils-wrapper") {
818             for (const Version& v : hal.versions) {
819                 if (v.minorVer != 0) {
820                     *error =
821                         "netutils-wrapper HAL must specify exactly one version x.0, "
822                         "but minor version is not 0. Perhaps you mean '" +
823                         to_string(Version{v.majorVer, 0}) + "'?";
824                     return false;
825                 }
826             }
827         }
828         return true;
829     }
830 #endif
831 };
832 
833 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
834 // .isValid() == true.
835 ManifestHalConverter manifestHalConverter{};
836 
837 XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
838 XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
839 
840 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter841     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter842     void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
843         appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
844         appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
845     }
buildObjectandroid::vintf::SepolicyConverter846     bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
847         if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
848                         error) ||
849             !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
850                            error)) {
851             return false;
852         }
853         return true;
854     }
855 };
856 SepolicyConverter sepolicyConverter{};
857 
858 [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
859 
860 XmlTextConverter<std::string> vndkVersionConverter{"version"};
861 XmlTextConverter<std::string> vndkLibraryConverter{"library"};
862 
863 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter864     std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter865     void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
866         appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
867         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
868     }
buildObjectandroid::vintf::VndkConverter869     bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
870         if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
871             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
872             return false;
873         }
874         return true;
875     }
876 };
877 
878 [[deprecated]] VndkConverter vndkConverter{};
879 
880 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter881     std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter882     void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
883         appendChild(root, vndkVersionConverter(object.mVersion, d));
884         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
885     }
buildObjectandroid::vintf::VendorNdkConverter886     bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
887         if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
888             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
889             return false;
890         }
891         return true;
892     }
893 };
894 
895 VendorNdkConverter vendorNdkConverter{};
896 
897 XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
898 
899 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter900     std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter901     void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
902         appendChildren(root, systemSdkVersionConverter, object.versions(), d);
903     }
buildObjectandroid::vintf::SystemSdkConverter904     bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
905         return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
906     }
907 };
908 
909 SystemSdkConverter systemSdkConverter{};
910 
911 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter912     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter913     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
914         appendChild(root, versionConverter(m, d));
915     }
buildObjectandroid::vintf::HalManifestSepolicyConverter916     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
917         return parseChild(root, versionConverter, object, error);
918     }
919 };
920 HalManifestSepolicyConverter halManifestSepolicyConverter{};
921 
922 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter923     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter924     void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
925         appendTextElement(root, "name", f.name(), d);
926         appendChild(root, versionConverter(f.version(), d));
927         if (!f.overriddenPath().empty()) {
928             appendTextElement(root, "path", f.overriddenPath(), d);
929         }
930     }
buildObjectandroid::vintf::ManifestXmlFileConverter931     bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
932         if (!parseTextElement(root, "name", &object->mName, error) ||
933             !parseChild(root, versionConverter, &object->mVersion, error) ||
934             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
935             return false;
936         }
937         return true;
938     }
939 };
940 ManifestXmlFileConverter manifestXmlFileConverter{};
941 
942 XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
943     "config", std::make_unique<XmlTextConverter<std::string>>("key"),
944     std::make_unique<XmlTextConverter<std::string>>("value")};
945 
946 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter947     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter948     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
949         mutateNode(o, root, d, SerializeFlags::EVERYTHING);
950     }
mutateNodeandroid::vintf::KernelInfoConverter951     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
952                     SerializeFlags::Type flags) const override {
953         if (o.version() != KernelVersion{}) {
954             appendAttr(root, "version", o.version());
955         }
956         if (o.level() != Level::UNSPECIFIED) {
957             appendAttr(root, "target-level", o.level());
958         }
959         if (flags.isKernelConfigsEnabled()) {
960             appendChildren(root, kernelConfigConverter, o.configs(), d);
961         }
962     }
buildObjectandroid::vintf::KernelInfoConverter963     bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
964         return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
965                parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
966                parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
967     }
968 };
969 
970 KernelInfoConverter kernelInfoConverter{};
971 
972 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter973     std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter974     void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
975         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
976     }
mutateNodeandroid::vintf::HalManifestConverter977     void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
978                     SerializeFlags::Type flags) const override {
979         if (flags.isMetaVersionEnabled()) {
980             appendAttr(root, "version", m.getMetaVersion());
981         }
982         if (flags.isSchemaTypeEnabled()) {
983             appendAttr(root, "type", m.mType);
984         }
985 
986         if (flags.isHalsEnabled()) {
987             appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
988         }
989         if (m.mType == SchemaType::DEVICE) {
990             if (flags.isSepolicyEnabled()) {
991                 if (m.device.mSepolicyVersion != Version{}) {
992                     appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
993                 }
994             }
995             if (m.mLevel != Level::UNSPECIFIED) {
996                 this->appendAttr(root, "target-level", m.mLevel);
997             }
998 
999             if (flags.isKernelEnabled()) {
1000                 if (!!m.kernel()) {
1001                     appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
1002                 }
1003             }
1004         } else if (m.mType == SchemaType::FRAMEWORK) {
1005             if (flags.isVndkEnabled()) {
1006 #pragma clang diagnostic push
1007 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1008                 appendChildren(root, vndkConverter, m.framework.mVndks, d);
1009 #pragma clang diagnostic pop
1010 
1011                 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
1012             }
1013             if (flags.isSsdkEnabled()) {
1014                 if (!m.framework.mSystemSdk.empty()) {
1015                     appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
1016                 }
1017             }
1018         }
1019 
1020         if (flags.isXmlFilesEnabled()) {
1021             appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
1022         }
1023     }
buildObjectandroid::vintf::HalManifestConverter1024     bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
1025         Version metaVersion;
1026         if (!parseAttr(root, "version", &metaVersion, error)) return false;
1027         if (metaVersion > kMetaVersion) {
1028             *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1029                      to_string(kMetaVersion) + ")";
1030             return false;
1031         }
1032 
1033         if (!parseAttr(root, "type", &object->mType, error)) {
1034             return false;
1035         }
1036 
1037         std::vector<ManifestHal> hals;
1038         if (!parseChildren(root, manifestHalConverter, &hals, error)) {
1039             return false;
1040         }
1041         for (auto&& hal : hals) {
1042             hal.setFileName(object->fileName());
1043         }
1044 
1045         if (object->mType == SchemaType::DEVICE) {
1046             // tags for device hal manifest only.
1047             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1048             // in the XML file.
1049             if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
1050                                     &object->device.mSepolicyVersion, error)) {
1051                 return false;
1052             }
1053 
1054             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1055                                    error)) {
1056                 return false;
1057             }
1058 
1059             if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
1060                 return false;
1061             }
1062         } else if (object->mType == SchemaType::FRAMEWORK) {
1063 #pragma clang diagnostic push
1064 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1065             if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
1066                 return false;
1067             }
1068             for (const auto &vndk : object->framework.mVndks) {
1069                 if (!vndk.mVersionRange.isSingleVersion()) {
1070                     *error = "vndk.version " + to_string(vndk.mVersionRange) +
1071                              " cannot be a range for manifests";
1072                     return false;
1073                 }
1074             }
1075 #pragma clang diagnostic pop
1076 
1077             if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
1078                 return false;
1079             }
1080 
1081             std::set<std::string> vendorNdkVersions;
1082             for (const auto& vendorNdk : object->framework.mVendorNdks) {
1083                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1084                     *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1085                     return false;
1086                 }
1087                 vendorNdkVersions.insert(vendorNdk.version());
1088             }
1089 
1090             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
1091                                     error)) {
1092                 return false;
1093             }
1094         }
1095         for (auto &&hal : hals) {
1096             std::string description{hal.name};
1097             if (!object->add(std::move(hal))) {
1098                 *error = "Duplicated manifest.hal entry " + description;
1099                 return false;
1100             }
1101         }
1102 
1103         std::vector<ManifestXmlFile> xmlFiles;
1104         if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
1105             return false;
1106         }
1107         for (auto&& xmlFile : xmlFiles) {
1108             std::string description{xmlFile.name()};
1109             if (!object->addXmlFile(std::move(xmlFile))) {
1110                 *error = "Duplicated manifest.xmlfile entry " + description +
1111                          "; entries cannot have duplicated name and version";
1112                 return false;
1113             }
1114         }
1115 
1116         return true;
1117     }
1118 };
1119 
1120 HalManifestConverter halManifestConverter{};
1121 
1122 XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
1123 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1124     std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1125     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1126         appendChild(root, avbVersionConverter(m, d));
1127     }
buildObjectandroid::vintf::AvbConverter1128     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1129         return parseChild(root, avbVersionConverter, object, error);
1130     }
1131 };
1132 AvbConverter avbConverter{};
1133 
1134 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1135     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1136     void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1137         appendTextElement(root, "name", f.name(), d);
1138         appendAttr(root, "format", f.format());
1139         appendAttr(root, "optional", f.optional());
1140         appendChild(root, versionRangeConverter(f.versionRange(), d));
1141         if (!f.overriddenPath().empty()) {
1142             appendTextElement(root, "path", f.overriddenPath(), d);
1143         }
1144     }
buildObjectandroid::vintf::MatrixXmlFileConverter1145     bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1146         if (!parseTextElement(root, "name", &object->mName, error) ||
1147             !parseAttr(root, "format", &object->mFormat, error) ||
1148             !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1149             !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
1150             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1151             return false;
1152         }
1153         return true;
1154     }
1155 };
1156 MatrixXmlFileConverter matrixXmlFileConverter{};
1157 
1158 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1159     std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1160     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1161         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1162     }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1163     void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1164                     SerializeFlags::Type flags) const override {
1165         if (flags.isMetaVersionEnabled()) {
1166             appendAttr(root, "version", kMetaVersion);
1167         }
1168         if (flags.isSchemaTypeEnabled()) {
1169             appendAttr(root, "type", m.mType);
1170         }
1171 
1172         if (flags.isHalsEnabled()) {
1173             appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
1174         }
1175         if (m.mType == SchemaType::FRAMEWORK) {
1176             if (flags.isKernelEnabled()) {
1177                 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
1178             }
1179             if (flags.isSepolicyEnabled()) {
1180                 if (!(m.framework.mSepolicy == Sepolicy{})) {
1181                     appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
1182                 }
1183             }
1184             if (flags.isAvbEnabled()) {
1185                 if (!(m.framework.mAvbMetaVersion == Version{})) {
1186                     appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
1187                 }
1188             }
1189             if (m.mLevel != Level::UNSPECIFIED) {
1190                 this->appendAttr(root, "level", m.mLevel);
1191             }
1192         } else if (m.mType == SchemaType::DEVICE) {
1193             if (flags.isVndkEnabled()) {
1194 #pragma clang diagnostic push
1195 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1196                 if (!(m.device.mVndk == Vndk{})) {
1197                     appendChild(root, vndkConverter(m.device.mVndk, d));
1198                 }
1199 #pragma clang diagnostic pop
1200 
1201                 if (!(m.device.mVendorNdk == VendorNdk{})) {
1202                     appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
1203                 }
1204             }
1205 
1206             if (flags.isSsdkEnabled()) {
1207                 if (!m.device.mSystemSdk.empty()) {
1208                     appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
1209                 }
1210             }
1211         }
1212 
1213         if (flags.isXmlFilesEnabled()) {
1214             appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
1215         }
1216     }
buildObjectandroid::vintf::CompatibilityMatrixConverter1217     bool buildObject(CompatibilityMatrix* object, NodeType* root,
1218                      std::string* error) const override {
1219         Version metaVersion;
1220         if (!parseAttr(root, "version", &metaVersion, error)) return false;
1221         if (metaVersion > kMetaVersion) {
1222             *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1223                      " (libvintf@" + to_string(kMetaVersion) + ")";
1224             return false;
1225         }
1226 
1227         std::vector<MatrixHal> hals;
1228         if (!parseAttr(root, "type", &object->mType, error) ||
1229             !parseChildren(root, matrixHalConverter, &hals, error)) {
1230             return false;
1231         }
1232 
1233         if (object->mType == SchemaType::FRAMEWORK) {
1234             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1235             // hard-coded in the XML file.
1236             if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1237                 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1238                                     error) ||
1239                 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1240                                     error)) {
1241                 return false;
1242             }
1243 
1244             std::set<Version> seenKernelVersions;
1245             for (const auto& kernel : object->framework.mKernels) {
1246                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1247                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1248                     continue;
1249                 }
1250                 if (!kernel.conditions().empty()) {
1251                     *error = "First <kernel> for version " + to_string(minLts) +
1252                              " must have empty <conditions> for backwards compatibility.";
1253                     return false;
1254                 }
1255                 seenKernelVersions.insert(minLts);
1256             }
1257 
1258             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1259                 return false;
1260             }
1261 
1262         } else if (object->mType == SchemaType::DEVICE) {
1263             // <vndk> can be missing because it can be determined at build time, not hard-coded
1264             // in the XML file.
1265 #pragma clang diagnostic push
1266 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1267             if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
1268                 return false;
1269             }
1270 #pragma clang diagnostic pop
1271 
1272             if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1273                                     error)) {
1274                 return false;
1275             }
1276 
1277             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1278                                     error)) {
1279                 return false;
1280             }
1281         }
1282 
1283         for (auto &&hal : hals) {
1284             if (!object->add(std::move(hal))) {
1285                 *error = "Duplicated compatibility-matrix.hal entry";
1286                 return false;
1287             }
1288         }
1289 
1290         std::vector<MatrixXmlFile> xmlFiles;
1291         if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
1292             return false;
1293         }
1294         for (auto&& xmlFile : xmlFiles) {
1295             if (!xmlFile.optional()) {
1296                 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1297                          " has to be optional for compatibility matrix version 1.0";
1298                 return false;
1299             }
1300             std::string description{xmlFile.name()};
1301             if (!object->addXmlFile(std::move(xmlFile))) {
1302                 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1303                 return false;
1304             }
1305         }
1306 
1307         return true;
1308     }
1309 };
1310 
1311 CompatibilityMatrixConverter compatibilityMatrixConverter{};
1312 
1313 // Publicly available as in parse_xml.h
1314 XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1315 XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
1316 
1317 // For testing in LibVintfTest
1318 XmlConverter<Version>& gVersionConverter = versionConverter;
1319 XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1320     kernelConfigTypedValueConverter;
1321 XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1322 XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
1323 XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
1324 
1325 } // namespace vintf
1326 } // namespace android
1327