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