• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()) {
468             *error = "transport == " + ::android::vintf::to_string(object->transport) +
469                      " and arch == " + ::android::vintf::to_string(object->arch) +
470                      " is not a valid combination.";
471             return false;
472         }
473         return true;
474     }
475 };
476 
477 TransportArchConverter transportArchConverter{};
478 
479 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter480     std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter481     void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
482         appendAttr(root, "type", object.mType);
483         appendText(root, ::android::vintf::to_string(object), d);
484     }
buildObjectandroid::vintf::KernelConfigTypedValueConverter485     bool buildObject(KernelConfigTypedValue* object, NodeType* root,
486                      std::string* error) const override {
487         std::string stringValue;
488         if (!parseAttr(root, "type", &object->mType, error) ||
489             !parseText(root, &stringValue, error)) {
490             return false;
491         }
492         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
493             *error = "Could not parse kernel config value \"" + stringValue + "\"";
494             return false;
495         }
496         return true;
497     }
498 };
499 
500 KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
501 
502 XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
503     "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
504     std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
505 
506 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter507     std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter508     void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
509         appendTextElement(root, "name", intf.name(), d);
510         appendTextElements(root, "instance", intf.mInstances, d);
511         appendTextElements(root, "regex-instance", intf.mRegexes, d);
512     }
buildObjectandroid::vintf::HalInterfaceConverter513     bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
514         std::vector<std::string> instances;
515         std::vector<std::string> regexes;
516         if (!parseTextElement(root, "name", &intf->mName, error) ||
517             !parseTextElements(root, "instance", &instances, error) ||
518             !parseTextElements(root, "regex-instance", &regexes, error)) {
519             return false;
520         }
521         bool success = true;
522         for (const auto& e : instances) {
523             if (!intf->insertInstance(e, false /* isRegex */)) {
524                 if (!error->empty()) *error += "\n";
525                 *error += "Duplicated instance '" + e + "' in " + intf->name();
526                 success = false;
527             }
528         }
529         for (const auto& e : regexes) {
530             details::Regex regex;
531             if (!regex.compile(e)) {
532                 if (!error->empty()) *error += "\n";
533                 *error += "Invalid regular expression '" + e + "' in " + intf->name();
534                 success = false;
535             }
536             if (!intf->insertInstance(e, true /* isRegex */)) {
537                 if (!error->empty()) *error += "\n";
538                 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
539                 success = false;
540             }
541         }
542         return success;
543     }
544 };
545 
546 HalInterfaceConverter halInterfaceConverter{};
547 
548 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter549     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter550     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
551         appendAttr(root, "format", hal.format);
552         appendAttr(root, "optional", hal.optional);
553         appendTextElement(root, "name", hal.name, d);
554         // Don't write <version> for format="aidl"
555         if (hal.format != HalFormat::AIDL) {
556             appendChildren(root, versionRangeConverter, hal.versionRanges, d);
557         }
558         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
559     }
buildObjectandroid::vintf::MatrixHalConverter560     bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
561         std::vector<HalInterface> interfaces;
562         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
563             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
564                                error) ||
565             !parseTextElement(root, "name", &object->name, error) ||
566             !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
567             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
568             return false;
569         }
570         if (object->format == HalFormat::AIDL) {
571             if (!object->versionRanges.empty()) {
572                 LOG(WARNING) << "Ignoring <version> on matrix <hal format=\"aidl\"> "
573                              << object->name;
574                 object->versionRanges.clear();
575             }
576             // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
577             // HAL formats can be unified.
578             object->versionRanges.push_back(details::kFakeAidlVersionRange);
579         }
580         for (auto&& interface : interfaces) {
581             std::string name{interface.name()};
582             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
583             if (!res.second) {
584                 *error = "Duplicated interface entry \"" + res.first->first +
585                          "\"; if additional instances are needed, add them to the "
586                          "existing <interface> node.";
587                 return false;
588             }
589         }
590 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
591 #ifndef LIBVINTF_TARGET
592         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
593             return false;
594         }
595 #endif
596         return true;
597     }
598 
599 #ifndef LIBVINTF_TARGET
600    private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter601     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
602         if (hal.getName() == "netutils-wrapper") {
603             if (hal.versionRanges.size() != 1) {
604                 *error =
605                     "netutils-wrapper HAL must specify exactly one version x.0, "
606                     "but multiple <version> element is specified.";
607                 return false;
608             }
609             const VersionRange& v = hal.versionRanges.at(0);
610             if (!v.isSingleVersion()) {
611                 *error =
612                     "netutils-wrapper HAL must specify exactly one version x.0, "
613                     "but a range is provided. Perhaps you mean '" +
614                     to_string(Version{v.majorVer, 0}) + "'?";
615                 return false;
616             }
617             if (v.minMinor != 0) {
618                 *error =
619                     "netutils-wrapper HAL must specify exactly one version x.0, "
620                     "but minor version is not 0. Perhaps you mean '" +
621                     to_string(Version{v.majorVer, 0}) + "'?";
622                 return false;
623             }
624         }
625         return true;
626     }
627 #endif
628 };
629 
630 MatrixHalConverter matrixHalConverter{};
631 
632 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter633     std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter634     void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
635                     DocType* d) const override {
636         appendChildren(root, matrixKernelConfigConverter, conds, d);
637     }
buildObjectandroid::vintf::MatrixKernelConditionsConverter638     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
639                      std::string* error) const override {
640         return parseChildren(root, matrixKernelConfigConverter, object, error);
641     }
642 };
643 
644 MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
645 
646 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter647     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter648     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
649         mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
650     }
mutateNodeandroid::vintf::MatrixKernelConverter651     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
652                     SerializeFlags::Type flags) const override {
653         KernelVersion kv = kernel.mMinLts;
654         if (!flags.isKernelMinorRevisionEnabled()) {
655             kv.minorRev = 0u;
656         }
657         appendAttr(root, "version", kv);
658 
659         if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
660             appendAttr(root, "level", kernel.getSourceMatrixLevel());
661         }
662 
663         if (!kernel.mConditions.empty()) {
664             appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
665         }
666         if (flags.isKernelConfigsEnabled()) {
667             appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
668         }
669     }
buildObjectandroid::vintf::MatrixKernelConverter670     bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
671         Level sourceMatrixLevel = Level::UNSPECIFIED;
672         if (!parseAttr(root, "version", &object->mMinLts, error) ||
673             !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
674             !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
675                                 error) ||
676             !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
677             return false;
678         }
679         object->setSourceMatrixLevel(sourceMatrixLevel);
680         return true;
681     }
682 };
683 
684 MatrixKernelConverter matrixKernelConverter{};
685 
686 XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
687 
688 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter689     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter690     void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
691         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
692     }
mutateNodeandroid::vintf::ManifestHalConverter693     void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
694                     SerializeFlags::Type flags) const override {
695         appendAttr(root, "format", hal.format);
696         appendTextElement(root, "name", hal.name, d);
697         if (!hal.transportArch.empty()) {
698             appendChild(root, transportArchConverter(hal.transportArch, d));
699         }
700         // Don't output <version> for format="aidl"
701         if (hal.format != HalFormat::AIDL) {
702             appendChildren(root, versionConverter, hal.versions, d);
703         }
704         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
705         if (hal.isOverride()) {
706             appendAttr(root, "override", hal.isOverride());
707         }
708 
709         if (flags.isFqnameEnabled()) {
710             std::set<std::string> simpleFqInstances;
711             hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
712                 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
713                 return true;
714             });
715             appendTextElements(root, fqInstanceConverter.elementName(), simpleFqInstances, d);
716         }
717     }
buildObjectandroid::vintf::ManifestHalConverter718     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
719         std::vector<HalInterface> interfaces;
720         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
721             !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
722             !parseTextElement(root, "name", &object->name, error) ||
723             !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
724             !parseChildren(root, versionConverter, &object->versions, error) ||
725             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
726             return false;
727         }
728 
729         switch (object->format) {
730             case HalFormat::HIDL: {
731                 if (object->transportArch.empty()) {
732                     *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
733                     return false;
734                 }
735             } break;
736             case HalFormat::NATIVE: {
737                 if (!object->transportArch.empty()) {
738                     *error =
739                         "Native HAL '" + object->name + "' should not have <transport> defined.";
740                     return false;
741                 }
742             } break;
743             case HalFormat::AIDL: {
744                 if (!object->transportArch.empty()) {
745                     LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
746                                  << object->name;
747                     object->transportArch = {};
748                 }
749                 if (!object->versions.empty()) {
750                     LOG(WARNING) << "Ignoring <version> on manifest <hal format=\"aidl\"> "
751                                  << object->name;
752                     object->versions.clear();
753                 }
754                 // Insert fake version for AIDL HALs so that forEachInstance works.
755                 object->versions.push_back(details::kFakeAidlVersion);
756             } break;
757             default: {
758                 LOG(FATAL) << "Unhandled HalFormat "
759                            << static_cast<typename std::underlying_type<HalFormat>::type>(
760                                   object->format);
761             } break;
762         }
763         if (!object->transportArch.isValid()) return false;
764 
765         object->interfaces.clear();
766         for (auto &&interface : interfaces) {
767             auto res = object->interfaces.emplace(interface.name(), std::move(interface));
768             if (!res.second) {
769                 *error = "Duplicated interface entry \"" + res.first->first +
770                          "\"; if additional instances are needed, add them to the "
771                          "existing <interface> node.";
772                 return false;
773             }
774         }
775         if (!object->isValid()) {
776             *error = "'" + object->name + "' is not a valid Manifest HAL.";
777             return false;
778         }
779 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
780 #ifndef LIBVINTF_TARGET
781         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
782             return false;
783         }
784 #endif
785 
786         std::set<FqInstance> fqInstances;
787         if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
788             return false;
789         }
790         std::set<FqInstance> fqInstancesToInsert;
791         for (auto& e : fqInstances) {
792             if (e.hasPackage()) {
793                 *error = "Should not specify package: \"" + e.string() + "\"";
794                 return false;
795             }
796             if (object->format == HalFormat::AIDL) {
797                 // <fqname> in AIDL HALs should not contain version. Put in the fake
798                 // kFakeAidlVersion so that compatibility check works.
799                 FqInstance withFakeVersion;
800                 if (!withFakeVersion.setTo(details::kFakeAidlVersion.majorVer,
801                                            details::kFakeAidlVersion.minorVer, e.getInterface(),
802                                            e.getInstance())) {
803                     return false;
804                 }
805                 fqInstancesToInsert.emplace(std::move(withFakeVersion));
806             } else {
807                 fqInstancesToInsert.emplace(std::move(e));
808             }
809         }
810         if (!object->insertInstances(fqInstancesToInsert, error)) {
811             return false;
812         }
813 
814         return true;
815     }
816 
817 #ifndef LIBVINTF_TARGET
818    private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter819     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
820         if (hal.getName() == "netutils-wrapper") {
821             for (const Version& v : hal.versions) {
822                 if (v.minorVer != 0) {
823                     *error =
824                         "netutils-wrapper HAL must specify exactly one version x.0, "
825                         "but minor version is not 0. Perhaps you mean '" +
826                         to_string(Version{v.majorVer, 0}) + "'?";
827                     return false;
828                 }
829             }
830         }
831         return true;
832     }
833 #endif
834 };
835 
836 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
837 // .isValid() == true.
838 ManifestHalConverter manifestHalConverter{};
839 
840 XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
841 XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
842 
843 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter844     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter845     void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
846         appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
847         appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
848     }
buildObjectandroid::vintf::SepolicyConverter849     bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
850         if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
851                         error) ||
852             !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
853                            error)) {
854             return false;
855         }
856         return true;
857     }
858 };
859 SepolicyConverter sepolicyConverter{};
860 
861 [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
862 
863 XmlTextConverter<std::string> vndkVersionConverter{"version"};
864 XmlTextConverter<std::string> vndkLibraryConverter{"library"};
865 
866 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter867     std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter868     void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
869         appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
870         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
871     }
buildObjectandroid::vintf::VndkConverter872     bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
873         if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
874             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
875             return false;
876         }
877         return true;
878     }
879 };
880 
881 [[deprecated]] VndkConverter vndkConverter{};
882 
883 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter884     std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter885     void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
886         appendChild(root, vndkVersionConverter(object.mVersion, d));
887         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
888     }
buildObjectandroid::vintf::VendorNdkConverter889     bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
890         if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
891             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
892             return false;
893         }
894         return true;
895     }
896 };
897 
898 VendorNdkConverter vendorNdkConverter{};
899 
900 XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
901 
902 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter903     std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter904     void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
905         appendChildren(root, systemSdkVersionConverter, object.versions(), d);
906     }
buildObjectandroid::vintf::SystemSdkConverter907     bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
908         return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
909     }
910 };
911 
912 SystemSdkConverter systemSdkConverter{};
913 
914 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter915     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter916     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
917         appendChild(root, versionConverter(m, d));
918     }
buildObjectandroid::vintf::HalManifestSepolicyConverter919     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
920         return parseChild(root, versionConverter, object, error);
921     }
922 };
923 HalManifestSepolicyConverter halManifestSepolicyConverter{};
924 
925 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter926     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter927     void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
928         appendTextElement(root, "name", f.name(), d);
929         appendChild(root, versionConverter(f.version(), d));
930         if (!f.overriddenPath().empty()) {
931             appendTextElement(root, "path", f.overriddenPath(), d);
932         }
933     }
buildObjectandroid::vintf::ManifestXmlFileConverter934     bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
935         if (!parseTextElement(root, "name", &object->mName, error) ||
936             !parseChild(root, versionConverter, &object->mVersion, error) ||
937             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
938             return false;
939         }
940         return true;
941     }
942 };
943 ManifestXmlFileConverter manifestXmlFileConverter{};
944 
945 XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
946     "config", std::make_unique<XmlTextConverter<std::string>>("key"),
947     std::make_unique<XmlTextConverter<std::string>>("value")};
948 
949 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter950     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter951     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
952         mutateNode(o, root, d, SerializeFlags::EVERYTHING);
953     }
mutateNodeandroid::vintf::KernelInfoConverter954     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
955                     SerializeFlags::Type flags) const override {
956         if (o.version() != KernelVersion{}) {
957             appendAttr(root, "version", o.version());
958         }
959         if (o.level() != Level::UNSPECIFIED) {
960             appendAttr(root, "target-level", o.level());
961         }
962         if (flags.isKernelConfigsEnabled()) {
963             appendChildren(root, kernelConfigConverter, o.configs(), d);
964         }
965     }
buildObjectandroid::vintf::KernelInfoConverter966     bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
967         return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
968                parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
969                parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
970     }
971 };
972 
973 KernelInfoConverter kernelInfoConverter{};
974 
975 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter976     std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter977     void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
978         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
979     }
mutateNodeandroid::vintf::HalManifestConverter980     void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
981                     SerializeFlags::Type flags) const override {
982         if (flags.isMetaVersionEnabled()) {
983             appendAttr(root, "version", m.getMetaVersion());
984         }
985         if (flags.isSchemaTypeEnabled()) {
986             appendAttr(root, "type", m.mType);
987         }
988 
989         if (flags.isHalsEnabled()) {
990             appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
991         }
992         if (m.mType == SchemaType::DEVICE) {
993             if (flags.isSepolicyEnabled()) {
994                 if (m.device.mSepolicyVersion != Version{}) {
995                     appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
996                 }
997             }
998             if (m.mLevel != Level::UNSPECIFIED) {
999                 this->appendAttr(root, "target-level", m.mLevel);
1000             }
1001 
1002             if (flags.isKernelEnabled()) {
1003                 if (!!m.kernel()) {
1004                     appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
1005                 }
1006             }
1007         } else if (m.mType == SchemaType::FRAMEWORK) {
1008             if (flags.isVndkEnabled()) {
1009 #pragma clang diagnostic push
1010 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1011                 appendChildren(root, vndkConverter, m.framework.mVndks, d);
1012 #pragma clang diagnostic pop
1013 
1014                 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
1015             }
1016             if (flags.isSsdkEnabled()) {
1017                 if (!m.framework.mSystemSdk.empty()) {
1018                     appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
1019                 }
1020             }
1021         }
1022 
1023         if (flags.isXmlFilesEnabled()) {
1024             appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
1025         }
1026     }
buildObjectandroid::vintf::HalManifestConverter1027     bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
1028         Version metaVersion;
1029         if (!parseAttr(root, "version", &metaVersion, error)) return false;
1030         if (metaVersion > kMetaVersion) {
1031             *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1032                      to_string(kMetaVersion) + ")";
1033             return false;
1034         }
1035 
1036         std::vector<ManifestHal> hals;
1037         if (!parseAttr(root, "type", &object->mType, error) ||
1038             !parseChildren(root, manifestHalConverter, &hals, error)) {
1039             return false;
1040         }
1041         if (object->mType == SchemaType::DEVICE) {
1042             // tags for device hal manifest only.
1043             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1044             // in the XML file.
1045             if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
1046                                     &object->device.mSepolicyVersion, error)) {
1047                 return false;
1048             }
1049 
1050             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1051                                    error)) {
1052                 return false;
1053             }
1054 
1055             if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
1056                 return false;
1057             }
1058         } else if (object->mType == SchemaType::FRAMEWORK) {
1059 #pragma clang diagnostic push
1060 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1061             if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
1062                 return false;
1063             }
1064             for (const auto &vndk : object->framework.mVndks) {
1065                 if (!vndk.mVersionRange.isSingleVersion()) {
1066                     *error = "vndk.version " + to_string(vndk.mVersionRange) +
1067                              " cannot be a range for manifests";
1068                     return false;
1069                 }
1070             }
1071 #pragma clang diagnostic pop
1072 
1073             if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
1074                 return false;
1075             }
1076 
1077             std::set<std::string> vendorNdkVersions;
1078             for (const auto& vendorNdk : object->framework.mVendorNdks) {
1079                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1080                     *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1081                     return false;
1082                 }
1083                 vendorNdkVersions.insert(vendorNdk.version());
1084             }
1085 
1086             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
1087                                     error)) {
1088                 return false;
1089             }
1090         }
1091         for (auto &&hal : hals) {
1092             std::string description{hal.name};
1093             if (!object->add(std::move(hal))) {
1094                 *error = "Duplicated manifest.hal entry " + description;
1095                 return false;
1096             }
1097         }
1098 
1099         std::vector<ManifestXmlFile> xmlFiles;
1100         if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
1101             return false;
1102         }
1103         for (auto&& xmlFile : xmlFiles) {
1104             std::string description{xmlFile.name()};
1105             if (!object->addXmlFile(std::move(xmlFile))) {
1106                 *error = "Duplicated manifest.xmlfile entry " + description +
1107                          "; entries cannot have duplicated name and version";
1108                 return false;
1109             }
1110         }
1111 
1112         return true;
1113     }
1114 };
1115 
1116 HalManifestConverter halManifestConverter{};
1117 
1118 XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
1119 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1120     std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1121     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1122         appendChild(root, avbVersionConverter(m, d));
1123     }
buildObjectandroid::vintf::AvbConverter1124     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1125         return parseChild(root, avbVersionConverter, object, error);
1126     }
1127 };
1128 AvbConverter avbConverter{};
1129 
1130 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1131     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1132     void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1133         appendTextElement(root, "name", f.name(), d);
1134         appendAttr(root, "format", f.format());
1135         appendAttr(root, "optional", f.optional());
1136         appendChild(root, versionRangeConverter(f.versionRange(), d));
1137         if (!f.overriddenPath().empty()) {
1138             appendTextElement(root, "path", f.overriddenPath(), d);
1139         }
1140     }
buildObjectandroid::vintf::MatrixXmlFileConverter1141     bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1142         if (!parseTextElement(root, "name", &object->mName, error) ||
1143             !parseAttr(root, "format", &object->mFormat, error) ||
1144             !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1145             !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
1146             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1147             return false;
1148         }
1149         return true;
1150     }
1151 };
1152 MatrixXmlFileConverter matrixXmlFileConverter{};
1153 
1154 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1155     std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1156     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1157         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1158     }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1159     void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1160                     SerializeFlags::Type flags) const override {
1161         if (flags.isMetaVersionEnabled()) {
1162             appendAttr(root, "version", kMetaVersion);
1163         }
1164         if (flags.isSchemaTypeEnabled()) {
1165             appendAttr(root, "type", m.mType);
1166         }
1167 
1168         if (flags.isHalsEnabled()) {
1169             appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
1170         }
1171         if (m.mType == SchemaType::FRAMEWORK) {
1172             if (flags.isKernelEnabled()) {
1173                 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
1174             }
1175             if (flags.isSepolicyEnabled()) {
1176                 if (!(m.framework.mSepolicy == Sepolicy{})) {
1177                     appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
1178                 }
1179             }
1180             if (flags.isAvbEnabled()) {
1181                 if (!(m.framework.mAvbMetaVersion == Version{})) {
1182                     appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
1183                 }
1184             }
1185             if (m.mLevel != Level::UNSPECIFIED) {
1186                 this->appendAttr(root, "level", m.mLevel);
1187             }
1188         } else if (m.mType == SchemaType::DEVICE) {
1189             if (flags.isVndkEnabled()) {
1190 #pragma clang diagnostic push
1191 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1192                 if (!(m.device.mVndk == Vndk{})) {
1193                     appendChild(root, vndkConverter(m.device.mVndk, d));
1194                 }
1195 #pragma clang diagnostic pop
1196 
1197                 if (!(m.device.mVendorNdk == VendorNdk{})) {
1198                     appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
1199                 }
1200             }
1201 
1202             if (flags.isSsdkEnabled()) {
1203                 if (!m.device.mSystemSdk.empty()) {
1204                     appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
1205                 }
1206             }
1207         }
1208 
1209         if (flags.isXmlFilesEnabled()) {
1210             appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
1211         }
1212     }
buildObjectandroid::vintf::CompatibilityMatrixConverter1213     bool buildObject(CompatibilityMatrix* object, NodeType* root,
1214                      std::string* error) const override {
1215         Version metaVersion;
1216         if (!parseAttr(root, "version", &metaVersion, error)) return false;
1217         if (metaVersion > kMetaVersion) {
1218             *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1219                      " (libvintf@" + to_string(kMetaVersion) + ")";
1220             return false;
1221         }
1222 
1223         std::vector<MatrixHal> hals;
1224         if (!parseAttr(root, "type", &object->mType, error) ||
1225             !parseChildren(root, matrixHalConverter, &hals, error)) {
1226             return false;
1227         }
1228 
1229         if (object->mType == SchemaType::FRAMEWORK) {
1230             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1231             // hard-coded in the XML file.
1232             if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1233                 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1234                                     error) ||
1235                 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1236                                     error)) {
1237                 return false;
1238             }
1239 
1240             std::set<Version> seenKernelVersions;
1241             for (const auto& kernel : object->framework.mKernels) {
1242                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1243                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1244                     continue;
1245                 }
1246                 if (!kernel.conditions().empty()) {
1247                     *error = "First <kernel> for version " + to_string(minLts) +
1248                              " must have empty <conditions> for backwards compatibility.";
1249                     return false;
1250                 }
1251                 seenKernelVersions.insert(minLts);
1252             }
1253 
1254             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1255                 return false;
1256             }
1257 
1258         } else if (object->mType == SchemaType::DEVICE) {
1259             // <vndk> can be missing because it can be determined at build time, not hard-coded
1260             // in the XML file.
1261 #pragma clang diagnostic push
1262 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1263             if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
1264                 return false;
1265             }
1266 #pragma clang diagnostic pop
1267 
1268             if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1269                                     error)) {
1270                 return false;
1271             }
1272 
1273             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1274                                     error)) {
1275                 return false;
1276             }
1277         }
1278 
1279         for (auto &&hal : hals) {
1280             if (!object->add(std::move(hal))) {
1281                 *error = "Duplicated compatibility-matrix.hal entry";
1282                 return false;
1283             }
1284         }
1285 
1286         std::vector<MatrixXmlFile> xmlFiles;
1287         if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
1288             return false;
1289         }
1290         for (auto&& xmlFile : xmlFiles) {
1291             if (!xmlFile.optional()) {
1292                 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1293                          " has to be optional for compatibility matrix version 1.0";
1294                 return false;
1295             }
1296             std::string description{xmlFile.name()};
1297             if (!object->addXmlFile(std::move(xmlFile))) {
1298                 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1299                 return false;
1300             }
1301         }
1302 
1303         return true;
1304     }
1305 };
1306 
1307 CompatibilityMatrixConverter compatibilityMatrixConverter{};
1308 
1309 // Publicly available as in parse_xml.h
1310 XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1311 XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
1312 
1313 // For testing in LibVintfTest
1314 XmlConverter<Version>& gVersionConverter = versionConverter;
1315 XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1316     kernelConfigTypedValueConverter;
1317 XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1318 XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
1319 XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
1320 
1321 } // namespace vintf
1322 } // namespace android
1323