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()) {
468 *error = "transport == " + ::android::vintf::to_string(object->transport) +
469 " and arch == " + ::android::vintf::to_string(object->arch) +
470 " is not a valid combination.";
471 return false;
472 }
473 return true;
474 }
475 };
476
477 TransportArchConverter transportArchConverter{};
478
479 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter480 std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter481 void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
482 appendAttr(root, "type", object.mType);
483 appendText(root, ::android::vintf::to_string(object), d);
484 }
buildObjectandroid::vintf::KernelConfigTypedValueConverter485 bool buildObject(KernelConfigTypedValue* object, NodeType* root,
486 std::string* error) const override {
487 std::string stringValue;
488 if (!parseAttr(root, "type", &object->mType, error) ||
489 !parseText(root, &stringValue, error)) {
490 return false;
491 }
492 if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
493 *error = "Could not parse kernel config value \"" + stringValue + "\"";
494 return false;
495 }
496 return true;
497 }
498 };
499
500 KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
501
502 XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
503 "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
504 std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
505
506 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter507 std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter508 void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
509 appendTextElement(root, "name", intf.name(), d);
510 appendTextElements(root, "instance", intf.mInstances, d);
511 appendTextElements(root, "regex-instance", intf.mRegexes, d);
512 }
buildObjectandroid::vintf::HalInterfaceConverter513 bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
514 std::vector<std::string> instances;
515 std::vector<std::string> regexes;
516 if (!parseTextElement(root, "name", &intf->mName, error) ||
517 !parseTextElements(root, "instance", &instances, error) ||
518 !parseTextElements(root, "regex-instance", ®exes, error)) {
519 return false;
520 }
521 bool success = true;
522 for (const auto& e : instances) {
523 if (!intf->insertInstance(e, false /* isRegex */)) {
524 if (!error->empty()) *error += "\n";
525 *error += "Duplicated instance '" + e + "' in " + intf->name();
526 success = false;
527 }
528 }
529 for (const auto& e : regexes) {
530 details::Regex regex;
531 if (!regex.compile(e)) {
532 if (!error->empty()) *error += "\n";
533 *error += "Invalid regular expression '" + e + "' in " + intf->name();
534 success = false;
535 }
536 if (!intf->insertInstance(e, true /* isRegex */)) {
537 if (!error->empty()) *error += "\n";
538 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
539 success = false;
540 }
541 }
542 return success;
543 }
544 };
545
546 HalInterfaceConverter halInterfaceConverter{};
547
548 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter549 std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter550 void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
551 appendAttr(root, "format", hal.format);
552 appendAttr(root, "optional", hal.optional);
553 appendTextElement(root, "name", hal.name, d);
554 // Don't write <version> for format="aidl"
555 if (hal.format != HalFormat::AIDL) {
556 appendChildren(root, versionRangeConverter, hal.versionRanges, d);
557 }
558 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
559 }
buildObjectandroid::vintf::MatrixHalConverter560 bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
561 std::vector<HalInterface> interfaces;
562 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
563 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
564 error) ||
565 !parseTextElement(root, "name", &object->name, error) ||
566 !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
567 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
568 return false;
569 }
570 if (object->format == HalFormat::AIDL) {
571 if (!object->versionRanges.empty()) {
572 LOG(WARNING) << "Ignoring <version> on matrix <hal format=\"aidl\"> "
573 << object->name;
574 object->versionRanges.clear();
575 }
576 // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
577 // HAL formats can be unified.
578 object->versionRanges.push_back(details::kFakeAidlVersionRange);
579 }
580 for (auto&& interface : interfaces) {
581 std::string name{interface.name()};
582 auto res = object->interfaces.emplace(std::move(name), std::move(interface));
583 if (!res.second) {
584 *error = "Duplicated interface entry \"" + res.first->first +
585 "\"; if additional instances are needed, add them to the "
586 "existing <interface> node.";
587 return false;
588 }
589 }
590 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
591 #ifndef LIBVINTF_TARGET
592 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
593 return false;
594 }
595 #endif
596 return true;
597 }
598
599 #ifndef LIBVINTF_TARGET
600 private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter601 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
602 if (hal.getName() == "netutils-wrapper") {
603 if (hal.versionRanges.size() != 1) {
604 *error =
605 "netutils-wrapper HAL must specify exactly one version x.0, "
606 "but multiple <version> element is specified.";
607 return false;
608 }
609 const VersionRange& v = hal.versionRanges.at(0);
610 if (!v.isSingleVersion()) {
611 *error =
612 "netutils-wrapper HAL must specify exactly one version x.0, "
613 "but a range is provided. Perhaps you mean '" +
614 to_string(Version{v.majorVer, 0}) + "'?";
615 return false;
616 }
617 if (v.minMinor != 0) {
618 *error =
619 "netutils-wrapper HAL must specify exactly one version x.0, "
620 "but minor version is not 0. Perhaps you mean '" +
621 to_string(Version{v.majorVer, 0}) + "'?";
622 return false;
623 }
624 }
625 return true;
626 }
627 #endif
628 };
629
630 MatrixHalConverter matrixHalConverter{};
631
632 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter633 std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter634 void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
635 DocType* d) const override {
636 appendChildren(root, matrixKernelConfigConverter, conds, d);
637 }
buildObjectandroid::vintf::MatrixKernelConditionsConverter638 bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
639 std::string* error) const override {
640 return parseChildren(root, matrixKernelConfigConverter, object, error);
641 }
642 };
643
644 MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
645
646 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter647 std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter648 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
649 mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
650 }
mutateNodeandroid::vintf::MatrixKernelConverter651 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
652 SerializeFlags::Type flags) const override {
653 KernelVersion kv = kernel.mMinLts;
654 if (!flags.isKernelMinorRevisionEnabled()) {
655 kv.minorRev = 0u;
656 }
657 appendAttr(root, "version", kv);
658
659 if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
660 appendAttr(root, "level", kernel.getSourceMatrixLevel());
661 }
662
663 if (!kernel.mConditions.empty()) {
664 appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
665 }
666 if (flags.isKernelConfigsEnabled()) {
667 appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
668 }
669 }
buildObjectandroid::vintf::MatrixKernelConverter670 bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
671 Level sourceMatrixLevel = Level::UNSPECIFIED;
672 if (!parseAttr(root, "version", &object->mMinLts, error) ||
673 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
674 !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
675 error) ||
676 !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
677 return false;
678 }
679 object->setSourceMatrixLevel(sourceMatrixLevel);
680 return true;
681 }
682 };
683
684 MatrixKernelConverter matrixKernelConverter{};
685
686 XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
687
688 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter689 std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter690 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
691 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
692 }
mutateNodeandroid::vintf::ManifestHalConverter693 void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
694 SerializeFlags::Type flags) const override {
695 appendAttr(root, "format", hal.format);
696 appendTextElement(root, "name", hal.name, d);
697 if (!hal.transportArch.empty()) {
698 appendChild(root, transportArchConverter(hal.transportArch, d));
699 }
700 // Don't output <version> for format="aidl"
701 if (hal.format != HalFormat::AIDL) {
702 appendChildren(root, versionConverter, hal.versions, d);
703 }
704 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
705 if (hal.isOverride()) {
706 appendAttr(root, "override", hal.isOverride());
707 }
708
709 if (flags.isFqnameEnabled()) {
710 std::set<std::string> simpleFqInstances;
711 hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
712 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
713 return true;
714 });
715 appendTextElements(root, fqInstanceConverter.elementName(), simpleFqInstances, d);
716 }
717 }
buildObjectandroid::vintf::ManifestHalConverter718 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
719 std::vector<HalInterface> interfaces;
720 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
721 !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
722 !parseTextElement(root, "name", &object->name, error) ||
723 !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
724 !parseChildren(root, versionConverter, &object->versions, error) ||
725 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
726 return false;
727 }
728
729 switch (object->format) {
730 case HalFormat::HIDL: {
731 if (object->transportArch.empty()) {
732 *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
733 return false;
734 }
735 } break;
736 case HalFormat::NATIVE: {
737 if (!object->transportArch.empty()) {
738 *error =
739 "Native HAL '" + object->name + "' should not have <transport> defined.";
740 return false;
741 }
742 } break;
743 case HalFormat::AIDL: {
744 if (!object->transportArch.empty()) {
745 LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
746 << object->name;
747 object->transportArch = {};
748 }
749 if (!object->versions.empty()) {
750 LOG(WARNING) << "Ignoring <version> on manifest <hal format=\"aidl\"> "
751 << object->name;
752 object->versions.clear();
753 }
754 // Insert fake version for AIDL HALs so that forEachInstance works.
755 object->versions.push_back(details::kFakeAidlVersion);
756 } break;
757 default: {
758 LOG(FATAL) << "Unhandled HalFormat "
759 << static_cast<typename std::underlying_type<HalFormat>::type>(
760 object->format);
761 } break;
762 }
763 if (!object->transportArch.isValid()) return false;
764
765 object->interfaces.clear();
766 for (auto &&interface : interfaces) {
767 auto res = object->interfaces.emplace(interface.name(), std::move(interface));
768 if (!res.second) {
769 *error = "Duplicated interface entry \"" + res.first->first +
770 "\"; if additional instances are needed, add them to the "
771 "existing <interface> node.";
772 return false;
773 }
774 }
775 if (!object->isValid()) {
776 *error = "'" + object->name + "' is not a valid Manifest HAL.";
777 return false;
778 }
779 // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
780 #ifndef LIBVINTF_TARGET
781 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
782 return false;
783 }
784 #endif
785
786 std::set<FqInstance> fqInstances;
787 if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
788 return false;
789 }
790 std::set<FqInstance> fqInstancesToInsert;
791 for (auto& e : fqInstances) {
792 if (e.hasPackage()) {
793 *error = "Should not specify package: \"" + e.string() + "\"";
794 return false;
795 }
796 if (object->format == HalFormat::AIDL) {
797 // <fqname> in AIDL HALs should not contain version. Put in the fake
798 // kFakeAidlVersion so that compatibility check works.
799 FqInstance withFakeVersion;
800 if (!withFakeVersion.setTo(details::kFakeAidlVersion.majorVer,
801 details::kFakeAidlVersion.minorVer, e.getInterface(),
802 e.getInstance())) {
803 return false;
804 }
805 fqInstancesToInsert.emplace(std::move(withFakeVersion));
806 } else {
807 fqInstancesToInsert.emplace(std::move(e));
808 }
809 }
810 if (!object->insertInstances(fqInstancesToInsert, error)) {
811 return false;
812 }
813
814 return true;
815 }
816
817 #ifndef LIBVINTF_TARGET
818 private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter819 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
820 if (hal.getName() == "netutils-wrapper") {
821 for (const Version& v : hal.versions) {
822 if (v.minorVer != 0) {
823 *error =
824 "netutils-wrapper HAL must specify exactly one version x.0, "
825 "but minor version is not 0. Perhaps you mean '" +
826 to_string(Version{v.majorVer, 0}) + "'?";
827 return false;
828 }
829 }
830 }
831 return true;
832 }
833 #endif
834 };
835
836 // Convert ManifestHal from and to XML. Returned object is guaranteed to have
837 // .isValid() == true.
838 ManifestHalConverter manifestHalConverter{};
839
840 XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
841 XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
842
843 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter844 std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter845 void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
846 appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
847 appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
848 }
buildObjectandroid::vintf::SepolicyConverter849 bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
850 if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
851 error) ||
852 !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
853 error)) {
854 return false;
855 }
856 return true;
857 }
858 };
859 SepolicyConverter sepolicyConverter{};
860
861 [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
862
863 XmlTextConverter<std::string> vndkVersionConverter{"version"};
864 XmlTextConverter<std::string> vndkLibraryConverter{"library"};
865
866 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter867 std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter868 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
869 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
870 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
871 }
buildObjectandroid::vintf::VndkConverter872 bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
873 if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
874 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
875 return false;
876 }
877 return true;
878 }
879 };
880
881 [[deprecated]] VndkConverter vndkConverter{};
882
883 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter884 std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter885 void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
886 appendChild(root, vndkVersionConverter(object.mVersion, d));
887 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
888 }
buildObjectandroid::vintf::VendorNdkConverter889 bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
890 if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
891 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
892 return false;
893 }
894 return true;
895 }
896 };
897
898 VendorNdkConverter vendorNdkConverter{};
899
900 XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
901
902 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter903 std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter904 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
905 appendChildren(root, systemSdkVersionConverter, object.versions(), d);
906 }
buildObjectandroid::vintf::SystemSdkConverter907 bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
908 return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
909 }
910 };
911
912 SystemSdkConverter systemSdkConverter{};
913
914 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::HalManifestSepolicyConverter915 std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter916 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
917 appendChild(root, versionConverter(m, d));
918 }
buildObjectandroid::vintf::HalManifestSepolicyConverter919 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
920 return parseChild(root, versionConverter, object, error);
921 }
922 };
923 HalManifestSepolicyConverter halManifestSepolicyConverter{};
924
925 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter926 std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter927 void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
928 appendTextElement(root, "name", f.name(), d);
929 appendChild(root, versionConverter(f.version(), d));
930 if (!f.overriddenPath().empty()) {
931 appendTextElement(root, "path", f.overriddenPath(), d);
932 }
933 }
buildObjectandroid::vintf::ManifestXmlFileConverter934 bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
935 if (!parseTextElement(root, "name", &object->mName, error) ||
936 !parseChild(root, versionConverter, &object->mVersion, error) ||
937 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
938 return false;
939 }
940 return true;
941 }
942 };
943 ManifestXmlFileConverter manifestXmlFileConverter{};
944
945 XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
946 "config", std::make_unique<XmlTextConverter<std::string>>("key"),
947 std::make_unique<XmlTextConverter<std::string>>("value")};
948
949 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter950 std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter951 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
952 mutateNode(o, root, d, SerializeFlags::EVERYTHING);
953 }
mutateNodeandroid::vintf::KernelInfoConverter954 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
955 SerializeFlags::Type flags) const override {
956 if (o.version() != KernelVersion{}) {
957 appendAttr(root, "version", o.version());
958 }
959 if (o.level() != Level::UNSPECIFIED) {
960 appendAttr(root, "target-level", o.level());
961 }
962 if (flags.isKernelConfigsEnabled()) {
963 appendChildren(root, kernelConfigConverter, o.configs(), d);
964 }
965 }
buildObjectandroid::vintf::KernelInfoConverter966 bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
967 return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
968 parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
969 parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
970 }
971 };
972
973 KernelInfoConverter kernelInfoConverter{};
974
975 struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter976 std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter977 void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
978 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
979 }
mutateNodeandroid::vintf::HalManifestConverter980 void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
981 SerializeFlags::Type flags) const override {
982 if (flags.isMetaVersionEnabled()) {
983 appendAttr(root, "version", m.getMetaVersion());
984 }
985 if (flags.isSchemaTypeEnabled()) {
986 appendAttr(root, "type", m.mType);
987 }
988
989 if (flags.isHalsEnabled()) {
990 appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
991 }
992 if (m.mType == SchemaType::DEVICE) {
993 if (flags.isSepolicyEnabled()) {
994 if (m.device.mSepolicyVersion != Version{}) {
995 appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
996 }
997 }
998 if (m.mLevel != Level::UNSPECIFIED) {
999 this->appendAttr(root, "target-level", m.mLevel);
1000 }
1001
1002 if (flags.isKernelEnabled()) {
1003 if (!!m.kernel()) {
1004 appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
1005 }
1006 }
1007 } else if (m.mType == SchemaType::FRAMEWORK) {
1008 if (flags.isVndkEnabled()) {
1009 #pragma clang diagnostic push
1010 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1011 appendChildren(root, vndkConverter, m.framework.mVndks, d);
1012 #pragma clang diagnostic pop
1013
1014 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
1015 }
1016 if (flags.isSsdkEnabled()) {
1017 if (!m.framework.mSystemSdk.empty()) {
1018 appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
1019 }
1020 }
1021 }
1022
1023 if (flags.isXmlFilesEnabled()) {
1024 appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
1025 }
1026 }
buildObjectandroid::vintf::HalManifestConverter1027 bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
1028 Version metaVersion;
1029 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1030 if (metaVersion > kMetaVersion) {
1031 *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1032 to_string(kMetaVersion) + ")";
1033 return false;
1034 }
1035
1036 std::vector<ManifestHal> hals;
1037 if (!parseAttr(root, "type", &object->mType, error) ||
1038 !parseChildren(root, manifestHalConverter, &hals, error)) {
1039 return false;
1040 }
1041 if (object->mType == SchemaType::DEVICE) {
1042 // tags for device hal manifest only.
1043 // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1044 // in the XML file.
1045 if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
1046 &object->device.mSepolicyVersion, error)) {
1047 return false;
1048 }
1049
1050 if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1051 error)) {
1052 return false;
1053 }
1054
1055 if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
1056 return false;
1057 }
1058 } else if (object->mType == SchemaType::FRAMEWORK) {
1059 #pragma clang diagnostic push
1060 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1061 if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
1062 return false;
1063 }
1064 for (const auto &vndk : object->framework.mVndks) {
1065 if (!vndk.mVersionRange.isSingleVersion()) {
1066 *error = "vndk.version " + to_string(vndk.mVersionRange) +
1067 " cannot be a range for manifests";
1068 return false;
1069 }
1070 }
1071 #pragma clang diagnostic pop
1072
1073 if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
1074 return false;
1075 }
1076
1077 std::set<std::string> vendorNdkVersions;
1078 for (const auto& vendorNdk : object->framework.mVendorNdks) {
1079 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1080 *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1081 return false;
1082 }
1083 vendorNdkVersions.insert(vendorNdk.version());
1084 }
1085
1086 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
1087 error)) {
1088 return false;
1089 }
1090 }
1091 for (auto &&hal : hals) {
1092 std::string description{hal.name};
1093 if (!object->add(std::move(hal))) {
1094 *error = "Duplicated manifest.hal entry " + description;
1095 return false;
1096 }
1097 }
1098
1099 std::vector<ManifestXmlFile> xmlFiles;
1100 if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
1101 return false;
1102 }
1103 for (auto&& xmlFile : xmlFiles) {
1104 std::string description{xmlFile.name()};
1105 if (!object->addXmlFile(std::move(xmlFile))) {
1106 *error = "Duplicated manifest.xmlfile entry " + description +
1107 "; entries cannot have duplicated name and version";
1108 return false;
1109 }
1110 }
1111
1112 return true;
1113 }
1114 };
1115
1116 HalManifestConverter halManifestConverter{};
1117
1118 XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
1119 struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1120 std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1121 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1122 appendChild(root, avbVersionConverter(m, d));
1123 }
buildObjectandroid::vintf::AvbConverter1124 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1125 return parseChild(root, avbVersionConverter, object, error);
1126 }
1127 };
1128 AvbConverter avbConverter{};
1129
1130 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1131 std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1132 void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1133 appendTextElement(root, "name", f.name(), d);
1134 appendAttr(root, "format", f.format());
1135 appendAttr(root, "optional", f.optional());
1136 appendChild(root, versionRangeConverter(f.versionRange(), d));
1137 if (!f.overriddenPath().empty()) {
1138 appendTextElement(root, "path", f.overriddenPath(), d);
1139 }
1140 }
buildObjectandroid::vintf::MatrixXmlFileConverter1141 bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1142 if (!parseTextElement(root, "name", &object->mName, error) ||
1143 !parseAttr(root, "format", &object->mFormat, error) ||
1144 !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1145 !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
1146 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
1147 return false;
1148 }
1149 return true;
1150 }
1151 };
1152 MatrixXmlFileConverter matrixXmlFileConverter{};
1153
1154 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1155 std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1156 void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
1157 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
1158 }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1159 void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
1160 SerializeFlags::Type flags) const override {
1161 if (flags.isMetaVersionEnabled()) {
1162 appendAttr(root, "version", kMetaVersion);
1163 }
1164 if (flags.isSchemaTypeEnabled()) {
1165 appendAttr(root, "type", m.mType);
1166 }
1167
1168 if (flags.isHalsEnabled()) {
1169 appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
1170 }
1171 if (m.mType == SchemaType::FRAMEWORK) {
1172 if (flags.isKernelEnabled()) {
1173 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
1174 }
1175 if (flags.isSepolicyEnabled()) {
1176 if (!(m.framework.mSepolicy == Sepolicy{})) {
1177 appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
1178 }
1179 }
1180 if (flags.isAvbEnabled()) {
1181 if (!(m.framework.mAvbMetaVersion == Version{})) {
1182 appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
1183 }
1184 }
1185 if (m.mLevel != Level::UNSPECIFIED) {
1186 this->appendAttr(root, "level", m.mLevel);
1187 }
1188 } else if (m.mType == SchemaType::DEVICE) {
1189 if (flags.isVndkEnabled()) {
1190 #pragma clang diagnostic push
1191 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1192 if (!(m.device.mVndk == Vndk{})) {
1193 appendChild(root, vndkConverter(m.device.mVndk, d));
1194 }
1195 #pragma clang diagnostic pop
1196
1197 if (!(m.device.mVendorNdk == VendorNdk{})) {
1198 appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
1199 }
1200 }
1201
1202 if (flags.isSsdkEnabled()) {
1203 if (!m.device.mSystemSdk.empty()) {
1204 appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
1205 }
1206 }
1207 }
1208
1209 if (flags.isXmlFilesEnabled()) {
1210 appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
1211 }
1212 }
buildObjectandroid::vintf::CompatibilityMatrixConverter1213 bool buildObject(CompatibilityMatrix* object, NodeType* root,
1214 std::string* error) const override {
1215 Version metaVersion;
1216 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1217 if (metaVersion > kMetaVersion) {
1218 *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1219 " (libvintf@" + to_string(kMetaVersion) + ")";
1220 return false;
1221 }
1222
1223 std::vector<MatrixHal> hals;
1224 if (!parseAttr(root, "type", &object->mType, error) ||
1225 !parseChildren(root, matrixHalConverter, &hals, error)) {
1226 return false;
1227 }
1228
1229 if (object->mType == SchemaType::FRAMEWORK) {
1230 // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1231 // hard-coded in the XML file.
1232 if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1233 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1234 error) ||
1235 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1236 error)) {
1237 return false;
1238 }
1239
1240 std::set<Version> seenKernelVersions;
1241 for (const auto& kernel : object->framework.mKernels) {
1242 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1243 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1244 continue;
1245 }
1246 if (!kernel.conditions().empty()) {
1247 *error = "First <kernel> for version " + to_string(minLts) +
1248 " must have empty <conditions> for backwards compatibility.";
1249 return false;
1250 }
1251 seenKernelVersions.insert(minLts);
1252 }
1253
1254 if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1255 return false;
1256 }
1257
1258 } else if (object->mType == SchemaType::DEVICE) {
1259 // <vndk> can be missing because it can be determined at build time, not hard-coded
1260 // in the XML file.
1261 #pragma clang diagnostic push
1262 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1263 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
1264 return false;
1265 }
1266 #pragma clang diagnostic pop
1267
1268 if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1269 error)) {
1270 return false;
1271 }
1272
1273 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1274 error)) {
1275 return false;
1276 }
1277 }
1278
1279 for (auto &&hal : hals) {
1280 if (!object->add(std::move(hal))) {
1281 *error = "Duplicated compatibility-matrix.hal entry";
1282 return false;
1283 }
1284 }
1285
1286 std::vector<MatrixXmlFile> xmlFiles;
1287 if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
1288 return false;
1289 }
1290 for (auto&& xmlFile : xmlFiles) {
1291 if (!xmlFile.optional()) {
1292 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1293 " has to be optional for compatibility matrix version 1.0";
1294 return false;
1295 }
1296 std::string description{xmlFile.name()};
1297 if (!object->addXmlFile(std::move(xmlFile))) {
1298 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1299 return false;
1300 }
1301 }
1302
1303 return true;
1304 }
1305 };
1306
1307 CompatibilityMatrixConverter compatibilityMatrixConverter{};
1308
1309 // Publicly available as in parse_xml.h
1310 XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1311 XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
1312
1313 // For testing in LibVintfTest
1314 XmlConverter<Version>& gVersionConverter = versionConverter;
1315 XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1316 kernelConfigTypedValueConverter;
1317 XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1318 XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
1319 XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
1320
1321 } // namespace vintf
1322 } // namespace android
1323