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 42 inline DocType *createDocument() { 43 return new tinyxml2::XMLDocument(); 44 } 45 46 // caller is responsible for deleteDocument() call 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 56 inline void deleteDocument(DocType *d) { 57 delete d; 58 } 59 60 inline std::string printDocument(DocType *d) { 61 tinyxml2::XMLPrinter p; 62 d->Print(&p); 63 return std::string{p.CStr()}; 64 } 65 66 inline NodeType *createNode(const std::string &name, DocType *d) { 67 return d->NewElement(name.c_str()); 68 } 69 70 inline void appendChild(NodeType *parent, NodeType *child) { 71 parent->InsertEndChild(child); 72 } 73 74 inline void appendChild(DocType *parent, NodeType *child) { 75 parent->InsertEndChild(child); 76 } 77 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 83 inline void appendText(NodeType *parent, const std::string &text, DocType *d) { 84 parent->InsertEndChild(d->NewText(text.c_str())); 85 } 86 87 inline std::string nameOf(NodeType *root) { 88 return root->Name() == NULL ? "" : root->Name(); 89 } 90 91 inline std::string getText(NodeType *root) { 92 return root->GetText() == NULL ? "" : root->GetText(); 93 } 94 95 inline NodeType *getChild(NodeType *parent, const std::string &name) { 96 return parent->FirstChildElement(name.c_str()); 97 } 98 99 inline NodeType *getRootChild(DocType *parent) { 100 return parent->FirstChildElement(); 101 } 102 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 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 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> { 140 XmlNodeConverter() {} 141 virtual ~XmlNodeConverter() {} 142 143 // sub-types should implement these. 144 virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0; 145 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 152 inline const std::string& lastError() const override { return mLastError; } 153 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 } 159 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 } 166 inline bool deserialize(Object* object, NodeType* root) { 167 bool ret = deserialize(object, root, &mLastError); 168 return ret; 169 } 170 inline bool deserialize(Object* o, const std::string& xml) override { 171 bool ret = (*this)(o, xml, &mLastError); 172 return ret; 173 } 174 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 } 180 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 } 193 inline NodeType *operator()(const Object &o, DocType *d) const { 194 return serialize(o, d); 195 } 196 inline std::string operator()(const Object& o, SerializeFlags::Type flags) const override { 197 return serialize(o, flags); 198 } 199 inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); } 200 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> 208 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 212 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> 217 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> 226 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> 236 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> 248 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> 260 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 271 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 281 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 293 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 301 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> 312 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> 324 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> 335 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> 347 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> 363 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> 381 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 386 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> 392 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> { 407 XmlTextConverter(const std::string &elementName) 408 : mElementName(elementName) {} 409 410 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override { 411 appendText(root, ::android::vintf::to_string(object), d); 412 } 413 virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override { 414 return this->parseText(root, object, error); 415 } 416 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> { 424 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 432 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 } 436 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 } 440 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> { 455 std::string elementName() const override { return "transport"; } 456 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 } 462 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> { 480 std::string elementName() const override { return "value"; } 481 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 } 485 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> { 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 HalInterfaceConverter halInterfaceConverter{}; 547 548 struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { 549 std::string elementName() const override { return "hal"; } 550 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 } 560 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: 601 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>> { 633 std::string elementName() const override { return "conditions"; } 634 void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root, 635 DocType* d) const override { 636 appendChildren(root, matrixKernelConfigConverter, conds, d); 637 } 638 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> { 647 std::string elementName() const override { return "kernel"; } 648 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override { 649 mutateNode(kernel, root, d, SerializeFlags::EVERYTHING); 650 } 651 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 } 670 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> { 689 std::string elementName() const override { return "hal"; } 690 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override { 691 mutateNode(m, root, d, SerializeFlags::EVERYTHING); 692 } 693 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 } 718 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: 819 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> { 844 std::string elementName() const override { return "sepolicy"; } 845 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 } 849 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> { 867 std::string elementName() const override { return "vndk"; } 868 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 } 872 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> { 884 std::string elementName() const override { return "vendor-ndk"; } 885 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 } 889 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> { 903 std::string elementName() const override { return "system-sdk"; } 904 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override { 905 appendChildren(root, systemSdkVersionConverter, object.versions(), d); 906 } 907 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> { 915 std::string elementName() const override { return "sepolicy"; } 916 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 917 appendChild(root, versionConverter(m, d)); 918 } 919 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> { 926 std::string elementName() const override { return "xmlfile"; } 927 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 } 934 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> { 950 std::string elementName() const override { return "kernel"; } 951 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override { 952 mutateNode(o, root, d, SerializeFlags::EVERYTHING); 953 } 954 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 } 966 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> { 976 std::string elementName() const override { return "manifest"; } 977 void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override { 978 mutateNode(m, root, d, SerializeFlags::EVERYTHING); 979 } 980 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 } 1027 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> { 1120 std::string elementName() const override { return "avb"; } 1121 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 1122 appendChild(root, avbVersionConverter(m, d)); 1123 } 1124 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> { 1131 std::string elementName() const override { return "xmlfile"; } 1132 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 } 1141 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> { 1155 std::string elementName() const override { return "compatibility-matrix"; } 1156 void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override { 1157 mutateNode(m, root, d, SerializeFlags::EVERYTHING); 1158 } 1159 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 } 1213 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