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", ®exes, 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", ¶m.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", ¶m.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