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-private.h"
30 #include "constants.h"
31 #include "parse_string.h"
32
33 namespace android {
34 namespace vintf {
35
36 // --------------- tinyxml2 details
37
38 using NodeType = tinyxml2::XMLElement;
39 using DocType = tinyxml2::XMLDocument;
40
41 // caller is responsible for deleteDocument() call
createDocument()42 inline DocType *createDocument() {
43 return new tinyxml2::XMLDocument();
44 }
45
46 // caller is responsible for deleteDocument() call
createDocument(const std::string & xml)47 inline DocType *createDocument(const std::string &xml) {
48 DocType *doc = new tinyxml2::XMLDocument();
49 if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
50 return doc;
51 }
52 delete doc;
53 return nullptr;
54 }
55
deleteDocument(DocType * d)56 inline void deleteDocument(DocType *d) {
57 delete d;
58 }
59
printDocument(DocType * d)60 inline std::string printDocument(DocType *d) {
61 tinyxml2::XMLPrinter p;
62 d->Print(&p);
63 return std::string{p.CStr()};
64 }
65
createNode(const std::string & name,DocType * d)66 inline NodeType *createNode(const std::string &name, DocType *d) {
67 return d->NewElement(name.c_str());
68 }
69
appendChild(NodeType * parent,NodeType * child)70 inline void appendChild(NodeType *parent, NodeType *child) {
71 parent->InsertEndChild(child);
72 }
73
appendChild(DocType * parent,NodeType * child)74 inline void appendChild(DocType *parent, NodeType *child) {
75 parent->InsertEndChild(child);
76 }
77
appendStrAttr(NodeType * e,const std::string & attrName,const std::string & attr)78 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
79 e->SetAttribute(attrName.c_str(), attr.c_str());
80 }
81
82 // text -> text
appendText(NodeType * parent,const std::string & text,DocType * d)83 inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
84 parent->InsertEndChild(d->NewText(text.c_str()));
85 }
86
nameOf(NodeType * root)87 inline std::string nameOf(NodeType *root) {
88 return root->Name() == NULL ? "" : root->Name();
89 }
90
getText(NodeType * root)91 inline std::string getText(NodeType *root) {
92 return root->GetText() == NULL ? "" : root->GetText();
93 }
94
getChild(NodeType * parent,const std::string & name)95 inline NodeType *getChild(NodeType *parent, const std::string &name) {
96 return parent->FirstChildElement(name.c_str());
97 }
98
getRootChild(DocType * parent)99 inline NodeType *getRootChild(DocType *parent) {
100 return parent->FirstChildElement();
101 }
102
getChildren(NodeType * parent,const std::string & name)103 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
104 std::vector<NodeType *> v;
105 for (NodeType *child = parent->FirstChildElement(name.c_str());
106 child != nullptr;
107 child = child->NextSiblingElement(name.c_str())) {
108 v.push_back(child);
109 }
110 return v;
111 }
112
getAttr(NodeType * root,const std::string & attrName,std::string * s)113 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
114 const char *c = root->Attribute(attrName.c_str());
115 if (c == NULL)
116 return false;
117 *s = c;
118 return true;
119 }
120
121 // --------------- tinyxml2 details end.
122
123 // Helper functions for XmlConverter
parse(const std::string & attrText,bool * attr)124 static bool parse(const std::string &attrText, bool *attr) {
125 if (attrText == "true" || attrText == "1") {
126 *attr = true;
127 return true;
128 }
129 if (attrText == "false" || attrText == "0") {
130 *attr = false;
131 return true;
132 }
133 return false;
134 }
135
136 // ---------------------- XmlNodeConverter definitions
137
138 template<typename Object>
139 struct XmlNodeConverter : public XmlConverter<Object> {
XmlNodeConverterandroid::vintf::XmlNodeConverter140 XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter141 virtual ~XmlNodeConverter() {}
142
143 // sub-types should implement these.
144 virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
mutateNodeandroid::vintf::XmlNodeConverter145 virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
146 mutateNode(o, n, d);
147 }
148 virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
149 virtual std::string elementName() const = 0;
150
151 // convenience methods for user
lastErrorandroid::vintf::XmlNodeConverter152 inline const std::string& lastError() const override { return mLastError; }
serializeandroid::vintf::XmlNodeConverter153 inline NodeType* serialize(const Object& o, DocType* d,
154 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
155 NodeType *root = createNode(this->elementName(), d);
156 this->mutateNode(o, root, d, flags);
157 return root;
158 }
serializeandroid::vintf::XmlNodeConverter159 inline std::string serialize(const Object& o, SerializeFlags::Type flags) const override {
160 DocType *doc = createDocument();
161 appendChild(doc, serialize(o, doc, flags));
162 std::string s = printDocument(doc);
163 deleteDocument(doc);
164 return s;
165 }
deserializeandroid::vintf::XmlNodeConverter166 inline bool deserialize(Object* object, NodeType* root) {
167 bool ret = deserialize(object, root, &mLastError);
168 return ret;
169 }
deserializeandroid::vintf::XmlNodeConverter170 inline bool deserialize(Object* o, const std::string& xml) override {
171 bool ret = (*this)(o, xml, &mLastError);
172 return ret;
173 }
deserializeandroid::vintf::XmlNodeConverter174 inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
175 if (nameOf(root) != this->elementName()) {
176 return false;
177 }
178 return this->buildObject(object, root, error);
179 }
operator ()android::vintf::XmlNodeConverter180 inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
181 std::string errorBuffer;
182 if (error == nullptr) error = &errorBuffer;
183
184 auto doc = createDocument(xml);
185 if (doc == nullptr) {
186 *error = "Not a valid XML";
187 return false;
188 }
189 bool ret = deserialize(o, getRootChild(doc), error);
190 deleteDocument(doc);
191 return ret;
192 }
operator ()android::vintf::XmlNodeConverter193 inline NodeType *operator()(const Object &o, DocType *d) const {
194 return serialize(o, d);
195 }
operator ()android::vintf::XmlNodeConverter196 inline std::string operator()(const Object& o, SerializeFlags::Type flags) const override {
197 return serialize(o, flags);
198 }
operator ()android::vintf::XmlNodeConverter199 inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
operator ()android::vintf::XmlNodeConverter200 inline bool operator()(Object* o, const std::string& xml) override {
201 return deserialize(o, xml);
202 }
203
204 // convenience methods for implementor.
205
206 // All append* functions helps mutateNode() to serialize the object into XML.
207 template <typename T>
appendAttrandroid::vintf::XmlNodeConverter208 inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
209 return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
210 }
211
appendAttrandroid::vintf::XmlNodeConverter212 inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
213 return appendStrAttr(e, attrName, attr ? "true" : "false");
214 }
215
216 // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter217 inline void appendTextElement(NodeType *parent, const std::string &name,
218 const std::string &text, DocType *d) const {
219 NodeType *c = createNode(name, d);
220 appendText(c, text, d);
221 appendChild(parent, c);
222 }
223
224 // text -> <name>text</name>
225 template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter226 inline void appendTextElements(NodeType *parent, const std::string &name,
227 const Array &array, DocType *d) const {
228 for (const std::string &text : array) {
229 NodeType *c = createNode(name, d);
230 appendText(c, text, d);
231 appendChild(parent, c);
232 }
233 }
234
235 template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter236 inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
237 const Array& array, DocType* d,
238 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
239 for (const T &t : array) {
240 appendChild(parent, conv.serialize(t, d, flags));
241 }
242 }
243
244 // All parse* functions helps buildObject() to deserialize XML to the object. Returns
245 // true if deserialization is successful, false if any error, and "error" will be
246 // set to error message.
247 template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter248 inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
249 T* attr, std::string* /* error */) const {
250 std::string attrText;
251 bool success = getAttr(root, attrName, &attrText) &&
252 ::android::vintf::parse(attrText, attr);
253 if (!success) {
254 *attr = std::move(defaultValue);
255 }
256 return true;
257 }
258
259 template <typename T>
parseAttrandroid::vintf::XmlNodeConverter260 inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
261 std::string* error) const {
262 std::string attrText;
263 bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
264 if (!ret) {
265 *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
266 attrText + "\" for element <" + elementName() + ">";
267 }
268 return ret;
269 }
270
parseAttrandroid::vintf::XmlNodeConverter271 inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
272 std::string* error) const {
273 bool ret = getAttr(root, attrName, attr);
274 if (!ret) {
275 *error = "Could not find attr with name \"" + attrName + "\" for element <" +
276 elementName() + ">";
277 }
278 return ret;
279 }
280
parseTextElementandroid::vintf::XmlNodeConverter281 inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
282 std::string* error) const {
283 NodeType *child = getChild(root, elementName);
284 if (child == nullptr) {
285 *error = "Could not find element with name <" + elementName + "> in element <" +
286 this->elementName() + ">";
287 return false;
288 }
289 *s = getText(child);
290 return true;
291 }
292
parseOptionalTextElementandroid::vintf::XmlNodeConverter293 inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
294 std::string&& defaultValue, std::string* s,
295 std::string* /* error */) const {
296 NodeType* child = getChild(root, elementName);
297 *s = child == nullptr ? std::move(defaultValue) : getText(child);
298 return true;
299 }
300
parseTextElementsandroid::vintf::XmlNodeConverter301 inline bool parseTextElements(NodeType* root, const std::string& elementName,
302 std::vector<std::string>* v, std::string* /* error */) const {
303 auto nodes = getChildren(root, elementName);
304 v->resize(nodes.size());
305 for (size_t i = 0; i < nodes.size(); ++i) {
306 v->at(i) = getText(nodes[i]);
307 }
308 return true;
309 }
310
311 template <typename T>
parseChildandroid::vintf::XmlNodeConverter312 inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
313 std::string* error) const {
314 NodeType *child = getChild(root, conv.elementName());
315 if (child == nullptr) {
316 *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
317 this->elementName() + ">";
318 return false;
319 }
320 return conv.deserialize(t, child, error);
321 }
322
323 template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter324 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
325 T&& defaultValue, T* t, std::string* error) const {
326 NodeType *child = getChild(root, conv.elementName());
327 if (child == nullptr) {
328 *t = std::move(defaultValue);
329 return true;
330 }
331 return conv.deserialize(t, child, error);
332 }
333
334 template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter335 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
336 std::optional<T>* t, std::string* error) const {
337 NodeType* child = getChild(root, conv.elementName());
338 if (child == nullptr) {
339 *t = std::nullopt;
340 return true;
341 }
342 *t = std::make_optional<T>();
343 return conv.deserialize(&**t, child, error);
344 }
345
346 template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter347 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
348 std::string* error) const {
349 auto nodes = getChildren(root, conv.elementName());
350 v->resize(nodes.size());
351 for (size_t i = 0; i < nodes.size(); ++i) {
352 if (!conv.deserialize(&v->at(i), nodes[i], error)) {
353 *error = "Could not parse element with name <" + conv.elementName() +
354 "> in element <" + this->elementName() + ">: " + *error;
355 return false;
356 }
357 }
358 return true;
359 }
360
361 template <typename Container, typename T = typename Container::value_type,
362 typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter363 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
364 std::string* error) const {
365 std::vector<T> vec;
366 if (!parseChildren(root, conv, &vec, error)) {
367 return false;
368 }
369 s->clear();
370 s->insert(vec.begin(), vec.end());
371 if (s->size() != vec.size()) {
372 *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
373 this->elementName() + ">";
374 s->clear();
375 return false;
376 }
377 return true;
378 }
379
380 template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter381 inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
382 std::map<K, V>* s, std::string* error) const {
383 return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
384 }
385
parseTextandroid::vintf::XmlNodeConverter386 inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
387 *s = getText(node);
388 return true;
389 }
390
391 template <typename T>
parseTextandroid::vintf::XmlNodeConverter392 inline bool parseText(NodeType* node, T* s, std::string* error) const {
393 std::string text = getText(node);
394 bool ret = ::android::vintf::parse(text, s);
395 if (!ret) {
396 *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
397 }
398 return ret;
399 }
400
401 private:
402 mutable std::string mLastError;
403 };
404
405 template<typename Object>
406 struct XmlTextConverter : public XmlNodeConverter<Object> {
XmlTextConverterandroid::vintf::XmlTextConverter407 XmlTextConverter(const std::string &elementName)
408 : mElementName(elementName) {}
409
mutateNodeandroid::vintf::XmlTextConverter410 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
411 appendText(root, ::android::vintf::to_string(object), d);
412 }
buildObjectandroid::vintf::XmlTextConverter413 virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
414 return this->parseText(root, object, error);
415 }
elementNameandroid::vintf::XmlTextConverter416 virtual std::string elementName() const { return mElementName; }
417
418 private:
419 std::string mElementName;
420 };
421
422 template <typename Pair>
423 struct XmlPairConverter : public XmlNodeConverter<Pair> {
XmlPairConverterandroid::vintf::XmlPairConverter424 XmlPairConverter(
425 const std::string& elementName,
426 std::unique_ptr<XmlNodeConverter<typename Pair::first_type>>&& firstConverter,
427 std::unique_ptr<XmlNodeConverter<typename Pair::second_type>>&& secondConverter)
428 : mElementName(elementName),
429 mFirstConverter(std::move(firstConverter)),
430 mSecondConverter(std::move(secondConverter)) {}
431
mutateNodeandroid::vintf::XmlPairConverter432 virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
433 appendChild(root, mFirstConverter->serialize(pair.first, d));
434 appendChild(root, mSecondConverter->serialize(pair.second, d));
435 }
buildObjectandroid::vintf::XmlPairConverter436 virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
437 return this->parseChild(root, *mFirstConverter, &pair->first, error) &&
438 this->parseChild(root, *mSecondConverter, &pair->second, error);
439 }
elementNameandroid::vintf::XmlPairConverter440 virtual std::string elementName() const { return mElementName; }
441
442 private:
443 std::string mElementName;
444 std::unique_ptr<XmlNodeConverter<typename Pair::first_type>> mFirstConverter;
445 std::unique_ptr<XmlNodeConverter<typename Pair::second_type>> mSecondConverter;
446 };
447
448 // ---------------------- XmlNodeConverter definitions end
449
450 XmlTextConverter<Version> versionConverter{"version"};
451
452 XmlTextConverter<VersionRange> versionRangeConverter{"version"};
453
454 struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter455 std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter456 void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
457 if (object.arch != Arch::ARCH_EMPTY) {
458 appendAttr(root, "arch", object.arch);
459 }
460 appendText(root, ::android::vintf::to_string(object.transport), d);
461 }
buildObjectandroid::vintf::TransportArchConverter462 bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
463 if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
464 !parseText(root, &object->transport, error)) {
465 return false;
466 }
467 if (!object->isValid(error)) {
468 return false;
469 }
470 return true;
471 }
472 };
473
474 TransportArchConverter transportArchConverter{};
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 KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
498
499 XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
500 "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
501 std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
502
503 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter504 std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter505 void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
506 appendTextElement(root, "name", intf.name(), d);
507 appendTextElements(root, "instance", intf.mInstances, d);
508 appendTextElements(root, "regex-instance", intf.mRegexes, d);
509 }
buildObjectandroid::vintf::HalInterfaceConverter510 bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
511 std::vector<std::string> instances;
512 std::vector<std::string> regexes;
513 if (!parseTextElement(root, "name", &intf->mName, error) ||
514 !parseTextElements(root, "instance", &instances, error) ||
515 !parseTextElements(root, "regex-instance", ®exes, error)) {
516 return false;
517 }
518 bool success = true;
519 for (const auto& e : instances) {
520 if (!intf->insertInstance(e, false /* isRegex */)) {
521 if (!error->empty()) *error += "\n";
522 *error += "Duplicated instance '" + e + "' in " + intf->name();
523 success = false;
524 }
525 }
526 for (const auto& e : regexes) {
527 details::Regex regex;
528 if (!regex.compile(e)) {
529 if (!error->empty()) *error += "\n";
530 *error += "Invalid regular expression '" + e + "' in " + intf->name();
531 success = false;
532 }
533 if (!intf->insertInstance(e, true /* isRegex */)) {
534 if (!error->empty()) *error += "\n";
535 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
536 success = false;
537 }
538 }
539 return success;
540 }
541 };
542
543 HalInterfaceConverter halInterfaceConverter{};
544
545 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter546 std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter547 void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
548 appendAttr(root, "format", hal.format);
549 appendAttr(root, "optional", hal.optional);
550 appendTextElement(root, "name", hal.name, d);
551 // Don't write <version> for format="aidl"
552 if (hal.format != HalFormat::AIDL) {
553 appendChildren(root, versionRangeConverter, hal.versionRanges, d);
554 }
555 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
556 }
buildObjectandroid::vintf::MatrixHalConverter557 bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
558 std::vector<HalInterface> interfaces;
559 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
560 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
561 error) ||
562 !parseTextElement(root, "name", &object->name, error) ||
563 !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
564 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
565 return false;
566 }
567 if (object->format == HalFormat::AIDL) {
568 if (!object->versionRanges.empty()) {
569 LOG(WARNING) << "Ignoring <version> on matrix <hal format=\"aidl\"> "
570 << object->name;
571 object->versionRanges.clear();
572 }
573 // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
574 // HAL formats can be unified.
575 object->versionRanges.push_back(details::kFakeAidlVersionRange);
576 }
577 for (auto&& interface : interfaces) {
578 std::string name{interface.name()};
579 auto res = object->interfaces.emplace(std::move(name), std::move(interface));
580 if (!res.second) {
581 *error = "Duplicated interface entry \"" + res.first->first +
582 "\"; if additional instances are needed, add them to the "
583 "existing <interface> node.";
584 return false;
585 }
586 }
587 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
588 #ifndef LIBVINTF_TARGET
589 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
590 return false;
591 }
592 #endif
593 return true;
594 }
595
596 #ifndef LIBVINTF_TARGET
597 private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter598 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
599 if (hal.getName() == "netutils-wrapper") {
600 if (hal.versionRanges.size() != 1) {
601 *error =
602 "netutils-wrapper HAL must specify exactly one version x.0, "
603 "but multiple <version> element is specified.";
604 return false;
605 }
606 const VersionRange& v = hal.versionRanges.at(0);
607 if (!v.isSingleVersion()) {
608 *error =
609 "netutils-wrapper HAL must specify exactly one version x.0, "
610 "but a range is provided. Perhaps you mean '" +
611 to_string(Version{v.majorVer, 0}) + "'?";
612 return false;
613 }
614 if (v.minMinor != 0) {
615 *error =
616 "netutils-wrapper HAL must specify exactly one version x.0, "
617 "but minor version is not 0. Perhaps you mean '" +
618 to_string(Version{v.majorVer, 0}) + "'?";
619 return false;
620 }
621 }
622 return true;
623 }
624 #endif
625 };
626
627 MatrixHalConverter matrixHalConverter{};
628
629 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter630 std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter631 void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
632 DocType* d) const override {
633 appendChildren(root, matrixKernelConfigConverter, conds, d);
634 }
buildObjectandroid::vintf::MatrixKernelConditionsConverter635 bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
636 std::string* error) const override {
637 return parseChildren(root, matrixKernelConfigConverter, object, error);
638 }
639 };
640
641 MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
642
643 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter644 std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter645 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
646 mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
647 }
mutateNodeandroid::vintf::MatrixKernelConverter648 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
649 SerializeFlags::Type flags) const override {
650 KernelVersion kv = kernel.mMinLts;
651 if (!flags.isKernelMinorRevisionEnabled()) {
652 kv.minorRev = 0u;
653 }
654 appendAttr(root, "version", kv);
655
656 if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
657 appendAttr(root, "level", kernel.getSourceMatrixLevel());
658 }
659
660 if (!kernel.mConditions.empty()) {
661 appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
662 }
663 if (flags.isKernelConfigsEnabled()) {
664 appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
665 }
666 }
buildObjectandroid::vintf::MatrixKernelConverter667 bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
668 Level sourceMatrixLevel = Level::UNSPECIFIED;
669 if (!parseAttr(root, "version", &object->mMinLts, error) ||
670 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
671 !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
672 error) ||
673 !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
674 return false;
675 }
676 object->setSourceMatrixLevel(sourceMatrixLevel);
677 return true;
678 }
679 };
680
681 MatrixKernelConverter matrixKernelConverter{};
682
683 XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
684
685 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter686 std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter687 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
688 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
689 }
mutateNodeandroid::vintf::ManifestHalConverter690 void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
691 SerializeFlags::Type flags) const override {
692 appendAttr(root, "format", hal.format);
693 appendTextElement(root, "name", hal.name, d);
694 if (!hal.transportArch.empty()) {
695 appendChild(root, transportArchConverter(hal.transportArch, d));
696 }
697 // Don't output <version> for format="aidl"
698 if (hal.format != HalFormat::AIDL) {
699 appendChildren(root, versionConverter, hal.versions, d);
700 }
701 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
702 if (hal.isOverride()) {
703 appendAttr(root, "override", hal.isOverride());
704 }
705
706 if (flags.isFqnameEnabled()) {
707 std::set<std::string> simpleFqInstances;
708 hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
709 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
710 return true;
711 });
712 appendTextElements(root, fqInstanceConverter.elementName(), simpleFqInstances, d);
713 }
714 }
buildObjectandroid::vintf::ManifestHalConverter715 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
716 std::vector<HalInterface> interfaces;
717 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
718 !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
719 !parseTextElement(root, "name", &object->name, error) ||
720 !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
721 !parseChildren(root, versionConverter, &object->versions, error) ||
722 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
723 return false;
724 }
725
726 switch (object->format) {
727 case HalFormat::HIDL: {
728 if (object->transportArch.empty()) {
729 *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
730 return false;
731 }
732 } break;
733 case HalFormat::NATIVE: {
734 if (!object->transportArch.empty()) {
735 *error =
736 "Native HAL '" + object->name + "' should not have <transport> defined.";
737 return false;
738 }
739 } break;
740 case HalFormat::AIDL: {
741 if (!object->transportArch.empty()) {
742 LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
743 << object->name;
744 object->transportArch = {};
745 }
746 if (!object->versions.empty()) {
747 LOG(WARNING) << "Ignoring <version> on manifest <hal format=\"aidl\"> "
748 << object->name;
749 object->versions.clear();
750 }
751 // Insert fake version for AIDL HALs so that forEachInstance works.
752 object->versions.push_back(details::kFakeAidlVersion);
753 } break;
754 default: {
755 LOG(FATAL) << "Unhandled HalFormat "
756 << static_cast<typename std::underlying_type<HalFormat>::type>(
757 object->format);
758 } break;
759 }
760 if (!object->transportArch.isValid(error)) return false;
761
762 object->interfaces.clear();
763 for (auto &&interface : interfaces) {
764 auto res = object->interfaces.emplace(interface.name(), std::move(interface));
765 if (!res.second) {
766 *error = "Duplicated interface entry \"" + res.first->first +
767 "\"; if additional instances are needed, add them to the "
768 "existing <interface> node.";
769 return false;
770 }
771 }
772 if (!object->isValid(error)) {
773 error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
774 return false;
775 }
776 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
777 #ifndef LIBVINTF_TARGET
778 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
779 return false;
780 }
781 #endif
782
783 std::set<FqInstance> fqInstances;
784 if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
785 return false;
786 }
787 std::set<FqInstance> fqInstancesToInsert;
788 for (auto& e : fqInstances) {
789 if (e.hasPackage()) {
790 *error = "Should not specify package: \"" + e.string() + "\"";
791 return false;
792 }
793 if (object->format == HalFormat::AIDL) {
794 // <fqname> in AIDL HALs should not contain version. Put in the fake
795 // kFakeAidlVersion so that compatibility check works.
796 FqInstance withFakeVersion;
797 if (!withFakeVersion.setTo(details::kFakeAidlVersion.majorVer,
798 details::kFakeAidlVersion.minorVer, e.getInterface(),
799 e.getInstance())) {
800 return false;
801 }
802 fqInstancesToInsert.emplace(std::move(withFakeVersion));
803 } else {
804 fqInstancesToInsert.emplace(std::move(e));
805 }
806 }
807 if (!object->insertInstances(fqInstancesToInsert, error)) {
808 return false;
809 }
810
811 return true;
812 }
813
814 #ifndef LIBVINTF_TARGET
815 private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter816 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
817 if (hal.getName() == "netutils-wrapper") {
818 for (const Version& v : hal.versions) {
819 if (v.minorVer != 0) {
820 *error =
821 "netutils-wrapper HAL must specify exactly one version x.0, "
822 "but minor version is not 0. Perhaps you mean '" +
823 to_string(Version{v.majorVer, 0}) + "'?";
824 return false;
825 }
826 }
827 }
828 return true;
829 }
830 #endif
831 };
832
833 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
834 // .isValid() == true.
835 ManifestHalConverter manifestHalConverter{};
836
837 XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
838 XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
839
840 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter841 std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter842 void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
843 appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
844 appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
845 }
buildObjectandroid::vintf::SepolicyConverter846 bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
847 if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
848 error) ||
849 !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
850 error)) {
851 return false;
852 }
853 return true;
854 }
855 };
856 SepolicyConverter sepolicyConverter{};
857
858 [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
859
860 XmlTextConverter<std::string> vndkVersionConverter{"version"};
861 XmlTextConverter<std::string> vndkLibraryConverter{"library"};
862
863 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter864 std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter865 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
866 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
867 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
868 }
buildObjectandroid::vintf::VndkConverter869 bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
870 if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
871 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
872 return false;
873 }
874 return true;
875 }
876 };
877
878 [[deprecated]] VndkConverter vndkConverter{};
879
880 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter881 std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter882 void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
883 appendChild(root, vndkVersionConverter(object.mVersion, d));
884 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
885 }
buildObjectandroid::vintf::VendorNdkConverter886 bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
887 if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
888 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
889 return false;
890 }
891 return true;
892 }
893 };
894
895 VendorNdkConverter vendorNdkConverter{};
896
897 XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
898
899 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter900 std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter901 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
902 appendChildren(root, systemSdkVersionConverter, object.versions(), d);
903 }
buildObjectandroid::vintf::SystemSdkConverter904 bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
905 return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
906 }
907 };
908
909 SystemSdkConverter systemSdkConverter{};
910
911 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter912 std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter913 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
914 appendChild(root, versionConverter(m, d));
915 }
buildObjectandroid::vintf::HalManifestSepolicyConverter916 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
917 return parseChild(root, versionConverter, object, error);
918 }
919 };
920 HalManifestSepolicyConverter halManifestSepolicyConverter{};
921
922 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter923 std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter924 void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
925 appendTextElement(root, "name", f.name(), d);
926 appendChild(root, versionConverter(f.version(), d));
927 if (!f.overriddenPath().empty()) {
928 appendTextElement(root, "path", f.overriddenPath(), d);
929 }
930 }
buildObjectandroid::vintf::ManifestXmlFileConverter931 bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
932 if (!parseTextElement(root, "name", &object->mName, error) ||
933 !parseChild(root, versionConverter, &object->mVersion, error) ||
934 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
935 return false;
936 }
937 return true;
938 }
939 };
940 ManifestXmlFileConverter manifestXmlFileConverter{};
941
942 XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
943 "config", std::make_unique<XmlTextConverter<std::string>>("key"),
944 std::make_unique<XmlTextConverter<std::string>>("value")};
945
946 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter947 std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter948 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
949 mutateNode(o, root, d, SerializeFlags::EVERYTHING);
950 }
mutateNodeandroid::vintf::KernelInfoConverter951 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
952 SerializeFlags::Type flags) const override {
953 if (o.version() != KernelVersion{}) {
954 appendAttr(root, "version", o.version());
955 }
956 if (o.level() != Level::UNSPECIFIED) {
957 appendAttr(root, "target-level", o.level());
958 }
959 if (flags.isKernelConfigsEnabled()) {
960 appendChildren(root, kernelConfigConverter, o.configs(), d);
961 }
962 }
buildObjectandroid::vintf::KernelInfoConverter963 bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
964 return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
965 parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
966 parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
967 }
968 };
969
970 KernelInfoConverter kernelInfoConverter{};
971
972 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter973 std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter974 void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
975 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
976 }
mutateNodeandroid::vintf::HalManifestConverter977 void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
978 SerializeFlags::Type flags) const override {
979 if (flags.isMetaVersionEnabled()) {
980 appendAttr(root, "version", m.getMetaVersion());
981 }
982 if (flags.isSchemaTypeEnabled()) {
983 appendAttr(root, "type", m.mType);
984 }
985
986 if (flags.isHalsEnabled()) {
987 appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
988 }
989 if (m.mType == SchemaType::DEVICE) {
990 if (flags.isSepolicyEnabled()) {
991 if (m.device.mSepolicyVersion != Version{}) {
992 appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
993 }
994 }
995 if (m.mLevel != Level::UNSPECIFIED) {
996 this->appendAttr(root, "target-level", m.mLevel);
997 }
998
999 if (flags.isKernelEnabled()) {
1000 if (!!m.kernel()) {
1001 appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
1002 }
1003 }
1004 } else if (m.mType == SchemaType::FRAMEWORK) {
1005 if (flags.isVndkEnabled()) {
1006 #pragma clang diagnostic push
1007 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1008 appendChildren(root, vndkConverter, m.framework.mVndks, d);
1009 #pragma clang diagnostic pop
1010
1011 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
1012 }
1013 if (flags.isSsdkEnabled()) {
1014 if (!m.framework.mSystemSdk.empty()) {
1015 appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
1016 }
1017 }
1018 }
1019
1020 if (flags.isXmlFilesEnabled()) {
1021 appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
1022 }
1023 }
buildObjectandroid::vintf::HalManifestConverter1024 bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
1025 Version metaVersion;
1026 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1027 if (metaVersion > kMetaVersion) {
1028 *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1029 to_string(kMetaVersion) + ")";
1030 return false;
1031 }
1032
1033 if (!parseAttr(root, "type", &object->mType, error)) {
1034 return false;
1035 }
1036
1037 std::vector<ManifestHal> hals;
1038 if (!parseChildren(root, manifestHalConverter, &hals, error)) {
1039 return false;
1040 }
1041 for (auto&& hal : hals) {
1042 hal.setFileName(object->fileName());
1043 }
1044
1045 if (object->mType == SchemaType::DEVICE) {
1046 // tags for device hal manifest only.
1047 // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1048 // in the XML file.
1049 if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
1050 &object->device.mSepolicyVersion, error)) {
1051 return false;
1052 }
1053
1054 if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1055 error)) {
1056 return false;
1057 }
1058
1059 if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
1060 return false;
1061 }
1062 } else if (object->mType == SchemaType::FRAMEWORK) {
1063 #pragma clang diagnostic push
1064 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1065 if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
1066 return false;
1067 }
1068 for (const auto &vndk : object->framework.mVndks) {
1069 if (!vndk.mVersionRange.isSingleVersion()) {
1070 *error = "vndk.version " + to_string(vndk.mVersionRange) +
1071 " cannot be a range for manifests";
1072 return false;
1073 }
1074 }
1075 #pragma clang diagnostic pop
1076
1077 if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
1078 return false;
1079 }
1080
1081 std::set<std::string> vendorNdkVersions;
1082 for (const auto& vendorNdk : object->framework.mVendorNdks) {
1083 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1084 *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1085 return false;
1086 }
1087 vendorNdkVersions.insert(vendorNdk.version());
1088 }
1089
1090 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
1091 error)) {
1092 return false;
1093 }
1094 }
1095 for (auto &&hal : hals) {
1096 std::string description{hal.name};
1097 if (!object->add(std::move(hal))) {
1098 *error = "Duplicated manifest.hal entry " + description;
1099 return false;
1100 }
1101 }
1102
1103 std::vector<ManifestXmlFile> xmlFiles;
1104 if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
1105 return false;
1106 }
1107 for (auto&& xmlFile : xmlFiles) {
1108 std::string description{xmlFile.name()};
1109 if (!object->addXmlFile(std::move(xmlFile))) {
1110 *error = "Duplicated manifest.xmlfile entry " + description +
1111 "; entries cannot have duplicated name and version";
1112 return false;
1113 }
1114 }
1115
1116 return true;
1117 }
1118 };
1119
1120 HalManifestConverter halManifestConverter{};
1121
1122 XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
1123 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1124 std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1125 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1126 appendChild(root, avbVersionConverter(m, d));
1127 }
buildObjectandroid::vintf::AvbConverter1128 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1129 return parseChild(root, avbVersionConverter, object, error);
1130 }
1131 };
1132 AvbConverter avbConverter{};
1133
1134 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1135 std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1136 void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1137 appendTextElement(root, "name", f.name(), d);
1138 appendAttr(root, "format", f.format());
1139 appendAttr(root, "optional", f.optional());
1140 appendChild(root, versionRangeConverter(f.versionRange(), d));
1141 if (!f.overriddenPath().empty()) {
1142 appendTextElement(root, "path", f.overriddenPath(), d);
1143 }
1144 }
buildObjectandroid::vintf::MatrixXmlFileConverter1145 bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1146 if (!parseTextElement(root, "name", &object->mName, error) ||
1147 !parseAttr(root, "format", &object->mFormat, error) ||
1148 !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1149 !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
1150 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1151 return false;
1152 }
1153 return true;
1154 }
1155 };
1156 MatrixXmlFileConverter matrixXmlFileConverter{};
1157
1158 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1159 std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1160 void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1161 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1162 }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1163 void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1164 SerializeFlags::Type flags) const override {
1165 if (flags.isMetaVersionEnabled()) {
1166 appendAttr(root, "version", kMetaVersion);
1167 }
1168 if (flags.isSchemaTypeEnabled()) {
1169 appendAttr(root, "type", m.mType);
1170 }
1171
1172 if (flags.isHalsEnabled()) {
1173 appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
1174 }
1175 if (m.mType == SchemaType::FRAMEWORK) {
1176 if (flags.isKernelEnabled()) {
1177 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
1178 }
1179 if (flags.isSepolicyEnabled()) {
1180 if (!(m.framework.mSepolicy == Sepolicy{})) {
1181 appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
1182 }
1183 }
1184 if (flags.isAvbEnabled()) {
1185 if (!(m.framework.mAvbMetaVersion == Version{})) {
1186 appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
1187 }
1188 }
1189 if (m.mLevel != Level::UNSPECIFIED) {
1190 this->appendAttr(root, "level", m.mLevel);
1191 }
1192 } else if (m.mType == SchemaType::DEVICE) {
1193 if (flags.isVndkEnabled()) {
1194 #pragma clang diagnostic push
1195 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1196 if (!(m.device.mVndk == Vndk{})) {
1197 appendChild(root, vndkConverter(m.device.mVndk, d));
1198 }
1199 #pragma clang diagnostic pop
1200
1201 if (!(m.device.mVendorNdk == VendorNdk{})) {
1202 appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
1203 }
1204 }
1205
1206 if (flags.isSsdkEnabled()) {
1207 if (!m.device.mSystemSdk.empty()) {
1208 appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
1209 }
1210 }
1211 }
1212
1213 if (flags.isXmlFilesEnabled()) {
1214 appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
1215 }
1216 }
buildObjectandroid::vintf::CompatibilityMatrixConverter1217 bool buildObject(CompatibilityMatrix* object, NodeType* root,
1218 std::string* error) const override {
1219 Version metaVersion;
1220 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1221 if (metaVersion > kMetaVersion) {
1222 *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1223 " (libvintf@" + to_string(kMetaVersion) + ")";
1224 return false;
1225 }
1226
1227 std::vector<MatrixHal> hals;
1228 if (!parseAttr(root, "type", &object->mType, error) ||
1229 !parseChildren(root, matrixHalConverter, &hals, error)) {
1230 return false;
1231 }
1232
1233 if (object->mType == SchemaType::FRAMEWORK) {
1234 // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1235 // hard-coded in the XML file.
1236 if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1237 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1238 error) ||
1239 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1240 error)) {
1241 return false;
1242 }
1243
1244 std::set<Version> seenKernelVersions;
1245 for (const auto& kernel : object->framework.mKernels) {
1246 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1247 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1248 continue;
1249 }
1250 if (!kernel.conditions().empty()) {
1251 *error = "First <kernel> for version " + to_string(minLts) +
1252 " must have empty <conditions> for backwards compatibility.";
1253 return false;
1254 }
1255 seenKernelVersions.insert(minLts);
1256 }
1257
1258 if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1259 return false;
1260 }
1261
1262 } else if (object->mType == SchemaType::DEVICE) {
1263 // <vndk> can be missing because it can be determined at build time, not hard-coded
1264 // in the XML file.
1265 #pragma clang diagnostic push
1266 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1267 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
1268 return false;
1269 }
1270 #pragma clang diagnostic pop
1271
1272 if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1273 error)) {
1274 return false;
1275 }
1276
1277 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1278 error)) {
1279 return false;
1280 }
1281 }
1282
1283 for (auto &&hal : hals) {
1284 if (!object->add(std::move(hal))) {
1285 *error = "Duplicated compatibility-matrix.hal entry";
1286 return false;
1287 }
1288 }
1289
1290 std::vector<MatrixXmlFile> xmlFiles;
1291 if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
1292 return false;
1293 }
1294 for (auto&& xmlFile : xmlFiles) {
1295 if (!xmlFile.optional()) {
1296 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1297 " has to be optional for compatibility matrix version 1.0";
1298 return false;
1299 }
1300 std::string description{xmlFile.name()};
1301 if (!object->addXmlFile(std::move(xmlFile))) {
1302 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1303 return false;
1304 }
1305 }
1306
1307 return true;
1308 }
1309 };
1310
1311 CompatibilityMatrixConverter compatibilityMatrixConverter{};
1312
1313 // Publicly available as in parse_xml.h
1314 XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1315 XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
1316
1317 // For testing in LibVintfTest
1318 XmlConverter<Version>& gVersionConverter = versionConverter;
1319 XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1320 kernelConfigTypedValueConverter;
1321 XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1322 XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
1323 XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
1324
1325 } // namespace vintf
1326 } // namespace android
1327