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 <android-base/parseint.h>
27 #include <android-base/strings.h>
28 #include <tinyxml2.h>
29 
30 #include "Regex.h"
31 #include "constants-private.h"
32 #include "constants.h"
33 #include "parse_string.h"
34 #include "parse_xml_for_test.h"
35 
36 using namespace std::string_literals;
37 
38 namespace android {
39 namespace vintf {
40 
41 // --------------- tinyxml2 details
42 
43 using NodeType = tinyxml2::XMLElement;
44 using DocType = tinyxml2::XMLDocument;
45 
46 // caller is responsible for deleteDocument() call
47 inline DocType *createDocument() {
48     return new tinyxml2::XMLDocument();
49 }
50 
51 // caller is responsible for deleteDocument() call
52 inline DocType *createDocument(const std::string &xml) {
53     DocType *doc = new tinyxml2::XMLDocument();
54     if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
55         return doc;
56     }
57     delete doc;
58     return nullptr;
59 }
60 
61 inline void deleteDocument(DocType *d) {
62     delete d;
63 }
64 
65 inline std::string printDocument(DocType *d) {
66     tinyxml2::XMLPrinter p;
67     d->Print(&p);
68     return std::string{p.CStr()};
69 }
70 
71 inline NodeType *createNode(const std::string &name, DocType *d) {
72     return d->NewElement(name.c_str());
73 }
74 
75 inline void appendChild(NodeType *parent, NodeType *child) {
76     parent->InsertEndChild(child);
77 }
78 
79 inline void appendChild(DocType *parent, NodeType *child) {
80     parent->InsertEndChild(child);
81 }
82 
83 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
84     e->SetAttribute(attrName.c_str(), attr.c_str());
85 }
86 
87 // text -> text
88 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
89     parent->InsertEndChild(d->NewText(text.c_str()));
90 }
91 
92 inline std::string nameOf(NodeType *root) {
93     return root->Name() == NULL ? "" : root->Name();
94 }
95 
96 inline std::string getText(NodeType *root) {
97     return root->GetText() == NULL ? "" : root->GetText();
98 }
99 
100 inline NodeType *getChild(NodeType *parent, const std::string &name) {
101     return parent->FirstChildElement(name.c_str());
102 }
103 
104 inline NodeType *getRootChild(DocType *parent) {
105     return parent->FirstChildElement();
106 }
107 
108 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
109     std::vector<NodeType *> v;
110     for (NodeType *child = parent->FirstChildElement(name.c_str());
111          child != nullptr;
112          child = child->NextSiblingElement(name.c_str())) {
113         v.push_back(child);
114     }
115     return v;
116 }
117 
118 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
119     const char *c = root->Attribute(attrName.c_str());
120     if (c == NULL)
121         return false;
122     *s = c;
123     return true;
124 }
125 
126 // --------------- tinyxml2 details end.
127 
128 // Helper functions for XmlConverter
129 static bool parse(const std::string &attrText, bool *attr) {
130     if (attrText == "true" || attrText == "1") {
131         *attr = true;
132         return true;
133     }
134     if (attrText == "false" || attrText == "0") {
135         *attr = false;
136         return true;
137     }
138     return false;
139 }
140 
141 static bool parse(const std::string& attrText, std::optional<std::string>* attr) {
142     *attr = attrText;
143     return true;
144 }
145 
146 // ---------------------- XmlNodeConverter definitions
147 
148 template <typename Object>
149 struct XmlNodeConverter {
150     XmlNodeConverter() {}
151     virtual ~XmlNodeConverter() {}
152 
153     // sub-types should implement these.
154     virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
155     virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
156         mutateNode(o, n, d);
157     }
158     virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
159     virtual std::string elementName() const = 0;
160 
161     // convenience methods for user
162     inline NodeType* operator()(const Object& o, DocType* d,
163                                 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
164         NodeType *root = createNode(this->elementName(), d);
165         this->mutateNode(o, root, d, flags);
166         return root;
167     }
168     inline std::string operator()(const Object& o, SerializeFlags::Type flags) const {
169         DocType *doc = createDocument();
170         appendChild(doc, (*this)(o, doc, flags));
171         std::string s = printDocument(doc);
172         deleteDocument(doc);
173         return s;
174     }
175     inline bool operator()(Object* object, NodeType* root, std::string* error) const {
176         if (nameOf(root) != this->elementName()) {
177             return false;
178         }
179         return this->buildObject(object, root, error);
180     }
181     inline bool operator()(Object* o, const std::string& xml, std::string* error) const {
182         std::string errorBuffer;
183         if (error == nullptr) error = &errorBuffer;
184 
185         auto doc = createDocument(xml);
186         if (doc == nullptr) {
187             *error = "Not a valid XML";
188             return false;
189         }
190         bool ret = (*this)(o, getRootChild(doc), error);
191         deleteDocument(doc);
192         return ret;
193     }
194 
195     // convenience methods for implementor.
196 
197     // All append* functions helps mutateNode() to serialize the object into XML.
198     template <typename T>
199     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
200         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
201     }
202 
203     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
204         return appendStrAttr(e, attrName, attr ? "true" : "false");
205     }
206 
207     // text -> <name>text</name>
208     inline void appendTextElement(NodeType *parent, const std::string &name,
209                 const std::string &text, DocType *d) const {
210         NodeType *c = createNode(name, d);
211         appendText(c, text, d);
212         appendChild(parent, c);
213     }
214 
215     // text -> <name>text</name>
216     template<typename Array>
217     inline void appendTextElements(NodeType *parent, const std::string &name,
218                 const Array &array, DocType *d) const {
219         for (const std::string &text : array) {
220             NodeType *c = createNode(name, d);
221             appendText(c, text, d);
222             appendChild(parent, c);
223         }
224     }
225 
226     template <typename T, typename Array>
227     inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
228                                const Array& array, DocType* d,
229                                SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
230         for (const T &t : array) {
231             appendChild(parent, conv(t, d, flags));
232         }
233     }
234 
235     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
236     // true if deserialization is successful, false if any error, and "error" will be
237     // set to error message.
238     template <typename T>
239     inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
240                                   T* attr, std::string* /* error */) const {
241         std::string attrText;
242         bool success = getAttr(root, attrName, &attrText) &&
243                        ::android::vintf::parse(attrText, attr);
244         if (!success) {
245             *attr = std::move(defaultValue);
246         }
247         return true;
248     }
249 
250     template <typename T>
251     inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
252                           std::string* error) const {
253         std::string attrText;
254         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
255         if (!ret) {
256             *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
257                      attrText + "\" for element <" + elementName() + ">";
258         }
259         return ret;
260     }
261 
262     inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
263                           std::string* error) const {
264         bool ret = getAttr(root, attrName, attr);
265         if (!ret) {
266             *error = "Could not find attr with name \"" + attrName + "\" for element <" +
267                      elementName() + ">";
268         }
269         return ret;
270     }
271 
272     inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
273                                  std::string* error) const {
274         NodeType *child = getChild(root, elementName);
275         if (child == nullptr) {
276             *error = "Could not find element with name <" + elementName + "> in element <" +
277                      this->elementName() + ">";
278             return false;
279         }
280         *s = getText(child);
281         return true;
282     }
283 
284     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
285                                          std::string&& defaultValue, std::string* s,
286                                          std::string* /* error */) const {
287         NodeType* child = getChild(root, elementName);
288         *s = child == nullptr ? std::move(defaultValue) : getText(child);
289         return true;
290     }
291 
292     inline bool parseTextElements(NodeType* root, const std::string& elementName,
293                                   std::vector<std::string>* v, std::string* /* error */) const {
294         auto nodes = getChildren(root, elementName);
295         v->resize(nodes.size());
296         for (size_t i = 0; i < nodes.size(); ++i) {
297             v->at(i) = getText(nodes[i]);
298         }
299         return true;
300     }
301 
302     template <typename T>
303     inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
304                            std::string* error) const {
305         NodeType *child = getChild(root, conv.elementName());
306         if (child == nullptr) {
307             *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
308                      this->elementName() + ">";
309             return false;
310         }
311         return conv(t, child, error);
312     }
313 
314     template <typename T>
315     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
316                                    T&& defaultValue, T* t, std::string* error) const {
317         NodeType *child = getChild(root, conv.elementName());
318         if (child == nullptr) {
319             *t = std::move(defaultValue);
320             return true;
321         }
322         return conv(t, child, error);
323     }
324 
325     template <typename T>
326     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
327                                    std::optional<T>* t, std::string* error) const {
328         NodeType* child = getChild(root, conv.elementName());
329         if (child == nullptr) {
330             *t = std::nullopt;
331             return true;
332         }
333         *t = std::make_optional<T>();
334         return conv(&**t, child, error);
335     }
336 
337     template <typename T>
338     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
339                               std::string* error) const {
340         auto nodes = getChildren(root, conv.elementName());
341         v->resize(nodes.size());
342         for (size_t i = 0; i < nodes.size(); ++i) {
343             if (!conv(&v->at(i), nodes[i], error)) {
344                 *error = "Could not parse element with name <" + conv.elementName() +
345                          "> in element <" + this->elementName() + ">: " + *error;
346                 return false;
347             }
348         }
349         return true;
350     }
351 
352     template <typename Container, typename T = typename Container::value_type,
353               typename = typename Container::key_compare>
354     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
355                               std::string* error) const {
356         std::vector<T> vec;
357         if (!parseChildren(root, conv, &vec, error)) {
358             return false;
359         }
360         s->clear();
361         s->insert(vec.begin(), vec.end());
362         if (s->size() != vec.size()) {
363             *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
364                      this->elementName() + ">";
365             s->clear();
366             return false;
367         }
368         return true;
369     }
370 
371     template <typename K, typename V>
372     inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
373                               std::map<K, V>* s, std::string* error) const {
374         return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
375     }
376 
377     inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
378         *s = getText(node);
379         return true;
380     }
381 
382     template <typename T>
383     inline bool parseText(NodeType* node, T* s, std::string* error) const {
384         bool (*parser)(const std::string&, T*) = ::android::vintf::parse;
385         return parseText(node, s, {parser}, error);
386     }
387 
388     template <typename T>
389     inline bool parseText(NodeType* node, T* s,
390                           const std::function<bool(const std::string&, T*)>& parse,
391                           std::string* error) const {
392         std::string text = getText(node);
393         bool ret = parse(text, s);
394         if (!ret) {
395             *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
396         }
397         return ret;
398     }
399 };
400 
401 template<typename Object>
402 struct XmlTextConverter : public XmlNodeConverter<Object> {
403     virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
404         appendText(root, ::android::vintf::to_string(object), d);
405     }
406     virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
407         return this->parseText(root, object, error);
408     }
409 };
410 
411 template <typename Pair, typename FirstConverter, typename SecondConverter>
412 struct XmlPairConverter : public XmlNodeConverter<Pair> {
413     virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
414         appendChild(root, FirstConverter{}(pair.first, d));
415         appendChild(root, SecondConverter{}(pair.second, d));
416     }
417     virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
418         return this->parseChild(root, FirstConverter{}, &pair->first, error) &&
419                this->parseChild(root, SecondConverter{}, &pair->second, error);
420     }
421 };
422 
423 // ---------------------- XmlNodeConverter definitions end
424 
425 struct VersionConverter : public XmlTextConverter<Version> {
426     std::string elementName() const override { return "version"; }
427 };
428 
429 struct VersionRangeConverter : public XmlTextConverter<VersionRange> {
430     std::string elementName() const override { return "version"; }
431 };
432 
433 // <version>100</version> <=> Version{kFakeAidlMajorVersion, 100}
434 struct AidlVersionConverter : public XmlNodeConverter<Version> {
435     std::string elementName() const override { return "version"; }
436     void mutateNode(const Version& object, NodeType* root, DocType* d) const override {
437         appendText(root, aidlVersionToString(object), d);
438     }
439     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
440         return parseText(root, object, {parseAidlVersion}, error);
441     }
442 };
443 
444 // <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100}
445 // <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105}
446 struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> {
447     std::string elementName() const override { return "version"; }
448     void mutateNode(const VersionRange& object, NodeType* root, DocType* d) const override {
449         appendText(root, aidlVersionRangeToString(object), d);
450     }
451     bool buildObject(VersionRange* object, NodeType* root, std::string* error) const override {
452         return parseText(root, object, {parseAidlVersionRange}, error);
453     }
454 };
455 
456 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
457     std::string elementName() const override { return "transport"; }
458     void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
459         if (object.arch != Arch::ARCH_EMPTY) {
460             appendAttr(root, "arch", object.arch);
461         }
462         appendText(root, ::android::vintf::to_string(object.transport), d);
463     }
464     bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
465         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
466             !parseText(root, &object->transport, error)) {
467             return false;
468         }
469         if (!object->isValid(error)) {
470             return false;
471         }
472         return true;
473     }
474 };
475 
476 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
477     std::string elementName() const override { return "value"; }
478     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     }
482     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 struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> {
498     std::string elementName() const override { return "key"; }
499 };
500 
501 struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter,
502                                                              KernelConfigTypedValueConverter> {
503     std::string elementName() const override { return "config"; }
504 };
505 
506 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
507     std::string elementName() const override { return "interface"; }
508     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     }
513     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 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
547     std::string elementName() const override { return "hal"; }
548     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
549         appendAttr(root, "format", hal.format);
550         appendAttr(root, "optional", hal.optional);
551         appendTextElement(root, "name", hal.name, d);
552         if (hal.format == HalFormat::AIDL) {
553             // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
554             // is specified. Don't output any <version> tag if there's only one <version>0</version>
555             // tag.
556             if (hal.versionRanges.size() != 1 ||
557                 hal.versionRanges[0] != details::kDefaultAidlVersionRange) {
558                 appendChildren(root, AidlVersionRangeConverter{}, hal.versionRanges, d);
559             }
560         } else {
561             appendChildren(root, VersionRangeConverter{}, hal.versionRanges, d);
562         }
563         appendChildren(root, HalInterfaceConverter{}, iterateValues(hal.interfaces), d);
564     }
565     bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
566         std::vector<HalInterface> interfaces;
567         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
568             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
569                                error) ||
570             !parseTextElement(root, "name", &object->name, error) ||
571             !parseChildren(root, HalInterfaceConverter{}, &interfaces, error)) {
572             return false;
573         }
574         if (object->format == HalFormat::AIDL) {
575             if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, error)) {
576                 return false;
577             }
578             // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
579             // HAL formats can be unified.
580             if (object->versionRanges.empty()) {
581                 object->versionRanges.push_back(details::kDefaultAidlVersionRange);
582             }
583         } else {
584             if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, error)) {
585                 return false;
586             }
587         }
588         for (auto&& interface : interfaces) {
589             std::string name{interface.name()};
590             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
591             if (!res.second) {
592                 *error = "Duplicated interface entry \"" + res.first->first +
593                          "\"; if additional instances are needed, add them to the "
594                          "existing <interface> node.";
595                 return false;
596             }
597         }
598 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
599 #ifndef LIBVINTF_TARGET
600         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
601             return false;
602         }
603 #endif
604 
605         if (!object->isValid(error)) {
606             error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: ");
607             return false;
608         }
609         return true;
610     }
611 
612 #ifndef LIBVINTF_TARGET
613    private:
614     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
615         if (hal.getName() == "netutils-wrapper") {
616             if (hal.versionRanges.size() != 1) {
617                 *error =
618                     "netutils-wrapper HAL must specify exactly one version x.0, "
619                     "but multiple <version> element is specified.";
620                 return false;
621             }
622             const VersionRange& v = hal.versionRanges.at(0);
623             if (!v.isSingleVersion()) {
624                 *error =
625                     "netutils-wrapper HAL must specify exactly one version x.0, "
626                     "but a range is provided. Perhaps you mean '" +
627                     to_string(Version{v.majorVer, 0}) + "'?";
628                 return false;
629             }
630             if (v.minMinor != 0) {
631                 *error =
632                     "netutils-wrapper HAL must specify exactly one version x.0, "
633                     "but minor version is not 0. Perhaps you mean '" +
634                     to_string(Version{v.majorVer, 0}) + "'?";
635                 return false;
636             }
637         }
638         return true;
639     }
640 #endif
641 };
642 
643 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
644     std::string elementName() const override { return "conditions"; }
645     void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
646                     DocType* d) const override {
647         appendChildren(root, MatrixKernelConfigConverter{}, conds, d);
648     }
649     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
650                      std::string* error) const override {
651         return parseChildren(root, MatrixKernelConfigConverter{}, object, error);
652     }
653 };
654 
655 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
656     std::string elementName() const override { return "kernel"; }
657     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
658         mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
659     }
660     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
661                     SerializeFlags::Type flags) const override {
662         KernelVersion kv = kernel.mMinLts;
663         if (!flags.isKernelMinorRevisionEnabled()) {
664             kv.minorRev = 0u;
665         }
666         appendAttr(root, "version", kv);
667 
668         if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
669             appendAttr(root, "level", kernel.getSourceMatrixLevel());
670         }
671 
672         if (!kernel.mConditions.empty()) {
673             appendChild(root, MatrixKernelConditionsConverter{}(kernel.mConditions, d));
674         }
675         if (flags.isKernelConfigsEnabled()) {
676             appendChildren(root, MatrixKernelConfigConverter{}, kernel.mConfigs, d);
677         }
678     }
679     bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
680         Level sourceMatrixLevel = Level::UNSPECIFIED;
681         if (!parseAttr(root, "version", &object->mMinLts, error) ||
682             !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
683             !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions,
684                                 error) ||
685             !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, error)) {
686             return false;
687         }
688         object->setSourceMatrixLevel(sourceMatrixLevel);
689         return true;
690     }
691 };
692 
693 struct FqInstanceConverter : public XmlTextConverter<FqInstance> {
694     std::string elementName() const override { return "fqname"; }
695 };
696 
697 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
698 // .isValid() == true.
699 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
700     std::string elementName() const override { return "hal"; }
701     void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
702         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
703     }
704     void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
705                     SerializeFlags::Type flags) const override {
706         appendAttr(root, "format", hal.format);
707         appendTextElement(root, "name", hal.name, d);
708         if (!hal.transportArch.empty()) {
709             appendChild(root, TransportArchConverter{}(hal.transportArch, d));
710         }
711         if (hal.format == HalFormat::AIDL) {
712             // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
713             // is specified. Don't output any <version> tag if there's only one <version>0</version>
714             // tag.
715             if (hal.versions.size() != 1 || hal.versions[0] != details::kDefaultAidlVersion) {
716                 appendChildren(root, AidlVersionConverter{}, hal.versions, d);
717             }
718         } else {
719             appendChildren(root, VersionConverter{}, hal.versions, d);
720         }
721         appendChildren(root, HalInterfaceConverter{}, iterateValues(hal.interfaces), d);
722         if (hal.isOverride()) {
723             appendAttr(root, "override", hal.isOverride());
724         }
725         if (const auto& apex = hal.updatableViaApex(); apex.has_value()) {
726             appendAttr(root, "updatable-via-apex", apex.value());
727         }
728         if (flags.isFqnameEnabled()) {
729             std::set<std::string> simpleFqInstances;
730             hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
731                 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
732                 return true;
733             });
734             appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances, d);
735         }
736         if (hal.getMaxLevel() != Level::UNSPECIFIED) {
737             appendAttr(root, "max-level", hal.getMaxLevel());
738         }
739     }
740     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
741         std::vector<HalInterface> interfaces;
742         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
743             !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
744             !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex, error) ||
745             !parseTextElement(root, "name", &object->name, error) ||
746             !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch,
747                                 error) ||
748             !parseChildren(root, HalInterfaceConverter{}, &interfaces, error) ||
749             !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel, error)) {
750             return false;
751         }
752 
753         switch (object->format) {
754             case HalFormat::HIDL: {
755                 if (!parseChildren(root, VersionConverter{}, &object->versions, error))
756                     return false;
757                 if (object->transportArch.empty()) {
758                     *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
759                     return false;
760                 }
761             } break;
762             case HalFormat::NATIVE: {
763                 if (!parseChildren(root, VersionConverter{}, &object->versions, error))
764                     return false;
765                 if (!object->transportArch.empty()) {
766                     *error =
767                         "Native HAL '" + object->name + "' should not have <transport> defined.";
768                     return false;
769                 }
770             } break;
771             case HalFormat::AIDL: {
772                 if (!object->transportArch.empty()) {
773                     LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
774                                  << object->name;
775                     object->transportArch = {};
776                 }
777                 if (!parseChildren(root, AidlVersionConverter{}, &object->versions, error)) {
778                     return false;
779                 }
780                 // Insert fake version for AIDL HALs so that forEachInstance works.
781                 if (object->versions.empty()) {
782                     object->versions.push_back(details::kDefaultAidlVersion);
783                 }
784             } break;
785             default: {
786                 LOG(FATAL) << "Unhandled HalFormat "
787                            << static_cast<typename std::underlying_type<HalFormat>::type>(
788                                   object->format);
789             } break;
790         }
791         if (!object->transportArch.isValid(error)) return false;
792 
793         object->interfaces.clear();
794         for (auto &&interface : interfaces) {
795             auto res = object->interfaces.emplace(interface.name(), std::move(interface));
796             if (!res.second) {
797                 *error = "Duplicated interface entry \"" + res.first->first +
798                          "\"; if additional instances are needed, add them to the "
799                          "existing <interface> node.";
800                 return false;
801             }
802         }
803 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
804 #ifndef LIBVINTF_TARGET
805         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
806             return false;
807         }
808 #endif
809 
810         std::set<FqInstance> fqInstances;
811         if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, error)) {
812             return false;
813         }
814         std::set<FqInstance> fqInstancesToInsert;
815         for (auto& e : fqInstances) {
816             if (e.hasPackage()) {
817                 *error = "Should not specify package: \"" + e.string() + "\"";
818                 return false;
819             }
820             if (object->format == HalFormat::AIDL) {
821                 // <fqname> in AIDL HALs should not contain version.
822                 if (e.hasVersion()) {
823                     *error = "Should not specify version in <fqname> for AIDL HAL: \"" +
824                              e.string() + "\"";
825                     return false;
826                 }
827                 // Put in the fake kDefaultAidlVersion so that HalManifest can
828                 // store it in an FqInstance object with a non-empty package.
829                 FqInstance withFakeVersion;
830                 if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer,
831                                            details::kDefaultAidlVersion.minorVer, e.getInterface(),
832                                            e.getInstance())) {
833                     return false;
834                 }
835                 fqInstancesToInsert.emplace(std::move(withFakeVersion));
836             } else {
837                 fqInstancesToInsert.emplace(std::move(e));
838             }
839         }
840         if (!object->insertInstances(fqInstancesToInsert, error)) {
841             return false;
842         }
843 
844         if (!object->isValid(error)) {
845             error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
846             return false;
847         }
848 
849         return true;
850     }
851 
852 #ifndef LIBVINTF_TARGET
853    private:
854     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
855         if (hal.getName() == "netutils-wrapper") {
856             for (const Version& v : hal.versions) {
857                 if (v.minorVer != 0) {
858                     *error =
859                         "netutils-wrapper HAL must specify exactly one version x.0, "
860                         "but minor version is not 0. Perhaps you mean '" +
861                         to_string(Version{v.majorVer, 0}) + "'?";
862                     return false;
863                 }
864             }
865         }
866         return true;
867     }
868 #endif
869 };
870 
871 struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> {
872     std::string elementName() const override { return "kernel-sepolicy-version"; }
873 };
874 
875 struct SepolicyVersionConverter : public XmlTextConverter<VersionRange> {
876     std::string elementName() const override { return "sepolicy-version"; }
877 };
878 
879 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
880     std::string elementName() const override { return "sepolicy"; }
881     void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
882         appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), d));
883         appendChildren(root, SepolicyVersionConverter{}, object.sepolicyVersions(), d);
884     }
885     bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
886         if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion,
887                         error) ||
888             !parseChildren(root, SepolicyVersionConverter{}, &object->mSepolicyVersionRanges,
889                            error)) {
890             return false;
891         }
892         return true;
893     }
894 };
895 
896 struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> {
897     std::string elementName() const override { return "version"; }
898 };
899 
900 struct VndkVersionConverter : public XmlTextConverter<std::string> {
901     std::string elementName() const override { return "version"; }
902 };
903 
904 struct VndkLibraryConverter : public XmlTextConverter<std::string> {
905     std::string elementName() const override { return "library"; }
906 };
907 
908 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
909     std::string elementName() const override { return "vndk"; }
910     void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
911         appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, d));
912         appendChildren(root, VndkLibraryConverter{}, object.mLibraries, d);
913     }
914     bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
915         if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, error) ||
916             !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, error)) {
917             return false;
918         }
919         return true;
920     }
921 };
922 
923 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
924     std::string elementName() const override { return "vendor-ndk"; }
925     void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
926         appendChild(root, VndkVersionConverter{}(object.mVersion, d));
927         appendChildren(root, VndkLibraryConverter{}, object.mLibraries, d);
928     }
929     bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
930         if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, error) ||
931             !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, error)) {
932             return false;
933         }
934         return true;
935     }
936 };
937 
938 struct SystemSdkVersionConverter : public XmlTextConverter<std::string> {
939     std::string elementName() const override { return "version"; }
940 };
941 
942 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
943     std::string elementName() const override { return "system-sdk"; }
944     void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
945         appendChildren(root, SystemSdkVersionConverter{}, object.versions(), d);
946     }
947     bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
948         return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, error);
949     }
950 };
951 
952 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
953     std::string elementName() const override { return "sepolicy"; }
954     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
955         appendChild(root, VersionConverter{}(m, d));
956     }
957     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
958         return parseChild(root, VersionConverter{}, object, error);
959     }
960 };
961 
962 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
963     std::string elementName() const override { return "xmlfile"; }
964     void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
965         appendTextElement(root, "name", f.name(), d);
966         appendChild(root, VersionConverter{}(f.version(), d));
967         if (!f.overriddenPath().empty()) {
968             appendTextElement(root, "path", f.overriddenPath(), d);
969         }
970     }
971     bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
972         if (!parseTextElement(root, "name", &object->mName, error) ||
973             !parseChild(root, VersionConverter{}, &object->mVersion, error) ||
974             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
975             return false;
976         }
977         return true;
978     }
979 };
980 
981 struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> {
982     std::string elementName() const override { return "key"; }
983 };
984 
985 struct KernelConfigValueConverter : public XmlTextConverter<std::string> {
986     std::string elementName() const override { return "value"; }
987 };
988 
989 struct StringKernelConfigConverter
990     : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter,
991                               KernelConfigValueConverter> {
992     std::string elementName() const override { return "config"; }
993 };
994 
995 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
996     std::string elementName() const override { return "kernel"; }
997     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
998         mutateNode(o, root, d, SerializeFlags::EVERYTHING);
999     }
1000     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
1001                     SerializeFlags::Type flags) const override {
1002         if (o.version() != KernelVersion{}) {
1003             appendAttr(root, "version", o.version());
1004         }
1005         if (o.level() != Level::UNSPECIFIED) {
1006             appendAttr(root, "target-level", o.level());
1007         }
1008         if (flags.isKernelConfigsEnabled()) {
1009             appendChildren(root, StringKernelConfigConverter{}, o.configs(), d);
1010         }
1011     }
1012     bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
1013         return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
1014                parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
1015                parseChildren(root, StringKernelConfigConverter{}, &o->mConfigs, error);
1016     }
1017 };
1018 
1019 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
1020     std::string elementName() const override { return "manifest"; }
1021     void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
1022         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1023     }
1024     void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
1025                     SerializeFlags::Type flags) const override {
1026         if (flags.isMetaVersionEnabled()) {
1027             appendAttr(root, "version", m.getMetaVersion());
1028         }
1029         if (flags.isSchemaTypeEnabled()) {
1030             appendAttr(root, "type", m.mType);
1031         }
1032 
1033         if (flags.isHalsEnabled()) {
1034             appendChildren(root, ManifestHalConverter{}, m.getHals(), d, flags);
1035         }
1036         if (m.mType == SchemaType::DEVICE) {
1037             if (flags.isSepolicyEnabled()) {
1038                 if (m.device.mSepolicyVersion != Version{}) {
1039                     appendChild(root, HalManifestSepolicyConverter{}(m.device.mSepolicyVersion, d));
1040                 }
1041             }
1042             if (m.mLevel != Level::UNSPECIFIED) {
1043                 this->appendAttr(root, "target-level", m.mLevel);
1044             }
1045 
1046             if (flags.isKernelEnabled()) {
1047                 if (!!m.kernel()) {
1048                     appendChild(root, KernelInfoConverter{}(*m.kernel(), d, flags));
1049                 }
1050             }
1051         } else if (m.mType == SchemaType::FRAMEWORK) {
1052             if (flags.isVndkEnabled()) {
1053 #pragma clang diagnostic push
1054 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1055                 appendChildren(root, VndkConverter{}, m.framework.mVndks, d);
1056 #pragma clang diagnostic pop
1057 
1058                 appendChildren(root, VendorNdkConverter{}, m.framework.mVendorNdks, d);
1059             }
1060             if (flags.isSsdkEnabled()) {
1061                 if (!m.framework.mSystemSdk.empty()) {
1062                     appendChild(root, SystemSdkConverter{}(m.framework.mSystemSdk, d));
1063                 }
1064             }
1065         }
1066 
1067         if (flags.isXmlFilesEnabled()) {
1068             appendChildren(root, ManifestXmlFileConverter{}, m.getXmlFiles(), d);
1069         }
1070     }
1071     bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
1072         Version metaVersion;
1073         if (!parseAttr(root, "version", &metaVersion, error)) return false;
1074         if (metaVersion > kMetaVersion) {
1075             *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1076                      to_string(kMetaVersion) + ")";
1077             return false;
1078         }
1079 
1080         if (!parseAttr(root, "type", &object->mType, error)) {
1081             return false;
1082         }
1083 
1084         std::vector<ManifestHal> hals;
1085         if (!parseChildren(root, ManifestHalConverter{}, &hals, error)) {
1086             return false;
1087         }
1088         for (auto&& hal : hals) {
1089             hal.setFileName(object->fileName());
1090         }
1091 
1092         if (object->mType == SchemaType::DEVICE) {
1093             // tags for device hal manifest only.
1094             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1095             // in the XML file.
1096             if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {},
1097                                     &object->device.mSepolicyVersion, error)) {
1098                 return false;
1099             }
1100 
1101             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1102                                    error)) {
1103                 return false;
1104             }
1105 
1106             if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, error)) {
1107                 return false;
1108             }
1109         } else if (object->mType == SchemaType::FRAMEWORK) {
1110 #pragma clang diagnostic push
1111 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1112             if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, error)) {
1113                 return false;
1114             }
1115             for (const auto &vndk : object->framework.mVndks) {
1116                 if (!vndk.mVersionRange.isSingleVersion()) {
1117                     *error = "vndk.version " + to_string(vndk.mVersionRange) +
1118                              " cannot be a range for manifests";
1119                     return false;
1120                 }
1121             }
1122 #pragma clang diagnostic pop
1123 
1124             if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, error)) {
1125                 return false;
1126             }
1127 
1128             std::set<std::string> vendorNdkVersions;
1129             for (const auto& vendorNdk : object->framework.mVendorNdks) {
1130                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1131                     *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1132                     return false;
1133                 }
1134                 vendorNdkVersions.insert(vendorNdk.version());
1135             }
1136 
1137             if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk,
1138                                     error)) {
1139                 return false;
1140             }
1141         }
1142         for (auto &&hal : hals) {
1143             std::string description{hal.name};
1144             if (!object->add(std::move(hal))) {
1145                 *error = "Duplicated manifest.hal entry " + description;
1146                 return false;
1147             }
1148         }
1149 
1150         std::vector<ManifestXmlFile> xmlFiles;
1151         if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, error)) {
1152             return false;
1153         }
1154         for (auto&& xmlFile : xmlFiles) {
1155             std::string description{xmlFile.name()};
1156             if (!object->addXmlFile(std::move(xmlFile))) {
1157                 *error = "Duplicated manifest.xmlfile entry " + description +
1158                          "; entries cannot have duplicated name and version";
1159                 return false;
1160             }
1161         }
1162 
1163         return true;
1164     }
1165 };
1166 
1167 struct AvbVersionConverter : public XmlTextConverter<Version> {
1168     std::string elementName() const override { return "vbmeta-version"; }
1169 };
1170 
1171 struct AvbConverter : public XmlNodeConverter<Version> {
1172     std::string elementName() const override { return "avb"; }
1173     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1174         appendChild(root, AvbVersionConverter{}(m, d));
1175     }
1176     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1177         return parseChild(root, AvbVersionConverter{}, object, error);
1178     }
1179 };
1180 
1181 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
1182     std::string elementName() const override { return "xmlfile"; }
1183     void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1184         appendTextElement(root, "name", f.name(), d);
1185         appendAttr(root, "format", f.format());
1186         appendAttr(root, "optional", f.optional());
1187         appendChild(root, VersionRangeConverter{}(f.versionRange(), d));
1188         if (!f.overriddenPath().empty()) {
1189             appendTextElement(root, "path", f.overriddenPath(), d);
1190         }
1191     }
1192     bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1193         if (!parseTextElement(root, "name", &object->mName, error) ||
1194             !parseAttr(root, "format", &object->mFormat, error) ||
1195             !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1196             !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, error) ||
1197             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1198             return false;
1199         }
1200         return true;
1201     }
1202 };
1203 
1204 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
1205     std::string elementName() const override { return "compatibility-matrix"; }
1206     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1207         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1208     }
1209     void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1210                     SerializeFlags::Type flags) const override {
1211         if (flags.isMetaVersionEnabled()) {
1212             appendAttr(root, "version", kMetaVersion);
1213         }
1214         if (flags.isSchemaTypeEnabled()) {
1215             appendAttr(root, "type", m.mType);
1216         }
1217 
1218         if (flags.isHalsEnabled()) {
1219             appendChildren(root, MatrixHalConverter{}, iterateValues(m.mHals), d);
1220         }
1221         if (m.mType == SchemaType::FRAMEWORK) {
1222             if (flags.isKernelEnabled()) {
1223                 appendChildren(root, MatrixKernelConverter{}, m.framework.mKernels, d, flags);
1224             }
1225             if (flags.isSepolicyEnabled()) {
1226                 if (!(m.framework.mSepolicy == Sepolicy{})) {
1227                     appendChild(root, SepolicyConverter{}(m.framework.mSepolicy, d));
1228                 }
1229             }
1230             if (flags.isAvbEnabled()) {
1231                 if (!(m.framework.mAvbMetaVersion == Version{})) {
1232                     appendChild(root, AvbConverter{}(m.framework.mAvbMetaVersion, d));
1233                 }
1234             }
1235             if (m.mLevel != Level::UNSPECIFIED) {
1236                 this->appendAttr(root, "level", m.mLevel);
1237             }
1238         } else if (m.mType == SchemaType::DEVICE) {
1239             if (flags.isVndkEnabled()) {
1240 #pragma clang diagnostic push
1241 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1242                 if (!(m.device.mVndk == Vndk{})) {
1243                     appendChild(root, VndkConverter{}(m.device.mVndk, d));
1244                 }
1245 #pragma clang diagnostic pop
1246 
1247                 if (!(m.device.mVendorNdk == VendorNdk{})) {
1248                     appendChild(root, VendorNdkConverter{}(m.device.mVendorNdk, d));
1249                 }
1250             }
1251 
1252             if (flags.isSsdkEnabled()) {
1253                 if (!m.device.mSystemSdk.empty()) {
1254                     appendChild(root, SystemSdkConverter{}(m.device.mSystemSdk, d));
1255                 }
1256             }
1257         }
1258 
1259         if (flags.isXmlFilesEnabled()) {
1260             appendChildren(root, MatrixXmlFileConverter{}, m.getXmlFiles(), d);
1261         }
1262     }
1263     bool buildObject(CompatibilityMatrix* object, NodeType* root,
1264                      std::string* error) const override {
1265         Version metaVersion;
1266         if (!parseAttr(root, "version", &metaVersion, error)) return false;
1267         if (metaVersion > kMetaVersion) {
1268             *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1269                      " (libvintf@" + to_string(kMetaVersion) + ")";
1270             return false;
1271         }
1272 
1273         std::vector<MatrixHal> hals;
1274         if (!parseAttr(root, "type", &object->mType, error) ||
1275             !parseChildren(root, MatrixHalConverter{}, &hals, error)) {
1276             return false;
1277         }
1278 
1279         if (object->mType == SchemaType::FRAMEWORK) {
1280             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1281             // hard-coded in the XML file.
1282             if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, error) ||
1283                 !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy,
1284                                     error) ||
1285                 !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion,
1286                                     error)) {
1287                 return false;
1288             }
1289 
1290             std::set<Version> seenKernelVersions;
1291             for (const auto& kernel : object->framework.mKernels) {
1292                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1293                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1294                     continue;
1295                 }
1296                 if (!kernel.conditions().empty()) {
1297                     *error = "First <kernel> for version " + to_string(minLts) +
1298                              " must have empty <conditions> for backwards compatibility.";
1299                     return false;
1300                 }
1301                 seenKernelVersions.insert(minLts);
1302             }
1303 
1304             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1305                 return false;
1306             }
1307 
1308         } else if (object->mType == SchemaType::DEVICE) {
1309             // <vndk> can be missing because it can be determined at build time, not hard-coded
1310             // in the XML file.
1311 #pragma clang diagnostic push
1312 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1313             if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, error)) {
1314                 return false;
1315             }
1316 #pragma clang diagnostic pop
1317 
1318             if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk,
1319                                     error)) {
1320                 return false;
1321             }
1322 
1323             if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk,
1324                                     error)) {
1325                 return false;
1326             }
1327         }
1328 
1329         for (auto &&hal : hals) {
1330             if (!object->add(std::move(hal))) {
1331                 *error = "Duplicated compatibility-matrix.hal entry";
1332                 return false;
1333             }
1334         }
1335 
1336         std::vector<MatrixXmlFile> xmlFiles;
1337         if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, error)) {
1338             return false;
1339         }
1340         for (auto&& xmlFile : xmlFiles) {
1341             if (!xmlFile.optional()) {
1342                 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1343                          " has to be optional for compatibility matrix version 1.0";
1344                 return false;
1345             }
1346             std::string description{xmlFile.name()};
1347             if (!object->addXmlFile(std::move(xmlFile))) {
1348                 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1349                 return false;
1350             }
1351         }
1352 
1353         return true;
1354     }
1355 };
1356 
1357 #define CREATE_CONVERT_FN(type)                                         \
1358     std::string toXml(const type& o, SerializeFlags::Type flags) {      \
1359         return type##Converter{}(o, flags);                             \
1360     }                                                                   \
1361     bool fromXml(type* o, const std::string& xml, std::string* error) { \
1362         return type##Converter{}(o, xml, error);                        \
1363     }
1364 
1365 // Create convert functions for public usage.
1366 CREATE_CONVERT_FN(HalManifest)
1367 CREATE_CONVERT_FN(CompatibilityMatrix)
1368 
1369 // Create convert functions for internal usage.
1370 CREATE_CONVERT_FN(KernelInfo)
1371 
1372 // Create convert functions for testing.
1373 CREATE_CONVERT_FN(Version)
1374 CREATE_CONVERT_FN(KernelConfigTypedValue)
1375 CREATE_CONVERT_FN(MatrixHal)
1376 CREATE_CONVERT_FN(ManifestHal)
1377 
1378 #undef CREATE_CONVERT_FN
1379 
1380 } // namespace vintf
1381 } // namespace android
1382