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
146 // ---------------------- XmlNodeConverter definitions
147
148 template <typename Object>
149 struct XmlNodeConverter {
XmlNodeConverterandroid::vintf::XmlNodeConverter150 XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter151 virtual ~XmlNodeConverter() {}
152
153 // sub-types should implement these.
154 virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
mutateNodeandroid::vintf::XmlNodeConverter155 virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
156 mutateNode(o, n, d);
157 }
158 virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
159 virtual std::string elementName() const = 0;
160
161 // convenience methods for user
operator ()android::vintf::XmlNodeConverter162 inline NodeType* operator()(const Object& o, DocType* d,
163 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
164 NodeType *root = createNode(this->elementName(), d);
165 this->mutateNode(o, root, d, flags);
166 return root;
167 }
operator ()android::vintf::XmlNodeConverter168 inline std::string operator()(const Object& o, SerializeFlags::Type flags) const {
169 DocType *doc = createDocument();
170 appendChild(doc, (*this)(o, doc, flags));
171 std::string s = printDocument(doc);
172 deleteDocument(doc);
173 return s;
174 }
operator ()android::vintf::XmlNodeConverter175 inline bool operator()(Object* object, NodeType* root, std::string* error) const {
176 if (nameOf(root) != this->elementName()) {
177 return false;
178 }
179 return this->buildObject(object, root, error);
180 }
operator ()android::vintf::XmlNodeConverter181 inline bool operator()(Object* o, const std::string& xml, std::string* error) const {
182 std::string errorBuffer;
183 if (error == nullptr) error = &errorBuffer;
184
185 auto doc = createDocument(xml);
186 if (doc == nullptr) {
187 *error = "Not a valid XML";
188 return false;
189 }
190 bool ret = (*this)(o, getRootChild(doc), error);
191 deleteDocument(doc);
192 return ret;
193 }
194
195 // convenience methods for implementor.
196
197 // All append* functions helps mutateNode() to serialize the object into XML.
198 template <typename T>
appendAttrandroid::vintf::XmlNodeConverter199 inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
200 return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
201 }
202
appendAttrandroid::vintf::XmlNodeConverter203 inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
204 return appendStrAttr(e, attrName, attr ? "true" : "false");
205 }
206
207 // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter208 inline void appendTextElement(NodeType *parent, const std::string &name,
209 const std::string &text, DocType *d) const {
210 NodeType *c = createNode(name, d);
211 appendText(c, text, d);
212 appendChild(parent, c);
213 }
214
215 // text -> <name>text</name>
216 template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter217 inline void appendTextElements(NodeType *parent, const std::string &name,
218 const Array &array, DocType *d) const {
219 for (const std::string &text : array) {
220 NodeType *c = createNode(name, d);
221 appendText(c, text, d);
222 appendChild(parent, c);
223 }
224 }
225
226 template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter227 inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
228 const Array& array, DocType* d,
229 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
230 for (const T &t : array) {
231 appendChild(parent, conv(t, d, flags));
232 }
233 }
234
235 // All parse* functions helps buildObject() to deserialize XML to the object. Returns
236 // true if deserialization is successful, false if any error, and "error" will be
237 // set to error message.
238 template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter239 inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
240 T* attr, std::string* /* error */) const {
241 std::string attrText;
242 bool success = getAttr(root, attrName, &attrText) &&
243 ::android::vintf::parse(attrText, attr);
244 if (!success) {
245 *attr = std::move(defaultValue);
246 }
247 return true;
248 }
249
250 template <typename T>
parseAttrandroid::vintf::XmlNodeConverter251 inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
252 std::string* error) const {
253 std::string attrText;
254 bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
255 if (!ret) {
256 *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
257 attrText + "\" for element <" + elementName() + ">";
258 }
259 return ret;
260 }
261
parseAttrandroid::vintf::XmlNodeConverter262 inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
263 std::string* error) const {
264 bool ret = getAttr(root, attrName, attr);
265 if (!ret) {
266 *error = "Could not find attr with name \"" + attrName + "\" for element <" +
267 elementName() + ">";
268 }
269 return ret;
270 }
271
parseTextElementandroid::vintf::XmlNodeConverter272 inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
273 std::string* error) const {
274 NodeType *child = getChild(root, elementName);
275 if (child == nullptr) {
276 *error = "Could not find element with name <" + elementName + "> in element <" +
277 this->elementName() + ">";
278 return false;
279 }
280 *s = getText(child);
281 return true;
282 }
283
parseOptionalTextElementandroid::vintf::XmlNodeConverter284 inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
285 std::string&& defaultValue, std::string* s,
286 std::string* /* error */) const {
287 NodeType* child = getChild(root, elementName);
288 *s = child == nullptr ? std::move(defaultValue) : getText(child);
289 return true;
290 }
291
parseTextElementsandroid::vintf::XmlNodeConverter292 inline bool parseTextElements(NodeType* root, const std::string& elementName,
293 std::vector<std::string>* v, std::string* /* error */) const {
294 auto nodes = getChildren(root, elementName);
295 v->resize(nodes.size());
296 for (size_t i = 0; i < nodes.size(); ++i) {
297 v->at(i) = getText(nodes[i]);
298 }
299 return true;
300 }
301
302 template <typename T>
parseChildandroid::vintf::XmlNodeConverter303 inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
304 std::string* error) const {
305 NodeType *child = getChild(root, conv.elementName());
306 if (child == nullptr) {
307 *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
308 this->elementName() + ">";
309 return false;
310 }
311 return conv(t, child, error);
312 }
313
314 template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter315 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
316 T&& defaultValue, T* t, std::string* error) const {
317 NodeType *child = getChild(root, conv.elementName());
318 if (child == nullptr) {
319 *t = std::move(defaultValue);
320 return true;
321 }
322 return conv(t, child, error);
323 }
324
325 template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter326 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
327 std::optional<T>* t, std::string* error) const {
328 NodeType* child = getChild(root, conv.elementName());
329 if (child == nullptr) {
330 *t = std::nullopt;
331 return true;
332 }
333 *t = std::make_optional<T>();
334 return conv(&**t, child, error);
335 }
336
337 template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter338 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
339 std::string* error) const {
340 auto nodes = getChildren(root, conv.elementName());
341 v->resize(nodes.size());
342 for (size_t i = 0; i < nodes.size(); ++i) {
343 if (!conv(&v->at(i), nodes[i], error)) {
344 *error = "Could not parse element with name <" + conv.elementName() +
345 "> in element <" + this->elementName() + ">: " + *error;
346 return false;
347 }
348 }
349 return true;
350 }
351
352 template <typename Container, typename T = typename Container::value_type,
353 typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter354 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
355 std::string* error) const {
356 std::vector<T> vec;
357 if (!parseChildren(root, conv, &vec, error)) {
358 return false;
359 }
360 s->clear();
361 s->insert(vec.begin(), vec.end());
362 if (s->size() != vec.size()) {
363 *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
364 this->elementName() + ">";
365 s->clear();
366 return false;
367 }
368 return true;
369 }
370
371 template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter372 inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
373 std::map<K, V>* s, std::string* error) const {
374 return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
375 }
376
parseTextandroid::vintf::XmlNodeConverter377 inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
378 *s = getText(node);
379 return true;
380 }
381
382 template <typename T>
parseTextandroid::vintf::XmlNodeConverter383 inline bool parseText(NodeType* node, T* s, std::string* error) const {
384 bool (*parser)(const std::string&, T*) = ::android::vintf::parse;
385 return parseText(node, s, {parser}, error);
386 }
387
388 template <typename T>
parseTextandroid::vintf::XmlNodeConverter389 inline bool parseText(NodeType* node, T* s,
390 const std::function<bool(const std::string&, T*)>& parse,
391 std::string* error) const {
392 std::string text = getText(node);
393 bool ret = parse(text, s);
394 if (!ret) {
395 *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
396 }
397 return ret;
398 }
399 };
400
401 template<typename Object>
402 struct XmlTextConverter : public XmlNodeConverter<Object> {
mutateNodeandroid::vintf::XmlTextConverter403 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
404 appendText(root, ::android::vintf::to_string(object), d);
405 }
buildObjectandroid::vintf::XmlTextConverter406 virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
407 return this->parseText(root, object, error);
408 }
409 };
410
411 template <typename Pair, typename FirstConverter, typename SecondConverter>
412 struct XmlPairConverter : public XmlNodeConverter<Pair> {
mutateNodeandroid::vintf::XmlPairConverter413 virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
414 appendChild(root, FirstConverter{}(pair.first, d));
415 appendChild(root, SecondConverter{}(pair.second, d));
416 }
buildObjectandroid::vintf::XmlPairConverter417 virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
418 return this->parseChild(root, FirstConverter{}, &pair->first, error) &&
419 this->parseChild(root, SecondConverter{}, &pair->second, error);
420 }
421 };
422
423 // ---------------------- XmlNodeConverter definitions end
424
425 struct VersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::VersionConverter426 std::string elementName() const override { return "version"; }
427 };
428
429 struct VersionRangeConverter : public XmlTextConverter<VersionRange> {
elementNameandroid::vintf::VersionRangeConverter430 std::string elementName() const override { return "version"; }
431 };
432
433 // <version>100</version> <=> Version{kFakeAidlMajorVersion, 100}
434 struct AidlVersionConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AidlVersionConverter435 std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionConverter436 void mutateNode(const Version& object, NodeType* root, DocType* d) const override {
437 appendText(root, aidlVersionToString(object), d);
438 }
buildObjectandroid::vintf::AidlVersionConverter439 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
440 return parseText(root, object, {parseAidlVersion}, error);
441 }
442 };
443
444 // <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100}
445 // <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105}
446 struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> {
elementNameandroid::vintf::AidlVersionRangeConverter447 std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionRangeConverter448 void mutateNode(const VersionRange& object, NodeType* root, DocType* d) const override {
449 appendText(root, aidlVersionRangeToString(object), d);
450 }
buildObjectandroid::vintf::AidlVersionRangeConverter451 bool buildObject(VersionRange* object, NodeType* root, std::string* error) const override {
452 return parseText(root, object, {parseAidlVersionRange}, error);
453 }
454 };
455
456 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter457 std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter458 void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
459 if (object.arch != Arch::ARCH_EMPTY) {
460 appendAttr(root, "arch", object.arch);
461 }
462 appendText(root, ::android::vintf::to_string(object.transport), d);
463 }
buildObjectandroid::vintf::TransportArchConverter464 bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
465 if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
466 !parseText(root, &object->transport, error)) {
467 return false;
468 }
469 if (!object->isValid(error)) {
470 return false;
471 }
472 return true;
473 }
474 };
475
476 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter477 std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter478 void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
479 appendAttr(root, "type", object.mType);
480 appendText(root, ::android::vintf::to_string(object), d);
481 }
buildObjectandroid::vintf::KernelConfigTypedValueConverter482 bool buildObject(KernelConfigTypedValue* object, NodeType* root,
483 std::string* error) const override {
484 std::string stringValue;
485 if (!parseAttr(root, "type", &object->mType, error) ||
486 !parseText(root, &stringValue, error)) {
487 return false;
488 }
489 if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
490 *error = "Could not parse kernel config value \"" + stringValue + "\"";
491 return false;
492 }
493 return true;
494 }
495 };
496
497 struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> {
elementNameandroid::vintf::KernelConfigKeyConverter498 std::string elementName() const override { return "key"; }
499 };
500
501 struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter,
502 KernelConfigTypedValueConverter> {
elementNameandroid::vintf::MatrixKernelConfigConverter503 std::string elementName() const override { return "config"; }
504 };
505
506 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter507 std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter508 void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
509 appendTextElement(root, "name", intf.name(), d);
510 appendTextElements(root, "instance", intf.mInstances, d);
511 appendTextElements(root, "regex-instance", intf.mRegexes, d);
512 }
buildObjectandroid::vintf::HalInterfaceConverter513 bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
514 std::vector<std::string> instances;
515 std::vector<std::string> regexes;
516 if (!parseTextElement(root, "name", &intf->mName, error) ||
517 !parseTextElements(root, "instance", &instances, error) ||
518 !parseTextElements(root, "regex-instance", ®exes, error)) {
519 return false;
520 }
521 bool success = true;
522 for (const auto& e : instances) {
523 if (!intf->insertInstance(e, false /* isRegex */)) {
524 if (!error->empty()) *error += "\n";
525 *error += "Duplicated instance '" + e + "' in " + intf->name();
526 success = false;
527 }
528 }
529 for (const auto& e : regexes) {
530 details::Regex regex;
531 if (!regex.compile(e)) {
532 if (!error->empty()) *error += "\n";
533 *error += "Invalid regular expression '" + e + "' in " + intf->name();
534 success = false;
535 }
536 if (!intf->insertInstance(e, true /* isRegex */)) {
537 if (!error->empty()) *error += "\n";
538 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
539 success = false;
540 }
541 }
542 return success;
543 }
544 };
545
546 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter547 std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter548 void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
549 appendAttr(root, "format", hal.format);
550 appendAttr(root, "optional", hal.optional);
551 appendTextElement(root, "name", hal.name, d);
552 if (hal.format == HalFormat::AIDL) {
553 // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
554 // is specified. Don't output any <version> tag if there's only one <version>0</version>
555 // tag.
556 if (hal.versionRanges.size() != 1 ||
557 hal.versionRanges[0] != details::kDefaultAidlVersionRange) {
558 appendChildren(root, AidlVersionRangeConverter{}, hal.versionRanges, d);
559 }
560 } else {
561 appendChildren(root, VersionRangeConverter{}, hal.versionRanges, d);
562 }
563 appendChildren(root, HalInterfaceConverter{}, iterateValues(hal.interfaces), d);
564 }
buildObjectandroid::vintf::MatrixHalConverter565 bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
566 std::vector<HalInterface> interfaces;
567 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
568 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
569 error) ||
570 !parseTextElement(root, "name", &object->name, error) ||
571 !parseChildren(root, HalInterfaceConverter{}, &interfaces, error)) {
572 return false;
573 }
574 if (object->format == HalFormat::AIDL) {
575 if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, error)) {
576 return false;
577 }
578 // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
579 // HAL formats can be unified.
580 if (object->versionRanges.empty()) {
581 object->versionRanges.push_back(details::kDefaultAidlVersionRange);
582 }
583 } else {
584 if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, error)) {
585 return false;
586 }
587 }
588 for (auto&& interface : interfaces) {
589 std::string name{interface.name()};
590 auto res = object->interfaces.emplace(std::move(name), std::move(interface));
591 if (!res.second) {
592 *error = "Duplicated interface entry \"" + res.first->first +
593 "\"; if additional instances are needed, add them to the "
594 "existing <interface> node.";
595 return false;
596 }
597 }
598 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
599 #ifndef LIBVINTF_TARGET
600 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
601 return false;
602 }
603 #endif
604
605 if (!object->isValid(error)) {
606 error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: ");
607 return false;
608 }
609 return true;
610 }
611
612 #ifndef LIBVINTF_TARGET
613 private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter614 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
615 if (hal.getName() == "netutils-wrapper") {
616 if (hal.versionRanges.size() != 1) {
617 *error =
618 "netutils-wrapper HAL must specify exactly one version x.0, "
619 "but multiple <version> element is specified.";
620 return false;
621 }
622 const VersionRange& v = hal.versionRanges.at(0);
623 if (!v.isSingleVersion()) {
624 *error =
625 "netutils-wrapper HAL must specify exactly one version x.0, "
626 "but a range is provided. Perhaps you mean '" +
627 to_string(Version{v.majorVer, 0}) + "'?";
628 return false;
629 }
630 if (v.minMinor != 0) {
631 *error =
632 "netutils-wrapper HAL must specify exactly one version x.0, "
633 "but minor version is not 0. Perhaps you mean '" +
634 to_string(Version{v.majorVer, 0}) + "'?";
635 return false;
636 }
637 }
638 return true;
639 }
640 #endif
641 };
642
643 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter644 std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter645 void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
646 DocType* d) const override {
647 appendChildren(root, MatrixKernelConfigConverter{}, conds, d);
648 }
buildObjectandroid::vintf::MatrixKernelConditionsConverter649 bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
650 std::string* error) const override {
651 return parseChildren(root, MatrixKernelConfigConverter{}, object, error);
652 }
653 };
654
655 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter656 std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter657 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
658 mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
659 }
mutateNodeandroid::vintf::MatrixKernelConverter660 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
661 SerializeFlags::Type flags) const override {
662 KernelVersion kv = kernel.mMinLts;
663 if (!flags.isKernelMinorRevisionEnabled()) {
664 kv.minorRev = 0u;
665 }
666 appendAttr(root, "version", kv);
667
668 if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
669 appendAttr(root, "level", kernel.getSourceMatrixLevel());
670 }
671
672 if (!kernel.mConditions.empty()) {
673 appendChild(root, MatrixKernelConditionsConverter{}(kernel.mConditions, d));
674 }
675 if (flags.isKernelConfigsEnabled()) {
676 appendChildren(root, MatrixKernelConfigConverter{}, kernel.mConfigs, d);
677 }
678 }
buildObjectandroid::vintf::MatrixKernelConverter679 bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
680 Level sourceMatrixLevel = Level::UNSPECIFIED;
681 if (!parseAttr(root, "version", &object->mMinLts, error) ||
682 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
683 !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions,
684 error) ||
685 !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, error)) {
686 return false;
687 }
688 object->setSourceMatrixLevel(sourceMatrixLevel);
689 return true;
690 }
691 };
692
693 struct FqInstanceConverter : public XmlTextConverter<FqInstance> {
elementNameandroid::vintf::FqInstanceConverter694 std::string elementName() const override { return "fqname"; }
695 };
696
697 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
698 // .isValid() == true.
699 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter700 std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter701 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
702 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
703 }
mutateNodeandroid::vintf::ManifestHalConverter704 void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
705 SerializeFlags::Type flags) const override {
706 appendAttr(root, "format", hal.format);
707 appendTextElement(root, "name", hal.name, d);
708 if (!hal.transportArch.empty()) {
709 appendChild(root, TransportArchConverter{}(hal.transportArch, d));
710 }
711 if (hal.format == HalFormat::AIDL) {
712 // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
713 // is specified. Don't output any <version> tag if there's only one <version>0</version>
714 // tag.
715 if (hal.versions.size() != 1 || hal.versions[0] != details::kDefaultAidlVersion) {
716 appendChildren(root, AidlVersionConverter{}, hal.versions, d);
717 }
718 } else {
719 appendChildren(root, VersionConverter{}, hal.versions, d);
720 }
721 appendChildren(root, HalInterfaceConverter{}, iterateValues(hal.interfaces), d);
722 if (hal.isOverride()) {
723 appendAttr(root, "override", hal.isOverride());
724 }
725 if (const auto& apex = hal.updatableViaApex(); apex.has_value()) {
726 appendAttr(root, "updatable-via-apex", apex.value());
727 }
728 if (flags.isFqnameEnabled()) {
729 std::set<std::string> simpleFqInstances;
730 hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
731 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
732 return true;
733 });
734 appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances, d);
735 }
736 if (hal.getMaxLevel() != Level::UNSPECIFIED) {
737 appendAttr(root, "max-level", hal.getMaxLevel());
738 }
739 }
buildObjectandroid::vintf::ManifestHalConverter740 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
741 std::vector<HalInterface> interfaces;
742 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
743 !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
744 !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex, error) ||
745 !parseTextElement(root, "name", &object->name, error) ||
746 !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch,
747 error) ||
748 !parseChildren(root, HalInterfaceConverter{}, &interfaces, error) ||
749 !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel, error)) {
750 return false;
751 }
752
753 switch (object->format) {
754 case HalFormat::HIDL: {
755 if (!parseChildren(root, VersionConverter{}, &object->versions, error))
756 return false;
757 if (object->transportArch.empty()) {
758 *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
759 return false;
760 }
761 } break;
762 case HalFormat::NATIVE: {
763 if (!parseChildren(root, VersionConverter{}, &object->versions, error))
764 return false;
765 if (!object->transportArch.empty()) {
766 *error =
767 "Native HAL '" + object->name + "' should not have <transport> defined.";
768 return false;
769 }
770 } break;
771 case HalFormat::AIDL: {
772 if (!object->transportArch.empty()) {
773 LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
774 << object->name;
775 object->transportArch = {};
776 }
777 if (!parseChildren(root, AidlVersionConverter{}, &object->versions, error)) {
778 return false;
779 }
780 // Insert fake version for AIDL HALs so that forEachInstance works.
781 if (object->versions.empty()) {
782 object->versions.push_back(details::kDefaultAidlVersion);
783 }
784 } break;
785 default: {
786 LOG(FATAL) << "Unhandled HalFormat "
787 << static_cast<typename std::underlying_type<HalFormat>::type>(
788 object->format);
789 } break;
790 }
791 if (!object->transportArch.isValid(error)) return false;
792
793 object->interfaces.clear();
794 for (auto &&interface : interfaces) {
795 auto res = object->interfaces.emplace(interface.name(), std::move(interface));
796 if (!res.second) {
797 *error = "Duplicated interface entry \"" + res.first->first +
798 "\"; if additional instances are needed, add them to the "
799 "existing <interface> node.";
800 return false;
801 }
802 }
803 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
804 #ifndef LIBVINTF_TARGET
805 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
806 return false;
807 }
808 #endif
809
810 std::set<FqInstance> fqInstances;
811 if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, error)) {
812 return false;
813 }
814 std::set<FqInstance> fqInstancesToInsert;
815 for (auto& e : fqInstances) {
816 if (e.hasPackage()) {
817 *error = "Should not specify package: \"" + e.string() + "\"";
818 return false;
819 }
820 if (object->format == HalFormat::AIDL) {
821 // <fqname> in AIDL HALs should not contain version.
822 if (e.hasVersion()) {
823 *error = "Should not specify version in <fqname> for AIDL HAL: \"" +
824 e.string() + "\"";
825 return false;
826 }
827 // Put in the fake kDefaultAidlVersion so that HalManifest can
828 // store it in an FqInstance object with a non-empty package.
829 FqInstance withFakeVersion;
830 if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer,
831 details::kDefaultAidlVersion.minorVer, e.getInterface(),
832 e.getInstance())) {
833 return false;
834 }
835 fqInstancesToInsert.emplace(std::move(withFakeVersion));
836 } else {
837 fqInstancesToInsert.emplace(std::move(e));
838 }
839 }
840 if (!object->insertInstances(fqInstancesToInsert, error)) {
841 return false;
842 }
843
844 if (!object->isValid(error)) {
845 error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
846 return false;
847 }
848
849 return true;
850 }
851
852 #ifndef LIBVINTF_TARGET
853 private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter854 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
855 if (hal.getName() == "netutils-wrapper") {
856 for (const Version& v : hal.versions) {
857 if (v.minorVer != 0) {
858 *error =
859 "netutils-wrapper HAL must specify exactly one version x.0, "
860 "but minor version is not 0. Perhaps you mean '" +
861 to_string(Version{v.majorVer, 0}) + "'?";
862 return false;
863 }
864 }
865 }
866 return true;
867 }
868 #endif
869 };
870
871 struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> {
elementNameandroid::vintf::KernelSepolicyVersionConverter872 std::string elementName() const override { return "kernel-sepolicy-version"; }
873 };
874
875 struct SepolicyVersionConverter : public XmlTextConverter<VersionRange> {
elementNameandroid::vintf::SepolicyVersionConverter876 std::string elementName() const override { return "sepolicy-version"; }
877 };
878
879 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter880 std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter881 void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
882 appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), d));
883 appendChildren(root, SepolicyVersionConverter{}, object.sepolicyVersions(), d);
884 }
buildObjectandroid::vintf::SepolicyConverter885 bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
886 if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion,
887 error) ||
888 !parseChildren(root, SepolicyVersionConverter{}, &object->mSepolicyVersionRanges,
889 error)) {
890 return false;
891 }
892 return true;
893 }
894 };
895
896 struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> {
elementNameandroid::vintf::VndkVersionRangeConverter897 std::string elementName() const override { return "version"; }
898 };
899
900 struct VndkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkVersionConverter901 std::string elementName() const override { return "version"; }
902 };
903
904 struct VndkLibraryConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkLibraryConverter905 std::string elementName() const override { return "library"; }
906 };
907
908 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter909 std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter910 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
911 appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, d));
912 appendChildren(root, VndkLibraryConverter{}, object.mLibraries, d);
913 }
buildObjectandroid::vintf::VndkConverter914 bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
915 if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, error) ||
916 !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, error)) {
917 return false;
918 }
919 return true;
920 }
921 };
922
923 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter924 std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter925 void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
926 appendChild(root, VndkVersionConverter{}(object.mVersion, d));
927 appendChildren(root, VndkLibraryConverter{}, object.mLibraries, d);
928 }
buildObjectandroid::vintf::VendorNdkConverter929 bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
930 if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, error) ||
931 !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, error)) {
932 return false;
933 }
934 return true;
935 }
936 };
937
938 struct SystemSdkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::SystemSdkVersionConverter939 std::string elementName() const override { return "version"; }
940 };
941
942 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter943 std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter944 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
945 appendChildren(root, SystemSdkVersionConverter{}, object.versions(), d);
946 }
buildObjectandroid::vintf::SystemSdkConverter947 bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
948 return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, error);
949 }
950 };
951
952 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter953 std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter954 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
955 appendChild(root, VersionConverter{}(m, d));
956 }
buildObjectandroid::vintf::HalManifestSepolicyConverter957 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
958 return parseChild(root, VersionConverter{}, object, error);
959 }
960 };
961
962 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter963 std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter964 void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
965 appendTextElement(root, "name", f.name(), d);
966 appendChild(root, VersionConverter{}(f.version(), d));
967 if (!f.overriddenPath().empty()) {
968 appendTextElement(root, "path", f.overriddenPath(), d);
969 }
970 }
buildObjectandroid::vintf::ManifestXmlFileConverter971 bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
972 if (!parseTextElement(root, "name", &object->mName, error) ||
973 !parseChild(root, VersionConverter{}, &object->mVersion, error) ||
974 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
975 return false;
976 }
977 return true;
978 }
979 };
980
981 struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::StringKernelConfigKeyConverter982 std::string elementName() const override { return "key"; }
983 };
984
985 struct KernelConfigValueConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::KernelConfigValueConverter986 std::string elementName() const override { return "value"; }
987 };
988
989 struct StringKernelConfigConverter
990 : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter,
991 KernelConfigValueConverter> {
elementNameandroid::vintf::StringKernelConfigConverter992 std::string elementName() const override { return "config"; }
993 };
994
995 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter996 std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter997 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
998 mutateNode(o, root, d, SerializeFlags::EVERYTHING);
999 }
mutateNodeandroid::vintf::KernelInfoConverter1000 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
1001 SerializeFlags::Type flags) const override {
1002 if (o.version() != KernelVersion{}) {
1003 appendAttr(root, "version", o.version());
1004 }
1005 if (o.level() != Level::UNSPECIFIED) {
1006 appendAttr(root, "target-level", o.level());
1007 }
1008 if (flags.isKernelConfigsEnabled()) {
1009 appendChildren(root, StringKernelConfigConverter{}, o.configs(), d);
1010 }
1011 }
buildObjectandroid::vintf::KernelInfoConverter1012 bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
1013 return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
1014 parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
1015 parseChildren(root, StringKernelConfigConverter{}, &o->mConfigs, error);
1016 }
1017 };
1018
1019 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter1020 std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter1021 void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
1022 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1023 }
mutateNodeandroid::vintf::HalManifestConverter1024 void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
1025 SerializeFlags::Type flags) const override {
1026 if (flags.isMetaVersionEnabled()) {
1027 appendAttr(root, "version", m.getMetaVersion());
1028 }
1029 if (flags.isSchemaTypeEnabled()) {
1030 appendAttr(root, "type", m.mType);
1031 }
1032
1033 if (flags.isHalsEnabled()) {
1034 appendChildren(root, ManifestHalConverter{}, m.getHals(), d, flags);
1035 }
1036 if (m.mType == SchemaType::DEVICE) {
1037 if (flags.isSepolicyEnabled()) {
1038 if (m.device.mSepolicyVersion != Version{}) {
1039 appendChild(root, HalManifestSepolicyConverter{}(m.device.mSepolicyVersion, d));
1040 }
1041 }
1042 if (m.mLevel != Level::UNSPECIFIED) {
1043 this->appendAttr(root, "target-level", m.mLevel);
1044 }
1045
1046 if (flags.isKernelEnabled()) {
1047 if (!!m.kernel()) {
1048 appendChild(root, KernelInfoConverter{}(*m.kernel(), d, flags));
1049 }
1050 }
1051 } else if (m.mType == SchemaType::FRAMEWORK) {
1052 if (flags.isVndkEnabled()) {
1053 #pragma clang diagnostic push
1054 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1055 appendChildren(root, VndkConverter{}, m.framework.mVndks, d);
1056 #pragma clang diagnostic pop
1057
1058 appendChildren(root, VendorNdkConverter{}, m.framework.mVendorNdks, d);
1059 }
1060 if (flags.isSsdkEnabled()) {
1061 if (!m.framework.mSystemSdk.empty()) {
1062 appendChild(root, SystemSdkConverter{}(m.framework.mSystemSdk, d));
1063 }
1064 }
1065 }
1066
1067 if (flags.isXmlFilesEnabled()) {
1068 appendChildren(root, ManifestXmlFileConverter{}, m.getXmlFiles(), d);
1069 }
1070 }
buildObjectandroid::vintf::HalManifestConverter1071 bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
1072 Version metaVersion;
1073 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1074 if (metaVersion > kMetaVersion) {
1075 *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1076 to_string(kMetaVersion) + ")";
1077 return false;
1078 }
1079
1080 if (!parseAttr(root, "type", &object->mType, error)) {
1081 return false;
1082 }
1083
1084 std::vector<ManifestHal> hals;
1085 if (!parseChildren(root, ManifestHalConverter{}, &hals, error)) {
1086 return false;
1087 }
1088 for (auto&& hal : hals) {
1089 hal.setFileName(object->fileName());
1090 }
1091
1092 if (object->mType == SchemaType::DEVICE) {
1093 // tags for device hal manifest only.
1094 // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1095 // in the XML file.
1096 if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {},
1097 &object->device.mSepolicyVersion, error)) {
1098 return false;
1099 }
1100
1101 if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1102 error)) {
1103 return false;
1104 }
1105
1106 if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, error)) {
1107 return false;
1108 }
1109 } else if (object->mType == SchemaType::FRAMEWORK) {
1110 #pragma clang diagnostic push
1111 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1112 if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, error)) {
1113 return false;
1114 }
1115 for (const auto &vndk : object->framework.mVndks) {
1116 if (!vndk.mVersionRange.isSingleVersion()) {
1117 *error = "vndk.version " + to_string(vndk.mVersionRange) +
1118 " cannot be a range for manifests";
1119 return false;
1120 }
1121 }
1122 #pragma clang diagnostic pop
1123
1124 if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, error)) {
1125 return false;
1126 }
1127
1128 std::set<std::string> vendorNdkVersions;
1129 for (const auto& vendorNdk : object->framework.mVendorNdks) {
1130 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1131 *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1132 return false;
1133 }
1134 vendorNdkVersions.insert(vendorNdk.version());
1135 }
1136
1137 if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk,
1138 error)) {
1139 return false;
1140 }
1141 }
1142 for (auto &&hal : hals) {
1143 std::string description{hal.name};
1144 if (!object->add(std::move(hal))) {
1145 *error = "Duplicated manifest.hal entry " + description;
1146 return false;
1147 }
1148 }
1149
1150 std::vector<ManifestXmlFile> xmlFiles;
1151 if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, error)) {
1152 return false;
1153 }
1154 for (auto&& xmlFile : xmlFiles) {
1155 std::string description{xmlFile.name()};
1156 if (!object->addXmlFile(std::move(xmlFile))) {
1157 *error = "Duplicated manifest.xmlfile entry " + description +
1158 "; entries cannot have duplicated name and version";
1159 return false;
1160 }
1161 }
1162
1163 return true;
1164 }
1165 };
1166
1167 struct AvbVersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::AvbVersionConverter1168 std::string elementName() const override { return "vbmeta-version"; }
1169 };
1170
1171 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1172 std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1173 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1174 appendChild(root, AvbVersionConverter{}(m, d));
1175 }
buildObjectandroid::vintf::AvbConverter1176 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1177 return parseChild(root, AvbVersionConverter{}, object, error);
1178 }
1179 };
1180
1181 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1182 std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1183 void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1184 appendTextElement(root, "name", f.name(), d);
1185 appendAttr(root, "format", f.format());
1186 appendAttr(root, "optional", f.optional());
1187 appendChild(root, VersionRangeConverter{}(f.versionRange(), d));
1188 if (!f.overriddenPath().empty()) {
1189 appendTextElement(root, "path", f.overriddenPath(), d);
1190 }
1191 }
buildObjectandroid::vintf::MatrixXmlFileConverter1192 bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1193 if (!parseTextElement(root, "name", &object->mName, error) ||
1194 !parseAttr(root, "format", &object->mFormat, error) ||
1195 !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1196 !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, error) ||
1197 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1198 return false;
1199 }
1200 return true;
1201 }
1202 };
1203
1204 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1205 std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1206 void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1207 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1208 }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1209 void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1210 SerializeFlags::Type flags) const override {
1211 if (flags.isMetaVersionEnabled()) {
1212 appendAttr(root, "version", kMetaVersion);
1213 }
1214 if (flags.isSchemaTypeEnabled()) {
1215 appendAttr(root, "type", m.mType);
1216 }
1217
1218 if (flags.isHalsEnabled()) {
1219 appendChildren(root, MatrixHalConverter{}, iterateValues(m.mHals), d);
1220 }
1221 if (m.mType == SchemaType::FRAMEWORK) {
1222 if (flags.isKernelEnabled()) {
1223 appendChildren(root, MatrixKernelConverter{}, m.framework.mKernels, d, flags);
1224 }
1225 if (flags.isSepolicyEnabled()) {
1226 if (!(m.framework.mSepolicy == Sepolicy{})) {
1227 appendChild(root, SepolicyConverter{}(m.framework.mSepolicy, d));
1228 }
1229 }
1230 if (flags.isAvbEnabled()) {
1231 if (!(m.framework.mAvbMetaVersion == Version{})) {
1232 appendChild(root, AvbConverter{}(m.framework.mAvbMetaVersion, d));
1233 }
1234 }
1235 if (m.mLevel != Level::UNSPECIFIED) {
1236 this->appendAttr(root, "level", m.mLevel);
1237 }
1238 } else if (m.mType == SchemaType::DEVICE) {
1239 if (flags.isVndkEnabled()) {
1240 #pragma clang diagnostic push
1241 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1242 if (!(m.device.mVndk == Vndk{})) {
1243 appendChild(root, VndkConverter{}(m.device.mVndk, d));
1244 }
1245 #pragma clang diagnostic pop
1246
1247 if (!(m.device.mVendorNdk == VendorNdk{})) {
1248 appendChild(root, VendorNdkConverter{}(m.device.mVendorNdk, d));
1249 }
1250 }
1251
1252 if (flags.isSsdkEnabled()) {
1253 if (!m.device.mSystemSdk.empty()) {
1254 appendChild(root, SystemSdkConverter{}(m.device.mSystemSdk, d));
1255 }
1256 }
1257 }
1258
1259 if (flags.isXmlFilesEnabled()) {
1260 appendChildren(root, MatrixXmlFileConverter{}, m.getXmlFiles(), d);
1261 }
1262 }
buildObjectandroid::vintf::CompatibilityMatrixConverter1263 bool buildObject(CompatibilityMatrix* object, NodeType* root,
1264 std::string* error) const override {
1265 Version metaVersion;
1266 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1267 if (metaVersion > kMetaVersion) {
1268 *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1269 " (libvintf@" + to_string(kMetaVersion) + ")";
1270 return false;
1271 }
1272
1273 std::vector<MatrixHal> hals;
1274 if (!parseAttr(root, "type", &object->mType, error) ||
1275 !parseChildren(root, MatrixHalConverter{}, &hals, error)) {
1276 return false;
1277 }
1278
1279 if (object->mType == SchemaType::FRAMEWORK) {
1280 // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1281 // hard-coded in the XML file.
1282 if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, error) ||
1283 !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy,
1284 error) ||
1285 !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion,
1286 error)) {
1287 return false;
1288 }
1289
1290 std::set<Version> seenKernelVersions;
1291 for (const auto& kernel : object->framework.mKernels) {
1292 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1293 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1294 continue;
1295 }
1296 if (!kernel.conditions().empty()) {
1297 *error = "First <kernel> for version " + to_string(minLts) +
1298 " must have empty <conditions> for backwards compatibility.";
1299 return false;
1300 }
1301 seenKernelVersions.insert(minLts);
1302 }
1303
1304 if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1305 return false;
1306 }
1307
1308 } else if (object->mType == SchemaType::DEVICE) {
1309 // <vndk> can be missing because it can be determined at build time, not hard-coded
1310 // in the XML file.
1311 #pragma clang diagnostic push
1312 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1313 if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, error)) {
1314 return false;
1315 }
1316 #pragma clang diagnostic pop
1317
1318 if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk,
1319 error)) {
1320 return false;
1321 }
1322
1323 if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk,
1324 error)) {
1325 return false;
1326 }
1327 }
1328
1329 for (auto &&hal : hals) {
1330 if (!object->add(std::move(hal))) {
1331 *error = "Duplicated compatibility-matrix.hal entry";
1332 return false;
1333 }
1334 }
1335
1336 std::vector<MatrixXmlFile> xmlFiles;
1337 if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, error)) {
1338 return false;
1339 }
1340 for (auto&& xmlFile : xmlFiles) {
1341 if (!xmlFile.optional()) {
1342 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1343 " has to be optional for compatibility matrix version 1.0";
1344 return false;
1345 }
1346 std::string description{xmlFile.name()};
1347 if (!object->addXmlFile(std::move(xmlFile))) {
1348 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1349 return false;
1350 }
1351 }
1352
1353 return true;
1354 }
1355 };
1356
1357 #define CREATE_CONVERT_FN(type) \
1358 std::string toXml(const type& o, SerializeFlags::Type flags) { \
1359 return type##Converter{}(o, flags); \
1360 } \
1361 bool fromXml(type* o, const std::string& xml, std::string* error) { \
1362 return type##Converter{}(o, xml, error); \
1363 }
1364
1365 // Create convert functions for public usage.
1366 CREATE_CONVERT_FN(HalManifest)
1367 CREATE_CONVERT_FN(CompatibilityMatrix)
1368
1369 // Create convert functions for internal usage.
1370 CREATE_CONVERT_FN(KernelInfo)
1371
1372 // Create convert functions for testing.
1373 CREATE_CONVERT_FN(Version)
1374 CREATE_CONVERT_FN(KernelConfigTypedValue)
1375 CREATE_CONVERT_FN(MatrixHal)
1376 CREATE_CONVERT_FN(ManifestHal)
1377
1378 #undef CREATE_CONVERT_FN
1379
1380 } // namespace vintf
1381 } // namespace android
1382