• 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 <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
createDocument()47 inline DocType *createDocument() {
48     return new tinyxml2::XMLDocument();
49 }
50 
51 // caller is responsible for deleteDocument() call
createDocument(const std::string & xml)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 
deleteDocument(DocType * d)61 inline void deleteDocument(DocType *d) {
62     delete d;
63 }
64 
printDocument(DocType * d)65 inline std::string printDocument(DocType *d) {
66     tinyxml2::XMLPrinter p;
67     d->Print(&p);
68     return std::string{p.CStr()};
69 }
70 
createNode(const std::string & name,DocType * d)71 inline NodeType *createNode(const std::string &name, DocType *d) {
72     return d->NewElement(name.c_str());
73 }
74 
appendChild(NodeType * parent,NodeType * child)75 inline void appendChild(NodeType *parent, NodeType *child) {
76     parent->InsertEndChild(child);
77 }
78 
appendChild(DocType * parent,NodeType * child)79 inline void appendChild(DocType *parent, NodeType *child) {
80     parent->InsertEndChild(child);
81 }
82 
appendStrAttr(NodeType * e,const std::string & attrName,const std::string & attr)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
appendText(NodeType * parent,const std::string & text,DocType * d)88 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
89     parent->InsertEndChild(d->NewText(text.c_str()));
90 }
91 
nameOf(NodeType * root)92 inline std::string nameOf(NodeType *root) {
93     return root->Name() == NULL ? "" : root->Name();
94 }
95 
getText(NodeType * root)96 inline std::string getText(NodeType *root) {
97     return root->GetText() == NULL ? "" : root->GetText();
98 }
99 
getChild(NodeType * parent,const std::string & name)100 inline NodeType *getChild(NodeType *parent, const std::string &name) {
101     return parent->FirstChildElement(name.c_str());
102 }
103 
getRootChild(DocType * parent)104 inline NodeType *getRootChild(DocType *parent) {
105     return parent->FirstChildElement();
106 }
107 
getChildren(NodeType * parent,const std::string & name)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 
getAttr(NodeType * root,const std::string & attrName,std::string * s)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
parse(const std::string & attrText,bool * attr)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 
parse(const std::string & attrText,std::optional<std::string> * attr)141 static bool parse(const std::string& attrText, std::optional<std::string>* attr) {
142     *attr = attrText;
143     return true;
144 }
145 
parse(const std::string & s,std::optional<uint64_t> * out)146 static bool parse(const std::string& s, std::optional<uint64_t>* out) {
147     uint64_t val;
148     if (base::ParseUint(s, &val)) {
149         *out = val;
150         return true;
151     }
152     return false;
153 }
154 
155 // ---------------------- XmlNodeConverter definitions
156 
157 // When serializing an object to an XML document, these parameters don't change until
158 // the object is fully serialized.
159 // These parameters are also passed to converters of child nodes so they see the same
160 // serialization parameters.
161 struct MutateNodeParam {
162     DocType* d;
163     SerializeFlags::Type flags = SerializeFlags::EVERYTHING;
164 };
165 
166 // When deserializing an XML document to an object, these parameters don't change until
167 // the XML document is fully deserialized.
168 // * Except metaVersion, which is immediately modified when parsing top-level <manifest>
169 //   or <compatibility-matrix>, and unchanged thereafter;
170 //   see HalManifestConverter::BuildObject and CompatibilityMatrixConverter::BuildObject)
171 // These parameters are also passed to converters of child nodes so they see the same
172 // deserialization parameters.
173 struct BuildObjectParam {
174     std::string* error;
175     Version metaVersion;
176 };
177 
178 template <typename Object>
179 struct XmlNodeConverter {
XmlNodeConverterandroid::vintf::XmlNodeConverter180     XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter181     virtual ~XmlNodeConverter() {}
182 
183    protected:
184     virtual void mutateNode(const Object& object, NodeType* root, const MutateNodeParam&) const = 0;
185     virtual bool buildObject(Object* object, NodeType* root, const BuildObjectParam&) const = 0;
186 
187    public:
188     // Methods for other (usually parent) converters
189     // Name of the XML element.
190     virtual std::string elementName() const = 0;
191     // Serialize |o| into an XML element.
operator ()android::vintf::XmlNodeConverter192     inline NodeType* operator()(const Object& o, const MutateNodeParam& param) const {
193         NodeType* root = createNode(this->elementName(), param.d);
194         this->mutateNode(o, root, param);
195         return root;
196     }
197     // Deserialize XML element |root| into |object|.
operator ()android::vintf::XmlNodeConverter198     inline bool operator()(Object* object, NodeType* root, const BuildObjectParam& param) const {
199         if (nameOf(root) != this->elementName()) {
200             return false;
201         }
202         return this->buildObject(object, root, param);
203     }
204 
205     // Public methods for android::vintf::fromXml / android::vintf::toXml.
206     // Serialize |o| into an XML string.
toXmlandroid::vintf::XmlNodeConverter207     inline std::string toXml(const Object& o, SerializeFlags::Type flags) const {
208         DocType* doc = createDocument();
209         appendChild(doc, (*this)(o, MutateNodeParam{doc, flags}));
210         std::string s = printDocument(doc);
211         deleteDocument(doc);
212         return s;
213     }
214     // Deserialize XML string |xml| into |o|.
fromXmlandroid::vintf::XmlNodeConverter215     inline bool fromXml(Object* o, const std::string& xml, std::string* error) const {
216         std::string errorBuffer;
217         if (error == nullptr) error = &errorBuffer;
218 
219         auto doc = createDocument(xml);
220         if (doc == nullptr) {
221             *error = "Not a valid XML";
222             return false;
223         }
224         // For top-level <manifest> and <compatibility-matrix>, HalManifestConverter and
225         // CompatibilityMatrixConverter fills in metaversion and pass down to children.
226         // For other nodes, we don't know metaversion of the original XML, so just leave empty
227         // for maximum backwards compatibility.
228         bool ret = (*this)(o, getRootChild(doc), BuildObjectParam{error, {}});
229         deleteDocument(doc);
230         return ret;
231     }
232 
233     // convenience methods for subclasses to implement virtual functions.
234 
235     // All append* functions helps mutateNode() to serialize the object into XML.
236     template <typename T>
appendAttrandroid::vintf::XmlNodeConverter237     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
238         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
239     }
240 
appendAttrandroid::vintf::XmlNodeConverter241     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
242         return appendStrAttr(e, attrName, attr ? "true" : "false");
243     }
244 
245     // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter246     inline void appendTextElement(NodeType *parent, const std::string &name,
247                 const std::string &text, DocType *d) const {
248         NodeType *c = createNode(name, d);
249         appendText(c, text, d);
250         appendChild(parent, c);
251     }
252 
253     // text -> <name>text</name>
254     template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter255     inline void appendTextElements(NodeType *parent, const std::string &name,
256                 const Array &array, DocType *d) const {
257         for (const std::string &text : array) {
258             NodeType *c = createNode(name, d);
259             appendText(c, text, d);
260             appendChild(parent, c);
261         }
262     }
263 
264     template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter265     inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
266                                const Array& array, const MutateNodeParam& param) const {
267         for (const T &t : array) {
268             appendChild(parent, conv(t, param));
269         }
270     }
271 
272     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
273     // true if deserialization is successful, false if any error, and "error" will be
274     // set to error message.
275     template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter276     inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
277                                   T* attr, std::string* /* error */) const {
278         std::string attrText;
279         bool success = getAttr(root, attrName, &attrText) &&
280                        ::android::vintf::parse(attrText, attr);
281         if (!success) {
282             *attr = std::move(defaultValue);
283         }
284         return true;
285     }
286 
287     template <typename T>
parseAttrandroid::vintf::XmlNodeConverter288     inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
289                           std::string* error) const {
290         std::string attrText;
291         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
292         if (!ret) {
293             *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
294                      attrText + "\" for element <" + elementName() + ">";
295         }
296         return ret;
297     }
298 
parseAttrandroid::vintf::XmlNodeConverter299     inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
300                           std::string* error) const {
301         bool ret = getAttr(root, attrName, attr);
302         if (!ret) {
303             *error = "Could not find attr with name \"" + attrName + "\" for element <" +
304                      elementName() + ">";
305         }
306         return ret;
307     }
308 
parseTextElementandroid::vintf::XmlNodeConverter309     inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
310                                  std::string* error) const {
311         NodeType *child = getChild(root, elementName);
312         if (child == nullptr) {
313             *error = "Could not find element with name <" + elementName + "> in element <" +
314                      this->elementName() + ">";
315             return false;
316         }
317         *s = getText(child);
318         return true;
319     }
320 
parseOptionalTextElementandroid::vintf::XmlNodeConverter321     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
322                                          std::string&& defaultValue, std::string* s,
323                                          std::string* /* error */) const {
324         NodeType* child = getChild(root, elementName);
325         *s = child == nullptr ? std::move(defaultValue) : getText(child);
326         return true;
327     }
328 
parseTextElementsandroid::vintf::XmlNodeConverter329     inline bool parseTextElements(NodeType* root, const std::string& elementName,
330                                   std::vector<std::string>* v, std::string* /* error */) const {
331         auto nodes = getChildren(root, elementName);
332         v->resize(nodes.size());
333         for (size_t i = 0; i < nodes.size(); ++i) {
334             v->at(i) = getText(nodes[i]);
335         }
336         return true;
337     }
338 
339     template <typename T>
parseChildandroid::vintf::XmlNodeConverter340     inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
341                            const BuildObjectParam& param) const {
342         NodeType *child = getChild(root, conv.elementName());
343         if (child == nullptr) {
344             *param.error = "Could not find element with name <" + conv.elementName() +
345                            "> in element <" + this->elementName() + ">";
346             return false;
347         }
348         return conv(t, child, param);
349     }
350 
351     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter352     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
353                                    T&& defaultValue, T* t, const BuildObjectParam& param) const {
354         NodeType *child = getChild(root, conv.elementName());
355         if (child == nullptr) {
356             *t = std::move(defaultValue);
357             return true;
358         }
359         return conv(t, child, param);
360     }
361 
362     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter363     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
364                                    std::optional<T>* t, const BuildObjectParam& param) const {
365         NodeType* child = getChild(root, conv.elementName());
366         if (child == nullptr) {
367             *t = std::nullopt;
368             return true;
369         }
370         *t = std::make_optional<T>();
371         return conv(&**t, child, param);
372     }
373 
374     template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter375     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
376                               const BuildObjectParam& param) const {
377         auto nodes = getChildren(root, conv.elementName());
378         v->resize(nodes.size());
379         for (size_t i = 0; i < nodes.size(); ++i) {
380             if (!conv(&v->at(i), nodes[i], param)) {
381                 *param.error = "Could not parse element with name <" + conv.elementName() +
382                                "> in element <" + this->elementName() + ">: " + *param.error;
383                 return false;
384             }
385         }
386         return true;
387     }
388 
389     template <typename Container, typename T = typename Container::value_type,
390               typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter391     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
392                               const BuildObjectParam& param) const {
393         std::vector<T> vec;
394         if (!parseChildren(root, conv, &vec, param)) {
395             return false;
396         }
397         s->clear();
398         s->insert(vec.begin(), vec.end());
399         if (s->size() != vec.size()) {
400             *param.error = "Duplicated elements <" + conv.elementName() + "> in element <" +
401                            this->elementName() + ">";
402             s->clear();
403             return false;
404         }
405         return true;
406     }
407 
408     template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter409     inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
410                               std::map<K, V>* s, const BuildObjectParam& param) const {
411         return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, param);
412     }
413 
parseTextandroid::vintf::XmlNodeConverter414     inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
415         *s = getText(node);
416         return true;
417     }
418 
419     template <typename T>
parseTextandroid::vintf::XmlNodeConverter420     inline bool parseText(NodeType* node, T* s, std::string* error) const {
421         bool (*parser)(const std::string&, T*) = ::android::vintf::parse;
422         return parseText(node, s, {parser}, error);
423     }
424 
425     template <typename T>
parseTextandroid::vintf::XmlNodeConverter426     inline bool parseText(NodeType* node, T* s,
427                           const std::function<bool(const std::string&, T*)>& parse,
428                           std::string* error) const {
429         std::string text = getText(node);
430         bool ret = parse(text, s);
431         if (!ret) {
432             *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
433         }
434         return ret;
435     }
436 };
437 
438 template<typename Object>
439 struct XmlTextConverter : public XmlNodeConverter<Object> {
mutateNodeandroid::vintf::XmlTextConverter440     void mutateNode(const Object& object, NodeType* root,
441                     const MutateNodeParam& param) const override {
442         appendText(root, ::android::vintf::to_string(object), param.d);
443     }
buildObjectandroid::vintf::XmlTextConverter444     bool buildObject(Object* object, NodeType* root, const BuildObjectParam& param) const override {
445         return this->parseText(root, object, param.error);
446     }
447 };
448 
449 template <typename Pair, typename FirstConverter, typename SecondConverter>
450 struct XmlPairConverter : public XmlNodeConverter<Pair> {
mutateNodeandroid::vintf::XmlPairConverter451     void mutateNode(const Pair& object, NodeType* root,
452                     const MutateNodeParam& param) const override {
453         appendChild(root, FirstConverter{}(object.first, param));
454         appendChild(root, SecondConverter{}(object.second, param));
455     }
buildObjectandroid::vintf::XmlPairConverter456     bool buildObject(Pair* object, NodeType* root, const BuildObjectParam& param) const override {
457         return this->parseChild(root, FirstConverter{}, &object->first, param) &&
458                this->parseChild(root, SecondConverter{}, &object->second, param);
459     }
460 };
461 
462 // ---------------------- XmlNodeConverter definitions end
463 
464 struct VersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::VersionConverter465     std::string elementName() const override { return "version"; }
466 };
467 
468 struct VersionRangeConverter : public XmlTextConverter<VersionRange> {
elementNameandroid::vintf::VersionRangeConverter469     std::string elementName() const override { return "version"; }
470 };
471 
472 // <version>100</version> <=> Version{kFakeAidlMajorVersion, 100}
473 struct AidlVersionConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AidlVersionConverter474     std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionConverter475     void mutateNode(const Version& object, NodeType* root,
476                     const MutateNodeParam& param) const override {
477         appendText(root, aidlVersionToString(object), param.d);
478     }
buildObjectandroid::vintf::AidlVersionConverter479     bool buildObject(Version* object, NodeType* root,
480                      const BuildObjectParam& param) const override {
481         return parseText(root, object, {parseAidlVersion}, param.error);
482     }
483 };
484 
485 // <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100}
486 // <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105}
487 struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> {
elementNameandroid::vintf::AidlVersionRangeConverter488     std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionRangeConverter489     void mutateNode(const VersionRange& object, NodeType* root,
490                     const MutateNodeParam& param) const override {
491         appendText(root, aidlVersionRangeToString(object), param.d);
492     }
buildObjectandroid::vintf::AidlVersionRangeConverter493     bool buildObject(VersionRange* object, NodeType* root,
494                      const BuildObjectParam& param) const override {
495         return parseText(root, object, {parseAidlVersionRange}, param.error);
496     }
497 };
498 
499 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter500     std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter501     void mutateNode(const TransportArch& object, NodeType* root,
502                     const MutateNodeParam& param) const override {
503         if (object.arch != Arch::ARCH_EMPTY) {
504             appendAttr(root, "arch", object.arch);
505         }
506         if (object.ip.has_value()) {
507             appendAttr(root, "ip", *object.ip);
508         }
509         if (object.port.has_value()) {
510             appendAttr(root, "port", *object.port);
511         }
512         appendText(root, ::android::vintf::to_string(object.transport), param.d);
513     }
buildObjectandroid::vintf::TransportArchConverter514     bool buildObject(TransportArch* object, NodeType* root,
515                      const BuildObjectParam& param) const override {
516         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, param.error) ||
517             !parseOptionalAttr(root, "ip", {}, &object->ip, param.error) ||
518             !parseOptionalAttr(root, "port", {}, &object->port, param.error) ||
519             !parseText(root, &object->transport, param.error)) {
520             return false;
521         }
522         if (!object->isValid(param.error)) {
523             return false;
524         }
525         return true;
526     }
527 };
528 
529 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter530     std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter531     void mutateNode(const KernelConfigTypedValue& object, NodeType* root,
532                     const MutateNodeParam& param) const override {
533         appendAttr(root, "type", object.mType);
534         appendText(root, ::android::vintf::to_string(object), param.d);
535     }
buildObjectandroid::vintf::KernelConfigTypedValueConverter536     bool buildObject(KernelConfigTypedValue* object, NodeType* root,
537                      const BuildObjectParam& param) const override {
538         std::string stringValue;
539         if (!parseAttr(root, "type", &object->mType, param.error) ||
540             !parseText(root, &stringValue, param.error)) {
541             return false;
542         }
543         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
544             *param.error = "Could not parse kernel config value \"" + stringValue + "\"";
545             return false;
546         }
547         return true;
548     }
549 };
550 
551 struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> {
elementNameandroid::vintf::KernelConfigKeyConverter552     std::string elementName() const override { return "key"; }
553 };
554 
555 struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter,
556                                                              KernelConfigTypedValueConverter> {
elementNameandroid::vintf::MatrixKernelConfigConverter557     std::string elementName() const override { return "config"; }
558 };
559 
560 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter561     std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter562     void mutateNode(const HalInterface& object, NodeType* root,
563                     const MutateNodeParam& param) const override {
564         appendTextElement(root, "name", object.name(), param.d);
565         appendTextElements(root, "instance", object.mInstances, param.d);
566         appendTextElements(root, "regex-instance", object.mRegexes, param.d);
567     }
buildObjectandroid::vintf::HalInterfaceConverter568     bool buildObject(HalInterface* object, NodeType* root,
569                      const BuildObjectParam& param) const override {
570         std::vector<std::string> instances;
571         std::vector<std::string> regexes;
572         if (!parseTextElement(root, "name", &object->mName, param.error) ||
573             !parseTextElements(root, "instance", &instances, param.error) ||
574             !parseTextElements(root, "regex-instance", &regexes, param.error)) {
575             return false;
576         }
577         bool success = true;
578         for (const auto& e : instances) {
579             if (!object->insertInstance(e, false /* isRegex */)) {
580                 if (!param.error->empty()) *param.error += "\n";
581                 *param.error += "Duplicated instance '" + e + "' in " + object->name();
582                 success = false;
583             }
584         }
585         for (const auto& e : regexes) {
586             details::Regex regex;
587             if (!regex.compile(e)) {
588                 if (!param.error->empty()) *param.error += "\n";
589                 *param.error += "Invalid regular expression '" + e + "' in " + object->name();
590                 success = false;
591             }
592             if (!object->insertInstance(e, true /* isRegex */)) {
593                 if (!param.error->empty()) *param.error += "\n";
594                 *param.error += "Duplicated regex-instance '" + e + "' in " + object->name();
595                 success = false;
596             }
597         }
598         return success;
599     }
600 };
601 
602 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter603     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter604     void mutateNode(const MatrixHal& object, NodeType* root,
605                     const MutateNodeParam& param) const override {
606         appendAttr(root, "format", object.format);
607         appendAttr(root, "optional", object.optional);
608         appendTextElement(root, "name", object.name, param.d);
609         if (object.format == HalFormat::AIDL) {
610             // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
611             // is specified. Don't output any <version> tag if there's only one <version>0</version>
612             // tag.
613             if (object.versionRanges.size() != 1 ||
614                 object.versionRanges[0] != details::kDefaultAidlVersionRange) {
615                 appendChildren(root, AidlVersionRangeConverter{}, object.versionRanges, param);
616             }
617         } else {
618             appendChildren(root, VersionRangeConverter{}, object.versionRanges, param);
619         }
620         appendChildren(root, HalInterfaceConverter{}, iterateValues(object.interfaces), param);
621     }
buildObjectandroid::vintf::MatrixHalConverter622     bool buildObject(MatrixHal* object, NodeType* root,
623                      const BuildObjectParam& param) const override {
624         std::vector<HalInterface> interfaces;
625         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param.error) ||
626             !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
627                                param.error) ||
628             !parseTextElement(root, "name", &object->name, param.error) ||
629             !parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
630             return false;
631         }
632         if (object->format == HalFormat::AIDL) {
633             if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, param)) {
634                 return false;
635             }
636             // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
637             // HAL formats can be unified.
638             if (object->versionRanges.empty()) {
639                 object->versionRanges.push_back(details::kDefaultAidlVersionRange);
640             }
641         } else {
642             if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, param)) {
643                 return false;
644             }
645         }
646         for (auto&& interface : interfaces) {
647             std::string name{interface.name()};
648             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
649             if (!res.second) {
650                 *param.error = "Duplicated interface entry \"" + res.first->first +
651                                "\"; if additional instances are needed, add them to the "
652                                "existing <interface> node.";
653                 return false;
654             }
655         }
656 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
657 #ifndef LIBVINTF_TARGET
658         if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
659             return false;
660         }
661 #endif
662 
663         if (!object->isValid(param.error)) {
664             param.error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: ");
665             return false;
666         }
667         return true;
668     }
669 
670 #ifndef LIBVINTF_TARGET
671    private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter672     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
673         if (hal.getName() == "netutils-wrapper") {
674             if (hal.versionRanges.size() != 1) {
675                 *error =
676                     "netutils-wrapper HAL must specify exactly one version x.0, "
677                     "but multiple <version> element is specified.";
678                 return false;
679             }
680             const VersionRange& v = hal.versionRanges.at(0);
681             if (!v.isSingleVersion()) {
682                 *error =
683                     "netutils-wrapper HAL must specify exactly one version x.0, "
684                     "but a range is provided. Perhaps you mean '" +
685                     to_string(Version{v.majorVer, 0}) + "'?";
686                 return false;
687             }
688             if (v.minMinor != 0) {
689                 *error =
690                     "netutils-wrapper HAL must specify exactly one version x.0, "
691                     "but minor version is not 0. Perhaps you mean '" +
692                     to_string(Version{v.majorVer, 0}) + "'?";
693                 return false;
694             }
695         }
696         return true;
697     }
698 #endif
699 };
700 
701 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter702     std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter703     void mutateNode(const std::vector<KernelConfig>& object, NodeType* root,
704                     const MutateNodeParam& param) const override {
705         appendChildren(root, MatrixKernelConfigConverter{}, object, param);
706     }
buildObjectandroid::vintf::MatrixKernelConditionsConverter707     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
708                      const BuildObjectParam& param) const override {
709         return parseChildren(root, MatrixKernelConfigConverter{}, object, param);
710     }
711 };
712 
713 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter714     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter715     void mutateNode(const MatrixKernel& object, NodeType* root,
716                     const MutateNodeParam& param) const override {
717         KernelVersion kv = object.mMinLts;
718         if (!param.flags.isKernelMinorRevisionEnabled()) {
719             kv.minorRev = 0u;
720         }
721         appendAttr(root, "version", kv);
722 
723         if (object.getSourceMatrixLevel() != Level::UNSPECIFIED) {
724             appendAttr(root, "level", object.getSourceMatrixLevel());
725         }
726 
727         if (!object.mConditions.empty()) {
728             appendChild(root, MatrixKernelConditionsConverter{}(object.mConditions, param));
729         }
730         if (param.flags.isKernelConfigsEnabled()) {
731             appendChildren(root, MatrixKernelConfigConverter{}, object.mConfigs, param);
732         }
733     }
buildObjectandroid::vintf::MatrixKernelConverter734     bool buildObject(MatrixKernel* object, NodeType* root,
735                      const BuildObjectParam& param) const override {
736         Level sourceMatrixLevel = Level::UNSPECIFIED;
737         if (!parseAttr(root, "version", &object->mMinLts, param.error) ||
738             !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel,
739                                param.error) ||
740             !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions,
741                                 param) ||
742             !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, param)) {
743             return false;
744         }
745         object->setSourceMatrixLevel(sourceMatrixLevel);
746         return true;
747     }
748 };
749 
750 struct FqInstanceConverter : public XmlTextConverter<FqInstance> {
elementNameandroid::vintf::FqInstanceConverter751     std::string elementName() const override { return "fqname"; }
752 };
753 
754 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
755 // .isValid() == true.
756 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter757     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter758     void mutateNode(const ManifestHal& object, NodeType* root,
759                     const MutateNodeParam& param) const override {
760         appendAttr(root, "format", object.format);
761         appendTextElement(root, "name", object.name, param.d);
762         if (!object.transportArch.empty()) {
763             appendChild(root, TransportArchConverter{}(object.transportArch, param));
764         }
765         if (object.format == HalFormat::AIDL) {
766             // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
767             // is specified. Don't output any <version> tag if there's only one <version>0</version>
768             // tag.
769             if (object.versions.size() != 1 || object.versions[0] != details::kDefaultAidlVersion) {
770                 appendChildren(root, AidlVersionConverter{}, object.versions, param);
771             }
772         } else {
773             appendChildren(root, VersionConverter{}, object.versions, param);
774         }
775         appendChildren(root, HalInterfaceConverter{}, iterateValues(object.interfaces), param);
776         if (object.isOverride()) {
777             appendAttr(root, "override", object.isOverride());
778         }
779         if (const auto& apex = object.updatableViaApex(); apex.has_value()) {
780             appendAttr(root, "updatable-via-apex", apex.value());
781         }
782         if (param.flags.isFqnameEnabled()) {
783             std::set<std::string> simpleFqInstances;
784             object.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
785                 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
786                 return true;
787             });
788             appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances,
789                                param.d);
790         }
791         if (object.getMaxLevel() != Level::UNSPECIFIED) {
792             appendAttr(root, "max-level", object.getMaxLevel());
793         }
794     }
buildObjectandroid::vintf::ManifestHalConverter795     bool buildObject(ManifestHal* object, NodeType* root,
796                      const BuildObjectParam& param) const override {
797         std::vector<HalInterface> interfaces;
798         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param.error) ||
799             !parseOptionalAttr(root, "override", false, &object->mIsOverride, param.error) ||
800             !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex,
801                                param.error) ||
802             !parseTextElement(root, "name", &object->name, param.error) ||
803             !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch,
804                                 param) ||
805             !parseChildren(root, HalInterfaceConverter{}, &interfaces, param) ||
806             !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel,
807                                param.error)) {
808             return false;
809         }
810 
811         switch (object->format) {
812             case HalFormat::HIDL: {
813                 if (!parseChildren(root, VersionConverter{}, &object->versions, param))
814                     return false;
815                 if (object->transportArch.empty()) {
816                     *param.error =
817                         "HIDL HAL '" + object->name + "' should have <transport> defined.";
818                     return false;
819                 }
820                 if (object->transportArch.transport == Transport::INET ||
821                     object->transportArch.ip.has_value() ||
822                     object->transportArch.port.has_value()) {
823                     *param.error = "HIDL HAL '" + object->name +
824                                    "' should not have <transport> \"inet\" " +
825                                    "or ip or port attributes defined.";
826                     return false;
827                 }
828             } break;
829             case HalFormat::NATIVE: {
830                 if (!parseChildren(root, VersionConverter{}, &object->versions, param))
831                     return false;
832                 if (!object->transportArch.empty()) {
833                     *param.error =
834                         "Native HAL '" + object->name + "' should not have <transport> defined.";
835                     return false;
836                 }
837             } break;
838             case HalFormat::AIDL: {
839                 if (!object->transportArch.empty() &&
840                     object->transportArch.transport != Transport::INET) {
841                     if (param.metaVersion >= kMetaVersionAidlInet) {
842                         *param.error = "AIDL HAL '" + object->name +
843                                        R"(' only supports "inet" or empty <transport>, found ")" +
844                                        to_string(object->transportArch) + "\"";
845                         return false;
846                     }
847                     LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
848                                  << object->name << ". Only \"inet\" supported.";
849                     object->transportArch = {};
850                 }
851                 if (!parseChildren(root, AidlVersionConverter{}, &object->versions, param)) {
852                     return false;
853                 }
854                 // Insert fake version for AIDL HALs so that forEachInstance works.
855                 if (object->versions.empty()) {
856                     object->versions.push_back(details::kDefaultAidlVersion);
857                 }
858             } break;
859             default: {
860                 LOG(FATAL) << "Unhandled HalFormat "
861                            << static_cast<typename std::underlying_type<HalFormat>::type>(
862                                   object->format);
863             } break;
864         }
865         if (!object->transportArch.isValid(param.error)) return false;
866 
867         object->interfaces.clear();
868         for (auto &&interface : interfaces) {
869             auto res = object->interfaces.emplace(interface.name(), std::move(interface));
870             if (!res.second) {
871                 *param.error = "Duplicated interface entry \"" + res.first->first +
872                                "\"; if additional instances are needed, add them to the "
873                                "existing <interface> node.";
874                 return false;
875             }
876         }
877 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
878 #ifndef LIBVINTF_TARGET
879         if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
880             return false;
881         }
882 #endif
883 
884         std::set<FqInstance> fqInstances;
885         if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, param)) {
886             return false;
887         }
888         std::set<FqInstance> fqInstancesToInsert;
889         for (auto& e : fqInstances) {
890             if (e.hasPackage()) {
891                 *param.error = "Should not specify package: \"" + e.string() + "\"";
892                 return false;
893             }
894             if (object->format == HalFormat::AIDL) {
895                 // <fqname> in AIDL HALs should not contain version.
896                 if (e.hasVersion()) {
897                     *param.error = "Should not specify version in <fqname> for AIDL HAL: \"" +
898                                    e.string() + "\"";
899                     return false;
900                 }
901                 // Put in the fake kDefaultAidlVersion so that HalManifest can
902                 // store it in an FqInstance object with a non-empty package.
903                 FqInstance withFakeVersion;
904                 if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer,
905                                            details::kDefaultAidlVersion.minorVer, e.getInterface(),
906                                            e.getInstance())) {
907                     return false;
908                 }
909                 fqInstancesToInsert.emplace(std::move(withFakeVersion));
910             } else {
911                 fqInstancesToInsert.emplace(std::move(e));
912             }
913         }
914         if (!object->insertInstances(fqInstancesToInsert, param.error)) {
915             return false;
916         }
917 
918         if (!object->isValid(param.error)) {
919             param.error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
920             return false;
921         }
922 
923         return true;
924     }
925 
926 #ifndef LIBVINTF_TARGET
927    private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter928     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
929         if (hal.getName() == "netutils-wrapper") {
930             for (const Version& v : hal.versions) {
931                 if (v.minorVer != 0) {
932                     *error =
933                         "netutils-wrapper HAL must specify exactly one version x.0, "
934                         "but minor version is not 0. Perhaps you mean '" +
935                         to_string(Version{v.majorVer, 0}) + "'?";
936                     return false;
937                 }
938             }
939         }
940         return true;
941     }
942 #endif
943 };
944 
945 struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> {
elementNameandroid::vintf::KernelSepolicyVersionConverter946     std::string elementName() const override { return "kernel-sepolicy-version"; }
947 };
948 
949 struct SepolicyVersionConverter : public XmlTextConverter<VersionRange> {
elementNameandroid::vintf::SepolicyVersionConverter950     std::string elementName() const override { return "sepolicy-version"; }
951 };
952 
953 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter954     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter955     void mutateNode(const Sepolicy& object, NodeType* root,
956                     const MutateNodeParam& param) const override {
957         appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), param));
958         appendChildren(root, SepolicyVersionConverter{}, object.sepolicyVersions(), param);
959     }
buildObjectandroid::vintf::SepolicyConverter960     bool buildObject(Sepolicy* object, NodeType* root,
961                      const BuildObjectParam& param) const override {
962         if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion,
963                         param) ||
964             !parseChildren(root, SepolicyVersionConverter{}, &object->mSepolicyVersionRanges,
965                            param)) {
966             return false;
967         }
968         return true;
969     }
970 };
971 
972 struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> {
elementNameandroid::vintf::VndkVersionRangeConverter973     std::string elementName() const override { return "version"; }
974 };
975 
976 struct VndkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkVersionConverter977     std::string elementName() const override { return "version"; }
978 };
979 
980 struct VndkLibraryConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkLibraryConverter981     std::string elementName() const override { return "library"; }
982 };
983 
984 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter985     std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter986     void mutateNode(const Vndk& object, NodeType* root,
987                     const MutateNodeParam& param) const override {
988         appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, param));
989         appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
990     }
buildObjectandroid::vintf::VndkConverter991     bool buildObject(Vndk* object, NodeType* root, const BuildObjectParam& param) const override {
992         if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, param) ||
993             !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
994             return false;
995         }
996         return true;
997     }
998 };
999 
1000 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter1001     std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter1002     void mutateNode(const VendorNdk& object, NodeType* root,
1003                     const MutateNodeParam& param) const override {
1004         appendChild(root, VndkVersionConverter{}(object.mVersion, param));
1005         appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
1006     }
buildObjectandroid::vintf::VendorNdkConverter1007     bool buildObject(VendorNdk* object, NodeType* root,
1008                      const BuildObjectParam& param) const override {
1009         if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, param) ||
1010             !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
1011             return false;
1012         }
1013         return true;
1014     }
1015 };
1016 
1017 struct SystemSdkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::SystemSdkVersionConverter1018     std::string elementName() const override { return "version"; }
1019 };
1020 
1021 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter1022     std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter1023     void mutateNode(const SystemSdk& object, NodeType* root,
1024                     const MutateNodeParam& param) const override {
1025         appendChildren(root, SystemSdkVersionConverter{}, object.versions(), param);
1026     }
buildObjectandroid::vintf::SystemSdkConverter1027     bool buildObject(SystemSdk* object, NodeType* root,
1028                      const BuildObjectParam& param) const override {
1029         return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, param);
1030     }
1031 };
1032 
1033 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter1034     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter1035     void mutateNode(const Version& object, NodeType* root,
1036                     const MutateNodeParam& param) const override {
1037         appendChild(root, VersionConverter{}(object, param));
1038     }
buildObjectandroid::vintf::HalManifestSepolicyConverter1039     bool buildObject(Version* object, NodeType* root,
1040                      const BuildObjectParam& param) const override {
1041         return parseChild(root, VersionConverter{}, object, param);
1042     }
1043 };
1044 
1045 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter1046     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter1047     void mutateNode(const ManifestXmlFile& object, NodeType* root,
1048                     const MutateNodeParam& param) const override {
1049         appendTextElement(root, "name", object.name(), param.d);
1050         appendChild(root, VersionConverter{}(object.version(), param));
1051         if (!object.overriddenPath().empty()) {
1052             appendTextElement(root, "path", object.overriddenPath(), param.d);
1053         }
1054     }
buildObjectandroid::vintf::ManifestXmlFileConverter1055     bool buildObject(ManifestXmlFile* object, NodeType* root,
1056                      const BuildObjectParam& param) const override {
1057         if (!parseTextElement(root, "name", &object->mName, param.error) ||
1058             !parseChild(root, VersionConverter{}, &object->mVersion, param) ||
1059             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
1060             return false;
1061         }
1062         return true;
1063     }
1064 };
1065 
1066 struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::StringKernelConfigKeyConverter1067     std::string elementName() const override { return "key"; }
1068 };
1069 
1070 struct KernelConfigValueConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::KernelConfigValueConverter1071     std::string elementName() const override { return "value"; }
1072 };
1073 
1074 struct StringKernelConfigConverter
1075     : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter,
1076                               KernelConfigValueConverter> {
elementNameandroid::vintf::StringKernelConfigConverter1077     std::string elementName() const override { return "config"; }
1078 };
1079 
1080 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter1081     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter1082     void mutateNode(const KernelInfo& object, NodeType* root,
1083                     const MutateNodeParam& param) const override {
1084         if (object.version() != KernelVersion{}) {
1085             appendAttr(root, "version", object.version());
1086         }
1087         if (object.level() != Level::UNSPECIFIED) {
1088             appendAttr(root, "target-level", object.level());
1089         }
1090         if (param.flags.isKernelConfigsEnabled()) {
1091             appendChildren(root, StringKernelConfigConverter{}, object.configs(), param);
1092         }
1093     }
buildObjectandroid::vintf::KernelInfoConverter1094     bool buildObject(KernelInfo* object, NodeType* root,
1095                      const BuildObjectParam& param) const override {
1096         return parseOptionalAttr(root, "version", {}, &object->mVersion, param.error) &&
1097                parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1098                                  param.error) &&
1099                parseChildren(root, StringKernelConfigConverter{}, &object->mConfigs, param);
1100     }
1101 };
1102 
1103 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter1104     std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter1105     void mutateNode(const HalManifest& object, NodeType* root,
1106                     const MutateNodeParam& param) const override {
1107         if (param.flags.isMetaVersionEnabled()) {
1108             appendAttr(root, "version", object.getMetaVersion());
1109         }
1110         if (param.flags.isSchemaTypeEnabled()) {
1111             appendAttr(root, "type", object.mType);
1112         }
1113 
1114         if (param.flags.isHalsEnabled()) {
1115             appendChildren(root, ManifestHalConverter{}, object.getHals(), param);
1116         }
1117         if (object.mType == SchemaType::DEVICE) {
1118             if (param.flags.isSepolicyEnabled()) {
1119                 if (object.device.mSepolicyVersion != Version{}) {
1120                     appendChild(root, HalManifestSepolicyConverter{}(object.device.mSepolicyVersion,
1121                                                                      param));
1122                 }
1123             }
1124             if (object.mLevel != Level::UNSPECIFIED) {
1125                 this->appendAttr(root, "target-level", object.mLevel);
1126             }
1127 
1128             if (param.flags.isKernelEnabled()) {
1129                 if (!!object.kernel()) {
1130                     appendChild(root, KernelInfoConverter{}(*object.kernel(), param));
1131                 }
1132             }
1133         } else if (object.mType == SchemaType::FRAMEWORK) {
1134             if (param.flags.isVndkEnabled()) {
1135 #pragma clang diagnostic push
1136 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1137                 appendChildren(root, VndkConverter{}, object.framework.mVndks, param);
1138 #pragma clang diagnostic pop
1139 
1140                 appendChildren(root, VendorNdkConverter{}, object.framework.mVendorNdks, param);
1141             }
1142             if (param.flags.isSsdkEnabled()) {
1143                 if (!object.framework.mSystemSdk.empty()) {
1144                     appendChild(root, SystemSdkConverter{}(object.framework.mSystemSdk, param));
1145                 }
1146             }
1147         }
1148 
1149         if (param.flags.isXmlFilesEnabled()) {
1150             appendChildren(root, ManifestXmlFileConverter{}, object.getXmlFiles(), param);
1151         }
1152     }
buildObjectandroid::vintf::HalManifestConverter1153     bool buildObject(HalManifest* object, NodeType* root,
1154                      const BuildObjectParam& constParam) const override {
1155         BuildObjectParam param = constParam;
1156         if (!parseAttr(root, "version", &param.metaVersion, param.error)) return false;
1157         if (param.metaVersion > kMetaVersion) {
1158             *param.error = "Unrecognized manifest.version " + to_string(param.metaVersion) +
1159                            " (libvintf@" + to_string(kMetaVersion) + ")";
1160             return false;
1161         }
1162 
1163         if (!parseAttr(root, "type", &object->mType, param.error)) {
1164             return false;
1165         }
1166 
1167         std::vector<ManifestHal> hals;
1168         if (!parseChildren(root, ManifestHalConverter{}, &hals, param)) {
1169             return false;
1170         }
1171         for (auto&& hal : hals) {
1172             hal.setFileName(object->fileName());
1173         }
1174 
1175         if (object->mType == SchemaType::DEVICE) {
1176             // tags for device hal manifest only.
1177             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1178             // in the XML file.
1179             if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {},
1180                                     &object->device.mSepolicyVersion, param)) {
1181                 return false;
1182             }
1183 
1184             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1185                                    param.error)) {
1186                 return false;
1187             }
1188 
1189             if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, param)) {
1190                 return false;
1191             }
1192         } else if (object->mType == SchemaType::FRAMEWORK) {
1193 #pragma clang diagnostic push
1194 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1195             if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, param)) {
1196                 return false;
1197             }
1198             for (const auto& vndk : object->framework.mVndks) {
1199                 if (!vndk.mVersionRange.isSingleVersion()) {
1200                     *param.error = "vndk.version " + to_string(vndk.mVersionRange) +
1201                                    " cannot be a range for manifests";
1202                     return false;
1203                 }
1204             }
1205 #pragma clang diagnostic pop
1206 
1207             if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, param)) {
1208                 return false;
1209             }
1210 
1211             std::set<std::string> vendorNdkVersions;
1212             for (const auto& vendorNdk : object->framework.mVendorNdks) {
1213                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1214                     *param.error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1215                     return false;
1216                 }
1217                 vendorNdkVersions.insert(vendorNdk.version());
1218             }
1219 
1220             if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk,
1221                                     param)) {
1222                 return false;
1223             }
1224         }
1225         for (auto &&hal : hals) {
1226             std::string description{hal.name};
1227             if (!object->add(std::move(hal))) {
1228                 *param.error = "Duplicated manifest.hal entry " + description;
1229                 return false;
1230             }
1231         }
1232 
1233         std::vector<ManifestXmlFile> xmlFiles;
1234         if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, param)) {
1235             return false;
1236         }
1237         for (auto&& xmlFile : xmlFiles) {
1238             std::string description{xmlFile.name()};
1239             if (!object->addXmlFile(std::move(xmlFile))) {
1240                 *param.error = "Duplicated manifest.xmlfile entry " + description +
1241                                "; entries cannot have duplicated name and version";
1242                 return false;
1243             }
1244         }
1245 
1246         return true;
1247     }
1248 };
1249 
1250 struct AvbVersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::AvbVersionConverter1251     std::string elementName() const override { return "vbmeta-version"; }
1252 };
1253 
1254 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1255     std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1256     void mutateNode(const Version& object, NodeType* root,
1257                     const MutateNodeParam& param) const override {
1258         appendChild(root, AvbVersionConverter{}(object, param));
1259     }
buildObjectandroid::vintf::AvbConverter1260     bool buildObject(Version* object, NodeType* root,
1261                      const BuildObjectParam& param) const override {
1262         return parseChild(root, AvbVersionConverter{}, object, param);
1263     }
1264 };
1265 
1266 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1267     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1268     void mutateNode(const MatrixXmlFile& object, NodeType* root,
1269                     const MutateNodeParam& param) const override {
1270         appendTextElement(root, "name", object.name(), param.d);
1271         appendAttr(root, "format", object.format());
1272         appendAttr(root, "optional", object.optional());
1273         appendChild(root, VersionRangeConverter{}(object.versionRange(), param));
1274         if (!object.overriddenPath().empty()) {
1275             appendTextElement(root, "path", object.overriddenPath(), param.d);
1276         }
1277     }
buildObjectandroid::vintf::MatrixXmlFileConverter1278     bool buildObject(MatrixXmlFile* object, NodeType* root,
1279                      const BuildObjectParam& param) const override {
1280         if (!parseTextElement(root, "name", &object->mName, param.error) ||
1281             !parseAttr(root, "format", &object->mFormat, param.error) ||
1282             !parseOptionalAttr(root, "optional", false, &object->mOptional, param.error) ||
1283             !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, param) ||
1284             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
1285             return false;
1286         }
1287         return true;
1288     }
1289 };
1290 
1291 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1292     std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1293     void mutateNode(const CompatibilityMatrix& object, NodeType* root,
1294                     const MutateNodeParam& param) const override {
1295         if (param.flags.isMetaVersionEnabled()) {
1296             appendAttr(root, "version", kMetaVersion);
1297         }
1298         if (param.flags.isSchemaTypeEnabled()) {
1299             appendAttr(root, "type", object.mType);
1300         }
1301 
1302         if (param.flags.isHalsEnabled()) {
1303             appendChildren(root, MatrixHalConverter{}, iterateValues(object.mHals), param);
1304         }
1305         if (object.mType == SchemaType::FRAMEWORK) {
1306             if (param.flags.isKernelEnabled()) {
1307                 appendChildren(root, MatrixKernelConverter{}, object.framework.mKernels, param);
1308             }
1309             if (param.flags.isSepolicyEnabled()) {
1310                 if (!(object.framework.mSepolicy == Sepolicy{})) {
1311                     appendChild(root, SepolicyConverter{}(object.framework.mSepolicy, param));
1312                 }
1313             }
1314             if (param.flags.isAvbEnabled()) {
1315                 if (!(object.framework.mAvbMetaVersion == Version{})) {
1316                     appendChild(root, AvbConverter{}(object.framework.mAvbMetaVersion, param));
1317                 }
1318             }
1319             if (object.mLevel != Level::UNSPECIFIED) {
1320                 this->appendAttr(root, "level", object.mLevel);
1321             }
1322         } else if (object.mType == SchemaType::DEVICE) {
1323             if (param.flags.isVndkEnabled()) {
1324 #pragma clang diagnostic push
1325 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1326                 if (!(object.device.mVndk == Vndk{})) {
1327                     appendChild(root, VndkConverter{}(object.device.mVndk, param));
1328                 }
1329 #pragma clang diagnostic pop
1330 
1331                 if (!(object.device.mVendorNdk == VendorNdk{})) {
1332                     appendChild(root, VendorNdkConverter{}(object.device.mVendorNdk, param));
1333                 }
1334             }
1335 
1336             if (param.flags.isSsdkEnabled()) {
1337                 if (!object.device.mSystemSdk.empty()) {
1338                     appendChild(root, SystemSdkConverter{}(object.device.mSystemSdk, param));
1339                 }
1340             }
1341         }
1342 
1343         if (param.flags.isXmlFilesEnabled()) {
1344             appendChildren(root, MatrixXmlFileConverter{}, object.getXmlFiles(), param);
1345         }
1346     }
buildObjectandroid::vintf::CompatibilityMatrixConverter1347     bool buildObject(CompatibilityMatrix* object, NodeType* root,
1348                      const BuildObjectParam& constParam) const override {
1349         BuildObjectParam param = constParam;
1350         if (!parseAttr(root, "version", &param.metaVersion, param.error)) return false;
1351         if (param.metaVersion > kMetaVersion) {
1352             *param.error = "Unrecognized compatibility-matrix.version " +
1353                            to_string(param.metaVersion) + " (libvintf@" + to_string(kMetaVersion) +
1354                            ")";
1355             return false;
1356         }
1357 
1358         std::vector<MatrixHal> hals;
1359         if (!parseAttr(root, "type", &object->mType, param.error) ||
1360             !parseChildren(root, MatrixHalConverter{}, &hals, param)) {
1361             return false;
1362         }
1363 
1364         if (object->mType == SchemaType::FRAMEWORK) {
1365             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1366             // hard-coded in the XML file.
1367             if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, param) ||
1368                 !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy,
1369                                     param) ||
1370                 !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion,
1371                                     param)) {
1372                 return false;
1373             }
1374 
1375             std::set<Version> seenKernelVersions;
1376             for (const auto& kernel : object->framework.mKernels) {
1377                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1378                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1379                     continue;
1380                 }
1381                 if (!kernel.conditions().empty()) {
1382                     *param.error = "First <kernel> for version " + to_string(minLts) +
1383                                    " must have empty <conditions> for backwards compatibility.";
1384                     return false;
1385                 }
1386                 seenKernelVersions.insert(minLts);
1387             }
1388 
1389             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel,
1390                                    param.error)) {
1391                 return false;
1392             }
1393 
1394         } else if (object->mType == SchemaType::DEVICE) {
1395             // <vndk> can be missing because it can be determined at build time, not hard-coded
1396             // in the XML file.
1397 #pragma clang diagnostic push
1398 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1399             if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, param)) {
1400                 return false;
1401             }
1402 #pragma clang diagnostic pop
1403 
1404             if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk,
1405                                     param)) {
1406                 return false;
1407             }
1408 
1409             if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk,
1410                                     param)) {
1411                 return false;
1412             }
1413         }
1414 
1415         for (auto &&hal : hals) {
1416             if (!object->add(std::move(hal))) {
1417                 *param.error = "Duplicated compatibility-matrix.hal entry";
1418                 return false;
1419             }
1420         }
1421 
1422         std::vector<MatrixXmlFile> xmlFiles;
1423         if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, param)) {
1424             return false;
1425         }
1426         for (auto&& xmlFile : xmlFiles) {
1427             if (!xmlFile.optional()) {
1428                 *param.error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1429                                " has to be optional for compatibility matrix version 1.0";
1430                 return false;
1431             }
1432             std::string description{xmlFile.name()};
1433             if (!object->addXmlFile(std::move(xmlFile))) {
1434                 *param.error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1435                 return false;
1436             }
1437         }
1438 
1439         return true;
1440     }
1441 };
1442 
1443 #define CREATE_CONVERT_FN(type)                                         \
1444     std::string toXml(const type& o, SerializeFlags::Type flags) {      \
1445         return type##Converter{}.toXml(o, flags);                       \
1446     }                                                                   \
1447     bool fromXml(type* o, const std::string& xml, std::string* error) { \
1448         return type##Converter{}.fromXml(o, xml, error);                \
1449     }
1450 
1451 // Create convert functions for public usage.
1452 CREATE_CONVERT_FN(HalManifest)
1453 CREATE_CONVERT_FN(CompatibilityMatrix)
1454 
1455 // Create convert functions for internal usage.
1456 CREATE_CONVERT_FN(KernelInfo)
1457 
1458 // Create convert functions for testing.
1459 CREATE_CONVERT_FN(Version)
1460 CREATE_CONVERT_FN(KernelConfigTypedValue)
1461 CREATE_CONVERT_FN(MatrixHal)
1462 CREATE_CONVERT_FN(ManifestHal)
1463 
1464 #undef CREATE_CONVERT_FN
1465 
1466 } // namespace vintf
1467 } // namespace android
1468