1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261 |
- /*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // Convert objects from and to xml.
- #define LOG_TAG "libvintf"
- #include <android-base/logging.h>
- #include "parse_xml.h"
- #include <type_traits>
- #include <tinyxml2.h>
- #include "Regex.h"
- #include "constants.h"
- #include "parse_string.h"
- namespace android {
- namespace vintf {
- // --------------- tinyxml2 details
- using NodeType = tinyxml2::XMLElement;
- using DocType = tinyxml2::XMLDocument;
- // caller is responsible for deleteDocument() call
- inline DocType *createDocument() {
- return new tinyxml2::XMLDocument();
- }
- // caller is responsible for deleteDocument() call
- inline DocType *createDocument(const std::string &xml) {
- DocType *doc = new tinyxml2::XMLDocument();
- if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
- return doc;
- }
- delete doc;
- return nullptr;
- }
- inline void deleteDocument(DocType *d) {
- delete d;
- }
- inline std::string printDocument(DocType *d) {
- tinyxml2::XMLPrinter p;
- d->Print(&p);
- return std::string{p.CStr()};
- }
- inline NodeType *createNode(const std::string &name, DocType *d) {
- return d->NewElement(name.c_str());
- }
- inline void appendChild(NodeType *parent, NodeType *child) {
- parent->InsertEndChild(child);
- }
- inline void appendChild(DocType *parent, NodeType *child) {
- parent->InsertEndChild(child);
- }
- inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
- e->SetAttribute(attrName.c_str(), attr.c_str());
- }
- // text -> text
- inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
- parent->InsertEndChild(d->NewText(text.c_str()));
- }
- inline std::string nameOf(NodeType *root) {
- return root->Name() == NULL ? "" : root->Name();
- }
- inline std::string getText(NodeType *root) {
- return root->GetText() == NULL ? "" : root->GetText();
- }
- inline NodeType *getChild(NodeType *parent, const std::string &name) {
- return parent->FirstChildElement(name.c_str());
- }
- inline NodeType *getRootChild(DocType *parent) {
- return parent->FirstChildElement();
- }
- inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
- std::vector<NodeType *> v;
- for (NodeType *child = parent->FirstChildElement(name.c_str());
- child != nullptr;
- child = child->NextSiblingElement(name.c_str())) {
- v.push_back(child);
- }
- return v;
- }
- inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
- const char *c = root->Attribute(attrName.c_str());
- if (c == NULL)
- return false;
- *s = c;
- return true;
- }
- // --------------- tinyxml2 details end.
- // Helper functions for XmlConverter
- static bool parse(const std::string &attrText, bool *attr) {
- if (attrText == "true" || attrText == "1") {
- *attr = true;
- return true;
- }
- if (attrText == "false" || attrText == "0") {
- *attr = false;
- return true;
- }
- return false;
- }
- // ---------------------- XmlNodeConverter definitions
- template<typename Object>
- struct XmlNodeConverter : public XmlConverter<Object> {
- XmlNodeConverter() {}
- virtual ~XmlNodeConverter() {}
- // sub-types should implement these.
- virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
- virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
- mutateNode(o, n, d);
- }
- virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
- virtual std::string elementName() const = 0;
- // convenience methods for user
- inline const std::string& lastError() const override { return mLastError; }
- inline NodeType* serialize(const Object& o, DocType* d,
- SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
- NodeType *root = createNode(this->elementName(), d);
- this->mutateNode(o, root, d, flags);
- return root;
- }
- inline std::string serialize(const Object& o, SerializeFlags::Type flags) const override {
- DocType *doc = createDocument();
- appendChild(doc, serialize(o, doc, flags));
- std::string s = printDocument(doc);
- deleteDocument(doc);
- return s;
- }
- inline bool deserialize(Object* object, NodeType* root) {
- bool ret = deserialize(object, root, &mLastError);
- return ret;
- }
- inline bool deserialize(Object* o, const std::string& xml) override {
- bool ret = (*this)(o, xml, &mLastError);
- return ret;
- }
- inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
- if (nameOf(root) != this->elementName()) {
- return false;
- }
- return this->buildObject(object, root, error);
- }
- inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
- std::string errorBuffer;
- if (error == nullptr) error = &errorBuffer;
- auto doc = createDocument(xml);
- if (doc == nullptr) {
- *error = "Not a valid XML";
- return false;
- }
- bool ret = deserialize(o, getRootChild(doc), error);
- deleteDocument(doc);
- return ret;
- }
- inline NodeType *operator()(const Object &o, DocType *d) const {
- return serialize(o, d);
- }
- inline std::string operator()(const Object& o, SerializeFlags::Type flags) const override {
- return serialize(o, flags);
- }
- inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
- inline bool operator()(Object* o, const std::string& xml) override {
- return deserialize(o, xml);
- }
- // convenience methods for implementor.
- // All append* functions helps mutateNode() to serialize the object into XML.
- template <typename T>
- inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
- return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
- }
- inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
- return appendStrAttr(e, attrName, attr ? "true" : "false");
- }
- // text -> <name>text</name>
- inline void appendTextElement(NodeType *parent, const std::string &name,
- const std::string &text, DocType *d) const {
- NodeType *c = createNode(name, d);
- appendText(c, text, d);
- appendChild(parent, c);
- }
- // text -> <name>text</name>
- template<typename Array>
- inline void appendTextElements(NodeType *parent, const std::string &name,
- const Array &array, DocType *d) const {
- for (const std::string &text : array) {
- NodeType *c = createNode(name, d);
- appendText(c, text, d);
- appendChild(parent, c);
- }
- }
- template <typename T, typename Array>
- inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
- const Array& array, DocType* d,
- SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
- for (const T &t : array) {
- appendChild(parent, conv.serialize(t, d, flags));
- }
- }
- // All parse* functions helps buildObject() to deserialize XML to the object. Returns
- // true if deserialization is successful, false if any error, and "error" will be
- // set to error message.
- template <typename T>
- inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
- T* attr, std::string* /* error */) const {
- std::string attrText;
- bool success = getAttr(root, attrName, &attrText) &&
- ::android::vintf::parse(attrText, attr);
- if (!success) {
- *attr = std::move(defaultValue);
- }
- return true;
- }
- template <typename T>
- inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
- std::string* error) const {
- std::string attrText;
- bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
- if (!ret) {
- *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
- attrText + "\" for element <" + elementName() + ">";
- }
- return ret;
- }
- inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
- std::string* error) const {
- bool ret = getAttr(root, attrName, attr);
- if (!ret) {
- *error = "Could not find attr with name \"" + attrName + "\" for element <" +
- elementName() + ">";
- }
- return ret;
- }
- inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
- std::string* error) const {
- NodeType *child = getChild(root, elementName);
- if (child == nullptr) {
- *error = "Could not find element with name <" + elementName + "> in element <" +
- this->elementName() + ">";
- return false;
- }
- *s = getText(child);
- return true;
- }
- inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
- std::string&& defaultValue, std::string* s,
- std::string* /* error */) const {
- NodeType* child = getChild(root, elementName);
- *s = child == nullptr ? std::move(defaultValue) : getText(child);
- return true;
- }
- inline bool parseTextElements(NodeType* root, const std::string& elementName,
- std::vector<std::string>* v, std::string* /* error */) const {
- auto nodes = getChildren(root, elementName);
- v->resize(nodes.size());
- for (size_t i = 0; i < nodes.size(); ++i) {
- v->at(i) = getText(nodes[i]);
- }
- return true;
- }
- template <typename T>
- inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
- std::string* error) const {
- NodeType *child = getChild(root, conv.elementName());
- if (child == nullptr) {
- *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
- this->elementName() + ">";
- return false;
- }
- return conv.deserialize(t, child, error);
- }
- template <typename T>
- inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
- T&& defaultValue, T* t, std::string* error) const {
- NodeType *child = getChild(root, conv.elementName());
- if (child == nullptr) {
- *t = std::move(defaultValue);
- return true;
- }
- return conv.deserialize(t, child, error);
- }
- template <typename T>
- inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
- std::optional<T>* t, std::string* error) const {
- NodeType* child = getChild(root, conv.elementName());
- if (child == nullptr) {
- *t = std::nullopt;
- return true;
- }
- *t = std::make_optional<T>();
- return conv.deserialize(&**t, child, error);
- }
- template <typename T>
- inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
- std::string* error) const {
- auto nodes = getChildren(root, conv.elementName());
- v->resize(nodes.size());
- for (size_t i = 0; i < nodes.size(); ++i) {
- if (!conv.deserialize(&v->at(i), nodes[i], error)) {
- *error = "Could not parse element with name <" + conv.elementName() +
- "> in element <" + this->elementName() + ">: " + *error;
- return false;
- }
- }
- return true;
- }
- template <typename Container, typename T = typename Container::value_type,
- typename = typename Container::key_compare>
- inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
- std::string* error) const {
- std::vector<T> vec;
- if (!parseChildren(root, conv, &vec, error)) {
- return false;
- }
- s->clear();
- s->insert(vec.begin(), vec.end());
- if (s->size() != vec.size()) {
- *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
- this->elementName() + ">";
- s->clear();
- return false;
- }
- return true;
- }
- template <typename K, typename V>
- inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
- std::map<K, V>* s, std::string* error) const {
- return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
- }
- inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
- *s = getText(node);
- return true;
- }
- template <typename T>
- inline bool parseText(NodeType* node, T* s, std::string* error) const {
- std::string text = getText(node);
- bool ret = ::android::vintf::parse(text, s);
- if (!ret) {
- *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
- }
- return ret;
- }
- private:
- mutable std::string mLastError;
- };
- template<typename Object>
- struct XmlTextConverter : public XmlNodeConverter<Object> {
- XmlTextConverter(const std::string &elementName)
- : mElementName(elementName) {}
- virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
- appendText(root, ::android::vintf::to_string(object), d);
- }
- virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
- return this->parseText(root, object, error);
- }
- virtual std::string elementName() const { return mElementName; }
- private:
- std::string mElementName;
- };
- template <typename Pair>
- struct XmlPairConverter : public XmlNodeConverter<Pair> {
- XmlPairConverter(
- const std::string& elementName,
- std::unique_ptr<XmlNodeConverter<typename Pair::first_type>>&& firstConverter,
- std::unique_ptr<XmlNodeConverter<typename Pair::second_type>>&& secondConverter)
- : mElementName(elementName),
- mFirstConverter(std::move(firstConverter)),
- mSecondConverter(std::move(secondConverter)) {}
- virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
- appendChild(root, mFirstConverter->serialize(pair.first, d));
- appendChild(root, mSecondConverter->serialize(pair.second, d));
- }
- virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
- return this->parseChild(root, *mFirstConverter, &pair->first, error) &&
- this->parseChild(root, *mSecondConverter, &pair->second, error);
- }
- virtual std::string elementName() const { return mElementName; }
- private:
- std::string mElementName;
- std::unique_ptr<XmlNodeConverter<typename Pair::first_type>> mFirstConverter;
- std::unique_ptr<XmlNodeConverter<typename Pair::second_type>> mSecondConverter;
- };
- // ---------------------- XmlNodeConverter definitions end
- XmlTextConverter<Version> versionConverter{"version"};
- XmlTextConverter<VersionRange> versionRangeConverter{"version"};
- struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
- std::string elementName() const override { return "transport"; }
- void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
- if (object.arch != Arch::ARCH_EMPTY) {
- appendAttr(root, "arch", object.arch);
- }
- appendText(root, ::android::vintf::to_string(object.transport), d);
- }
- bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
- if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
- !parseText(root, &object->transport, error)) {
- return false;
- }
- if (!object->isValid()) {
- *error = "transport == " + ::android::vintf::to_string(object->transport) +
- " and arch == " + ::android::vintf::to_string(object->arch) +
- " is not a valid combination.";
- return false;
- }
- return true;
- }
- };
- TransportArchConverter transportArchConverter{};
- struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
- std::string elementName() const override { return "value"; }
- void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
- appendAttr(root, "type", object.mType);
- appendText(root, ::android::vintf::to_string(object), d);
- }
- bool buildObject(KernelConfigTypedValue* object, NodeType* root,
- std::string* error) const override {
- std::string stringValue;
- if (!parseAttr(root, "type", &object->mType, error) ||
- !parseText(root, &stringValue, error)) {
- return false;
- }
- if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
- *error = "Could not parse kernel config value \"" + stringValue + "\"";
- return false;
- }
- return true;
- }
- };
- KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
- XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
- "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
- std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
- struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
- std::string elementName() const override { return "interface"; }
- void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
- appendTextElement(root, "name", intf.name(), d);
- appendTextElements(root, "instance", intf.mInstances, d);
- appendTextElements(root, "regex-instance", intf.mRegexes, d);
- }
- bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
- std::vector<std::string> instances;
- std::vector<std::string> regexes;
- if (!parseTextElement(root, "name", &intf->mName, error) ||
- !parseTextElements(root, "instance", &instances, error) ||
- !parseTextElements(root, "regex-instance", ®exes, error)) {
- return false;
- }
- bool success = true;
- for (const auto& e : instances) {
- if (!intf->insertInstance(e, false /* isRegex */)) {
- if (!error->empty()) *error += "\n";
- *error += "Duplicated instance '" + e + "' in " + intf->name();
- success = false;
- }
- }
- for (const auto& e : regexes) {
- details::Regex regex;
- if (!regex.compile(e)) {
- if (!error->empty()) *error += "\n";
- *error += "Invalid regular expression '" + e + "' in " + intf->name();
- success = false;
- }
- if (!intf->insertInstance(e, true /* isRegex */)) {
- if (!error->empty()) *error += "\n";
- *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
- success = false;
- }
- }
- return success;
- }
- };
- HalInterfaceConverter halInterfaceConverter{};
- struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
- std::string elementName() const override { return "hal"; }
- void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
- appendAttr(root, "format", hal.format);
- appendAttr(root, "optional", hal.optional);
- appendTextElement(root, "name", hal.name, d);
- appendChildren(root, versionRangeConverter, hal.versionRanges, d);
- appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
- }
- bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
- std::vector<HalInterface> interfaces;
- if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
- !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
- error) ||
- !parseTextElement(root, "name", &object->name, error) ||
- !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
- !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
- return false;
- }
- for (auto&& interface : interfaces) {
- std::string name{interface.name()};
- auto res = object->interfaces.emplace(std::move(name), std::move(interface));
- if (!res.second) {
- *error = "Duplicated interface entry \"" + res.first->first +
- "\"; if additional instances are needed, add them to the "
- "existing <interface> node.";
- return false;
- }
- }
- // Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
- #ifndef LIBVINTF_TARGET
- if (!checkAdditionalRestrictionsOnHal(*object, error)) {
- return false;
- }
- #endif
- return true;
- }
- #ifndef LIBVINTF_TARGET
- private:
- bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
- if (hal.getName() == "netutils-wrapper") {
- if (hal.versionRanges.size() != 1) {
- *error =
- "netutils-wrapper HAL must specify exactly one version x.0, "
- "but multiple <version> element is specified.";
- return false;
- }
- const VersionRange& v = hal.versionRanges.at(0);
- if (!v.isSingleVersion()) {
- *error =
- "netutils-wrapper HAL must specify exactly one version x.0, "
- "but a range is provided. Perhaps you mean '" +
- to_string(Version{v.majorVer, 0}) + "'?";
- return false;
- }
- if (v.minMinor != 0) {
- *error =
- "netutils-wrapper HAL must specify exactly one version x.0, "
- "but minor version is not 0. Perhaps you mean '" +
- to_string(Version{v.majorVer, 0}) + "'?";
- return false;
- }
- }
- return true;
- }
- #endif
- };
- MatrixHalConverter matrixHalConverter{};
- struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
- std::string elementName() const override { return "conditions"; }
- void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
- DocType* d) const override {
- appendChildren(root, matrixKernelConfigConverter, conds, d);
- }
- bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
- std::string* error) const override {
- return parseChildren(root, matrixKernelConfigConverter, object, error);
- }
- };
- MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
- struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
- std::string elementName() const override { return "kernel"; }
- void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
- mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
- }
- void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
- SerializeFlags::Type flags) const override {
- KernelVersion kv = kernel.mMinLts;
- if (!flags.isKernelMinorRevisionEnabled()) {
- kv.minorRev = 0u;
- }
- appendAttr(root, "version", kv);
- if (!kernel.mConditions.empty()) {
- appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
- }
- if (flags.isKernelConfigsEnabled()) {
- appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
- }
- }
- bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
- if (!parseAttr(root, "version", &object->mMinLts, error) ||
- !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
- error) ||
- !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
- return false;
- }
- return true;
- }
- };
- MatrixKernelConverter matrixKernelConverter{};
- XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
- struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
- std::string elementName() const override { return "hal"; }
- void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
- mutateNode(m, root, d, SerializeFlags::EVERYTHING);
- }
- void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
- SerializeFlags::Type flags) const override {
- appendAttr(root, "format", hal.format);
- appendTextElement(root, "name", hal.name, d);
- appendChild(root, transportArchConverter(hal.transportArch, d));
- appendChildren(root, versionConverter, hal.versions, d);
- appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
- if (hal.isOverride()) {
- appendAttr(root, "override", hal.isOverride());
- }
- if (flags.isFqnameEnabled()) {
- std::set<FqInstance> fqInstances;
- hal.forEachInstance([&fqInstances](const auto& manifestInstance) {
- fqInstances.emplace(manifestInstance.getFqInstanceNoPackage());
- return true;
- });
- appendChildren(root, fqInstanceConverter, fqInstances, d);
- }
- }
- bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
- std::vector<HalInterface> interfaces;
- if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
- !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
- !parseTextElement(root, "name", &object->name, error) ||
- !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
- !parseChildren(root, versionConverter, &object->versions, error) ||
- !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
- return false;
- }
- switch (object->format) {
- case HalFormat::HIDL: {
- if (object->transportArch.empty()) {
- *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
- return false;
- }
- } break;
- case HalFormat::NATIVE: {
- if (!object->transportArch.empty()) {
- *error =
- "Native HAL '" + object->name + "' should not have <transport> defined.";
- return false;
- }
- } break;
- default: {
- LOG(FATAL) << "Unhandled HalFormat "
- << static_cast<typename std::underlying_type<HalFormat>::type>(
- object->format);
- } break;
- }
- if (!object->transportArch.isValid()) return false;
- object->interfaces.clear();
- for (auto &&interface : interfaces) {
- auto res = object->interfaces.emplace(interface.name(), std::move(interface));
- if (!res.second) {
- *error = "Duplicated interface entry \"" + res.first->first +
- "\"; if additional instances are needed, add them to the "
- "existing <interface> node.";
- return false;
- }
- }
- if (!object->isValid()) {
- *error = "'" + object->name + "' is not a valid Manifest HAL.";
- return false;
- }
- // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
- #ifndef LIBVINTF_TARGET
- if (!checkAdditionalRestrictionsOnHal(*object, error)) {
- return false;
- }
- #endif
- std::set<FqInstance> fqInstances;
- if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
- return false;
- }
- for (const auto& e : fqInstances) {
- if (e.hasPackage()) {
- *error = "Should not specify package: \"" + e.string() + "\"";
- return false;
- }
- }
- if (!object->insertInstances(fqInstances, error)) {
- return false;
- }
- return true;
- }
- #ifndef LIBVINTF_TARGET
- private:
- bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
- if (hal.getName() == "netutils-wrapper") {
- for (const Version& v : hal.versions) {
- if (v.minorVer != 0) {
- *error =
- "netutils-wrapper HAL must specify exactly one version x.0, "
- "but minor version is not 0. Perhaps you mean '" +
- to_string(Version{v.majorVer, 0}) + "'?";
- return false;
- }
- }
- }
- return true;
- }
- #endif
- };
- // Convert ManifestHal from and to XML. Returned object is guaranteed to have
- // .isValid() == true.
- ManifestHalConverter manifestHalConverter{};
- XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
- XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
- struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
- std::string elementName() const override { return "sepolicy"; }
- void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
- appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
- appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
- }
- bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
- if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
- error) ||
- !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
- error)) {
- return false;
- }
- return true;
- }
- };
- SepolicyConverter sepolicyConverter{};
- [[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
- XmlTextConverter<std::string> vndkVersionConverter{"version"};
- XmlTextConverter<std::string> vndkLibraryConverter{"library"};
- struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
- std::string elementName() const override { return "vndk"; }
- void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
- appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
- appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
- }
- bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
- if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
- !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
- return false;
- }
- return true;
- }
- };
- [[deprecated]] VndkConverter vndkConverter{};
- struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
- std::string elementName() const override { return "vendor-ndk"; }
- void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
- appendChild(root, vndkVersionConverter(object.mVersion, d));
- appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
- }
- bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
- if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
- !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
- return false;
- }
- return true;
- }
- };
- VendorNdkConverter vendorNdkConverter{};
- XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
- struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
- std::string elementName() const override { return "system-sdk"; }
- void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
- appendChildren(root, systemSdkVersionConverter, object.versions(), d);
- }
- bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
- return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
- }
- };
- SystemSdkConverter systemSdkConverter{};
- struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
- std::string elementName() const override { return "sepolicy"; }
- void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
- appendChild(root, versionConverter(m, d));
- }
- bool buildObject(Version* object, NodeType* root, std::string* error) const override {
- return parseChild(root, versionConverter, object, error);
- }
- };
- HalManifestSepolicyConverter halManifestSepolicyConverter{};
- struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
- std::string elementName() const override { return "xmlfile"; }
- void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
- appendTextElement(root, "name", f.name(), d);
- appendChild(root, versionConverter(f.version(), d));
- if (!f.overriddenPath().empty()) {
- appendTextElement(root, "path", f.overriddenPath(), d);
- }
- }
- bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
- if (!parseTextElement(root, "name", &object->mName, error) ||
- !parseChild(root, versionConverter, &object->mVersion, error) ||
- !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
- return false;
- }
- return true;
- }
- };
- ManifestXmlFileConverter manifestXmlFileConverter{};
- XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
- "config", std::make_unique<XmlTextConverter<std::string>>("key"),
- std::make_unique<XmlTextConverter<std::string>>("value")};
- struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
- std::string elementName() const override { return "kernel"; }
- void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
- mutateNode(o, root, d, SerializeFlags::EVERYTHING);
- }
- void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
- SerializeFlags::Type flags) const override {
- if (o.version() != KernelVersion{}) {
- appendAttr(root, "version", o.version());
- }
- if (flags.isKernelConfigsEnabled()) {
- appendChildren(root, kernelConfigConverter, o.configs(), d);
- }
- }
- bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
- return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
- parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
- }
- };
- KernelInfoConverter kernelInfoConverter{};
- struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
- std::string elementName() const override { return "manifest"; }
- void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
- mutateNode(m, root, d, SerializeFlags::EVERYTHING);
- }
- void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
- SerializeFlags::Type flags) const override {
- if (flags.isMetaVersionEnabled()) {
- appendAttr(root, "version", m.getMetaVersion());
- }
- if (flags.isSchemaTypeEnabled()) {
- appendAttr(root, "type", m.mType);
- }
- if (flags.isHalsEnabled()) {
- appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
- }
- if (m.mType == SchemaType::DEVICE) {
- if (flags.isSepolicyEnabled()) {
- if (m.device.mSepolicyVersion != Version{}) {
- appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
- }
- }
- if (m.mLevel != Level::UNSPECIFIED) {
- this->appendAttr(root, "target-level", m.mLevel);
- }
- if (flags.isKernelEnabled()) {
- if (!!m.kernel()) {
- appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
- }
- }
- } else if (m.mType == SchemaType::FRAMEWORK) {
- if (flags.isVndkEnabled()) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- appendChildren(root, vndkConverter, m.framework.mVndks, d);
- #pragma clang diagnostic pop
- appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
- }
- if (flags.isSsdkEnabled()) {
- if (!m.framework.mSystemSdk.empty()) {
- appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
- }
- }
- }
- if (flags.isXmlFilesEnabled()) {
- appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
- }
- }
- bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
- std::vector<ManifestHal> hals;
- if (!parseAttr(root, "version", &object->mMetaVersion, error) ||
- !parseAttr(root, "type", &object->mType, error) ||
- !parseChildren(root, manifestHalConverter, &hals, error)) {
- return false;
- }
- if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) {
- *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
- " (libvintf@" + to_string(kMetaVersion) + ")";
- return false;
- }
- if (object->mType == SchemaType::DEVICE) {
- // tags for device hal manifest only.
- // <sepolicy> can be missing because it can be determined at build time, not hard-coded
- // in the XML file.
- if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
- &object->device.mSepolicyVersion, error)) {
- return false;
- }
- if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
- error)) {
- return false;
- }
- if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
- return false;
- }
- } else if (object->mType == SchemaType::FRAMEWORK) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
- return false;
- }
- for (const auto &vndk : object->framework.mVndks) {
- if (!vndk.mVersionRange.isSingleVersion()) {
- *error = "vndk.version " + to_string(vndk.mVersionRange) +
- " cannot be a range for manifests";
- return false;
- }
- }
- #pragma clang diagnostic pop
- if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
- return false;
- }
- std::set<std::string> vendorNdkVersions;
- for (const auto& vendorNdk : object->framework.mVendorNdks) {
- if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
- *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
- return false;
- }
- vendorNdkVersions.insert(vendorNdk.version());
- }
- if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
- error)) {
- return false;
- }
- }
- for (auto &&hal : hals) {
- std::string description{hal.name};
- if (!object->add(std::move(hal))) {
- *error = "Duplicated manifest.hal entry " + description;
- return false;
- }
- }
- std::vector<ManifestXmlFile> xmlFiles;
- if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
- return false;
- }
- for (auto&& xmlFile : xmlFiles) {
- std::string description{xmlFile.name()};
- if (!object->addXmlFile(std::move(xmlFile))) {
- *error = "Duplicated manifest.xmlfile entry " + description +
- "; entries cannot have duplicated name and version";
- return false;
- }
- }
- return true;
- }
- };
- HalManifestConverter halManifestConverter{};
- XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
- struct AvbConverter : public XmlNodeConverter<Version> {
- std::string elementName() const override { return "avb"; }
- void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
- appendChild(root, avbVersionConverter(m, d));
- }
- bool buildObject(Version* object, NodeType* root, std::string* error) const override {
- return parseChild(root, avbVersionConverter, object, error);
- }
- };
- AvbConverter avbConverter{};
- struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
- std::string elementName() const override { return "xmlfile"; }
- void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
- appendTextElement(root, "name", f.name(), d);
- appendAttr(root, "format", f.format());
- appendAttr(root, "optional", f.optional());
- appendChild(root, versionRangeConverter(f.versionRange(), d));
- if (!f.overriddenPath().empty()) {
- appendTextElement(root, "path", f.overriddenPath(), d);
- }
- }
- bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
- if (!parseTextElement(root, "name", &object->mName, error) ||
- !parseAttr(root, "format", &object->mFormat, error) ||
- !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
- !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
- !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
- return false;
- }
- return true;
- }
- };
- MatrixXmlFileConverter matrixXmlFileConverter{};
- struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
- std::string elementName() const override { return "compatibility-matrix"; }
- void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
- mutateNode(m, root, d, SerializeFlags::EVERYTHING);
- }
- void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
- SerializeFlags::Type flags) const override {
- if (flags.isMetaVersionEnabled()) {
- appendAttr(root, "version", m.getMinimumMetaVersion());
- }
- if (flags.isSchemaTypeEnabled()) {
- appendAttr(root, "type", m.mType);
- }
- if (flags.isHalsEnabled()) {
- appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
- }
- if (m.mType == SchemaType::FRAMEWORK) {
- if (flags.isKernelEnabled()) {
- appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
- }
- if (flags.isSepolicyEnabled()) {
- if (!(m.framework.mSepolicy == Sepolicy{})) {
- appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
- }
- }
- if (flags.isAvbEnabled()) {
- if (!(m.framework.mAvbMetaVersion == Version{})) {
- appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
- }
- }
- if (m.mLevel != Level::UNSPECIFIED) {
- this->appendAttr(root, "level", m.mLevel);
- }
- } else if (m.mType == SchemaType::DEVICE) {
- if (flags.isVndkEnabled()) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if (!(m.device.mVndk == Vndk{})) {
- appendChild(root, vndkConverter(m.device.mVndk, d));
- }
- #pragma clang diagnostic pop
- if (!(m.device.mVendorNdk == VendorNdk{})) {
- appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
- }
- }
- if (flags.isSsdkEnabled()) {
- if (!m.device.mSystemSdk.empty()) {
- appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
- }
- }
- }
- if (flags.isXmlFilesEnabled()) {
- appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
- }
- }
- bool buildObject(CompatibilityMatrix* object, NodeType* root,
- std::string* error) const override {
- Version version;
- std::vector<MatrixHal> hals;
- if (!parseAttr(root, "version", &version, error) ||
- !parseAttr(root, "type", &object->mType, error) ||
- !parseChildren(root, matrixHalConverter, &hals, error)) {
- return false;
- }
- if (object->mType == SchemaType::FRAMEWORK) {
- // <avb> and <sepolicy> can be missing because it can be determined at build time, not
- // hard-coded in the XML file.
- if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
- !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
- error) ||
- !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
- error)) {
- return false;
- }
- std::set<Version> seenKernelVersions;
- for (const auto& kernel : object->framework.mKernels) {
- Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
- if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
- continue;
- }
- if (!kernel.conditions().empty()) {
- *error = "First <kernel> for version " + to_string(minLts) +
- " must have empty <conditions> for backwards compatibility.";
- return false;
- }
- seenKernelVersions.insert(minLts);
- }
- if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
- return false;
- }
- } else if (object->mType == SchemaType::DEVICE) {
- // <vndk> can be missing because it can be determined at build time, not hard-coded
- // in the XML file.
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
- return false;
- }
- #pragma clang diagnostic pop
- if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
- error)) {
- return false;
- }
- if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
- error)) {
- return false;
- }
- }
- if (!kMetaVersion.minorAtLeast(version)) {
- *error = "Unrecognized compatibility-matrix.version " + to_string(version) +
- " (libvintf@" + to_string(kMetaVersion) + ")";
- return false;
- }
- for (auto &&hal : hals) {
- if (!object->add(std::move(hal))) {
- *error = "Duplicated compatibility-matrix.hal entry";
- return false;
- }
- }
- std::vector<MatrixXmlFile> xmlFiles;
- if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
- return false;
- }
- for (auto&& xmlFile : xmlFiles) {
- if (!xmlFile.optional()) {
- *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
- " has to be optional for compatibility matrix version 1.0";
- return false;
- }
- std::string description{xmlFile.name()};
- if (!object->addXmlFile(std::move(xmlFile))) {
- *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
- return false;
- }
- }
- return true;
- }
- };
- CompatibilityMatrixConverter compatibilityMatrixConverter{};
- // Publicly available as in parse_xml.h
- XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
- XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
- // For testing in LibVintfTest
- XmlConverter<Version>& gVersionConverter = versionConverter;
- XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
- kernelConfigTypedValueConverter;
- XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
- XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
- XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
- } // namespace vintf
- } // namespace android
|