1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Convert objects from and to xml. 18 19 #define LOG_TAG "libvintf" 20 #include <android-base/logging.h> 21 22 #include "parse_xml.h" 23 24 #include <type_traits> 25 26 #include <android-base/parseint.h> 27 #include <android-base/strings.h> 28 #include <tinyxml2.h> 29 30 #include "Regex.h" 31 #include "constants-private.h" 32 #include "constants.h" 33 #include "parse_string.h" 34 #include "parse_xml_for_test.h" 35 36 using namespace std::string_literals; 37 38 namespace android { 39 namespace vintf { 40 41 // --------------- tinyxml2 details 42 43 using NodeType = tinyxml2::XMLElement; 44 using DocType = tinyxml2::XMLDocument; 45 46 // caller is responsible for deleteDocument() call 47 inline DocType *createDocument() { 48 return new tinyxml2::XMLDocument(); 49 } 50 51 // caller is responsible for deleteDocument() call 52 inline DocType *createDocument(const std::string &xml) { 53 DocType *doc = new tinyxml2::XMLDocument(); 54 if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) { 55 return doc; 56 } 57 delete doc; 58 return nullptr; 59 } 60 61 inline void deleteDocument(DocType *d) { 62 delete d; 63 } 64 65 inline std::string printDocument(DocType *d) { 66 tinyxml2::XMLPrinter p; 67 d->Print(&p); 68 return std::string{p.CStr()}; 69 } 70 71 inline NodeType *createNode(const std::string &name, DocType *d) { 72 return d->NewElement(name.c_str()); 73 } 74 75 inline void appendChild(NodeType *parent, NodeType *child) { 76 parent->InsertEndChild(child); 77 } 78 79 inline void appendChild(DocType *parent, NodeType *child) { 80 parent->InsertEndChild(child); 81 } 82 83 inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) { 84 e->SetAttribute(attrName.c_str(), attr.c_str()); 85 } 86 87 // text -> text 88 inline void appendText(NodeType *parent, const std::string &text, DocType *d) { 89 parent->InsertEndChild(d->NewText(text.c_str())); 90 } 91 92 inline std::string nameOf(NodeType *root) { 93 return root->Name() == NULL ? "" : root->Name(); 94 } 95 96 inline std::string getText(NodeType *root) { 97 return root->GetText() == NULL ? "" : root->GetText(); 98 } 99 100 inline NodeType *getChild(NodeType *parent, const std::string &name) { 101 return parent->FirstChildElement(name.c_str()); 102 } 103 104 inline NodeType *getRootChild(DocType *parent) { 105 return parent->FirstChildElement(); 106 } 107 108 inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) { 109 std::vector<NodeType *> v; 110 for (NodeType *child = parent->FirstChildElement(name.c_str()); 111 child != nullptr; 112 child = child->NextSiblingElement(name.c_str())) { 113 v.push_back(child); 114 } 115 return v; 116 } 117 118 inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) { 119 const char *c = root->Attribute(attrName.c_str()); 120 if (c == NULL) 121 return false; 122 *s = c; 123 return true; 124 } 125 126 // --------------- tinyxml2 details end. 127 128 // Helper functions for XmlConverter 129 static bool parse(const std::string &attrText, bool *attr) { 130 if (attrText == "true" || attrText == "1") { 131 *attr = true; 132 return true; 133 } 134 if (attrText == "false" || attrText == "0") { 135 *attr = false; 136 return true; 137 } 138 return false; 139 } 140 141 static bool parse(const std::string& attrText, std::optional<std::string>* attr) { 142 *attr = attrText; 143 return true; 144 } 145 146 // ---------------------- XmlNodeConverter definitions 147 148 template <typename Object> 149 struct XmlNodeConverter { 150 XmlNodeConverter() {} 151 virtual ~XmlNodeConverter() {} 152 153 // sub-types should implement these. 154 virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0; 155 virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const { 156 mutateNode(o, n, d); 157 } 158 virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0; 159 virtual std::string elementName() const = 0; 160 161 // convenience methods for user 162 inline NodeType* operator()(const Object& o, DocType* d, 163 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const { 164 NodeType *root = createNode(this->elementName(), d); 165 this->mutateNode(o, root, d, flags); 166 return root; 167 } 168 inline std::string operator()(const Object& o, SerializeFlags::Type flags) const { 169 DocType *doc = createDocument(); 170 appendChild(doc, (*this)(o, doc, flags)); 171 std::string s = printDocument(doc); 172 deleteDocument(doc); 173 return s; 174 } 175 inline bool operator()(Object* object, NodeType* root, std::string* error) const { 176 if (nameOf(root) != this->elementName()) { 177 return false; 178 } 179 return this->buildObject(object, root, error); 180 } 181 inline bool operator()(Object* o, const std::string& xml, std::string* error) const { 182 std::string errorBuffer; 183 if (error == nullptr) error = &errorBuffer; 184 185 auto doc = createDocument(xml); 186 if (doc == nullptr) { 187 *error = "Not a valid XML"; 188 return false; 189 } 190 bool ret = (*this)(o, getRootChild(doc), error); 191 deleteDocument(doc); 192 return ret; 193 } 194 195 // convenience methods for implementor. 196 197 // All append* functions helps mutateNode() to serialize the object into XML. 198 template <typename T> 199 inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const { 200 return appendStrAttr(e, attrName, ::android::vintf::to_string(attr)); 201 } 202 203 inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const { 204 return appendStrAttr(e, attrName, attr ? "true" : "false"); 205 } 206 207 // text -> <name>text</name> 208 inline void appendTextElement(NodeType *parent, const std::string &name, 209 const std::string &text, DocType *d) const { 210 NodeType *c = createNode(name, d); 211 appendText(c, text, d); 212 appendChild(parent, c); 213 } 214 215 // text -> <name>text</name> 216 template<typename Array> 217 inline void appendTextElements(NodeType *parent, const std::string &name, 218 const Array &array, DocType *d) const { 219 for (const std::string &text : array) { 220 NodeType *c = createNode(name, d); 221 appendText(c, text, d); 222 appendChild(parent, c); 223 } 224 } 225 226 template <typename T, typename Array> 227 inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv, 228 const Array& array, DocType* d, 229 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const { 230 for (const T &t : array) { 231 appendChild(parent, conv(t, d, flags)); 232 } 233 } 234 235 // All parse* functions helps buildObject() to deserialize XML to the object. Returns 236 // true if deserialization is successful, false if any error, and "error" will be 237 // set to error message. 238 template <typename T> 239 inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue, 240 T* attr, std::string* /* error */) const { 241 std::string attrText; 242 bool success = getAttr(root, attrName, &attrText) && 243 ::android::vintf::parse(attrText, attr); 244 if (!success) { 245 *attr = std::move(defaultValue); 246 } 247 return true; 248 } 249 250 template <typename T> 251 inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr, 252 std::string* error) const { 253 std::string attrText; 254 bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr); 255 if (!ret) { 256 *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" + 257 attrText + "\" for element <" + elementName() + ">"; 258 } 259 return ret; 260 } 261 262 inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr, 263 std::string* error) const { 264 bool ret = getAttr(root, attrName, attr); 265 if (!ret) { 266 *error = "Could not find attr with name \"" + attrName + "\" for element <" + 267 elementName() + ">"; 268 } 269 return ret; 270 } 271 272 inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s, 273 std::string* error) const { 274 NodeType *child = getChild(root, elementName); 275 if (child == nullptr) { 276 *error = "Could not find element with name <" + elementName + "> in element <" + 277 this->elementName() + ">"; 278 return false; 279 } 280 *s = getText(child); 281 return true; 282 } 283 284 inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName, 285 std::string&& defaultValue, std::string* s, 286 std::string* /* error */) const { 287 NodeType* child = getChild(root, elementName); 288 *s = child == nullptr ? std::move(defaultValue) : getText(child); 289 return true; 290 } 291 292 inline bool parseTextElements(NodeType* root, const std::string& elementName, 293 std::vector<std::string>* v, std::string* /* error */) const { 294 auto nodes = getChildren(root, elementName); 295 v->resize(nodes.size()); 296 for (size_t i = 0; i < nodes.size(); ++i) { 297 v->at(i) = getText(nodes[i]); 298 } 299 return true; 300 } 301 302 template <typename T> 303 inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t, 304 std::string* error) const { 305 NodeType *child = getChild(root, conv.elementName()); 306 if (child == nullptr) { 307 *error = "Could not find element with name <" + conv.elementName() + "> in element <" + 308 this->elementName() + ">"; 309 return false; 310 } 311 return conv(t, child, error); 312 } 313 314 template <typename T> 315 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv, 316 T&& defaultValue, T* t, std::string* error) const { 317 NodeType *child = getChild(root, conv.elementName()); 318 if (child == nullptr) { 319 *t = std::move(defaultValue); 320 return true; 321 } 322 return conv(t, child, error); 323 } 324 325 template <typename T> 326 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv, 327 std::optional<T>* t, std::string* error) const { 328 NodeType* child = getChild(root, conv.elementName()); 329 if (child == nullptr) { 330 *t = std::nullopt; 331 return true; 332 } 333 *t = std::make_optional<T>(); 334 return conv(&**t, child, error); 335 } 336 337 template <typename T> 338 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v, 339 std::string* error) const { 340 auto nodes = getChildren(root, conv.elementName()); 341 v->resize(nodes.size()); 342 for (size_t i = 0; i < nodes.size(); ++i) { 343 if (!conv(&v->at(i), nodes[i], error)) { 344 *error = "Could not parse element with name <" + conv.elementName() + 345 "> in element <" + this->elementName() + ">: " + *error; 346 return false; 347 } 348 } 349 return true; 350 } 351 352 template <typename Container, typename T = typename Container::value_type, 353 typename = typename Container::key_compare> 354 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s, 355 std::string* error) const { 356 std::vector<T> vec; 357 if (!parseChildren(root, conv, &vec, error)) { 358 return false; 359 } 360 s->clear(); 361 s->insert(vec.begin(), vec.end()); 362 if (s->size() != vec.size()) { 363 *error = "Duplicated elements <" + conv.elementName() + "> in element <" + 364 this->elementName() + ">"; 365 s->clear(); 366 return false; 367 } 368 return true; 369 } 370 371 template <typename K, typename V> 372 inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv, 373 std::map<K, V>* s, std::string* error) const { 374 return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error); 375 } 376 377 inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const { 378 *s = getText(node); 379 return true; 380 } 381 382 template <typename T> 383 inline bool parseText(NodeType* node, T* s, std::string* error) const { 384 bool (*parser)(const std::string&, T*) = ::android::vintf::parse; 385 return parseText(node, s, {parser}, error); 386 } 387 388 template <typename T> 389 inline bool parseText(NodeType* node, T* s, 390 const std::function<bool(const std::string&, T*)>& parse, 391 std::string* error) const { 392 std::string text = getText(node); 393 bool ret = parse(text, s); 394 if (!ret) { 395 *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">"; 396 } 397 return ret; 398 } 399 }; 400 401 template<typename Object> 402 struct XmlTextConverter : public XmlNodeConverter<Object> { 403 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override { 404 appendText(root, ::android::vintf::to_string(object), d); 405 } 406 virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override { 407 return this->parseText(root, object, error); 408 } 409 }; 410 411 template <typename Pair, typename FirstConverter, typename SecondConverter> 412 struct XmlPairConverter : public XmlNodeConverter<Pair> { 413 virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override { 414 appendChild(root, FirstConverter{}(pair.first, d)); 415 appendChild(root, SecondConverter{}(pair.second, d)); 416 } 417 virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override { 418 return this->parseChild(root, FirstConverter{}, &pair->first, error) && 419 this->parseChild(root, SecondConverter{}, &pair->second, error); 420 } 421 }; 422 423 // ---------------------- XmlNodeConverter definitions end 424 425 struct VersionConverter : public XmlTextConverter<Version> { 426 std::string elementName() const override { return "version"; } 427 }; 428 429 struct VersionRangeConverter : public XmlTextConverter<VersionRange> { 430 std::string elementName() const override { return "version"; } 431 }; 432 433 // <version>100</version> <=> Version{kFakeAidlMajorVersion, 100} 434 struct AidlVersionConverter : public XmlNodeConverter<Version> { 435 std::string elementName() const override { return "version"; } 436 void mutateNode(const Version& object, NodeType* root, DocType* d) const override { 437 appendText(root, aidlVersionToString(object), d); 438 } 439 bool buildObject(Version* object, NodeType* root, std::string* error) const override { 440 return parseText(root, object, {parseAidlVersion}, error); 441 } 442 }; 443 444 // <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100} 445 // <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105} 446 struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> { 447 std::string elementName() const override { return "version"; } 448 void mutateNode(const VersionRange& object, NodeType* root, DocType* d) const override { 449 appendText(root, aidlVersionRangeToString(object), d); 450 } 451 bool buildObject(VersionRange* object, NodeType* root, std::string* error) const override { 452 return parseText(root, object, {parseAidlVersionRange}, error); 453 } 454 }; 455 456 struct TransportArchConverter : public XmlNodeConverter<TransportArch> { 457 std::string elementName() const override { return "transport"; } 458 void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override { 459 if (object.arch != Arch::ARCH_EMPTY) { 460 appendAttr(root, "arch", object.arch); 461 } 462 appendText(root, ::android::vintf::to_string(object.transport), d); 463 } 464 bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override { 465 if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) || 466 !parseText(root, &object->transport, error)) { 467 return false; 468 } 469 if (!object->isValid(error)) { 470 return false; 471 } 472 return true; 473 } 474 }; 475 476 struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> { 477 std::string elementName() const override { return "value"; } 478 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 } 482 bool buildObject(KernelConfigTypedValue* object, NodeType* root, 483 std::string* error) const override { 484 std::string stringValue; 485 if (!parseAttr(root, "type", &object->mType, error) || 486 !parseText(root, &stringValue, error)) { 487 return false; 488 } 489 if (!::android::vintf::parseKernelConfigValue(stringValue, object)) { 490 *error = "Could not parse kernel config value \"" + stringValue + "\""; 491 return false; 492 } 493 return true; 494 } 495 }; 496 497 struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> { 498 std::string elementName() const override { return "key"; } 499 }; 500 501 struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter, 502 KernelConfigTypedValueConverter> { 503 std::string elementName() const override { return "config"; } 504 }; 505 506 struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> { 507 std::string elementName() const override { return "interface"; } 508 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 } 513 bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override { 514 std::vector<std::string> instances; 515 std::vector<std::string> regexes; 516 if (!parseTextElement(root, "name", &intf->mName, error) || 517 !parseTextElements(root, "instance", &instances, error) || 518 !parseTextElements(root, "regex-instance", ®exes, error)) { 519 return false; 520 } 521 bool success = true; 522 for (const auto& e : instances) { 523 if (!intf->insertInstance(e, false /* isRegex */)) { 524 if (!error->empty()) *error += "\n"; 525 *error += "Duplicated instance '" + e + "' in " + intf->name(); 526 success = false; 527 } 528 } 529 for (const auto& e : regexes) { 530 details::Regex regex; 531 if (!regex.compile(e)) { 532 if (!error->empty()) *error += "\n"; 533 *error += "Invalid regular expression '" + e + "' in " + intf->name(); 534 success = false; 535 } 536 if (!intf->insertInstance(e, true /* isRegex */)) { 537 if (!error->empty()) *error += "\n"; 538 *error += "Duplicated regex-instance '" + e + "' in " + intf->name(); 539 success = false; 540 } 541 } 542 return success; 543 } 544 }; 545 546 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { 547 std::string elementName() const override { return "hal"; } 548 void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override { 549 appendAttr(root, "format", hal.format); 550 appendAttr(root, "optional", hal.optional); 551 appendTextElement(root, "name", hal.name, d); 552 if (hal.format == HalFormat::AIDL) { 553 // By default, buildObject() assumes a <version>0</version> tag if no <version> tag 554 // is specified. Don't output any <version> tag if there's only one <version>0</version> 555 // tag. 556 if (hal.versionRanges.size() != 1 || 557 hal.versionRanges[0] != details::kDefaultAidlVersionRange) { 558 appendChildren(root, AidlVersionRangeConverter{}, hal.versionRanges, d); 559 } 560 } else { 561 appendChildren(root, VersionRangeConverter{}, hal.versionRanges, d); 562 } 563 appendChildren(root, HalInterfaceConverter{}, iterateValues(hal.interfaces), d); 564 } 565 bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override { 566 std::vector<HalInterface> interfaces; 567 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) || 568 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional, 569 error) || 570 !parseTextElement(root, "name", &object->name, error) || 571 !parseChildren(root, HalInterfaceConverter{}, &interfaces, error)) { 572 return false; 573 } 574 if (object->format == HalFormat::AIDL) { 575 if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, error)) { 576 return false; 577 } 578 // Insert fake version for AIDL HALs so that compatibility check for AIDL and other 579 // HAL formats can be unified. 580 if (object->versionRanges.empty()) { 581 object->versionRanges.push_back(details::kDefaultAidlVersionRange); 582 } 583 } else { 584 if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, error)) { 585 return false; 586 } 587 } 588 for (auto&& interface : interfaces) { 589 std::string name{interface.name()}; 590 auto res = object->interfaces.emplace(std::move(name), std::move(interface)); 591 if (!res.second) { 592 *error = "Duplicated interface entry \"" + res.first->first + 593 "\"; if additional instances are needed, add them to the " 594 "existing <interface> node."; 595 return false; 596 } 597 } 598 // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally. 599 #ifndef LIBVINTF_TARGET 600 if (!checkAdditionalRestrictionsOnHal(*object, error)) { 601 return false; 602 } 603 #endif 604 605 if (!object->isValid(error)) { 606 error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: "); 607 return false; 608 } 609 return true; 610 } 611 612 #ifndef LIBVINTF_TARGET 613 private: 614 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const { 615 if (hal.getName() == "netutils-wrapper") { 616 if (hal.versionRanges.size() != 1) { 617 *error = 618 "netutils-wrapper HAL must specify exactly one version x.0, " 619 "but multiple <version> element is specified."; 620 return false; 621 } 622 const VersionRange& v = hal.versionRanges.at(0); 623 if (!v.isSingleVersion()) { 624 *error = 625 "netutils-wrapper HAL must specify exactly one version x.0, " 626 "but a range is provided. Perhaps you mean '" + 627 to_string(Version{v.majorVer, 0}) + "'?"; 628 return false; 629 } 630 if (v.minMinor != 0) { 631 *error = 632 "netutils-wrapper HAL must specify exactly one version x.0, " 633 "but minor version is not 0. Perhaps you mean '" + 634 to_string(Version{v.majorVer, 0}) + "'?"; 635 return false; 636 } 637 } 638 return true; 639 } 640 #endif 641 }; 642 643 struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> { 644 std::string elementName() const override { return "conditions"; } 645 void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root, 646 DocType* d) const override { 647 appendChildren(root, MatrixKernelConfigConverter{}, conds, d); 648 } 649 bool buildObject(std::vector<KernelConfig>* object, NodeType* root, 650 std::string* error) const override { 651 return parseChildren(root, MatrixKernelConfigConverter{}, object, error); 652 } 653 }; 654 655 struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> { 656 std::string elementName() const override { return "kernel"; } 657 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override { 658 mutateNode(kernel, root, d, SerializeFlags::EVERYTHING); 659 } 660 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d, 661 SerializeFlags::Type flags) const override { 662 KernelVersion kv = kernel.mMinLts; 663 if (!flags.isKernelMinorRevisionEnabled()) { 664 kv.minorRev = 0u; 665 } 666 appendAttr(root, "version", kv); 667 668 if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) { 669 appendAttr(root, "level", kernel.getSourceMatrixLevel()); 670 } 671 672 if (!kernel.mConditions.empty()) { 673 appendChild(root, MatrixKernelConditionsConverter{}(kernel.mConditions, d)); 674 } 675 if (flags.isKernelConfigsEnabled()) { 676 appendChildren(root, MatrixKernelConfigConverter{}, kernel.mConfigs, d); 677 } 678 } 679 bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override { 680 Level sourceMatrixLevel = Level::UNSPECIFIED; 681 if (!parseAttr(root, "version", &object->mMinLts, error) || 682 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) || 683 !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions, 684 error) || 685 !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, error)) { 686 return false; 687 } 688 object->setSourceMatrixLevel(sourceMatrixLevel); 689 return true; 690 } 691 }; 692 693 struct FqInstanceConverter : public XmlTextConverter<FqInstance> { 694 std::string elementName() const override { return "fqname"; } 695 }; 696 697 // Convert ManifestHal from and to XML. Returned object is guaranteed to have 698 // .isValid() == true. 699 struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { 700 std::string elementName() const override { return "hal"; } 701 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override { 702 mutateNode(m, root, d, SerializeFlags::EVERYTHING); 703 } 704 void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d, 705 SerializeFlags::Type flags) const override { 706 appendAttr(root, "format", hal.format); 707 appendTextElement(root, "name", hal.name, d); 708 if (!hal.transportArch.empty()) { 709 appendChild(root, TransportArchConverter{}(hal.transportArch, d)); 710 } 711 if (hal.format == HalFormat::AIDL) { 712 // By default, buildObject() assumes a <version>0</version> tag if no <version> tag 713 // is specified. Don't output any <version> tag if there's only one <version>0</version> 714 // tag. 715 if (hal.versions.size() != 1 || hal.versions[0] != details::kDefaultAidlVersion) { 716 appendChildren(root, AidlVersionConverter{}, hal.versions, d); 717 } 718 } else { 719 appendChildren(root, VersionConverter{}, hal.versions, d); 720 } 721 appendChildren(root, HalInterfaceConverter{}, iterateValues(hal.interfaces), d); 722 if (hal.isOverride()) { 723 appendAttr(root, "override", hal.isOverride()); 724 } 725 if (const auto& apex = hal.updatableViaApex(); apex.has_value()) { 726 appendAttr(root, "updatable-via-apex", apex.value()); 727 } 728 if (flags.isFqnameEnabled()) { 729 std::set<std::string> simpleFqInstances; 730 hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) { 731 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance()); 732 return true; 733 }); 734 appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances, d); 735 } 736 if (hal.getMaxLevel() != Level::UNSPECIFIED) { 737 appendAttr(root, "max-level", hal.getMaxLevel()); 738 } 739 } 740 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override { 741 std::vector<HalInterface> interfaces; 742 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) || 743 !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) || 744 !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex, error) || 745 !parseTextElement(root, "name", &object->name, error) || 746 !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch, 747 error) || 748 !parseChildren(root, HalInterfaceConverter{}, &interfaces, error) || 749 !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel, error)) { 750 return false; 751 } 752 753 switch (object->format) { 754 case HalFormat::HIDL: { 755 if (!parseChildren(root, VersionConverter{}, &object->versions, error)) 756 return false; 757 if (object->transportArch.empty()) { 758 *error = "HIDL HAL '" + object->name + "' should have <transport> defined."; 759 return false; 760 } 761 } break; 762 case HalFormat::NATIVE: { 763 if (!parseChildren(root, VersionConverter{}, &object->versions, error)) 764 return false; 765 if (!object->transportArch.empty()) { 766 *error = 767 "Native HAL '" + object->name + "' should not have <transport> defined."; 768 return false; 769 } 770 } break; 771 case HalFormat::AIDL: { 772 if (!object->transportArch.empty()) { 773 LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> " 774 << object->name; 775 object->transportArch = {}; 776 } 777 if (!parseChildren(root, AidlVersionConverter{}, &object->versions, error)) { 778 return false; 779 } 780 // Insert fake version for AIDL HALs so that forEachInstance works. 781 if (object->versions.empty()) { 782 object->versions.push_back(details::kDefaultAidlVersion); 783 } 784 } break; 785 default: { 786 LOG(FATAL) << "Unhandled HalFormat " 787 << static_cast<typename std::underlying_type<HalFormat>::type>( 788 object->format); 789 } break; 790 } 791 if (!object->transportArch.isValid(error)) return false; 792 793 object->interfaces.clear(); 794 for (auto &&interface : interfaces) { 795 auto res = object->interfaces.emplace(interface.name(), std::move(interface)); 796 if (!res.second) { 797 *error = "Duplicated interface entry \"" + res.first->first + 798 "\"; if additional instances are needed, add them to the " 799 "existing <interface> node."; 800 return false; 801 } 802 } 803 // Do not check for target-side libvintf to avoid restricting upgrade accidentally. 804 #ifndef LIBVINTF_TARGET 805 if (!checkAdditionalRestrictionsOnHal(*object, error)) { 806 return false; 807 } 808 #endif 809 810 std::set<FqInstance> fqInstances; 811 if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, error)) { 812 return false; 813 } 814 std::set<FqInstance> fqInstancesToInsert; 815 for (auto& e : fqInstances) { 816 if (e.hasPackage()) { 817 *error = "Should not specify package: \"" + e.string() + "\""; 818 return false; 819 } 820 if (object->format == HalFormat::AIDL) { 821 // <fqname> in AIDL HALs should not contain version. 822 if (e.hasVersion()) { 823 *error = "Should not specify version in <fqname> for AIDL HAL: \"" + 824 e.string() + "\""; 825 return false; 826 } 827 // Put in the fake kDefaultAidlVersion so that HalManifest can 828 // store it in an FqInstance object with a non-empty package. 829 FqInstance withFakeVersion; 830 if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer, 831 details::kDefaultAidlVersion.minorVer, e.getInterface(), 832 e.getInstance())) { 833 return false; 834 } 835 fqInstancesToInsert.emplace(std::move(withFakeVersion)); 836 } else { 837 fqInstancesToInsert.emplace(std::move(e)); 838 } 839 } 840 if (!object->insertInstances(fqInstancesToInsert, error)) { 841 return false; 842 } 843 844 if (!object->isValid(error)) { 845 error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: "); 846 return false; 847 } 848 849 return true; 850 } 851 852 #ifndef LIBVINTF_TARGET 853 private: 854 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const { 855 if (hal.getName() == "netutils-wrapper") { 856 for (const Version& v : hal.versions) { 857 if (v.minorVer != 0) { 858 *error = 859 "netutils-wrapper HAL must specify exactly one version x.0, " 860 "but minor version is not 0. Perhaps you mean '" + 861 to_string(Version{v.majorVer, 0}) + "'?"; 862 return false; 863 } 864 } 865 } 866 return true; 867 } 868 #endif 869 }; 870 871 struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> { 872 std::string elementName() const override { return "kernel-sepolicy-version"; } 873 }; 874 875 struct SepolicyVersionConverter : public XmlTextConverter<VersionRange> { 876 std::string elementName() const override { return "sepolicy-version"; } 877 }; 878 879 struct SepolicyConverter : public XmlNodeConverter<Sepolicy> { 880 std::string elementName() const override { return "sepolicy"; } 881 void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override { 882 appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), d)); 883 appendChildren(root, SepolicyVersionConverter{}, object.sepolicyVersions(), d); 884 } 885 bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override { 886 if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion, 887 error) || 888 !parseChildren(root, SepolicyVersionConverter{}, &object->mSepolicyVersionRanges, 889 error)) { 890 return false; 891 } 892 return true; 893 } 894 }; 895 896 struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> { 897 std::string elementName() const override { return "version"; } 898 }; 899 900 struct VndkVersionConverter : public XmlTextConverter<std::string> { 901 std::string elementName() const override { return "version"; } 902 }; 903 904 struct VndkLibraryConverter : public XmlTextConverter<std::string> { 905 std::string elementName() const override { return "library"; } 906 }; 907 908 struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> { 909 std::string elementName() const override { return "vndk"; } 910 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override { 911 appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, d)); 912 appendChildren(root, VndkLibraryConverter{}, object.mLibraries, d); 913 } 914 bool buildObject(Vndk* object, NodeType* root, std::string* error) const override { 915 if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, error) || 916 !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, error)) { 917 return false; 918 } 919 return true; 920 } 921 }; 922 923 struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> { 924 std::string elementName() const override { return "vendor-ndk"; } 925 void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override { 926 appendChild(root, VndkVersionConverter{}(object.mVersion, d)); 927 appendChildren(root, VndkLibraryConverter{}, object.mLibraries, d); 928 } 929 bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override { 930 if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, error) || 931 !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, error)) { 932 return false; 933 } 934 return true; 935 } 936 }; 937 938 struct SystemSdkVersionConverter : public XmlTextConverter<std::string> { 939 std::string elementName() const override { return "version"; } 940 }; 941 942 struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> { 943 std::string elementName() const override { return "system-sdk"; } 944 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override { 945 appendChildren(root, SystemSdkVersionConverter{}, object.versions(), d); 946 } 947 bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override { 948 return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, error); 949 } 950 }; 951 952 struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> { 953 std::string elementName() const override { return "sepolicy"; } 954 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 955 appendChild(root, VersionConverter{}(m, d)); 956 } 957 bool buildObject(Version* object, NodeType* root, std::string* error) const override { 958 return parseChild(root, VersionConverter{}, object, error); 959 } 960 }; 961 962 struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> { 963 std::string elementName() const override { return "xmlfile"; } 964 void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override { 965 appendTextElement(root, "name", f.name(), d); 966 appendChild(root, VersionConverter{}(f.version(), d)); 967 if (!f.overriddenPath().empty()) { 968 appendTextElement(root, "path", f.overriddenPath(), d); 969 } 970 } 971 bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override { 972 if (!parseTextElement(root, "name", &object->mName, error) || 973 !parseChild(root, VersionConverter{}, &object->mVersion, error) || 974 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) { 975 return false; 976 } 977 return true; 978 } 979 }; 980 981 struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> { 982 std::string elementName() const override { return "key"; } 983 }; 984 985 struct KernelConfigValueConverter : public XmlTextConverter<std::string> { 986 std::string elementName() const override { return "value"; } 987 }; 988 989 struct StringKernelConfigConverter 990 : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter, 991 KernelConfigValueConverter> { 992 std::string elementName() const override { return "config"; } 993 }; 994 995 struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> { 996 std::string elementName() const override { return "kernel"; } 997 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override { 998 mutateNode(o, root, d, SerializeFlags::EVERYTHING); 999 } 1000 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d, 1001 SerializeFlags::Type flags) const override { 1002 if (o.version() != KernelVersion{}) { 1003 appendAttr(root, "version", o.version()); 1004 } 1005 if (o.level() != Level::UNSPECIFIED) { 1006 appendAttr(root, "target-level", o.level()); 1007 } 1008 if (flags.isKernelConfigsEnabled()) { 1009 appendChildren(root, StringKernelConfigConverter{}, o.configs(), d); 1010 } 1011 } 1012 bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override { 1013 return parseOptionalAttr(root, "version", {}, &o->mVersion, error) && 1014 parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) && 1015 parseChildren(root, StringKernelConfigConverter{}, &o->mConfigs, error); 1016 } 1017 }; 1018 1019 struct HalManifestConverter : public XmlNodeConverter<HalManifest> { 1020 std::string elementName() const override { return "manifest"; } 1021 void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override { 1022 mutateNode(m, root, d, SerializeFlags::EVERYTHING); 1023 } 1024 void mutateNode(const HalManifest& m, NodeType* root, DocType* d, 1025 SerializeFlags::Type flags) const override { 1026 if (flags.isMetaVersionEnabled()) { 1027 appendAttr(root, "version", m.getMetaVersion()); 1028 } 1029 if (flags.isSchemaTypeEnabled()) { 1030 appendAttr(root, "type", m.mType); 1031 } 1032 1033 if (flags.isHalsEnabled()) { 1034 appendChildren(root, ManifestHalConverter{}, m.getHals(), d, flags); 1035 } 1036 if (m.mType == SchemaType::DEVICE) { 1037 if (flags.isSepolicyEnabled()) { 1038 if (m.device.mSepolicyVersion != Version{}) { 1039 appendChild(root, HalManifestSepolicyConverter{}(m.device.mSepolicyVersion, d)); 1040 } 1041 } 1042 if (m.mLevel != Level::UNSPECIFIED) { 1043 this->appendAttr(root, "target-level", m.mLevel); 1044 } 1045 1046 if (flags.isKernelEnabled()) { 1047 if (!!m.kernel()) { 1048 appendChild(root, KernelInfoConverter{}(*m.kernel(), d, flags)); 1049 } 1050 } 1051 } else if (m.mType == SchemaType::FRAMEWORK) { 1052 if (flags.isVndkEnabled()) { 1053 #pragma clang diagnostic push 1054 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 1055 appendChildren(root, VndkConverter{}, m.framework.mVndks, d); 1056 #pragma clang diagnostic pop 1057 1058 appendChildren(root, VendorNdkConverter{}, m.framework.mVendorNdks, d); 1059 } 1060 if (flags.isSsdkEnabled()) { 1061 if (!m.framework.mSystemSdk.empty()) { 1062 appendChild(root, SystemSdkConverter{}(m.framework.mSystemSdk, d)); 1063 } 1064 } 1065 } 1066 1067 if (flags.isXmlFilesEnabled()) { 1068 appendChildren(root, ManifestXmlFileConverter{}, m.getXmlFiles(), d); 1069 } 1070 } 1071 bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override { 1072 Version metaVersion; 1073 if (!parseAttr(root, "version", &metaVersion, error)) return false; 1074 if (metaVersion > kMetaVersion) { 1075 *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" + 1076 to_string(kMetaVersion) + ")"; 1077 return false; 1078 } 1079 1080 if (!parseAttr(root, "type", &object->mType, error)) { 1081 return false; 1082 } 1083 1084 std::vector<ManifestHal> hals; 1085 if (!parseChildren(root, ManifestHalConverter{}, &hals, error)) { 1086 return false; 1087 } 1088 for (auto&& hal : hals) { 1089 hal.setFileName(object->fileName()); 1090 } 1091 1092 if (object->mType == SchemaType::DEVICE) { 1093 // tags for device hal manifest only. 1094 // <sepolicy> can be missing because it can be determined at build time, not hard-coded 1095 // in the XML file. 1096 if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {}, 1097 &object->device.mSepolicyVersion, error)) { 1098 return false; 1099 } 1100 1101 if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel, 1102 error)) { 1103 return false; 1104 } 1105 1106 if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, error)) { 1107 return false; 1108 } 1109 } else if (object->mType == SchemaType::FRAMEWORK) { 1110 #pragma clang diagnostic push 1111 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 1112 if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, error)) { 1113 return false; 1114 } 1115 for (const auto &vndk : object->framework.mVndks) { 1116 if (!vndk.mVersionRange.isSingleVersion()) { 1117 *error = "vndk.version " + to_string(vndk.mVersionRange) + 1118 " cannot be a range for manifests"; 1119 return false; 1120 } 1121 } 1122 #pragma clang diagnostic pop 1123 1124 if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, error)) { 1125 return false; 1126 } 1127 1128 std::set<std::string> vendorNdkVersions; 1129 for (const auto& vendorNdk : object->framework.mVendorNdks) { 1130 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) { 1131 *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version(); 1132 return false; 1133 } 1134 vendorNdkVersions.insert(vendorNdk.version()); 1135 } 1136 1137 if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk, 1138 error)) { 1139 return false; 1140 } 1141 } 1142 for (auto &&hal : hals) { 1143 std::string description{hal.name}; 1144 if (!object->add(std::move(hal))) { 1145 *error = "Duplicated manifest.hal entry " + description; 1146 return false; 1147 } 1148 } 1149 1150 std::vector<ManifestXmlFile> xmlFiles; 1151 if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, error)) { 1152 return false; 1153 } 1154 for (auto&& xmlFile : xmlFiles) { 1155 std::string description{xmlFile.name()}; 1156 if (!object->addXmlFile(std::move(xmlFile))) { 1157 *error = "Duplicated manifest.xmlfile entry " + description + 1158 "; entries cannot have duplicated name and version"; 1159 return false; 1160 } 1161 } 1162 1163 return true; 1164 } 1165 }; 1166 1167 struct AvbVersionConverter : public XmlTextConverter<Version> { 1168 std::string elementName() const override { return "vbmeta-version"; } 1169 }; 1170 1171 struct AvbConverter : public XmlNodeConverter<Version> { 1172 std::string elementName() const override { return "avb"; } 1173 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 1174 appendChild(root, AvbVersionConverter{}(m, d)); 1175 } 1176 bool buildObject(Version* object, NodeType* root, std::string* error) const override { 1177 return parseChild(root, AvbVersionConverter{}, object, error); 1178 } 1179 }; 1180 1181 struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> { 1182 std::string elementName() const override { return "xmlfile"; } 1183 void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override { 1184 appendTextElement(root, "name", f.name(), d); 1185 appendAttr(root, "format", f.format()); 1186 appendAttr(root, "optional", f.optional()); 1187 appendChild(root, VersionRangeConverter{}(f.versionRange(), d)); 1188 if (!f.overriddenPath().empty()) { 1189 appendTextElement(root, "path", f.overriddenPath(), d); 1190 } 1191 } 1192 bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override { 1193 if (!parseTextElement(root, "name", &object->mName, error) || 1194 !parseAttr(root, "format", &object->mFormat, error) || 1195 !parseOptionalAttr(root, "optional", false, &object->mOptional, error) || 1196 !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, error) || 1197 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) { 1198 return false; 1199 } 1200 return true; 1201 } 1202 }; 1203 1204 struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> { 1205 std::string elementName() const override { return "compatibility-matrix"; } 1206 void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override { 1207 mutateNode(m, root, d, SerializeFlags::EVERYTHING); 1208 } 1209 void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d, 1210 SerializeFlags::Type flags) const override { 1211 if (flags.isMetaVersionEnabled()) { 1212 appendAttr(root, "version", kMetaVersion); 1213 } 1214 if (flags.isSchemaTypeEnabled()) { 1215 appendAttr(root, "type", m.mType); 1216 } 1217 1218 if (flags.isHalsEnabled()) { 1219 appendChildren(root, MatrixHalConverter{}, iterateValues(m.mHals), d); 1220 } 1221 if (m.mType == SchemaType::FRAMEWORK) { 1222 if (flags.isKernelEnabled()) { 1223 appendChildren(root, MatrixKernelConverter{}, m.framework.mKernels, d, flags); 1224 } 1225 if (flags.isSepolicyEnabled()) { 1226 if (!(m.framework.mSepolicy == Sepolicy{})) { 1227 appendChild(root, SepolicyConverter{}(m.framework.mSepolicy, d)); 1228 } 1229 } 1230 if (flags.isAvbEnabled()) { 1231 if (!(m.framework.mAvbMetaVersion == Version{})) { 1232 appendChild(root, AvbConverter{}(m.framework.mAvbMetaVersion, d)); 1233 } 1234 } 1235 if (m.mLevel != Level::UNSPECIFIED) { 1236 this->appendAttr(root, "level", m.mLevel); 1237 } 1238 } else if (m.mType == SchemaType::DEVICE) { 1239 if (flags.isVndkEnabled()) { 1240 #pragma clang diagnostic push 1241 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 1242 if (!(m.device.mVndk == Vndk{})) { 1243 appendChild(root, VndkConverter{}(m.device.mVndk, d)); 1244 } 1245 #pragma clang diagnostic pop 1246 1247 if (!(m.device.mVendorNdk == VendorNdk{})) { 1248 appendChild(root, VendorNdkConverter{}(m.device.mVendorNdk, d)); 1249 } 1250 } 1251 1252 if (flags.isSsdkEnabled()) { 1253 if (!m.device.mSystemSdk.empty()) { 1254 appendChild(root, SystemSdkConverter{}(m.device.mSystemSdk, d)); 1255 } 1256 } 1257 } 1258 1259 if (flags.isXmlFilesEnabled()) { 1260 appendChildren(root, MatrixXmlFileConverter{}, m.getXmlFiles(), d); 1261 } 1262 } 1263 bool buildObject(CompatibilityMatrix* object, NodeType* root, 1264 std::string* error) const override { 1265 Version metaVersion; 1266 if (!parseAttr(root, "version", &metaVersion, error)) return false; 1267 if (metaVersion > kMetaVersion) { 1268 *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) + 1269 " (libvintf@" + to_string(kMetaVersion) + ")"; 1270 return false; 1271 } 1272 1273 std::vector<MatrixHal> hals; 1274 if (!parseAttr(root, "type", &object->mType, error) || 1275 !parseChildren(root, MatrixHalConverter{}, &hals, error)) { 1276 return false; 1277 } 1278 1279 if (object->mType == SchemaType::FRAMEWORK) { 1280 // <avb> and <sepolicy> can be missing because it can be determined at build time, not 1281 // hard-coded in the XML file. 1282 if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, error) || 1283 !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy, 1284 error) || 1285 !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion, 1286 error)) { 1287 return false; 1288 } 1289 1290 std::set<Version> seenKernelVersions; 1291 for (const auto& kernel : object->framework.mKernels) { 1292 Version minLts(kernel.minLts().version, kernel.minLts().majorRev); 1293 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) { 1294 continue; 1295 } 1296 if (!kernel.conditions().empty()) { 1297 *error = "First <kernel> for version " + to_string(minLts) + 1298 " must have empty <conditions> for backwards compatibility."; 1299 return false; 1300 } 1301 seenKernelVersions.insert(minLts); 1302 } 1303 1304 if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) { 1305 return false; 1306 } 1307 1308 } else if (object->mType == SchemaType::DEVICE) { 1309 // <vndk> can be missing because it can be determined at build time, not hard-coded 1310 // in the XML file. 1311 #pragma clang diagnostic push 1312 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 1313 if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, error)) { 1314 return false; 1315 } 1316 #pragma clang diagnostic pop 1317 1318 if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk, 1319 error)) { 1320 return false; 1321 } 1322 1323 if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk, 1324 error)) { 1325 return false; 1326 } 1327 } 1328 1329 for (auto &&hal : hals) { 1330 if (!object->add(std::move(hal))) { 1331 *error = "Duplicated compatibility-matrix.hal entry"; 1332 return false; 1333 } 1334 } 1335 1336 std::vector<MatrixXmlFile> xmlFiles; 1337 if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, error)) { 1338 return false; 1339 } 1340 for (auto&& xmlFile : xmlFiles) { 1341 if (!xmlFile.optional()) { 1342 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() + 1343 " has to be optional for compatibility matrix version 1.0"; 1344 return false; 1345 } 1346 std::string description{xmlFile.name()}; 1347 if (!object->addXmlFile(std::move(xmlFile))) { 1348 *error = "Duplicated compatibility-matrix.xmlfile entry " + description; 1349 return false; 1350 } 1351 } 1352 1353 return true; 1354 } 1355 }; 1356 1357 #define CREATE_CONVERT_FN(type) \ 1358 std::string toXml(const type& o, SerializeFlags::Type flags) { \ 1359 return type##Converter{}(o, flags); \ 1360 } \ 1361 bool fromXml(type* o, const std::string& xml, std::string* error) { \ 1362 return type##Converter{}(o, xml, error); \ 1363 } 1364 1365 // Create convert functions for public usage. 1366 CREATE_CONVERT_FN(HalManifest) 1367 CREATE_CONVERT_FN(CompatibilityMatrix) 1368 1369 // Create convert functions for internal usage. 1370 CREATE_CONVERT_FN(KernelInfo) 1371 1372 // Create convert functions for testing. 1373 CREATE_CONVERT_FN(Version) 1374 CREATE_CONVERT_FN(KernelConfigTypedValue) 1375 CREATE_CONVERT_FN(MatrixHal) 1376 CREATE_CONVERT_FN(ManifestHal) 1377 1378 #undef CREATE_CONVERT_FN 1379 1380 } // namespace vintf 1381 } // namespace android 1382