• 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.h"
30 #include "parse_string.h"
31 
32 namespace android {
33 namespace vintf {
34 
35 // --------------- tinyxml2 details
36 
37 using NodeType = tinyxml2::XMLElement;
38 using DocType = tinyxml2::XMLDocument;
39 
40 // caller is responsible for deleteDocument() call
createDocument()41 inline DocType *createDocument() {
42     return new tinyxml2::XMLDocument();
43 }
44 
45 // caller is responsible for deleteDocument() call
createDocument(const std::string & xml)46 inline DocType *createDocument(const std::string &xml) {
47     DocType *doc = new tinyxml2::XMLDocument();
48     if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
49         return doc;
50     }
51     delete doc;
52     return nullptr;
53 }
54 
deleteDocument(DocType * d)55 inline void deleteDocument(DocType *d) {
56     delete d;
57 }
58 
printDocument(DocType * d)59 inline std::string printDocument(DocType *d) {
60     tinyxml2::XMLPrinter p;
61     d->Print(&p);
62     return std::string{p.CStr()};
63 }
64 
createNode(const std::string & name,DocType * d)65 inline NodeType *createNode(const std::string &name, DocType *d) {
66     return d->NewElement(name.c_str());
67 }
68 
appendChild(NodeType * parent,NodeType * child)69 inline void appendChild(NodeType *parent, NodeType *child) {
70     parent->InsertEndChild(child);
71 }
72 
appendChild(DocType * parent,NodeType * child)73 inline void appendChild(DocType *parent, NodeType *child) {
74     parent->InsertEndChild(child);
75 }
76 
appendStrAttr(NodeType * e,const std::string & attrName,const std::string & attr)77 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
78     e->SetAttribute(attrName.c_str(), attr.c_str());
79 }
80 
81 // text -> text
appendText(NodeType * parent,const std::string & text,DocType * d)82 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
83     parent->InsertEndChild(d->NewText(text.c_str()));
84 }
85 
nameOf(NodeType * root)86 inline std::string nameOf(NodeType *root) {
87     return root->Name() == NULL ? "" : root->Name();
88 }
89 
getText(NodeType * root)90 inline std::string getText(NodeType *root) {
91     return root->GetText() == NULL ? "" : root->GetText();
92 }
93 
getChild(NodeType * parent,const std::string & name)94 inline NodeType *getChild(NodeType *parent, const std::string &name) {
95     return parent->FirstChildElement(name.c_str());
96 }
97 
getRootChild(DocType * parent)98 inline NodeType *getRootChild(DocType *parent) {
99     return parent->FirstChildElement();
100 }
101 
getChildren(NodeType * parent,const std::string & name)102 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
103     std::vector<NodeType *> v;
104     for (NodeType *child = parent->FirstChildElement(name.c_str());
105          child != nullptr;
106          child = child->NextSiblingElement(name.c_str())) {
107         v.push_back(child);
108     }
109     return v;
110 }
111 
getAttr(NodeType * root,const std::string & attrName,std::string * s)112 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
113     const char *c = root->Attribute(attrName.c_str());
114     if (c == NULL)
115         return false;
116     *s = c;
117     return true;
118 }
119 
120 // --------------- tinyxml2 details end.
121 
122 // Helper functions for XmlConverter
parse(const std::string & attrText,bool * attr)123 static bool parse(const std::string &attrText, bool *attr) {
124     if (attrText == "true" || attrText == "1") {
125         *attr = true;
126         return true;
127     }
128     if (attrText == "false" || attrText == "0") {
129         *attr = false;
130         return true;
131     }
132     return false;
133 }
134 
135 // ---------------------- XmlNodeConverter definitions
136 
137 template<typename Object>
138 struct XmlNodeConverter : public XmlConverter<Object> {
XmlNodeConverterandroid::vintf::XmlNodeConverter139     XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter140     virtual ~XmlNodeConverter() {}
141 
142     // sub-types should implement these.
143     virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
mutateNodeandroid::vintf::XmlNodeConverter144     virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
145         mutateNode(o, n, d);
146     }
147     virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
148     virtual std::string elementName() const = 0;
149 
150     // convenience methods for user
lastErrorandroid::vintf::XmlNodeConverter151     inline const std::string& lastError() const override { return mLastError; }
serializeandroid::vintf::XmlNodeConverter152     inline NodeType* serialize(const Object& o, DocType* d,
153                                SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
154         NodeType *root = createNode(this->elementName(), d);
155         this->mutateNode(o, root, d, flags);
156         return root;
157     }
serializeandroid::vintf::XmlNodeConverter158     inline std::string serialize(const Object& o, SerializeFlags::Type flags) const override {
159         DocType *doc = createDocument();
160         appendChild(doc, serialize(o, doc, flags));
161         std::string s = printDocument(doc);
162         deleteDocument(doc);
163         return s;
164     }
deserializeandroid::vintf::XmlNodeConverter165     inline bool deserialize(Object* object, NodeType* root) {
166         bool ret = deserialize(object, root, &mLastError);
167         return ret;
168     }
deserializeandroid::vintf::XmlNodeConverter169     inline bool deserialize(Object* o, const std::string& xml) override {
170         bool ret = (*this)(o, xml, &mLastError);
171         return ret;
172     }
deserializeandroid::vintf::XmlNodeConverter173     inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
174         if (nameOf(root) != this->elementName()) {
175             return false;
176         }
177         return this->buildObject(object, root, error);
178     }
operator ()android::vintf::XmlNodeConverter179     inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
180         std::string errorBuffer;
181         if (error == nullptr) error = &errorBuffer;
182 
183         auto doc = createDocument(xml);
184         if (doc == nullptr) {
185             *error = "Not a valid XML";
186             return false;
187         }
188         bool ret = deserialize(o, getRootChild(doc), error);
189         deleteDocument(doc);
190         return ret;
191     }
operator ()android::vintf::XmlNodeConverter192     inline NodeType *operator()(const Object &o, DocType *d) const {
193         return serialize(o, d);
194     }
operator ()android::vintf::XmlNodeConverter195     inline std::string operator()(const Object& o, SerializeFlags::Type flags) const override {
196         return serialize(o, flags);
197     }
operator ()android::vintf::XmlNodeConverter198     inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
operator ()android::vintf::XmlNodeConverter199     inline bool operator()(Object* o, const std::string& xml) override {
200         return deserialize(o, xml);
201     }
202 
203     // convenience methods for implementor.
204 
205     // All append* functions helps mutateNode() to serialize the object into XML.
206     template <typename T>
appendAttrandroid::vintf::XmlNodeConverter207     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
208         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
209     }
210 
appendAttrandroid::vintf::XmlNodeConverter211     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
212         return appendStrAttr(e, attrName, attr ? "true" : "false");
213     }
214 
215     // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter216     inline void appendTextElement(NodeType *parent, const std::string &name,
217                 const std::string &text, DocType *d) const {
218         NodeType *c = createNode(name, d);
219         appendText(c, text, d);
220         appendChild(parent, c);
221     }
222 
223     // text -> <name>text</name>
224     template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter225     inline void appendTextElements(NodeType *parent, const std::string &name,
226                 const Array &array, DocType *d) const {
227         for (const std::string &text : array) {
228             NodeType *c = createNode(name, d);
229             appendText(c, text, d);
230             appendChild(parent, c);
231         }
232     }
233 
234     template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter235     inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
236                                const Array& array, DocType* d,
237                                SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
238         for (const T &t : array) {
239             appendChild(parent, conv.serialize(t, d, flags));
240         }
241     }
242 
243     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
244     // true if deserialization is successful, false if any error, and "error" will be
245     // set to error message.
246     template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter247     inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
248                                   T* attr, std::string* /* error */) const {
249         std::string attrText;
250         bool success = getAttr(root, attrName, &attrText) &&
251                        ::android::vintf::parse(attrText, attr);
252         if (!success) {
253             *attr = std::move(defaultValue);
254         }
255         return true;
256     }
257 
258     template <typename T>
parseAttrandroid::vintf::XmlNodeConverter259     inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
260                           std::string* error) const {
261         std::string attrText;
262         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
263         if (!ret) {
264             *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
265                      attrText + "\" for element <" + elementName() + ">";
266         }
267         return ret;
268     }
269 
parseAttrandroid::vintf::XmlNodeConverter270     inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
271                           std::string* error) const {
272         bool ret = getAttr(root, attrName, attr);
273         if (!ret) {
274             *error = "Could not find attr with name \"" + attrName + "\" for element <" +
275                      elementName() + ">";
276         }
277         return ret;
278     }
279 
parseTextElementandroid::vintf::XmlNodeConverter280     inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
281                                  std::string* error) const {
282         NodeType *child = getChild(root, elementName);
283         if (child == nullptr) {
284             *error = "Could not find element with name <" + elementName + "> in element <" +
285                      this->elementName() + ">";
286             return false;
287         }
288         *s = getText(child);
289         return true;
290     }
291 
parseOptionalTextElementandroid::vintf::XmlNodeConverter292     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
293                                          std::string&& defaultValue, std::string* s,
294                                          std::string* /* error */) const {
295         NodeType* child = getChild(root, elementName);
296         *s = child == nullptr ? std::move(defaultValue) : getText(child);
297         return true;
298     }
299 
parseTextElementsandroid::vintf::XmlNodeConverter300     inline bool parseTextElements(NodeType* root, const std::string& elementName,
301                                   std::vector<std::string>* v, std::string* /* error */) const {
302         auto nodes = getChildren(root, elementName);
303         v->resize(nodes.size());
304         for (size_t i = 0; i < nodes.size(); ++i) {
305             v->at(i) = getText(nodes[i]);
306         }
307         return true;
308     }
309 
310     template <typename T>
parseChildandroid::vintf::XmlNodeConverter311     inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
312                            std::string* error) const {
313         NodeType *child = getChild(root, conv.elementName());
314         if (child == nullptr) {
315             *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
316                      this->elementName() + ">";
317             return false;
318         }
319         return conv.deserialize(t, child, error);
320     }
321 
322     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter323     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
324                                    T&& defaultValue, T* t, std::string* error) const {
325         NodeType *child = getChild(root, conv.elementName());
326         if (child == nullptr) {
327             *t = std::move(defaultValue);
328             return true;
329         }
330         return conv.deserialize(t, child, error);
331     }
332 
333     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter334     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
335                                    std::optional<T>* t, std::string* error) const {
336         NodeType* child = getChild(root, conv.elementName());
337         if (child == nullptr) {
338             *t = std::nullopt;
339             return true;
340         }
341         *t = std::make_optional<T>();
342         return conv.deserialize(&**t, child, error);
343     }
344 
345     template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter346     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
347                               std::string* error) const {
348         auto nodes = getChildren(root, conv.elementName());
349         v->resize(nodes.size());
350         for (size_t i = 0; i < nodes.size(); ++i) {
351             if (!conv.deserialize(&v->at(i), nodes[i], error)) {
352                 *error = "Could not parse element with name <" + conv.elementName() +
353                          "> in element <" + this->elementName() + ">: " + *error;
354                 return false;
355             }
356         }
357         return true;
358     }
359 
360     template <typename Container, typename T = typename Container::value_type,
361               typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter362     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
363                               std::string* error) const {
364         std::vector<T> vec;
365         if (!parseChildren(root, conv, &vec, error)) {
366             return false;
367         }
368         s->clear();
369         s->insert(vec.begin(), vec.end());
370         if (s->size() != vec.size()) {
371             *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
372                      this->elementName() + ">";
373             s->clear();
374             return false;
375         }
376         return true;
377     }
378 
379     template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter380     inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
381                               std::map<K, V>* s, std::string* error) const {
382         return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
383     }
384 
parseTextandroid::vintf::XmlNodeConverter385     inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
386         *s = getText(node);
387         return true;
388     }
389 
390     template <typename T>
parseTextandroid::vintf::XmlNodeConverter391     inline bool parseText(NodeType* node, T* s, std::string* error) const {
392         std::string text = getText(node);
393         bool ret = ::android::vintf::parse(text, s);
394         if (!ret) {
395             *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
396         }
397         return ret;
398     }
399 
400    private:
401     mutable std::string mLastError;
402 };
403 
404 template<typename Object>
405 struct XmlTextConverter : public XmlNodeConverter<Object> {
XmlTextConverterandroid::vintf::XmlTextConverter406     XmlTextConverter(const std::string &elementName)
407         : mElementName(elementName) {}
408 
mutateNodeandroid::vintf::XmlTextConverter409     virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
410         appendText(root, ::android::vintf::to_string(object), d);
411     }
buildObjectandroid::vintf::XmlTextConverter412     virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
413         return this->parseText(root, object, error);
414     }
elementNameandroid::vintf::XmlTextConverter415     virtual std::string elementName() const { return mElementName; }
416 
417    private:
418     std::string mElementName;
419 };
420 
421 template <typename Pair>
422 struct XmlPairConverter : public XmlNodeConverter<Pair> {
XmlPairConverterandroid::vintf::XmlPairConverter423     XmlPairConverter(
424         const std::string& elementName,
425         std::unique_ptr<XmlNodeConverter<typename Pair::first_type>>&& firstConverter,
426         std::unique_ptr<XmlNodeConverter<typename Pair::second_type>>&& secondConverter)
427         : mElementName(elementName),
428           mFirstConverter(std::move(firstConverter)),
429           mSecondConverter(std::move(secondConverter)) {}
430 
mutateNodeandroid::vintf::XmlPairConverter431     virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
432         appendChild(root, mFirstConverter->serialize(pair.first, d));
433         appendChild(root, mSecondConverter->serialize(pair.second, d));
434     }
buildObjectandroid::vintf::XmlPairConverter435     virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
436         return this->parseChild(root, *mFirstConverter, &pair->first, error) &&
437                this->parseChild(root, *mSecondConverter, &pair->second, error);
438     }
elementNameandroid::vintf::XmlPairConverter439     virtual std::string elementName() const { return mElementName; }
440 
441    private:
442     std::string mElementName;
443     std::unique_ptr<XmlNodeConverter<typename Pair::first_type>> mFirstConverter;
444     std::unique_ptr<XmlNodeConverter<typename Pair::second_type>> mSecondConverter;
445 };
446 
447 // ---------------------- XmlNodeConverter definitions end
448 
449 XmlTextConverter<Version> versionConverter{"version"};
450 
451 XmlTextConverter<VersionRange> versionRangeConverter{"version"};
452 
453 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter454     std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter455     void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
456         if (object.arch != Arch::ARCH_EMPTY) {
457             appendAttr(root, "arch", object.arch);
458         }
459         appendText(root, ::android::vintf::to_string(object.transport), d);
460     }
buildObjectandroid::vintf::TransportArchConverter461     bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
462         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
463             !parseText(root, &object->transport, error)) {
464             return false;
465         }
466         if (!object->isValid()) {
467             *error = "transport == " + ::android::vintf::to_string(object->transport) +
468                      " and arch == " + ::android::vintf::to_string(object->arch) +
469                      " is not a valid combination.";
470             return false;
471         }
472         return true;
473     }
474 };
475 
476 TransportArchConverter transportArchConverter{};
477 
478 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter479     std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter480     void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
481         appendAttr(root, "type", object.mType);
482         appendText(root, ::android::vintf::to_string(object), d);
483     }
buildObjectandroid::vintf::KernelConfigTypedValueConverter484     bool buildObject(KernelConfigTypedValue* object, NodeType* root,
485                      std::string* error) const override {
486         std::string stringValue;
487         if (!parseAttr(root, "type", &object->mType, error) ||
488             !parseText(root, &stringValue, error)) {
489             return false;
490         }
491         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
492             *error = "Could not parse kernel config value \"" + stringValue + "\"";
493             return false;
494         }
495         return true;
496     }
497 };
498 
499 KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
500 
501 XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
502     "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
503     std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
504 
505 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter506     std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter507     void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
508         appendTextElement(root, "name", intf.name(), d);
509         appendTextElements(root, "instance", intf.mInstances, d);
510         appendTextElements(root, "regex-instance", intf.mRegexes, d);
511     }
buildObjectandroid::vintf::HalInterfaceConverter512     bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
513         std::vector<std::string> instances;
514         std::vector<std::string> regexes;
515         if (!parseTextElement(root, "name", &intf->mName, error) ||
516             !parseTextElements(root, "instance", &instances, error) ||
517             !parseTextElements(root, "regex-instance", &regexes, error)) {
518             return false;
519         }
520         bool success = true;
521         for (const auto& e : instances) {
522             if (!intf->insertInstance(e, false /* isRegex */)) {
523                 if (!error->empty()) *error += "\n";
524                 *error += "Duplicated instance '" + e + "' in " + intf->name();
525                 success = false;
526             }
527         }
528         for (const auto& e : regexes) {
529             details::Regex regex;
530             if (!regex.compile(e)) {
531                 if (!error->empty()) *error += "\n";
532                 *error += "Invalid regular expression '" + e + "' in " + intf->name();
533                 success = false;
534             }
535             if (!intf->insertInstance(e, true /* isRegex */)) {
536                 if (!error->empty()) *error += "\n";
537                 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
538                 success = false;
539             }
540         }
541         return success;
542     }
543 };
544 
545 HalInterfaceConverter halInterfaceConverter{};
546 
547 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter548     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter549     void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
550         appendAttr(root, "format", hal.format);
551         appendAttr(root, "optional", hal.optional);
552         appendTextElement(root, "name", hal.name, d);
553         appendChildren(root, versionRangeConverter, hal.versionRanges, d);
554         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
555     }
buildObjectandroid::vintf::MatrixHalConverter556     bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
557         std::vector<HalInterface> interfaces;
558         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
559             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
560                                error) ||
561             !parseTextElement(root, "name", &object->name, error) ||
562             !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
563             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
564             return false;
565         }
566         for (auto&& interface : interfaces) {
567             std::string name{interface.name()};
568             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
569             if (!res.second) {
570                 *error = "Duplicated interface entry \"" + res.first->first +
571                          "\"; if additional instances are needed, add them to the "
572                          "existing <interface> node.";
573                 return false;
574             }
575         }
576 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
577 #ifndef LIBVINTF_TARGET
578         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
579             return false;
580         }
581 #endif
582         return true;
583     }
584 
585 #ifndef LIBVINTF_TARGET
586    private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter587     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
588         if (hal.getName() == "netutils-wrapper") {
589             if (hal.versionRanges.size() != 1) {
590                 *error =
591                     "netutils-wrapper HAL must specify exactly one version x.0, "
592                     "but multiple <version> element is specified.";
593                 return false;
594             }
595             const VersionRange& v = hal.versionRanges.at(0);
596             if (!v.isSingleVersion()) {
597                 *error =
598                     "netutils-wrapper HAL must specify exactly one version x.0, "
599                     "but a range is provided. Perhaps you mean '" +
600                     to_string(Version{v.majorVer, 0}) + "'?";
601                 return false;
602             }
603             if (v.minMinor != 0) {
604                 *error =
605                     "netutils-wrapper HAL must specify exactly one version x.0, "
606                     "but minor version is not 0. Perhaps you mean '" +
607                     to_string(Version{v.majorVer, 0}) + "'?";
608                 return false;
609             }
610         }
611         return true;
612     }
613 #endif
614 };
615 
616 MatrixHalConverter matrixHalConverter{};
617 
618 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter619     std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter620     void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
621                     DocType* d) const override {
622         appendChildren(root, matrixKernelConfigConverter, conds, d);
623     }
buildObjectandroid::vintf::MatrixKernelConditionsConverter624     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
625                      std::string* error) const override {
626         return parseChildren(root, matrixKernelConfigConverter, object, error);
627     }
628 };
629 
630 MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
631 
632 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter633     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter634     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
635         mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
636     }
mutateNodeandroid::vintf::MatrixKernelConverter637     void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
638                     SerializeFlags::Type flags) const override {
639         KernelVersion kv = kernel.mMinLts;
640         if (!flags.isKernelMinorRevisionEnabled()) {
641             kv.minorRev = 0u;
642         }
643         appendAttr(root, "version", kv);
644 
645         if (!kernel.mConditions.empty()) {
646             appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
647         }
648         if (flags.isKernelConfigsEnabled()) {
649             appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
650         }
651     }
buildObjectandroid::vintf::MatrixKernelConverter652     bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
653         if (!parseAttr(root, "version", &object->mMinLts, error) ||
654             !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
655                                 error) ||
656             !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
657             return false;
658         }
659         return true;
660     }
661 };
662 
663 MatrixKernelConverter matrixKernelConverter{};
664 
665 XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
666 
667 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter668     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter669     void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
670         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
671     }
mutateNodeandroid::vintf::ManifestHalConverter672     void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
673                     SerializeFlags::Type flags) const override {
674         appendAttr(root, "format", hal.format);
675         appendTextElement(root, "name", hal.name, d);
676         appendChild(root, transportArchConverter(hal.transportArch, d));
677         appendChildren(root, versionConverter, hal.versions, d);
678         appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
679         if (hal.isOverride()) {
680             appendAttr(root, "override", hal.isOverride());
681         }
682 
683         if (flags.isFqnameEnabled()) {
684             std::set<FqInstance> fqInstances;
685             hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
686                 fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
687                 return true;
688             });
689             appendChildren(root, fqInstanceConverter, fqInstances, d);
690         }
691     }
buildObjectandroid::vintf::ManifestHalConverter692     bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
693         std::vector<HalInterface> interfaces;
694         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
695             !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
696             !parseTextElement(root, "name", &object->name, error) ||
697             !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
698             !parseChildren(root, versionConverter, &object->versions, error) ||
699             !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
700             return false;
701         }
702 
703         switch (object->format) {
704             case HalFormat::HIDL: {
705                 if (object->transportArch.empty()) {
706                     *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
707                     return false;
708                 }
709             } break;
710             case HalFormat::NATIVE: {
711                 if (!object->transportArch.empty()) {
712                     *error =
713                         "Native HAL '" + object->name + "' should not have <transport> defined.";
714                     return false;
715                 }
716             } break;
717             default: {
718                 LOG(FATAL) << "Unhandled HalFormat "
719                            << static_cast<typename std::underlying_type<HalFormat>::type>(
720                                   object->format);
721             } break;
722         }
723         if (!object->transportArch.isValid()) return false;
724 
725         object->interfaces.clear();
726         for (auto &&interface : interfaces) {
727             auto res = object->interfaces.emplace(interface.name(), std::move(interface));
728             if (!res.second) {
729                 *error = "Duplicated interface entry \"" + res.first->first +
730                          "\"; if additional instances are needed, add them to the "
731                          "existing <interface> node.";
732                 return false;
733             }
734         }
735         if (!object->isValid()) {
736             *error = "'" + object->name + "' is not a valid Manifest HAL.";
737             return false;
738         }
739 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
740 #ifndef LIBVINTF_TARGET
741         if (!checkAdditionalRestrictionsOnHal(*object, error)) {
742             return false;
743         }
744 #endif
745 
746         std::set<FqInstance> fqInstances;
747         if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
748             return false;
749         }
750         for (const auto& e : fqInstances) {
751             if (e.hasPackage()) {
752                 *error = "Should not specify package: \"" + e.string() + "\"";
753                 return false;
754             }
755         }
756         if (!object->insertInstances(fqInstances, error)) {
757             return false;
758         }
759 
760         return true;
761     }
762 
763 #ifndef LIBVINTF_TARGET
764    private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter765     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
766         if (hal.getName() == "netutils-wrapper") {
767             for (const Version& v : hal.versions) {
768                 if (v.minorVer != 0) {
769                     *error =
770                         "netutils-wrapper HAL must specify exactly one version x.0, "
771                         "but minor version is not 0. Perhaps you mean '" +
772                         to_string(Version{v.majorVer, 0}) + "'?";
773                     return false;
774                 }
775             }
776         }
777         return true;
778     }
779 #endif
780 };
781 
782 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
783 // .isValid() == true.
784 ManifestHalConverter manifestHalConverter{};
785 
786 XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
787 XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
788 
789 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter790     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter791     void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
792         appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
793         appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
794     }
buildObjectandroid::vintf::SepolicyConverter795     bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
796         if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
797                         error) ||
798             !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
799                            error)) {
800             return false;
801         }
802         return true;
803     }
804 };
805 SepolicyConverter sepolicyConverter{};
806 
807 [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
808 
809 XmlTextConverter<std::string> vndkVersionConverter{"version"};
810 XmlTextConverter<std::string> vndkLibraryConverter{"library"};
811 
812 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter813     std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter814     void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
815         appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
816         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
817     }
buildObjectandroid::vintf::VndkConverter818     bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
819         if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
820             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
821             return false;
822         }
823         return true;
824     }
825 };
826 
827 [[deprecated]] VndkConverter vndkConverter{};
828 
829 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter830     std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter831     void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
832         appendChild(root, vndkVersionConverter(object.mVersion, d));
833         appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
834     }
buildObjectandroid::vintf::VendorNdkConverter835     bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
836         if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
837             !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
838             return false;
839         }
840         return true;
841     }
842 };
843 
844 VendorNdkConverter vendorNdkConverter{};
845 
846 XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
847 
848 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter849     std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter850     void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
851         appendChildren(root, systemSdkVersionConverter, object.versions(), d);
852     }
buildObjectandroid::vintf::SystemSdkConverter853     bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
854         return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
855     }
856 };
857 
858 SystemSdkConverter systemSdkConverter{};
859 
860 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter861     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter862     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
863         appendChild(root, versionConverter(m, d));
864     }
buildObjectandroid::vintf::HalManifestSepolicyConverter865     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
866         return parseChild(root, versionConverter, object, error);
867     }
868 };
869 HalManifestSepolicyConverter halManifestSepolicyConverter{};
870 
871 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter872     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter873     void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
874         appendTextElement(root, "name", f.name(), d);
875         appendChild(root, versionConverter(f.version(), d));
876         if (!f.overriddenPath().empty()) {
877             appendTextElement(root, "path", f.overriddenPath(), d);
878         }
879     }
buildObjectandroid::vintf::ManifestXmlFileConverter880     bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
881         if (!parseTextElement(root, "name", &object->mName, error) ||
882             !parseChild(root, versionConverter, &object->mVersion, error) ||
883             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
884             return false;
885         }
886         return true;
887     }
888 };
889 ManifestXmlFileConverter manifestXmlFileConverter{};
890 
891 XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
892     "config", std::make_unique<XmlTextConverter<std::string>>("key"),
893     std::make_unique<XmlTextConverter<std::string>>("value")};
894 
895 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter896     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter897     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
898         mutateNode(o, root, d, SerializeFlags::EVERYTHING);
899     }
mutateNodeandroid::vintf::KernelInfoConverter900     void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
901                     SerializeFlags::Type flags) const override {
902         if (o.version() != KernelVersion{}) {
903             appendAttr(root, "version", o.version());
904         }
905         if (flags.isKernelConfigsEnabled()) {
906             appendChildren(root, kernelConfigConverter, o.configs(), d);
907         }
908     }
buildObjectandroid::vintf::KernelInfoConverter909     bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
910         return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
911                parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
912     }
913 };
914 
915 KernelInfoConverter kernelInfoConverter{};
916 
917 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter918     std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter919     void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
920         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
921     }
mutateNodeandroid::vintf::HalManifestConverter922     void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
923                     SerializeFlags::Type flags) const override {
924         if (flags.isMetaVersionEnabled()) {
925             appendAttr(root, "version", m.getMetaVersion());
926         }
927         if (flags.isSchemaTypeEnabled()) {
928             appendAttr(root, "type", m.mType);
929         }
930 
931         if (flags.isHalsEnabled()) {
932             appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
933         }
934         if (m.mType == SchemaType::DEVICE) {
935             if (flags.isSepolicyEnabled()) {
936                 if (m.device.mSepolicyVersion != Version{}) {
937                     appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
938                 }
939             }
940             if (m.mLevel != Level::UNSPECIFIED) {
941                 this->appendAttr(root, "target-level", m.mLevel);
942             }
943 
944             if (flags.isKernelEnabled()) {
945                 if (!!m.kernel()) {
946                     appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
947                 }
948             }
949         } else if (m.mType == SchemaType::FRAMEWORK) {
950             if (flags.isVndkEnabled()) {
951 #pragma clang diagnostic push
952 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
953                 appendChildren(root, vndkConverter, m.framework.mVndks, d);
954 #pragma clang diagnostic pop
955 
956                 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
957             }
958             if (flags.isSsdkEnabled()) {
959                 if (!m.framework.mSystemSdk.empty()) {
960                     appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
961                 }
962             }
963         }
964 
965         if (flags.isXmlFilesEnabled()) {
966             appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
967         }
968     }
buildObjectandroid::vintf::HalManifestConverter969     bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
970         std::vector<ManifestHal> hals;
971         if (!parseAttr(root, "version", &object->mMetaVersion, error) ||
972             !parseAttr(root, "type", &object->mType, error) ||
973             !parseChildren(root, manifestHalConverter, &hals, error)) {
974             return false;
975         }
976         if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) {
977             *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
978                      " (libvintf@" + to_string(kMetaVersion) + ")";
979             return false;
980         }
981         if (object->mType == SchemaType::DEVICE) {
982             // tags for device hal manifest only.
983             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
984             // in the XML file.
985             if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
986                                     &object->device.mSepolicyVersion, error)) {
987                 return false;
988             }
989 
990             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
991                                    error)) {
992                 return false;
993             }
994 
995             if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
996                 return false;
997             }
998         } else if (object->mType == SchemaType::FRAMEWORK) {
999 #pragma clang diagnostic push
1000 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1001             if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
1002                 return false;
1003             }
1004             for (const auto &vndk : object->framework.mVndks) {
1005                 if (!vndk.mVersionRange.isSingleVersion()) {
1006                     *error = "vndk.version " + to_string(vndk.mVersionRange) +
1007                              " cannot be a range for manifests";
1008                     return false;
1009                 }
1010             }
1011 #pragma clang diagnostic pop
1012 
1013             if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
1014                 return false;
1015             }
1016 
1017             std::set<std::string> vendorNdkVersions;
1018             for (const auto& vendorNdk : object->framework.mVendorNdks) {
1019                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1020                     *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1021                     return false;
1022                 }
1023                 vendorNdkVersions.insert(vendorNdk.version());
1024             }
1025 
1026             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
1027                                     error)) {
1028                 return false;
1029             }
1030         }
1031         for (auto &&hal : hals) {
1032             std::string description{hal.name};
1033             if (!object->add(std::move(hal))) {
1034                 *error = "Duplicated manifest.hal entry " + description;
1035                 return false;
1036             }
1037         }
1038 
1039         std::vector<ManifestXmlFile> xmlFiles;
1040         if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
1041             return false;
1042         }
1043         for (auto&& xmlFile : xmlFiles) {
1044             std::string description{xmlFile.name()};
1045             if (!object->addXmlFile(std::move(xmlFile))) {
1046                 *error = "Duplicated manifest.xmlfile entry " + description +
1047                          "; entries cannot have duplicated name and version";
1048                 return false;
1049             }
1050         }
1051 
1052         return true;
1053     }
1054 };
1055 
1056 HalManifestConverter halManifestConverter{};
1057 
1058 XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
1059 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1060     std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1061     void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1062         appendChild(root, avbVersionConverter(m, d));
1063     }
buildObjectandroid::vintf::AvbConverter1064     bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1065         return parseChild(root, avbVersionConverter, object, error);
1066     }
1067 };
1068 AvbConverter avbConverter{};
1069 
1070 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1071     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1072     void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1073         appendTextElement(root, "name", f.name(), d);
1074         appendAttr(root, "format", f.format());
1075         appendAttr(root, "optional", f.optional());
1076         appendChild(root, versionRangeConverter(f.versionRange(), d));
1077         if (!f.overriddenPath().empty()) {
1078             appendTextElement(root, "path", f.overriddenPath(), d);
1079         }
1080     }
buildObjectandroid::vintf::MatrixXmlFileConverter1081     bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1082         if (!parseTextElement(root, "name", &object->mName, error) ||
1083             !parseAttr(root, "format", &object->mFormat, error) ||
1084             !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1085             !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
1086             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1087             return false;
1088         }
1089         return true;
1090     }
1091 };
1092 MatrixXmlFileConverter matrixXmlFileConverter{};
1093 
1094 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1095     std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1096     void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1097         mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1098     }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1099     void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1100                     SerializeFlags::Type flags) const override {
1101         if (flags.isMetaVersionEnabled()) {
1102             appendAttr(root, "version", m.getMinimumMetaVersion());
1103         }
1104         if (flags.isSchemaTypeEnabled()) {
1105             appendAttr(root, "type", m.mType);
1106         }
1107 
1108         if (flags.isHalsEnabled()) {
1109             appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
1110         }
1111         if (m.mType == SchemaType::FRAMEWORK) {
1112             if (flags.isKernelEnabled()) {
1113                 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
1114             }
1115             if (flags.isSepolicyEnabled()) {
1116                 if (!(m.framework.mSepolicy == Sepolicy{})) {
1117                     appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
1118                 }
1119             }
1120             if (flags.isAvbEnabled()) {
1121                 if (!(m.framework.mAvbMetaVersion == Version{})) {
1122                     appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
1123                 }
1124             }
1125             if (m.mLevel != Level::UNSPECIFIED) {
1126                 this->appendAttr(root, "level", m.mLevel);
1127             }
1128         } else if (m.mType == SchemaType::DEVICE) {
1129             if (flags.isVndkEnabled()) {
1130 #pragma clang diagnostic push
1131 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1132                 if (!(m.device.mVndk == Vndk{})) {
1133                     appendChild(root, vndkConverter(m.device.mVndk, d));
1134                 }
1135 #pragma clang diagnostic pop
1136 
1137                 if (!(m.device.mVendorNdk == VendorNdk{})) {
1138                     appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
1139                 }
1140             }
1141 
1142             if (flags.isSsdkEnabled()) {
1143                 if (!m.device.mSystemSdk.empty()) {
1144                     appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
1145                 }
1146             }
1147         }
1148 
1149         if (flags.isXmlFilesEnabled()) {
1150             appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
1151         }
1152     }
buildObjectandroid::vintf::CompatibilityMatrixConverter1153     bool buildObject(CompatibilityMatrix* object, NodeType* root,
1154                      std::string* error) const override {
1155         Version version;
1156         std::vector<MatrixHal> hals;
1157         if (!parseAttr(root, "version", &version, error) ||
1158             !parseAttr(root, "type", &object->mType, error) ||
1159             !parseChildren(root, matrixHalConverter, &hals, error)) {
1160             return false;
1161         }
1162 
1163         if (object->mType == SchemaType::FRAMEWORK) {
1164             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1165             // hard-coded in the XML file.
1166             if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1167                 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1168                                     error) ||
1169                 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1170                                     error)) {
1171                 return false;
1172             }
1173 
1174             std::set<Version> seenKernelVersions;
1175             for (const auto& kernel : object->framework.mKernels) {
1176                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1177                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1178                     continue;
1179                 }
1180                 if (!kernel.conditions().empty()) {
1181                     *error = "First <kernel> for version " + to_string(minLts) +
1182                              " must have empty <conditions> for backwards compatibility.";
1183                     return false;
1184                 }
1185                 seenKernelVersions.insert(minLts);
1186             }
1187 
1188             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1189                 return false;
1190             }
1191 
1192         } else if (object->mType == SchemaType::DEVICE) {
1193             // <vndk> can be missing because it can be determined at build time, not hard-coded
1194             // in the XML file.
1195 #pragma clang diagnostic push
1196 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1197             if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
1198                 return false;
1199             }
1200 #pragma clang diagnostic pop
1201 
1202             if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1203                                     error)) {
1204                 return false;
1205             }
1206 
1207             if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1208                                     error)) {
1209                 return false;
1210             }
1211         }
1212 
1213         if (!kMetaVersion.minorAtLeast(version)) {
1214             *error = "Unrecognized compatibility-matrix.version " + to_string(version) +
1215                      " (libvintf@" + to_string(kMetaVersion) + ")";
1216             return false;
1217         }
1218         for (auto &&hal : hals) {
1219             if (!object->add(std::move(hal))) {
1220                 *error = "Duplicated compatibility-matrix.hal entry";
1221                 return false;
1222             }
1223         }
1224 
1225         std::vector<MatrixXmlFile> xmlFiles;
1226         if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
1227             return false;
1228         }
1229         for (auto&& xmlFile : xmlFiles) {
1230             if (!xmlFile.optional()) {
1231                 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1232                          " has to be optional for compatibility matrix version 1.0";
1233                 return false;
1234             }
1235             std::string description{xmlFile.name()};
1236             if (!object->addXmlFile(std::move(xmlFile))) {
1237                 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1238                 return false;
1239             }
1240         }
1241 
1242         return true;
1243     }
1244 };
1245 
1246 CompatibilityMatrixConverter compatibilityMatrixConverter{};
1247 
1248 // Publicly available as in parse_xml.h
1249 XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1250 XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
1251 
1252 // For testing in LibVintfTest
1253 XmlConverter<Version>& gVersionConverter = versionConverter;
1254 XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1255     kernelConfigTypedValueConverter;
1256 XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1257 XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
1258 XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
1259 
1260 } // namespace vintf
1261 } // namespace android
1262