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 #include "utils.h"
36 
37 using namespace std::string_literals;
38 
39 #ifdef LIBVINTF_TARGET
40 static constexpr bool kDevice = true;
41 #else
42 static constexpr bool kDevice = false;
43 #endif
44 
45 namespace android {
46 namespace vintf {
47 
48 // --------------- tinyxml2 details
49 
50 using NodeType = tinyxml2::XMLElement;
51 using DocType = tinyxml2::XMLDocument;
52 
53 // caller is responsible for deleteDocument() call
createDocument()54 inline DocType *createDocument() {
55     return new tinyxml2::XMLDocument();
56 }
57 
58 // caller is responsible for deleteDocument() call
createDocument(const std::string & xml)59 inline DocType *createDocument(const std::string &xml) {
60     DocType *doc = new tinyxml2::XMLDocument();
61     if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
62         return doc;
63     }
64     delete doc;
65     return nullptr;
66 }
67 
deleteDocument(DocType * d)68 inline void deleteDocument(DocType *d) {
69     delete d;
70 }
71 
printDocument(DocType * d)72 inline std::string printDocument(DocType *d) {
73     tinyxml2::XMLPrinter p;
74     d->Print(&p);
75     return std::string{p.CStr()};
76 }
77 
createNode(const std::string & name,DocType * d)78 inline NodeType *createNode(const std::string &name, DocType *d) {
79     return d->NewElement(name.c_str());
80 }
81 
appendChild(NodeType * parent,NodeType * child)82 inline void appendChild(NodeType *parent, NodeType *child) {
83     parent->InsertEndChild(child);
84 }
85 
appendChild(DocType * parent,NodeType * child)86 inline void appendChild(DocType *parent, NodeType *child) {
87     parent->InsertEndChild(child);
88 }
89 
appendStrAttr(NodeType * e,const std::string & attrName,const std::string & attr)90 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
91     e->SetAttribute(attrName.c_str(), attr.c_str());
92 }
93 
94 // text -> text
appendText(NodeType * parent,const std::string & text,DocType * d)95 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
96     parent->InsertEndChild(d->NewText(text.c_str()));
97 }
98 
nameOf(NodeType * root)99 inline std::string nameOf(NodeType *root) {
100     return root->Name() == NULL ? "" : root->Name();
101 }
102 
getText(NodeType * root)103 inline std::string getText(NodeType *root) {
104     return root->GetText() == NULL ? "" : root->GetText();
105 }
106 
getChild(NodeType * parent,const std::string & name)107 inline NodeType *getChild(NodeType *parent, const std::string &name) {
108     return parent->FirstChildElement(name.c_str());
109 }
110 
getRootChild(DocType * parent)111 inline NodeType *getRootChild(DocType *parent) {
112     return parent->FirstChildElement();
113 }
114 
getChildren(NodeType * parent,const std::string & name)115 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
116     std::vector<NodeType *> v;
117     for (NodeType *child = parent->FirstChildElement(name.c_str());
118          child != nullptr;
119          child = child->NextSiblingElement(name.c_str())) {
120         v.push_back(child);
121     }
122     return v;
123 }
124 
getAttr(NodeType * root,const std::string & attrName,std::string * s)125 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
126     const char *c = root->Attribute(attrName.c_str());
127     if (c == NULL)
128         return false;
129     *s = c;
130     return true;
131 }
132 
133 // --------------- tinyxml2 details end.
134 
135 // Helper functions for XmlConverter
parse(const std::string & attrText,bool * attr)136 static bool parse(const std::string &attrText, bool *attr) {
137     if (attrText == "true" || attrText == "1") {
138         *attr = true;
139         return true;
140     }
141     if (attrText == "false" || attrText == "0") {
142         *attr = false;
143         return true;
144     }
145     return false;
146 }
147 
parse(const std::string & attrText,std::optional<std::string> * attr)148 static bool parse(const std::string& attrText, std::optional<std::string>* attr) {
149     *attr = attrText;
150     return true;
151 }
152 
parse(const std::string & s,std::optional<uint64_t> * out)153 static bool parse(const std::string& s, std::optional<uint64_t>* out) {
154     uint64_t val;
155     if (base::ParseUint(s, &val)) {
156         *out = val;
157         return true;
158     }
159     return false;
160 }
161 
162 // ---------------------- XmlNodeConverter definitions
163 
164 // When serializing an object to an XML document, these parameters don't change until
165 // the object is fully serialized.
166 // These parameters are also passed to converters of child nodes so they see the same
167 // serialization parameters.
168 struct MutateNodeParam {
169     DocType* d;
170     SerializeFlags::Type flags = SerializeFlags::EVERYTHING;
171 };
172 
173 // When deserializing an XML document to an object, these parameters don't change until
174 // the XML document is fully deserialized.
175 // * Except metaVersion, which is immediately modified when parsing top-level <manifest>
176 //   or <compatibility-matrix>, and unchanged thereafter;
177 //   see HalManifestConverter::BuildObject and CompatibilityMatrixConverter::BuildObject)
178 // These parameters are also passed to converters of child nodes so they see the same
179 // deserialization parameters.
180 struct BuildObjectParam {
181     std::string* error;
182     Version metaVersion;
183     std::string fileName;
184 };
185 
186 template <typename Object>
187 struct XmlNodeConverter {
XmlNodeConverterandroid::vintf::XmlNodeConverter188     XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter189     virtual ~XmlNodeConverter() {}
190 
191    protected:
192     virtual void mutateNode(const Object& object, NodeType* root, const MutateNodeParam&) const = 0;
193     virtual bool buildObject(Object* object, NodeType* root, const BuildObjectParam&) const = 0;
194 
195    public:
196     // Methods for other (usually parent) converters
197     // Name of the XML element.
198     virtual std::string elementName() const = 0;
199     // Serialize |o| into an XML element.
operator ()android::vintf::XmlNodeConverter200     inline NodeType* operator()(const Object& o, const MutateNodeParam& param) const {
201         NodeType* root = createNode(this->elementName(), param.d);
202         this->mutateNode(o, root, param);
203         return root;
204     }
205     // Deserialize XML element |root| into |object|.
operator ()android::vintf::XmlNodeConverter206     inline bool operator()(Object* object, NodeType* root, const BuildObjectParam& param) const {
207         if (nameOf(root) != this->elementName()) {
208             return false;
209         }
210         return this->buildObject(object, root, param);
211     }
212 
213     // Public methods for android::vintf::fromXml / android::vintf::toXml.
214     // Serialize |o| into an XML string.
toXmlandroid::vintf::XmlNodeConverter215     inline std::string toXml(const Object& o, SerializeFlags::Type flags) const {
216         DocType* doc = createDocument();
217         appendChild(doc, (*this)(o, MutateNodeParam{doc, flags}));
218         std::string s = printDocument(doc);
219         deleteDocument(doc);
220         return s;
221     }
222     // Deserialize XML string |xml| into |o|.
fromXmlandroid::vintf::XmlNodeConverter223     inline bool fromXml(Object* o, const std::string& xml, std::string* error) const {
224         std::string errorBuffer;
225         if (error == nullptr) error = &errorBuffer;
226 
227         auto doc = createDocument(xml);
228         if (doc == nullptr) {
229             *error = "Not a valid XML";
230             return false;
231         }
232         // For top-level <manifest> and <compatibility-matrix>, HalManifestConverter and
233         // CompatibilityMatrixConverter fills in metaversion and pass down to children.
234         // For other nodes, we don't know metaversion of the original XML, so just leave empty
235         // for maximum backwards compatibility.
236         BuildObjectParam buildObjectParam{error, {}, {}};
237         // Pass down filename for the current XML document.
238         if constexpr (std::is_base_of_v<WithFileName, Object>) {
239             // Get the last filename in case `o` keeps the list of filenames
240             std::string_view fileName{o->fileName()};
241             if (auto pos = fileName.rfind(':'); pos != fileName.npos) {
242                 fileName.remove_prefix(pos + 1);
243             }
244             buildObjectParam.fileName = std::string(fileName);
245         }
246         bool ret = (*this)(o, getRootChild(doc), buildObjectParam);
247         deleteDocument(doc);
248         return ret;
249     }
250 
251     // convenience methods for subclasses to implement virtual functions.
252 
253     // All append* functions helps mutateNode() to serialize the object into XML.
254     template <typename T>
appendAttrandroid::vintf::XmlNodeConverter255     inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
256         return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
257     }
258 
appendAttrandroid::vintf::XmlNodeConverter259     inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
260         return appendStrAttr(e, attrName, attr ? "true" : "false");
261     }
262 
263     // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter264     inline void appendTextElement(NodeType *parent, const std::string &name,
265                 const std::string &text, DocType *d) const {
266         NodeType *c = createNode(name, d);
267         appendText(c, text, d);
268         appendChild(parent, c);
269     }
270 
271     // text -> <name>text</name>
272     template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter273     inline void appendTextElements(NodeType *parent, const std::string &name,
274                 const Array &array, DocType *d) const {
275         for (const std::string &text : array) {
276             NodeType *c = createNode(name, d);
277             appendText(c, text, d);
278             appendChild(parent, c);
279         }
280     }
281 
282     template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter283     inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
284                                const Array& array, const MutateNodeParam& param) const {
285         for (const T &t : array) {
286             appendChild(parent, conv(t, param));
287         }
288     }
289 
290     // All parse* functions helps buildObject() to deserialize XML to the object. Returns
291     // true if deserialization is successful, false if any error, and "error" will be
292     // set to error message.
293     template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter294     inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
295                                   T* attr, std::string* /* error */) const {
296         std::string attrText;
297         bool success = getAttr(root, attrName, &attrText) &&
298                        ::android::vintf::parse(attrText, attr);
299         if (!success) {
300             *attr = std::move(defaultValue);
301         }
302         return true;
303     }
304 
305     template <typename T>
parseAttrandroid::vintf::XmlNodeConverter306     inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
307                           std::string* error) const {
308         std::string attrText;
309         bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
310         if (!ret) {
311             *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
312                      attrText + "\" for element <" + elementName() + ">";
313         }
314         return ret;
315     }
316 
parseAttrandroid::vintf::XmlNodeConverter317     inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
318                           std::string* error) const {
319         bool ret = getAttr(root, attrName, attr);
320         if (!ret) {
321             *error = "Could not find attr with name \"" + attrName + "\" for element <" +
322                      elementName() + ">";
323         }
324         return ret;
325     }
326 
parseTextElementandroid::vintf::XmlNodeConverter327     inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
328                                  std::string* error) const {
329         NodeType *child = getChild(root, elementName);
330         if (child == nullptr) {
331             *error = "Could not find element with name <" + elementName + "> in element <" +
332                      this->elementName() + ">";
333             return false;
334         }
335         *s = getText(child);
336         return true;
337     }
338 
parseOptionalTextElementandroid::vintf::XmlNodeConverter339     inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
340                                          std::string&& defaultValue, std::string* s,
341                                          std::string* /* error */) const {
342         NodeType* child = getChild(root, elementName);
343         *s = child == nullptr ? std::move(defaultValue) : getText(child);
344         return true;
345     }
346 
parseTextElementsandroid::vintf::XmlNodeConverter347     inline bool parseTextElements(NodeType* root, const std::string& elementName,
348                                   std::vector<std::string>* v, std::string* /* error */) const {
349         auto nodes = getChildren(root, elementName);
350         v->resize(nodes.size());
351         for (size_t i = 0; i < nodes.size(); ++i) {
352             v->at(i) = getText(nodes[i]);
353         }
354         return true;
355     }
356 
357     template <typename T>
parseChildandroid::vintf::XmlNodeConverter358     inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
359                            const BuildObjectParam& param) const {
360         NodeType *child = getChild(root, conv.elementName());
361         if (child == nullptr) {
362             *param.error = "Could not find element with name <" + conv.elementName() +
363                            "> in element <" + this->elementName() + ">";
364             return false;
365         }
366         return conv(t, child, param);
367     }
368 
369     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter370     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
371                                    T&& defaultValue, T* t, const BuildObjectParam& param) const {
372         NodeType *child = getChild(root, conv.elementName());
373         if (child == nullptr) {
374             *t = std::move(defaultValue);
375             return true;
376         }
377         return conv(t, child, param);
378     }
379 
380     template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter381     inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
382                                    std::optional<T>* t, const BuildObjectParam& param) const {
383         NodeType* child = getChild(root, conv.elementName());
384         if (child == nullptr) {
385             *t = std::nullopt;
386             return true;
387         }
388         *t = std::make_optional<T>();
389         return conv(&**t, child, param);
390     }
391 
392     template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter393     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
394                               const BuildObjectParam& param) const {
395         auto nodes = getChildren(root, conv.elementName());
396         v->resize(nodes.size());
397         for (size_t i = 0; i < nodes.size(); ++i) {
398             if (!conv(&v->at(i), nodes[i], param)) {
399                 *param.error = "Could not parse element with name <" + conv.elementName() +
400                                "> in element <" + this->elementName() + ">: " + *param.error;
401                 return false;
402             }
403         }
404         return true;
405     }
406 
407     template <typename Container, typename T = typename Container::value_type,
408               typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter409     inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
410                               const BuildObjectParam& param) const {
411         std::vector<T> vec;
412         if (!parseChildren(root, conv, &vec, param)) {
413             return false;
414         }
415         s->clear();
416         s->insert(vec.begin(), vec.end());
417         if (s->size() != vec.size()) {
418             *param.error = "Duplicated elements <" + conv.elementName() + "> in element <" +
419                            this->elementName() + ">";
420             s->clear();
421             return false;
422         }
423         return true;
424     }
425 
426     template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter427     inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
428                               std::map<K, V>* s, const BuildObjectParam& param) const {
429         return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, param);
430     }
431 
parseTextandroid::vintf::XmlNodeConverter432     inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
433         *s = getText(node);
434         return true;
435     }
436 
437     template <typename T>
parseTextandroid::vintf::XmlNodeConverter438     inline bool parseText(NodeType* node, T* s, std::string* error) const {
439         bool (*parser)(const std::string&, T*) = ::android::vintf::parse;
440         return parseText(node, s, {parser}, error);
441     }
442 
443     template <typename T>
parseTextandroid::vintf::XmlNodeConverter444     inline bool parseText(NodeType* node, T* s,
445                           const std::function<bool(const std::string&, T*)>& parse,
446                           std::string* error) const {
447         std::string text = getText(node);
448         bool ret = parse(text, s);
449         if (!ret) {
450             *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
451         }
452         return ret;
453     }
454 };
455 
456 template<typename Object>
457 struct XmlTextConverter : public XmlNodeConverter<Object> {
mutateNodeandroid::vintf::XmlTextConverter458     void mutateNode(const Object& object, NodeType* root,
459                     const MutateNodeParam& param) const override {
460         appendText(root, ::android::vintf::to_string(object), param.d);
461     }
buildObjectandroid::vintf::XmlTextConverter462     bool buildObject(Object* object, NodeType* root, const BuildObjectParam& param) const override {
463         return this->parseText(root, object, param.error);
464     }
465 };
466 
467 template <typename Pair, typename FirstConverter, typename SecondConverter>
468 struct XmlPairConverter : public XmlNodeConverter<Pair> {
mutateNodeandroid::vintf::XmlPairConverter469     void mutateNode(const Pair& object, NodeType* root,
470                     const MutateNodeParam& param) const override {
471         appendChild(root, FirstConverter{}(object.first, param));
472         appendChild(root, SecondConverter{}(object.second, param));
473     }
buildObjectandroid::vintf::XmlPairConverter474     bool buildObject(Pair* object, NodeType* root, const BuildObjectParam& param) const override {
475         return this->parseChild(root, FirstConverter{}, &object->first, param) &&
476                this->parseChild(root, SecondConverter{}, &object->second, param);
477     }
478 };
479 
480 // ---------------------- XmlNodeConverter definitions end
481 
482 struct VersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::VersionConverter483     std::string elementName() const override { return "version"; }
484 };
485 
486 struct SepolicyVersionConverter : public XmlTextConverter<SepolicyVersion> {
elementNameandroid::vintf::SepolicyVersionConverter487     std::string elementName() const override { return "version"; }
488 };
489 
490 struct VersionRangeConverter : public XmlTextConverter<VersionRange> {
elementNameandroid::vintf::VersionRangeConverter491     std::string elementName() const override { return "version"; }
492 };
493 
494 struct SepolicyVersionRangeConverter : public XmlTextConverter<SepolicyVersionRange> {
elementNameandroid::vintf::SepolicyVersionRangeConverter495     std::string elementName() const override { return "sepolicy-version"; }
496 };
497 
498 // <version>100</version> <=> Version{kFakeAidlMajorVersion, 100}
499 struct AidlVersionConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AidlVersionConverter500     std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionConverter501     void mutateNode(const Version& object, NodeType* root,
502                     const MutateNodeParam& param) const override {
503         appendText(root, aidlVersionToString(object), param.d);
504     }
buildObjectandroid::vintf::AidlVersionConverter505     bool buildObject(Version* object, NodeType* root,
506                      const BuildObjectParam& param) const override {
507         return parseText(root, object, {parseAidlVersion}, param.error);
508     }
509 };
510 
511 // <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100}
512 // <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105}
513 struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> {
elementNameandroid::vintf::AidlVersionRangeConverter514     std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionRangeConverter515     void mutateNode(const VersionRange& object, NodeType* root,
516                     const MutateNodeParam& param) const override {
517         appendText(root, aidlVersionRangeToString(object), param.d);
518     }
buildObjectandroid::vintf::AidlVersionRangeConverter519     bool buildObject(VersionRange* object, NodeType* root,
520                      const BuildObjectParam& param) const override {
521         return parseText(root, object, {parseAidlVersionRange}, param.error);
522     }
523 };
524 
525 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter526     std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter527     void mutateNode(const TransportArch& object, NodeType* root,
528                     const MutateNodeParam& param) const override {
529         if (object.arch != Arch::ARCH_EMPTY) {
530             appendAttr(root, "arch", object.arch);
531         }
532         if (object.ip.has_value()) {
533             appendAttr(root, "ip", *object.ip);
534         }
535         if (object.port.has_value()) {
536             appendAttr(root, "port", *object.port);
537         }
538         appendText(root, ::android::vintf::to_string(object.transport), param.d);
539     }
buildObjectandroid::vintf::TransportArchConverter540     bool buildObject(TransportArch* object, NodeType* root,
541                      const BuildObjectParam& param) const override {
542         if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, param.error) ||
543             !parseOptionalAttr(root, "ip", {}, &object->ip, param.error) ||
544             !parseOptionalAttr(root, "port", {}, &object->port, param.error) ||
545             !parseText(root, &object->transport, param.error)) {
546             return false;
547         }
548         if (!object->isValid(param.error)) {
549             return false;
550         }
551         return true;
552     }
553 };
554 
555 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter556     std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter557     void mutateNode(const KernelConfigTypedValue& object, NodeType* root,
558                     const MutateNodeParam& param) const override {
559         appendAttr(root, "type", object.mType);
560         appendText(root, ::android::vintf::to_string(object), param.d);
561     }
buildObjectandroid::vintf::KernelConfigTypedValueConverter562     bool buildObject(KernelConfigTypedValue* object, NodeType* root,
563                      const BuildObjectParam& param) const override {
564         std::string stringValue;
565         if (!parseAttr(root, "type", &object->mType, param.error) ||
566             !parseText(root, &stringValue, param.error)) {
567             return false;
568         }
569         if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
570             *param.error = "Could not parse kernel config value \"" + stringValue + "\"";
571             return false;
572         }
573         return true;
574     }
575 };
576 
577 struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> {
elementNameandroid::vintf::KernelConfigKeyConverter578     std::string elementName() const override { return "key"; }
579 };
580 
581 struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter,
582                                                              KernelConfigTypedValueConverter> {
elementNameandroid::vintf::MatrixKernelConfigConverter583     std::string elementName() const override { return "config"; }
584 };
585 
586 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter587     std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter588     void mutateNode(const HalInterface& object, NodeType* root,
589                     const MutateNodeParam& param) const override {
590         if (!object.name().empty()) {
591             appendTextElement(root, "name", object.name(), param.d);
592         }
593         appendTextElements(root, "instance", object.mInstances, param.d);
594         appendTextElements(root, "regex-instance", object.mRegexes, param.d);
595     }
buildObjectandroid::vintf::HalInterfaceConverter596     bool buildObject(HalInterface* object, NodeType* root,
597                      const BuildObjectParam& param) const override {
598         std::vector<std::string> instances;
599         std::vector<std::string> regexes;
600         if (!parseOptionalTextElement(root, "name", {}, &object->mName, param.error) ||
601             !parseTextElements(root, "instance", &instances, param.error) ||
602             !parseTextElements(root, "regex-instance", &regexes, param.error)) {
603             return false;
604         }
605         bool success = true;
606         for (const auto& e : instances) {
607             if (!object->insertInstance(e, false /* isRegex */)) {
608                 if (!param.error->empty()) *param.error += "\n";
609                 *param.error += "Duplicated instance '" + e + "' in " + object->name();
610                 success = false;
611             }
612         }
613         for (const auto& e : regexes) {
614             details::Regex regex;
615             if (!regex.compile(e)) {
616                 if (!param.error->empty()) *param.error += "\n";
617                 *param.error += "Invalid regular expression '" + e + "' in " + object->name();
618                 success = false;
619             }
620             if (!object->insertInstance(e, true /* isRegex */)) {
621                 if (!param.error->empty()) *param.error += "\n";
622                 *param.error += "Duplicated regex-instance '" + e + "' in " + object->name();
623                 success = false;
624             }
625         }
626         return success;
627     }
628 };
629 
630 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter631     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter632     void mutateNode(const MatrixHal& object, NodeType* root,
633                     const MutateNodeParam& param) const override {
634         appendAttr(root, "format", object.format);
635         appendAttr(root, "optional", object.optional);
636         // Only include update-via-apex if enabled
637         if (object.updatableViaApex) {
638             appendAttr(root, "updatable-via-apex", object.updatableViaApex);
639         }
640         appendTextElement(root, "name", object.name, param.d);
641         if (object.format == HalFormat::AIDL) {
642             // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
643             // is specified. Don't output any <version> tag if there's only one <version>0</version>
644             // tag.
645             if (object.versionRanges.size() != 1 ||
646                 object.versionRanges[0] != details::kDefaultAidlVersionRange) {
647                 appendChildren(root, AidlVersionRangeConverter{}, object.versionRanges, param);
648             }
649         } else {
650             appendChildren(root, VersionRangeConverter{}, object.versionRanges, param);
651         }
652         appendChildren(root, HalInterfaceConverter{}, iterateValues(object.interfaces), param);
653     }
buildObjectandroid::vintf::MatrixHalConverter654     bool buildObject(MatrixHal* object, NodeType* root,
655                      const BuildObjectParam& param) const override {
656         std::vector<HalInterface> interfaces;
657         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param.error) ||
658             !parseOptionalAttr(root, "optional", true /* defaultValue */, &object->optional,
659                                param.error) ||
660             !parseOptionalAttr(root, "updatable-via-apex", false /* defaultValue */,
661                                &object->updatableViaApex, param.error) ||
662             !parseTextElement(root, "name", &object->name, param.error) ||
663             !parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
664             return false;
665         }
666         if (object->format == HalFormat::AIDL) {
667             if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, param)) {
668                 return false;
669             }
670             // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
671             // HAL formats can be unified.
672             if (object->versionRanges.empty()) {
673                 object->versionRanges.push_back(details::kDefaultAidlVersionRange);
674             }
675         } else {
676             if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, param)) {
677                 return false;
678             }
679         }
680         for (auto&& interface : interfaces) {
681             std::string name{interface.name()};
682             auto res = object->interfaces.emplace(std::move(name), std::move(interface));
683             if (!res.second) {
684                 *param.error = "Duplicated interface entry \"" + res.first->first +
685                                "\"; if additional instances are needed, add them to the "
686                                "existing <interface> node.";
687                 return false;
688             }
689         }
690         if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
691             return false;
692         }
693 
694         if (!object->isValid(param.error)) {
695             param.error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: ");
696             return false;
697         }
698         return true;
699     }
700 
701    private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter702     bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
703         // Do not check for target-side libvintf to avoid restricting ability for upgrade
704         // accidentally.
705         if constexpr (kDevice) {
706             return true;
707         }
708         if (hal.getName() == "netutils-wrapper") {
709             if (hal.versionRanges.size() != 1) {
710                 *error =
711                     "netutils-wrapper HAL must specify exactly one version x.0, "
712                     "but multiple <version> element is specified.";
713                 return false;
714             }
715             const VersionRange& v = hal.versionRanges.at(0);
716             if (!v.isSingleVersion()) {
717                 *error =
718                     "netutils-wrapper HAL must specify exactly one version x.0, "
719                     "but a range is provided. Perhaps you mean '" +
720                     to_string(Version{v.majorVer, 0}) + "'?";
721                 return false;
722             }
723             if (v.minMinor != 0) {
724                 *error =
725                     "netutils-wrapper HAL must specify exactly one version x.0, "
726                     "but minor version is not 0. Perhaps you mean '" +
727                     to_string(Version{v.majorVer, 0}) + "'?";
728                 return false;
729             }
730         }
731         return true;
732     }
733 };
734 
735 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter736     std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter737     void mutateNode(const std::vector<KernelConfig>& object, NodeType* root,
738                     const MutateNodeParam& param) const override {
739         appendChildren(root, MatrixKernelConfigConverter{}, object, param);
740     }
buildObjectandroid::vintf::MatrixKernelConditionsConverter741     bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
742                      const BuildObjectParam& param) const override {
743         return parseChildren(root, MatrixKernelConfigConverter{}, object, param);
744     }
745 };
746 
747 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter748     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter749     void mutateNode(const MatrixKernel& object, NodeType* root,
750                     const MutateNodeParam& param) const override {
751         KernelVersion kv = object.mMinLts;
752         if (!param.flags.isKernelMinorRevisionEnabled()) {
753             kv.minorRev = 0u;
754         }
755         appendAttr(root, "version", kv);
756 
757         if (object.getSourceMatrixLevel() != Level::UNSPECIFIED) {
758             appendAttr(root, "level", object.getSourceMatrixLevel());
759         }
760 
761         if (!object.mConditions.empty()) {
762             appendChild(root, MatrixKernelConditionsConverter{}(object.mConditions, param));
763         }
764         if (param.flags.isKernelConfigsEnabled()) {
765             appendChildren(root, MatrixKernelConfigConverter{}, object.mConfigs, param);
766         }
767     }
buildObjectandroid::vintf::MatrixKernelConverter768     bool buildObject(MatrixKernel* object, NodeType* root,
769                      const BuildObjectParam& param) const override {
770         Level sourceMatrixLevel = Level::UNSPECIFIED;
771         if (!parseAttr(root, "version", &object->mMinLts, param.error) ||
772             !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel,
773                                param.error) ||
774             !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions,
775                                 param) ||
776             !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, param)) {
777             return false;
778         }
779         object->setSourceMatrixLevel(sourceMatrixLevel);
780         return true;
781     }
782 };
783 
784 struct FqInstanceConverter : public XmlTextConverter<FqInstance> {
elementNameandroid::vintf::FqInstanceConverter785     std::string elementName() const override { return "fqname"; }
786 };
787 
788 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
789 // .isValid() == true.
790 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter791     std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter792     void mutateNode(const ManifestHal& object, NodeType* root,
793                     const MutateNodeParam& param) const override {
794         appendAttr(root, "format", object.format);
795         appendTextElement(root, "name", object.name, param.d);
796         if (!object.transportArch.empty()) {
797             appendChild(root, TransportArchConverter{}(object.transportArch, param));
798         }
799         if (object.format == HalFormat::AIDL) {
800             // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
801             // is specified. Don't output any <version> tag if there's only one <version>0</version>
802             // tag.
803             if (object.versions.size() != 1 || object.versions[0] != details::kDefaultAidlVersion) {
804                 appendChildren(root, AidlVersionConverter{}, object.versions, param);
805             }
806         } else {
807             appendChildren(root, VersionConverter{}, object.versions, param);
808         }
809         if (object.isOverride()) {
810             appendAttr(root, "override", object.isOverride());
811         }
812         if (const auto& apex = object.updatableViaApex(); apex.has_value()) {
813             appendAttr(root, "updatable-via-apex", apex.value());
814         }
815         if (param.flags.isFqnameEnabled()) {
816             std::set<std::string> simpleFqInstances;
817             object.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
818                 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
819                 return true;
820             });
821             appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances,
822                                param.d);
823         }
824         if (object.getMaxLevel() != Level::UNSPECIFIED) {
825             appendAttr(root, "max-level", object.getMaxLevel());
826         }
827         if (object.getMinLevel() != Level::UNSPECIFIED) {
828             appendAttr(root, "min-level", object.getMinLevel());
829         }
830     }
buildObjectandroid::vintf::ManifestHalConverter831     bool buildObject(ManifestHal* object, NodeType* root,
832                      const BuildObjectParam& param) const override {
833         std::vector<HalInterface> interfaces;
834         if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param.error) ||
835             !parseOptionalAttr(root, "override", false, &object->mIsOverride, param.error) ||
836             !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex,
837                                param.error) ||
838             !parseTextElement(root, "name", &object->name, param.error) ||
839             !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch,
840                                 param) ||
841             !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel,
842                                param.error) ||
843             !parseOptionalAttr(root, "min-level", Level::UNSPECIFIED, &object->mMinLevel,
844                                param.error)) {
845             return false;
846         }
847 
848         std::string_view apexName = parseApexName(param.fileName);
849         if (!apexName.empty()) {
850             if (object->mUpdatableViaApex.has_value()) {
851                 // When defined in APEX, updatable-via-apex can be either
852                 // - ""(empty)  : the HAL isn't updatable even if it's in APEX
853                 // - {apex name}: the HAL is updtable via the current APEX
854                 const std::string& updatableViaApex = object->mUpdatableViaApex.value();
855                 if (!updatableViaApex.empty() && apexName.compare(updatableViaApex) != 0) {
856                     *param.error = "Invalid APEX HAL " + object->name + ": updatable-via-apex " +
857                                    updatableViaApex + " doesn't match with the defining APEX " +
858                                    std::string(apexName) + "\n";
859                     return false;
860                 }
861             } else {
862                 // Set updatable-via-apex to the defining APEX when it's not set explicitly.
863                 // This should be set before calling insertInstances() which copies the current
864                 // value to ManifestInstance.
865                 object->mUpdatableViaApex = apexName;
866             }
867         }
868 
869         switch (object->format) {
870             case HalFormat::HIDL: {
871                 if (!parseChildren(root, VersionConverter{}, &object->versions, param))
872                     return false;
873                 if (object->transportArch.empty()) {
874                     *param.error =
875                         "HIDL HAL '" + object->name + "' should have <transport> defined.";
876                     return false;
877                 }
878                 if (object->transportArch.transport == Transport::INET ||
879                     object->transportArch.ip.has_value() ||
880                     object->transportArch.port.has_value()) {
881                     *param.error = "HIDL HAL '" + object->name +
882                                    "' should not have <transport> \"inet\" " +
883                                    "or ip or port attributes defined.";
884                     return false;
885                 }
886             } break;
887             case HalFormat::NATIVE: {
888                 if (!parseChildren(root, VersionConverter{}, &object->versions, param))
889                     return false;
890                 if (!object->transportArch.empty()) {
891                     *param.error =
892                         "Native HAL '" + object->name + "' should not have <transport> defined.";
893                     return false;
894                 }
895             } break;
896             case HalFormat::AIDL: {
897                 if (!object->transportArch.empty() &&
898                     object->transportArch.transport != Transport::INET) {
899                     if (param.metaVersion >= kMetaVersionAidlInet) {
900                         *param.error = "AIDL HAL '" + object->name +
901                                        R"(' only supports "inet" or empty <transport>, found ")" +
902                                        to_string(object->transportArch) + "\"";
903                         return false;
904                     }
905                     LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
906                                  << object->name << ". Only \"inet\" supported.";
907                     object->transportArch = {};
908                 }
909                 if (!parseChildren(root, AidlVersionConverter{}, &object->versions, param)) {
910                     return false;
911                 }
912                 // Insert fake version for AIDL HALs so that forEachInstance works.
913                 if (object->versions.empty()) {
914                     object->versions.push_back(details::kDefaultAidlVersion);
915                 }
916             } break;
917             default: {
918                 LOG(FATAL) << "Unhandled HalFormat "
919                            << static_cast<typename std::underlying_type<HalFormat>::type>(
920                                   object->format);
921             } break;
922         }
923         if (!object->transportArch.isValid(param.error)) return false;
924 
925         // Parse <fqname> into fqInstances list
926         std::set<FqInstance> fqInstances;
927         if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, param)) {
928             return false;
929         }
930 
931         // Handle deprecated <interface> x <instance>
932         if (!parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
933             return false;
934         }
935         // Check duplicated <interface><name>
936         std::set<std::string> interface_names;
937         for (auto &&interface : interfaces) {
938             auto res = interface_names.emplace(interface.name());
939             if (!res.second) {
940                 *param.error = "Duplicated interface entry \"" + *res.first +
941                                "\"; if additional instances are needed, add them to the "
942                                "existing <interface> node.";
943                 return false;
944             }
945         }
946         // Turn <version> x <interface> x <instance> into <fqname>s; insert into
947         // fqInstances list.
948         bool convertedInstancesIntoFqnames = false;
949         for (const auto& v : object->versions) {
950             for (const auto& intf : interfaces) {
951                 if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance &&
952                     (object->format == HalFormat::HIDL || object->format == HalFormat::AIDL) &&
953                     !intf.hasAnyInstance()) {
954                     *param.error +=
955                         "<hal> " + object->name + " <interface> " + intf.name() +
956                         " has no <instance>. Either specify <instance> or, "
957                         "preferably, specify <fqname> and delete <version> and <interface>.";
958                     return false;
959                 }
960                 bool cont = intf.forEachInstance(
961                     [&v, &fqInstances, &convertedInstancesIntoFqnames, &object, &param](
962                         const auto& interface, const auto& instance, bool /* isRegex */) {
963                         auto fqInstance = details::convertLegacyInstanceIntoFqInstance(
964                             object->name, v, interface, instance, object->format, param.error);
965 
966                         if (!fqInstance.has_value()) {
967                             return false;
968                         }
969 
970                         // Check for duplication in fqInstances.
971                         // Before kMetaVersionNoHalInterfaceInstance: It is okay to have duplication
972                         // between <interface> and <fqname>.
973                         // After kMetaVersionNoHalInterfaceInstance: Duplication between
974                         // <interface> and <fqname> is not allowed.
975                         auto&& [it, inserted] = fqInstances.emplace(std::move(fqInstance.value()));
976                         if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance && !inserted) {
977                             std::string debugString =
978                                 object->format == HalFormat::AIDL
979                                     ? toAidlFqnameString(object->name, interface, instance)
980                                     : toFQNameString(object->name, v, interface, instance);
981                             *param.error = "Duplicated " + debugString +
982                                            " in <interface><instance> and <fqname>. ";
983                             if constexpr (kDevice) {
984                                 *param.error +=
985                                     "(Did you copy source manifests to the device directly "
986                                     "without going through assemble_vintf, e.g. not using "
987                                     "DEVICE_MANIFEST_FILE or ODM_MANIFEST_FILES?)";
988                             } else {
989                                 *param.error += "Remove deprecated <interface>.";
990                             }
991                             return false;
992                         }
993 
994                         convertedInstancesIntoFqnames = true;
995                         return true;  // continue
996                     });
997                 if (!cont) {
998                     return false;
999                 }
1000             }
1001         }
1002 
1003         if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
1004             return false;
1005         }
1006 
1007         // For HIDL, if any <version> x <interface> x <instance> tuple, all <version>
1008         // tags can be cleared. <version> information is already in <fqname>'s.
1009         // For AIDL, <version> information is not in <fqname>, so don't clear them.
1010         // For HALs with only <version> but no <interface>
1011         // (e.g. native HALs like netutils-wrapper), <version> is kept.
1012         if (convertedInstancesIntoFqnames && object->format != HalFormat::AIDL) {
1013             object->versions.clear();
1014         }
1015 
1016         std::set<FqInstance> fqInstancesToInsert;
1017         for (auto& e : fqInstances) {
1018             if (e.hasPackage()) {
1019                 *param.error = "Should not specify package: \"" + e.string() + "\"";
1020                 return false;
1021             }
1022             if (object->format == HalFormat::AIDL) {
1023                 // <fqname> in AIDL HALs should not contain version.
1024                 if (e.hasVersion()) {
1025                     *param.error = "Should not specify version in <fqname> for AIDL HAL: \"" +
1026                                    e.string() + "\"";
1027                     return false;
1028                 }
1029                 // Put in the fake kDefaultAidlVersion so that HalManifest can
1030                 // store it in an FqInstance object with a non-empty package.
1031                 FqInstance withFakeVersion;
1032                 if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer,
1033                                            details::kDefaultAidlVersion.minorVer, e.getInterface(),
1034                                            e.getInstance())) {
1035                     return false;
1036                 }
1037                 fqInstancesToInsert.emplace(std::move(withFakeVersion));
1038             } else {
1039                 fqInstancesToInsert.emplace(std::move(e));
1040             }
1041         }
1042 
1043         if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance &&
1044             (object->format == HalFormat::HIDL || object->format == HalFormat::AIDL) &&
1045             fqInstancesToInsert.empty() && !object->isOverride()) {
1046             *param.error = "<hal> " + object->name + " has no instance. Fix by adding <fqname>.";
1047             return false;
1048         }
1049 
1050         bool allowMajorVersionDup = param.metaVersion < kMetaVersionNoHalInterfaceInstance;
1051         if (!object->insertInstances(fqInstancesToInsert, allowMajorVersionDup, param.error)) {
1052             return false;
1053         }
1054 
1055         if (!object->isValid(param.error)) {
1056             param.error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
1057             return false;
1058         }
1059 
1060         return true;
1061     }
1062 
1063    private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter1064     bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
1065         // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
1066         if constexpr (kDevice) {
1067             return true;
1068         }
1069         if (hal.getName() == "netutils-wrapper") {
1070             for (const Version& v : hal.versions) {
1071                 if (v.minorVer != 0) {
1072                     *error =
1073                         "netutils-wrapper HAL must specify exactly one version x.0, "
1074                         "but minor version is not 0. Perhaps you mean '" +
1075                         to_string(Version{v.majorVer, 0}) + "'?";
1076                     return false;
1077                 }
1078             }
1079         }
1080         return true;
1081     }
1082 };
1083 
1084 struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> {
elementNameandroid::vintf::KernelSepolicyVersionConverter1085     std::string elementName() const override { return "kernel-sepolicy-version"; }
1086 };
1087 
1088 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter1089     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter1090     void mutateNode(const Sepolicy& object, NodeType* root,
1091                     const MutateNodeParam& param) const override {
1092         appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), param));
1093         appendChildren(root, SepolicyVersionRangeConverter{}, object.sepolicyVersions(), param);
1094     }
buildObjectandroid::vintf::SepolicyConverter1095     bool buildObject(Sepolicy* object, NodeType* root,
1096                      const BuildObjectParam& param) const override {
1097         if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion,
1098                         param) ||
1099             !parseChildren(root, SepolicyVersionRangeConverter{}, &object->mSepolicyVersionRanges,
1100                            param)) {
1101             return false;
1102         }
1103         return true;
1104     }
1105 };
1106 
1107 struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> {
elementNameandroid::vintf::VndkVersionRangeConverter1108     std::string elementName() const override { return "version"; }
1109 };
1110 
1111 struct VndkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkVersionConverter1112     std::string elementName() const override { return "version"; }
1113 };
1114 
1115 struct VndkLibraryConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkLibraryConverter1116     std::string elementName() const override { return "library"; }
1117 };
1118 
1119 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter1120     std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter1121     void mutateNode(const Vndk& object, NodeType* root,
1122                     const MutateNodeParam& param) const override {
1123         appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, param));
1124         appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
1125     }
buildObjectandroid::vintf::VndkConverter1126     bool buildObject(Vndk* object, NodeType* root, const BuildObjectParam& param) const override {
1127         if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, param) ||
1128             !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
1129             return false;
1130         }
1131         return true;
1132     }
1133 };
1134 
1135 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter1136     std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter1137     void mutateNode(const VendorNdk& object, NodeType* root,
1138                     const MutateNodeParam& param) const override {
1139         appendChild(root, VndkVersionConverter{}(object.mVersion, param));
1140         appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
1141     }
buildObjectandroid::vintf::VendorNdkConverter1142     bool buildObject(VendorNdk* object, NodeType* root,
1143                      const BuildObjectParam& param) const override {
1144         if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, param) ||
1145             !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
1146             return false;
1147         }
1148         return true;
1149     }
1150 };
1151 
1152 struct SystemSdkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::SystemSdkVersionConverter1153     std::string elementName() const override { return "version"; }
1154 };
1155 
1156 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter1157     std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter1158     void mutateNode(const SystemSdk& object, NodeType* root,
1159                     const MutateNodeParam& param) const override {
1160         appendChildren(root, SystemSdkVersionConverter{}, object.versions(), param);
1161     }
buildObjectandroid::vintf::SystemSdkConverter1162     bool buildObject(SystemSdk* object, NodeType* root,
1163                      const BuildObjectParam& param) const override {
1164         return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, param);
1165     }
1166 };
1167 
1168 struct HalManifestSepolicyConverter : public XmlNodeConverter<SepolicyVersion> {
elementNameandroid::vintf::HalManifestSepolicyConverter1169     std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter1170     void mutateNode(const SepolicyVersion& object, NodeType* root,
1171                     const MutateNodeParam& param) const override {
1172         appendChild(root, SepolicyVersionConverter{}(object, param));
1173     }
buildObjectandroid::vintf::HalManifestSepolicyConverter1174     bool buildObject(SepolicyVersion* object, NodeType* root,
1175                      const BuildObjectParam& param) const override {
1176         return parseChild(root, SepolicyVersionConverter{}, object, param);
1177     }
1178 };
1179 
1180 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter1181     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter1182     void mutateNode(const ManifestXmlFile& object, NodeType* root,
1183                     const MutateNodeParam& param) const override {
1184         appendTextElement(root, "name", object.name(), param.d);
1185         appendChild(root, VersionConverter{}(object.version(), param));
1186         if (!object.overriddenPath().empty()) {
1187             appendTextElement(root, "path", object.overriddenPath(), param.d);
1188         }
1189     }
buildObjectandroid::vintf::ManifestXmlFileConverter1190     bool buildObject(ManifestXmlFile* object, NodeType* root,
1191                      const BuildObjectParam& param) const override {
1192         if (!parseTextElement(root, "name", &object->mName, param.error) ||
1193             !parseChild(root, VersionConverter{}, &object->mVersion, param) ||
1194             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
1195             return false;
1196         }
1197         return true;
1198     }
1199 };
1200 
1201 struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::StringKernelConfigKeyConverter1202     std::string elementName() const override { return "key"; }
1203 };
1204 
1205 struct KernelConfigValueConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::KernelConfigValueConverter1206     std::string elementName() const override { return "value"; }
1207 };
1208 
1209 struct StringKernelConfigConverter
1210     : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter,
1211                               KernelConfigValueConverter> {
elementNameandroid::vintf::StringKernelConfigConverter1212     std::string elementName() const override { return "config"; }
1213 };
1214 
1215 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter1216     std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter1217     void mutateNode(const KernelInfo& object, NodeType* root,
1218                     const MutateNodeParam& param) const override {
1219         if (object.version() != KernelVersion{}) {
1220             appendAttr(root, "version", object.version());
1221         }
1222         if (object.level() != Level::UNSPECIFIED) {
1223             appendAttr(root, "target-level", object.level());
1224         }
1225         if (param.flags.isKernelConfigsEnabled()) {
1226             appendChildren(root, StringKernelConfigConverter{}, object.configs(), param);
1227         }
1228     }
buildObjectandroid::vintf::KernelInfoConverter1229     bool buildObject(KernelInfo* object, NodeType* root,
1230                      const BuildObjectParam& param) const override {
1231         return parseOptionalAttr(root, "version", {}, &object->mVersion, param.error) &&
1232                parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1233                                  param.error) &&
1234                parseChildren(root, StringKernelConfigConverter{}, &object->mConfigs, param);
1235     }
1236 };
1237 
1238 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter1239     std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter1240     void mutateNode(const HalManifest& object, NodeType* root,
1241                     const MutateNodeParam& param) const override {
1242         if (param.flags.isMetaVersionEnabled()) {
1243             // Append the current metaversion of libvintf because the XML file
1244             // is generated with libvintf @ current meta version.
1245             appendAttr(root, "version", kMetaVersion);
1246         }
1247         if (param.flags.isSchemaTypeEnabled()) {
1248             appendAttr(root, "type", object.mType);
1249         }
1250 
1251         if (param.flags.isHalsEnabled()) {
1252             appendChildren(root, ManifestHalConverter{}, object.getHals(), param);
1253         }
1254         if (object.mType == SchemaType::DEVICE) {
1255             if (param.flags.isSepolicyEnabled()) {
1256                 if (object.device.mSepolicyVersion != SepolicyVersion{}) {
1257                     appendChild(root, HalManifestSepolicyConverter{}(object.device.mSepolicyVersion,
1258                                                                      param));
1259                 }
1260             }
1261             if (object.mLevel != Level::UNSPECIFIED) {
1262                 this->appendAttr(root, "target-level", object.mLevel);
1263             }
1264 
1265             if (param.flags.isKernelEnabled()) {
1266                 if (!!object.kernel()) {
1267                     appendChild(root, KernelInfoConverter{}(*object.kernel(), param));
1268                 }
1269             }
1270         } else if (object.mType == SchemaType::FRAMEWORK) {
1271             if (param.flags.isVndkEnabled()) {
1272 #pragma clang diagnostic push
1273 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1274                 appendChildren(root, VndkConverter{}, object.framework.mVndks, param);
1275 #pragma clang diagnostic pop
1276 
1277                 appendChildren(root, VendorNdkConverter{}, object.framework.mVendorNdks, param);
1278             }
1279             if (param.flags.isSsdkEnabled()) {
1280                 if (!object.framework.mSystemSdk.empty()) {
1281                     appendChild(root, SystemSdkConverter{}(object.framework.mSystemSdk, param));
1282                 }
1283             }
1284         }
1285 
1286         if (param.flags.isXmlFilesEnabled()) {
1287             appendChildren(root, ManifestXmlFileConverter{}, object.getXmlFiles(), param);
1288         }
1289     }
buildObjectandroid::vintf::HalManifestConverter1290     bool buildObject(HalManifest* object, NodeType* root,
1291                      const BuildObjectParam& constParam) const override {
1292         BuildObjectParam param = constParam;
1293         if (!parseAttr(root, "version", &param.metaVersion, param.error)) return false;
1294         if (param.metaVersion > kMetaVersion) {
1295             *param.error = "Unrecognized manifest.version " + to_string(param.metaVersion) +
1296                            " (libvintf@" + to_string(kMetaVersion) + ")";
1297             return false;
1298         }
1299         object->mSourceMetaVersion = param.metaVersion;
1300 
1301         if (!parseAttr(root, "type", &object->mType, param.error)) {
1302             return false;
1303         }
1304 
1305         std::vector<ManifestHal> hals;
1306         if (!parseChildren(root, ManifestHalConverter{}, &hals, param)) {
1307             return false;
1308         }
1309         for (auto&& hal : hals) {
1310             hal.setFileName(object->fileName());
1311         }
1312 
1313         if (object->mType == SchemaType::DEVICE) {
1314             // tags for device hal manifest only.
1315             // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1316             // in the XML file.
1317             if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {},
1318                                     &object->device.mSepolicyVersion, param)) {
1319                 return false;
1320             }
1321 
1322             if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1323                                    param.error)) {
1324                 return false;
1325             }
1326 
1327             if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, param)) {
1328                 return false;
1329             }
1330         } else if (object->mType == SchemaType::FRAMEWORK) {
1331 #pragma clang diagnostic push
1332 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1333             if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, param)) {
1334                 return false;
1335             }
1336             for (const auto& vndk : object->framework.mVndks) {
1337                 if (!vndk.mVersionRange.isSingleVersion()) {
1338                     *param.error = "vndk.version " + to_string(vndk.mVersionRange) +
1339                                    " cannot be a range for manifests";
1340                     return false;
1341                 }
1342             }
1343 #pragma clang diagnostic pop
1344 
1345             if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, param)) {
1346                 return false;
1347             }
1348 
1349             std::set<std::string> vendorNdkVersions;
1350             for (const auto& vendorNdk : object->framework.mVendorNdks) {
1351                 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1352                     *param.error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1353                     return false;
1354                 }
1355                 vendorNdkVersions.insert(vendorNdk.version());
1356             }
1357 
1358             if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk,
1359                                     param)) {
1360                 return false;
1361             }
1362         }
1363         for (auto &&hal : hals) {
1364             std::string description{hal.name};
1365             if (!object->add(std::move(hal), param.error)) {
1366                 param.error->insert(0, "Duplicated manifest.hal entry " + description + ": ");
1367                 return false;
1368             }
1369         }
1370 
1371         std::vector<ManifestXmlFile> xmlFiles;
1372         if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, param)) {
1373             return false;
1374         }
1375         for (auto&& xmlFile : xmlFiles) {
1376             std::string description{xmlFile.name()};
1377             if (!object->addXmlFile(std::move(xmlFile))) {
1378                 *param.error = "Duplicated manifest.xmlfile entry " + description +
1379                                "; entries cannot have duplicated name and version";
1380                 return false;
1381             }
1382         }
1383 
1384         return true;
1385     }
1386 };
1387 
1388 struct AvbVersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::AvbVersionConverter1389     std::string elementName() const override { return "vbmeta-version"; }
1390 };
1391 
1392 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1393     std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1394     void mutateNode(const Version& object, NodeType* root,
1395                     const MutateNodeParam& param) const override {
1396         appendChild(root, AvbVersionConverter{}(object, param));
1397     }
buildObjectandroid::vintf::AvbConverter1398     bool buildObject(Version* object, NodeType* root,
1399                      const BuildObjectParam& param) const override {
1400         return parseChild(root, AvbVersionConverter{}, object, param);
1401     }
1402 };
1403 
1404 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1405     std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1406     void mutateNode(const MatrixXmlFile& object, NodeType* root,
1407                     const MutateNodeParam& param) const override {
1408         appendTextElement(root, "name", object.name(), param.d);
1409         appendAttr(root, "format", object.format());
1410         appendAttr(root, "optional", object.optional());
1411         appendChild(root, VersionRangeConverter{}(object.versionRange(), param));
1412         if (!object.overriddenPath().empty()) {
1413             appendTextElement(root, "path", object.overriddenPath(), param.d);
1414         }
1415     }
buildObjectandroid::vintf::MatrixXmlFileConverter1416     bool buildObject(MatrixXmlFile* object, NodeType* root,
1417                      const BuildObjectParam& param) const override {
1418         if (!parseTextElement(root, "name", &object->mName, param.error) ||
1419             !parseAttr(root, "format", &object->mFormat, param.error) ||
1420             !parseOptionalAttr(root, "optional", false, &object->mOptional, param.error) ||
1421             !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, param) ||
1422             !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
1423             return false;
1424         }
1425         return true;
1426     }
1427 };
1428 
1429 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1430     std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1431     void mutateNode(const CompatibilityMatrix& object, NodeType* root,
1432                     const MutateNodeParam& param) const override {
1433         if (param.flags.isMetaVersionEnabled()) {
1434             appendAttr(root, "version", kMetaVersion);
1435         }
1436         if (param.flags.isSchemaTypeEnabled()) {
1437             appendAttr(root, "type", object.mType);
1438         }
1439 
1440         if (param.flags.isHalsEnabled()) {
1441             appendChildren(root, MatrixHalConverter{}, iterateValues(object.mHals), param);
1442         }
1443         if (object.mType == SchemaType::FRAMEWORK) {
1444             if (param.flags.isKernelEnabled()) {
1445                 appendChildren(root, MatrixKernelConverter{}, object.framework.mKernels, param);
1446             }
1447             if (param.flags.isSepolicyEnabled()) {
1448                 if (!(object.framework.mSepolicy == Sepolicy{})) {
1449                     appendChild(root, SepolicyConverter{}(object.framework.mSepolicy, param));
1450                 }
1451             }
1452             if (param.flags.isAvbEnabled()) {
1453                 if (!(object.framework.mAvbMetaVersion == Version{})) {
1454                     appendChild(root, AvbConverter{}(object.framework.mAvbMetaVersion, param));
1455                 }
1456             }
1457             if (object.mLevel != Level::UNSPECIFIED) {
1458                 this->appendAttr(root, "level", object.mLevel);
1459             }
1460         } else if (object.mType == SchemaType::DEVICE) {
1461             if (param.flags.isVndkEnabled()) {
1462 #pragma clang diagnostic push
1463 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1464                 if (!(object.device.mVndk == Vndk{})) {
1465                     appendChild(root, VndkConverter{}(object.device.mVndk, param));
1466                 }
1467 #pragma clang diagnostic pop
1468 
1469                 if (!(object.device.mVendorNdk == VendorNdk{})) {
1470                     appendChild(root, VendorNdkConverter{}(object.device.mVendorNdk, param));
1471                 }
1472             }
1473 
1474             if (param.flags.isSsdkEnabled()) {
1475                 if (!object.device.mSystemSdk.empty()) {
1476                     appendChild(root, SystemSdkConverter{}(object.device.mSystemSdk, param));
1477                 }
1478             }
1479         }
1480 
1481         if (param.flags.isXmlFilesEnabled()) {
1482             appendChildren(root, MatrixXmlFileConverter{}, object.getXmlFiles(), param);
1483         }
1484     }
buildObjectandroid::vintf::CompatibilityMatrixConverter1485     bool buildObject(CompatibilityMatrix* object, NodeType* root,
1486                      const BuildObjectParam& constParam) const override {
1487         BuildObjectParam param = constParam;
1488         if (!parseAttr(root, "version", &param.metaVersion, param.error)) return false;
1489         if (param.metaVersion > kMetaVersion) {
1490             *param.error = "Unrecognized compatibility-matrix.version " +
1491                            to_string(param.metaVersion) + " (libvintf@" + to_string(kMetaVersion) +
1492                            ")";
1493             return false;
1494         }
1495 
1496         std::vector<MatrixHal> hals;
1497         if (!parseAttr(root, "type", &object->mType, param.error) ||
1498             !parseChildren(root, MatrixHalConverter{}, &hals, param)) {
1499             return false;
1500         }
1501 
1502         if (object->mType == SchemaType::FRAMEWORK) {
1503             // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1504             // hard-coded in the XML file.
1505             if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, param) ||
1506                 !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy,
1507                                     param) ||
1508                 !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion,
1509                                     param)) {
1510                 return false;
1511             }
1512 
1513             std::set<Version> seenKernelVersions;
1514             for (const auto& kernel : object->framework.mKernels) {
1515                 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1516                 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1517                     continue;
1518                 }
1519                 if (!kernel.conditions().empty()) {
1520                     *param.error = "First <kernel> for version " + to_string(minLts) +
1521                                    " must have empty <conditions> for backwards compatibility.";
1522                     return false;
1523                 }
1524                 seenKernelVersions.insert(minLts);
1525             }
1526 
1527             if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel,
1528                                    param.error)) {
1529                 return false;
1530             }
1531 
1532         } else if (object->mType == SchemaType::DEVICE) {
1533             // <vndk> can be missing because it can be determined at build time, not hard-coded
1534             // in the XML file.
1535 #pragma clang diagnostic push
1536 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1537             if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, param)) {
1538                 return false;
1539             }
1540 #pragma clang diagnostic pop
1541 
1542             if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk,
1543                                     param)) {
1544                 return false;
1545             }
1546 
1547             if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk,
1548                                     param)) {
1549                 return false;
1550             }
1551         }
1552 
1553         for (auto &&hal : hals) {
1554             if (!object->add(std::move(hal))) {
1555                 *param.error = "Duplicated compatibility-matrix.hal entry";
1556                 return false;
1557             }
1558         }
1559 
1560         std::vector<MatrixXmlFile> xmlFiles;
1561         if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, param)) {
1562             return false;
1563         }
1564         for (auto&& xmlFile : xmlFiles) {
1565             if (!xmlFile.optional()) {
1566                 *param.error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1567                                " has to be optional for compatibility matrix version 1.0";
1568                 return false;
1569             }
1570             std::string description{xmlFile.name()};
1571             if (!object->addXmlFile(std::move(xmlFile))) {
1572                 *param.error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1573                 return false;
1574             }
1575         }
1576 
1577         return true;
1578     }
1579 };
1580 
1581 #define CREATE_CONVERT_FN(type)                                         \
1582     std::string toXml(const type& o, SerializeFlags::Type flags) {      \
1583         return type##Converter{}.toXml(o, flags);                       \
1584     }                                                                   \
1585     bool fromXml(type* o, const std::string& xml, std::string* error) { \
1586         return type##Converter{}.fromXml(o, xml, error);                \
1587     }
1588 
1589 // Create convert functions for public usage.
1590 CREATE_CONVERT_FN(HalManifest)
1591 CREATE_CONVERT_FN(CompatibilityMatrix)
1592 
1593 // Create convert functions for internal usage.
1594 CREATE_CONVERT_FN(KernelInfo)
1595 
1596 // Create convert functions for testing.
1597 CREATE_CONVERT_FN(Version)
1598 CREATE_CONVERT_FN(SepolicyVersion)
1599 CREATE_CONVERT_FN(KernelConfigTypedValue)
1600 CREATE_CONVERT_FN(MatrixHal)
1601 CREATE_CONVERT_FN(ManifestHal)
1602 
1603 #undef CREATE_CONVERT_FN
1604 
1605 } // namespace vintf
1606 } // namespace android
1607