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