1*70a7ec85SAndroid Build Coastguard Worker /*
2*70a7ec85SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*70a7ec85SAndroid Build Coastguard Worker *
4*70a7ec85SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*70a7ec85SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*70a7ec85SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*70a7ec85SAndroid Build Coastguard Worker *
8*70a7ec85SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*70a7ec85SAndroid Build Coastguard Worker *
10*70a7ec85SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*70a7ec85SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*70a7ec85SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*70a7ec85SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*70a7ec85SAndroid Build Coastguard Worker * limitations under the License.
15*70a7ec85SAndroid Build Coastguard Worker */
16*70a7ec85SAndroid Build Coastguard Worker
17*70a7ec85SAndroid Build Coastguard Worker // Convert objects from and to xml.
18*70a7ec85SAndroid Build Coastguard Worker
19*70a7ec85SAndroid Build Coastguard Worker #define LOG_TAG "libvintf"
20*70a7ec85SAndroid Build Coastguard Worker #include <android-base/logging.h>
21*70a7ec85SAndroid Build Coastguard Worker
22*70a7ec85SAndroid Build Coastguard Worker #include "parse_xml.h"
23*70a7ec85SAndroid Build Coastguard Worker
24*70a7ec85SAndroid Build Coastguard Worker #include <type_traits>
25*70a7ec85SAndroid Build Coastguard Worker
26*70a7ec85SAndroid Build Coastguard Worker #include <android-base/parseint.h>
27*70a7ec85SAndroid Build Coastguard Worker #include <android-base/strings.h>
28*70a7ec85SAndroid Build Coastguard Worker #include <tinyxml2.h>
29*70a7ec85SAndroid Build Coastguard Worker
30*70a7ec85SAndroid Build Coastguard Worker #include "Regex.h"
31*70a7ec85SAndroid Build Coastguard Worker #include "constants-private.h"
32*70a7ec85SAndroid Build Coastguard Worker #include "constants.h"
33*70a7ec85SAndroid Build Coastguard Worker #include "parse_string.h"
34*70a7ec85SAndroid Build Coastguard Worker #include "parse_xml_for_test.h"
35*70a7ec85SAndroid Build Coastguard Worker #include "utils.h"
36*70a7ec85SAndroid Build Coastguard Worker
37*70a7ec85SAndroid Build Coastguard Worker using namespace std::string_literals;
38*70a7ec85SAndroid Build Coastguard Worker
39*70a7ec85SAndroid Build Coastguard Worker #ifdef LIBVINTF_TARGET
40*70a7ec85SAndroid Build Coastguard Worker static constexpr bool kDevice = true;
41*70a7ec85SAndroid Build Coastguard Worker #else
42*70a7ec85SAndroid Build Coastguard Worker static constexpr bool kDevice = false;
43*70a7ec85SAndroid Build Coastguard Worker #endif
44*70a7ec85SAndroid Build Coastguard Worker
45*70a7ec85SAndroid Build Coastguard Worker namespace android {
46*70a7ec85SAndroid Build Coastguard Worker namespace vintf {
47*70a7ec85SAndroid Build Coastguard Worker
48*70a7ec85SAndroid Build Coastguard Worker // --------------- tinyxml2 details
49*70a7ec85SAndroid Build Coastguard Worker
50*70a7ec85SAndroid Build Coastguard Worker using NodeType = tinyxml2::XMLElement;
51*70a7ec85SAndroid Build Coastguard Worker using DocType = tinyxml2::XMLDocument;
52*70a7ec85SAndroid Build Coastguard Worker
53*70a7ec85SAndroid Build Coastguard Worker // caller is responsible for deleteDocument() call
createDocument()54*70a7ec85SAndroid Build Coastguard Worker inline DocType *createDocument() {
55*70a7ec85SAndroid Build Coastguard Worker return new tinyxml2::XMLDocument();
56*70a7ec85SAndroid Build Coastguard Worker }
57*70a7ec85SAndroid Build Coastguard Worker
58*70a7ec85SAndroid Build Coastguard Worker // caller is responsible for deleteDocument() call
createDocument(const std::string & xml)59*70a7ec85SAndroid Build Coastguard Worker inline DocType *createDocument(const std::string &xml) {
60*70a7ec85SAndroid Build Coastguard Worker DocType *doc = new tinyxml2::XMLDocument();
61*70a7ec85SAndroid Build Coastguard Worker if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
62*70a7ec85SAndroid Build Coastguard Worker return doc;
63*70a7ec85SAndroid Build Coastguard Worker }
64*70a7ec85SAndroid Build Coastguard Worker delete doc;
65*70a7ec85SAndroid Build Coastguard Worker return nullptr;
66*70a7ec85SAndroid Build Coastguard Worker }
67*70a7ec85SAndroid Build Coastguard Worker
deleteDocument(DocType * d)68*70a7ec85SAndroid Build Coastguard Worker inline void deleteDocument(DocType *d) {
69*70a7ec85SAndroid Build Coastguard Worker delete d;
70*70a7ec85SAndroid Build Coastguard Worker }
71*70a7ec85SAndroid Build Coastguard Worker
printDocument(DocType * d)72*70a7ec85SAndroid Build Coastguard Worker inline std::string printDocument(DocType *d) {
73*70a7ec85SAndroid Build Coastguard Worker tinyxml2::XMLPrinter p;
74*70a7ec85SAndroid Build Coastguard Worker d->Print(&p);
75*70a7ec85SAndroid Build Coastguard Worker return std::string{p.CStr()};
76*70a7ec85SAndroid Build Coastguard Worker }
77*70a7ec85SAndroid Build Coastguard Worker
createNode(const std::string & name,DocType * d)78*70a7ec85SAndroid Build Coastguard Worker inline NodeType *createNode(const std::string &name, DocType *d) {
79*70a7ec85SAndroid Build Coastguard Worker return d->NewElement(name.c_str());
80*70a7ec85SAndroid Build Coastguard Worker }
81*70a7ec85SAndroid Build Coastguard Worker
appendChild(NodeType * parent,NodeType * child)82*70a7ec85SAndroid Build Coastguard Worker inline void appendChild(NodeType *parent, NodeType *child) {
83*70a7ec85SAndroid Build Coastguard Worker parent->InsertEndChild(child);
84*70a7ec85SAndroid Build Coastguard Worker }
85*70a7ec85SAndroid Build Coastguard Worker
appendChild(DocType * parent,NodeType * child)86*70a7ec85SAndroid Build Coastguard Worker inline void appendChild(DocType *parent, NodeType *child) {
87*70a7ec85SAndroid Build Coastguard Worker parent->InsertEndChild(child);
88*70a7ec85SAndroid Build Coastguard Worker }
89*70a7ec85SAndroid Build Coastguard Worker
appendStrAttr(NodeType * e,const std::string & attrName,const std::string & attr)90*70a7ec85SAndroid Build Coastguard Worker inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
91*70a7ec85SAndroid Build Coastguard Worker e->SetAttribute(attrName.c_str(), attr.c_str());
92*70a7ec85SAndroid Build Coastguard Worker }
93*70a7ec85SAndroid Build Coastguard Worker
94*70a7ec85SAndroid Build Coastguard Worker // text -> text
appendText(NodeType * parent,const std::string & text,DocType * d)95*70a7ec85SAndroid Build Coastguard Worker inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
96*70a7ec85SAndroid Build Coastguard Worker parent->InsertEndChild(d->NewText(text.c_str()));
97*70a7ec85SAndroid Build Coastguard Worker }
98*70a7ec85SAndroid Build Coastguard Worker
nameOf(NodeType * root)99*70a7ec85SAndroid Build Coastguard Worker inline std::string nameOf(NodeType *root) {
100*70a7ec85SAndroid Build Coastguard Worker return root->Name() == NULL ? "" : root->Name();
101*70a7ec85SAndroid Build Coastguard Worker }
102*70a7ec85SAndroid Build Coastguard Worker
getText(NodeType * root)103*70a7ec85SAndroid Build Coastguard Worker inline std::string getText(NodeType *root) {
104*70a7ec85SAndroid Build Coastguard Worker return root->GetText() == NULL ? "" : root->GetText();
105*70a7ec85SAndroid Build Coastguard Worker }
106*70a7ec85SAndroid Build Coastguard Worker
getChild(NodeType * parent,const std::string & name)107*70a7ec85SAndroid Build Coastguard Worker inline NodeType *getChild(NodeType *parent, const std::string &name) {
108*70a7ec85SAndroid Build Coastguard Worker return parent->FirstChildElement(name.c_str());
109*70a7ec85SAndroid Build Coastguard Worker }
110*70a7ec85SAndroid Build Coastguard Worker
getRootChild(DocType * parent)111*70a7ec85SAndroid Build Coastguard Worker inline NodeType *getRootChild(DocType *parent) {
112*70a7ec85SAndroid Build Coastguard Worker return parent->FirstChildElement();
113*70a7ec85SAndroid Build Coastguard Worker }
114*70a7ec85SAndroid Build Coastguard Worker
getChildren(NodeType * parent,const std::string & name)115*70a7ec85SAndroid Build Coastguard Worker inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
116*70a7ec85SAndroid Build Coastguard Worker std::vector<NodeType *> v;
117*70a7ec85SAndroid Build Coastguard Worker for (NodeType *child = parent->FirstChildElement(name.c_str());
118*70a7ec85SAndroid Build Coastguard Worker child != nullptr;
119*70a7ec85SAndroid Build Coastguard Worker child = child->NextSiblingElement(name.c_str())) {
120*70a7ec85SAndroid Build Coastguard Worker v.push_back(child);
121*70a7ec85SAndroid Build Coastguard Worker }
122*70a7ec85SAndroid Build Coastguard Worker return v;
123*70a7ec85SAndroid Build Coastguard Worker }
124*70a7ec85SAndroid Build Coastguard Worker
getAttr(NodeType * root,const std::string & attrName,std::string * s)125*70a7ec85SAndroid Build Coastguard Worker inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
126*70a7ec85SAndroid Build Coastguard Worker const char *c = root->Attribute(attrName.c_str());
127*70a7ec85SAndroid Build Coastguard Worker if (c == NULL)
128*70a7ec85SAndroid Build Coastguard Worker return false;
129*70a7ec85SAndroid Build Coastguard Worker *s = c;
130*70a7ec85SAndroid Build Coastguard Worker return true;
131*70a7ec85SAndroid Build Coastguard Worker }
132*70a7ec85SAndroid Build Coastguard Worker
133*70a7ec85SAndroid Build Coastguard Worker // --------------- tinyxml2 details end.
134*70a7ec85SAndroid Build Coastguard Worker
135*70a7ec85SAndroid Build Coastguard Worker // Helper functions for XmlConverter
parse(const std::string & attrText,bool * attr)136*70a7ec85SAndroid Build Coastguard Worker static bool parse(const std::string &attrText, bool *attr) {
137*70a7ec85SAndroid Build Coastguard Worker if (attrText == "true" || attrText == "1") {
138*70a7ec85SAndroid Build Coastguard Worker *attr = true;
139*70a7ec85SAndroid Build Coastguard Worker return true;
140*70a7ec85SAndroid Build Coastguard Worker }
141*70a7ec85SAndroid Build Coastguard Worker if (attrText == "false" || attrText == "0") {
142*70a7ec85SAndroid Build Coastguard Worker *attr = false;
143*70a7ec85SAndroid Build Coastguard Worker return true;
144*70a7ec85SAndroid Build Coastguard Worker }
145*70a7ec85SAndroid Build Coastguard Worker return false;
146*70a7ec85SAndroid Build Coastguard Worker }
147*70a7ec85SAndroid Build Coastguard Worker
parse(const std::string & attrText,std::optional<std::string> * attr)148*70a7ec85SAndroid Build Coastguard Worker static bool parse(const std::string& attrText, std::optional<std::string>* attr) {
149*70a7ec85SAndroid Build Coastguard Worker *attr = attrText;
150*70a7ec85SAndroid Build Coastguard Worker return true;
151*70a7ec85SAndroid Build Coastguard Worker }
152*70a7ec85SAndroid Build Coastguard Worker
parse(const std::string & s,std::optional<uint64_t> * out)153*70a7ec85SAndroid Build Coastguard Worker static bool parse(const std::string& s, std::optional<uint64_t>* out) {
154*70a7ec85SAndroid Build Coastguard Worker uint64_t val;
155*70a7ec85SAndroid Build Coastguard Worker if (base::ParseUint(s, &val)) {
156*70a7ec85SAndroid Build Coastguard Worker *out = val;
157*70a7ec85SAndroid Build Coastguard Worker return true;
158*70a7ec85SAndroid Build Coastguard Worker }
159*70a7ec85SAndroid Build Coastguard Worker return false;
160*70a7ec85SAndroid Build Coastguard Worker }
161*70a7ec85SAndroid Build Coastguard Worker
162*70a7ec85SAndroid Build Coastguard Worker // ---------------------- XmlNodeConverter definitions
163*70a7ec85SAndroid Build Coastguard Worker
164*70a7ec85SAndroid Build Coastguard Worker // When serializing an object to an XML document, these parameters don't change until
165*70a7ec85SAndroid Build Coastguard Worker // the object is fully serialized.
166*70a7ec85SAndroid Build Coastguard Worker // These parameters are also passed to converters of child nodes so they see the same
167*70a7ec85SAndroid Build Coastguard Worker // serialization parameters.
168*70a7ec85SAndroid Build Coastguard Worker struct MutateNodeParam {
169*70a7ec85SAndroid Build Coastguard Worker DocType* d;
170*70a7ec85SAndroid Build Coastguard Worker SerializeFlags::Type flags = SerializeFlags::EVERYTHING;
171*70a7ec85SAndroid Build Coastguard Worker };
172*70a7ec85SAndroid Build Coastguard Worker
173*70a7ec85SAndroid Build Coastguard Worker // When deserializing an XML document to an object, these parameters don't change until
174*70a7ec85SAndroid Build Coastguard Worker // the XML document is fully deserialized.
175*70a7ec85SAndroid Build Coastguard Worker // * Except metaVersion, which is immediately modified when parsing top-level <manifest>
176*70a7ec85SAndroid Build Coastguard Worker // or <compatibility-matrix>, and unchanged thereafter;
177*70a7ec85SAndroid Build Coastguard Worker // see HalManifestConverter::BuildObject and CompatibilityMatrixConverter::BuildObject)
178*70a7ec85SAndroid Build Coastguard Worker // These parameters are also passed to converters of child nodes so they see the same
179*70a7ec85SAndroid Build Coastguard Worker // deserialization parameters.
180*70a7ec85SAndroid Build Coastguard Worker struct BuildObjectParam {
181*70a7ec85SAndroid Build Coastguard Worker std::string* error;
182*70a7ec85SAndroid Build Coastguard Worker Version metaVersion;
183*70a7ec85SAndroid Build Coastguard Worker std::string fileName;
184*70a7ec85SAndroid Build Coastguard Worker };
185*70a7ec85SAndroid Build Coastguard Worker
186*70a7ec85SAndroid Build Coastguard Worker template <typename Object>
187*70a7ec85SAndroid Build Coastguard Worker struct XmlNodeConverter {
XmlNodeConverterandroid::vintf::XmlNodeConverter188*70a7ec85SAndroid Build Coastguard Worker XmlNodeConverter() {}
~XmlNodeConverterandroid::vintf::XmlNodeConverter189*70a7ec85SAndroid Build Coastguard Worker virtual ~XmlNodeConverter() {}
190*70a7ec85SAndroid Build Coastguard Worker
191*70a7ec85SAndroid Build Coastguard Worker protected:
192*70a7ec85SAndroid Build Coastguard Worker virtual void mutateNode(const Object& object, NodeType* root, const MutateNodeParam&) const = 0;
193*70a7ec85SAndroid Build Coastguard Worker virtual bool buildObject(Object* object, NodeType* root, const BuildObjectParam&) const = 0;
194*70a7ec85SAndroid Build Coastguard Worker
195*70a7ec85SAndroid Build Coastguard Worker public:
196*70a7ec85SAndroid Build Coastguard Worker // Methods for other (usually parent) converters
197*70a7ec85SAndroid Build Coastguard Worker // Name of the XML element.
198*70a7ec85SAndroid Build Coastguard Worker virtual std::string elementName() const = 0;
199*70a7ec85SAndroid Build Coastguard Worker // Serialize |o| into an XML element.
operator ()android::vintf::XmlNodeConverter200*70a7ec85SAndroid Build Coastguard Worker inline NodeType* operator()(const Object& o, const MutateNodeParam& param) const {
201*70a7ec85SAndroid Build Coastguard Worker NodeType* root = createNode(this->elementName(), param.d);
202*70a7ec85SAndroid Build Coastguard Worker this->mutateNode(o, root, param);
203*70a7ec85SAndroid Build Coastguard Worker return root;
204*70a7ec85SAndroid Build Coastguard Worker }
205*70a7ec85SAndroid Build Coastguard Worker // Deserialize XML element |root| into |object|.
operator ()android::vintf::XmlNodeConverter206*70a7ec85SAndroid Build Coastguard Worker inline bool operator()(Object* object, NodeType* root, const BuildObjectParam& param) const {
207*70a7ec85SAndroid Build Coastguard Worker if (nameOf(root) != this->elementName()) {
208*70a7ec85SAndroid Build Coastguard Worker *param.error = "The root name(" + nameOf(root) + ") does not match the element name (" +
209*70a7ec85SAndroid Build Coastguard Worker this->elementName() + ")";
210*70a7ec85SAndroid Build Coastguard Worker return false;
211*70a7ec85SAndroid Build Coastguard Worker }
212*70a7ec85SAndroid Build Coastguard Worker return this->buildObject(object, root, param);
213*70a7ec85SAndroid Build Coastguard Worker }
214*70a7ec85SAndroid Build Coastguard Worker
215*70a7ec85SAndroid Build Coastguard Worker // Public methods for android::vintf::fromXml / android::vintf::toXml.
216*70a7ec85SAndroid Build Coastguard Worker // Serialize |o| into an XML string.
toXmlandroid::vintf::XmlNodeConverter217*70a7ec85SAndroid Build Coastguard Worker inline std::string toXml(const Object& o, SerializeFlags::Type flags) const {
218*70a7ec85SAndroid Build Coastguard Worker DocType* doc = createDocument();
219*70a7ec85SAndroid Build Coastguard Worker appendChild(doc, (*this)(o, MutateNodeParam{doc, flags}));
220*70a7ec85SAndroid Build Coastguard Worker std::string s = printDocument(doc);
221*70a7ec85SAndroid Build Coastguard Worker deleteDocument(doc);
222*70a7ec85SAndroid Build Coastguard Worker return s;
223*70a7ec85SAndroid Build Coastguard Worker }
224*70a7ec85SAndroid Build Coastguard Worker // Deserialize XML string |xml| into |o|.
fromXmlandroid::vintf::XmlNodeConverter225*70a7ec85SAndroid Build Coastguard Worker inline bool fromXml(Object* o, const std::string& xml, std::string* error) const {
226*70a7ec85SAndroid Build Coastguard Worker std::string errorBuffer;
227*70a7ec85SAndroid Build Coastguard Worker if (error == nullptr) error = &errorBuffer;
228*70a7ec85SAndroid Build Coastguard Worker
229*70a7ec85SAndroid Build Coastguard Worker auto doc = createDocument(xml);
230*70a7ec85SAndroid Build Coastguard Worker if (doc == nullptr) {
231*70a7ec85SAndroid Build Coastguard Worker *error = "Not a valid XML";
232*70a7ec85SAndroid Build Coastguard Worker return false;
233*70a7ec85SAndroid Build Coastguard Worker }
234*70a7ec85SAndroid Build Coastguard Worker // For top-level <manifest> and <compatibility-matrix>, HalManifestConverter and
235*70a7ec85SAndroid Build Coastguard Worker // CompatibilityMatrixConverter fills in metaversion and pass down to children.
236*70a7ec85SAndroid Build Coastguard Worker // For other nodes, we don't know metaversion of the original XML, so just leave empty
237*70a7ec85SAndroid Build Coastguard Worker // for maximum backwards compatibility.
238*70a7ec85SAndroid Build Coastguard Worker BuildObjectParam buildObjectParam{error, {}, {}};
239*70a7ec85SAndroid Build Coastguard Worker // Pass down filename for the current XML document.
240*70a7ec85SAndroid Build Coastguard Worker if constexpr (std::is_base_of_v<WithFileName, Object>) {
241*70a7ec85SAndroid Build Coastguard Worker // Get the last filename in case `o` keeps the list of filenames
242*70a7ec85SAndroid Build Coastguard Worker std::string_view fileName{o->fileName()};
243*70a7ec85SAndroid Build Coastguard Worker if (auto pos = fileName.rfind(':'); pos != fileName.npos) {
244*70a7ec85SAndroid Build Coastguard Worker fileName.remove_prefix(pos + 1);
245*70a7ec85SAndroid Build Coastguard Worker }
246*70a7ec85SAndroid Build Coastguard Worker buildObjectParam.fileName = std::string(fileName);
247*70a7ec85SAndroid Build Coastguard Worker }
248*70a7ec85SAndroid Build Coastguard Worker bool ret = (*this)(o, getRootChild(doc), buildObjectParam);
249*70a7ec85SAndroid Build Coastguard Worker deleteDocument(doc);
250*70a7ec85SAndroid Build Coastguard Worker return ret;
251*70a7ec85SAndroid Build Coastguard Worker }
252*70a7ec85SAndroid Build Coastguard Worker
253*70a7ec85SAndroid Build Coastguard Worker // convenience methods for subclasses to implement virtual functions.
254*70a7ec85SAndroid Build Coastguard Worker
255*70a7ec85SAndroid Build Coastguard Worker // All append* functions helps mutateNode() to serialize the object into XML.
256*70a7ec85SAndroid Build Coastguard Worker template <typename T>
appendAttrandroid::vintf::XmlNodeConverter257*70a7ec85SAndroid Build Coastguard Worker inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
258*70a7ec85SAndroid Build Coastguard Worker return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
259*70a7ec85SAndroid Build Coastguard Worker }
260*70a7ec85SAndroid Build Coastguard Worker
appendAttrandroid::vintf::XmlNodeConverter261*70a7ec85SAndroid Build Coastguard Worker inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
262*70a7ec85SAndroid Build Coastguard Worker return appendStrAttr(e, attrName, attr ? "true" : "false");
263*70a7ec85SAndroid Build Coastguard Worker }
264*70a7ec85SAndroid Build Coastguard Worker
265*70a7ec85SAndroid Build Coastguard Worker // text -> <name>text</name>
appendTextElementandroid::vintf::XmlNodeConverter266*70a7ec85SAndroid Build Coastguard Worker inline void appendTextElement(NodeType *parent, const std::string &name,
267*70a7ec85SAndroid Build Coastguard Worker const std::string &text, DocType *d) const {
268*70a7ec85SAndroid Build Coastguard Worker NodeType *c = createNode(name, d);
269*70a7ec85SAndroid Build Coastguard Worker appendText(c, text, d);
270*70a7ec85SAndroid Build Coastguard Worker appendChild(parent, c);
271*70a7ec85SAndroid Build Coastguard Worker }
272*70a7ec85SAndroid Build Coastguard Worker
273*70a7ec85SAndroid Build Coastguard Worker // text -> <name>text</name>
274*70a7ec85SAndroid Build Coastguard Worker template<typename Array>
appendTextElementsandroid::vintf::XmlNodeConverter275*70a7ec85SAndroid Build Coastguard Worker inline void appendTextElements(NodeType *parent, const std::string &name,
276*70a7ec85SAndroid Build Coastguard Worker const Array &array, DocType *d) const {
277*70a7ec85SAndroid Build Coastguard Worker for (const std::string &text : array) {
278*70a7ec85SAndroid Build Coastguard Worker NodeType *c = createNode(name, d);
279*70a7ec85SAndroid Build Coastguard Worker appendText(c, text, d);
280*70a7ec85SAndroid Build Coastguard Worker appendChild(parent, c);
281*70a7ec85SAndroid Build Coastguard Worker }
282*70a7ec85SAndroid Build Coastguard Worker }
283*70a7ec85SAndroid Build Coastguard Worker
284*70a7ec85SAndroid Build Coastguard Worker template <typename T, typename Array>
appendChildrenandroid::vintf::XmlNodeConverter285*70a7ec85SAndroid Build Coastguard Worker inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
286*70a7ec85SAndroid Build Coastguard Worker const Array& array, const MutateNodeParam& param) const {
287*70a7ec85SAndroid Build Coastguard Worker for (const T &t : array) {
288*70a7ec85SAndroid Build Coastguard Worker appendChild(parent, conv(t, param));
289*70a7ec85SAndroid Build Coastguard Worker }
290*70a7ec85SAndroid Build Coastguard Worker }
291*70a7ec85SAndroid Build Coastguard Worker
292*70a7ec85SAndroid Build Coastguard Worker // All parse* functions helps buildObject() to deserialize XML to the object. Returns
293*70a7ec85SAndroid Build Coastguard Worker // true if deserialization is successful, false if any error, and "error" will be
294*70a7ec85SAndroid Build Coastguard Worker // set to error message.
295*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseOptionalAttrandroid::vintf::XmlNodeConverter296*70a7ec85SAndroid Build Coastguard Worker inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
297*70a7ec85SAndroid Build Coastguard Worker T* attr, const BuildObjectParam& param) const {
298*70a7ec85SAndroid Build Coastguard Worker std::string attrText;
299*70a7ec85SAndroid Build Coastguard Worker bool success = getAttr(root, attrName, &attrText);
300*70a7ec85SAndroid Build Coastguard Worker bool parseSuccess = true;
301*70a7ec85SAndroid Build Coastguard Worker if (success) {
302*70a7ec85SAndroid Build Coastguard Worker parseSuccess = ::android::vintf::parse(attrText, attr);
303*70a7ec85SAndroid Build Coastguard Worker } else {
304*70a7ec85SAndroid Build Coastguard Worker *attr = std::move(defaultValue);
305*70a7ec85SAndroid Build Coastguard Worker }
306*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion >= kMetaVersionStrictAttributeValues) {
307*70a7ec85SAndroid Build Coastguard Worker if (!parseSuccess && param.error) {
308*70a7ec85SAndroid Build Coastguard Worker *param.error += "Unknown value (\"" + attrText + "\") for attribute '" + attrName +
309*70a7ec85SAndroid Build Coastguard Worker "' is considered a failure.";
310*70a7ec85SAndroid Build Coastguard Worker }
311*70a7ec85SAndroid Build Coastguard Worker return parseSuccess;
312*70a7ec85SAndroid Build Coastguard Worker } else {
313*70a7ec85SAndroid Build Coastguard Worker return true;
314*70a7ec85SAndroid Build Coastguard Worker }
315*70a7ec85SAndroid Build Coastguard Worker }
316*70a7ec85SAndroid Build Coastguard Worker
317*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseAttrandroid::vintf::XmlNodeConverter318*70a7ec85SAndroid Build Coastguard Worker inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
319*70a7ec85SAndroid Build Coastguard Worker std::string* error) const {
320*70a7ec85SAndroid Build Coastguard Worker std::string attrText;
321*70a7ec85SAndroid Build Coastguard Worker bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
322*70a7ec85SAndroid Build Coastguard Worker if (!ret) {
323*70a7ec85SAndroid Build Coastguard Worker *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
324*70a7ec85SAndroid Build Coastguard Worker attrText + "\" for element <" + elementName() + ">";
325*70a7ec85SAndroid Build Coastguard Worker }
326*70a7ec85SAndroid Build Coastguard Worker return ret;
327*70a7ec85SAndroid Build Coastguard Worker }
328*70a7ec85SAndroid Build Coastguard Worker
parseAttrandroid::vintf::XmlNodeConverter329*70a7ec85SAndroid Build Coastguard Worker inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
330*70a7ec85SAndroid Build Coastguard Worker std::string* error) const {
331*70a7ec85SAndroid Build Coastguard Worker bool ret = getAttr(root, attrName, attr);
332*70a7ec85SAndroid Build Coastguard Worker if (!ret) {
333*70a7ec85SAndroid Build Coastguard Worker *error = "Could not find attr with name \"" + attrName + "\" for element <" +
334*70a7ec85SAndroid Build Coastguard Worker elementName() + ">";
335*70a7ec85SAndroid Build Coastguard Worker }
336*70a7ec85SAndroid Build Coastguard Worker return ret;
337*70a7ec85SAndroid Build Coastguard Worker }
338*70a7ec85SAndroid Build Coastguard Worker
parseTextElementandroid::vintf::XmlNodeConverter339*70a7ec85SAndroid Build Coastguard Worker inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
340*70a7ec85SAndroid Build Coastguard Worker std::string* error) const {
341*70a7ec85SAndroid Build Coastguard Worker NodeType *child = getChild(root, elementName);
342*70a7ec85SAndroid Build Coastguard Worker if (child == nullptr) {
343*70a7ec85SAndroid Build Coastguard Worker *error = "Could not find element with name <" + elementName + "> in element <" +
344*70a7ec85SAndroid Build Coastguard Worker this->elementName() + ">";
345*70a7ec85SAndroid Build Coastguard Worker return false;
346*70a7ec85SAndroid Build Coastguard Worker }
347*70a7ec85SAndroid Build Coastguard Worker *s = getText(child);
348*70a7ec85SAndroid Build Coastguard Worker return true;
349*70a7ec85SAndroid Build Coastguard Worker }
350*70a7ec85SAndroid Build Coastguard Worker
351*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseOptionalTextElementandroid::vintf::XmlNodeConverter352*70a7ec85SAndroid Build Coastguard Worker inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
353*70a7ec85SAndroid Build Coastguard Worker T&& defaultValue, T* s, std::string* /* error */) const {
354*70a7ec85SAndroid Build Coastguard Worker NodeType* child = getChild(root, elementName);
355*70a7ec85SAndroid Build Coastguard Worker *s = child == nullptr ? std::move(defaultValue) : getText(child);
356*70a7ec85SAndroid Build Coastguard Worker return true;
357*70a7ec85SAndroid Build Coastguard Worker }
358*70a7ec85SAndroid Build Coastguard Worker
parseTextElementsandroid::vintf::XmlNodeConverter359*70a7ec85SAndroid Build Coastguard Worker inline bool parseTextElements(NodeType* root, const std::string& elementName,
360*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string>* v, std::string* /* error */) const {
361*70a7ec85SAndroid Build Coastguard Worker auto nodes = getChildren(root, elementName);
362*70a7ec85SAndroid Build Coastguard Worker v->resize(nodes.size());
363*70a7ec85SAndroid Build Coastguard Worker for (size_t i = 0; i < nodes.size(); ++i) {
364*70a7ec85SAndroid Build Coastguard Worker v->at(i) = getText(nodes[i]);
365*70a7ec85SAndroid Build Coastguard Worker }
366*70a7ec85SAndroid Build Coastguard Worker return true;
367*70a7ec85SAndroid Build Coastguard Worker }
368*70a7ec85SAndroid Build Coastguard Worker
369*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseChildandroid::vintf::XmlNodeConverter370*70a7ec85SAndroid Build Coastguard Worker inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
371*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const {
372*70a7ec85SAndroid Build Coastguard Worker NodeType *child = getChild(root, conv.elementName());
373*70a7ec85SAndroid Build Coastguard Worker if (child == nullptr) {
374*70a7ec85SAndroid Build Coastguard Worker *param.error = "Could not find element with name <" + conv.elementName() +
375*70a7ec85SAndroid Build Coastguard Worker "> in element <" + this->elementName() + ">";
376*70a7ec85SAndroid Build Coastguard Worker return false;
377*70a7ec85SAndroid Build Coastguard Worker }
378*70a7ec85SAndroid Build Coastguard Worker return conv(t, child, param);
379*70a7ec85SAndroid Build Coastguard Worker }
380*70a7ec85SAndroid Build Coastguard Worker
381*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter382*70a7ec85SAndroid Build Coastguard Worker inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
383*70a7ec85SAndroid Build Coastguard Worker T&& defaultValue, T* t, const BuildObjectParam& param) const {
384*70a7ec85SAndroid Build Coastguard Worker NodeType *child = getChild(root, conv.elementName());
385*70a7ec85SAndroid Build Coastguard Worker if (child == nullptr) {
386*70a7ec85SAndroid Build Coastguard Worker *t = std::move(defaultValue);
387*70a7ec85SAndroid Build Coastguard Worker return true;
388*70a7ec85SAndroid Build Coastguard Worker }
389*70a7ec85SAndroid Build Coastguard Worker return conv(t, child, param);
390*70a7ec85SAndroid Build Coastguard Worker }
391*70a7ec85SAndroid Build Coastguard Worker
392*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseOptionalChildandroid::vintf::XmlNodeConverter393*70a7ec85SAndroid Build Coastguard Worker inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
394*70a7ec85SAndroid Build Coastguard Worker std::optional<T>* t, const BuildObjectParam& param) const {
395*70a7ec85SAndroid Build Coastguard Worker NodeType* child = getChild(root, conv.elementName());
396*70a7ec85SAndroid Build Coastguard Worker if (child == nullptr) {
397*70a7ec85SAndroid Build Coastguard Worker *t = std::nullopt;
398*70a7ec85SAndroid Build Coastguard Worker return true;
399*70a7ec85SAndroid Build Coastguard Worker }
400*70a7ec85SAndroid Build Coastguard Worker *t = std::make_optional<T>();
401*70a7ec85SAndroid Build Coastguard Worker return conv(&**t, child, param);
402*70a7ec85SAndroid Build Coastguard Worker }
403*70a7ec85SAndroid Build Coastguard Worker
404*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseChildrenandroid::vintf::XmlNodeConverter405*70a7ec85SAndroid Build Coastguard Worker inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
406*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const {
407*70a7ec85SAndroid Build Coastguard Worker auto nodes = getChildren(root, conv.elementName());
408*70a7ec85SAndroid Build Coastguard Worker v->resize(nodes.size());
409*70a7ec85SAndroid Build Coastguard Worker for (size_t i = 0; i < nodes.size(); ++i) {
410*70a7ec85SAndroid Build Coastguard Worker if (!conv(&v->at(i), nodes[i], param)) {
411*70a7ec85SAndroid Build Coastguard Worker *param.error = "Could not parse element with name <" + conv.elementName() +
412*70a7ec85SAndroid Build Coastguard Worker "> in element <" + this->elementName() + ">: " + *param.error;
413*70a7ec85SAndroid Build Coastguard Worker return false;
414*70a7ec85SAndroid Build Coastguard Worker }
415*70a7ec85SAndroid Build Coastguard Worker }
416*70a7ec85SAndroid Build Coastguard Worker return true;
417*70a7ec85SAndroid Build Coastguard Worker }
418*70a7ec85SAndroid Build Coastguard Worker
419*70a7ec85SAndroid Build Coastguard Worker template <typename Container, typename T = typename Container::value_type,
420*70a7ec85SAndroid Build Coastguard Worker typename = typename Container::key_compare>
parseChildrenandroid::vintf::XmlNodeConverter421*70a7ec85SAndroid Build Coastguard Worker inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
422*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const {
423*70a7ec85SAndroid Build Coastguard Worker std::vector<T> vec;
424*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, conv, &vec, param)) {
425*70a7ec85SAndroid Build Coastguard Worker return false;
426*70a7ec85SAndroid Build Coastguard Worker }
427*70a7ec85SAndroid Build Coastguard Worker s->clear();
428*70a7ec85SAndroid Build Coastguard Worker s->insert(vec.begin(), vec.end());
429*70a7ec85SAndroid Build Coastguard Worker if (s->size() != vec.size()) {
430*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated elements <" + conv.elementName() + "> in element <" +
431*70a7ec85SAndroid Build Coastguard Worker this->elementName() + ">";
432*70a7ec85SAndroid Build Coastguard Worker s->clear();
433*70a7ec85SAndroid Build Coastguard Worker return false;
434*70a7ec85SAndroid Build Coastguard Worker }
435*70a7ec85SAndroid Build Coastguard Worker return true;
436*70a7ec85SAndroid Build Coastguard Worker }
437*70a7ec85SAndroid Build Coastguard Worker
438*70a7ec85SAndroid Build Coastguard Worker template <typename K, typename V>
parseChildrenandroid::vintf::XmlNodeConverter439*70a7ec85SAndroid Build Coastguard Worker inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
440*70a7ec85SAndroid Build Coastguard Worker std::map<K, V>* s, const BuildObjectParam& param) const {
441*70a7ec85SAndroid Build Coastguard Worker return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, param);
442*70a7ec85SAndroid Build Coastguard Worker }
443*70a7ec85SAndroid Build Coastguard Worker
parseTextandroid::vintf::XmlNodeConverter444*70a7ec85SAndroid Build Coastguard Worker inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
445*70a7ec85SAndroid Build Coastguard Worker *s = getText(node);
446*70a7ec85SAndroid Build Coastguard Worker return true;
447*70a7ec85SAndroid Build Coastguard Worker }
448*70a7ec85SAndroid Build Coastguard Worker
449*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseTextandroid::vintf::XmlNodeConverter450*70a7ec85SAndroid Build Coastguard Worker inline bool parseText(NodeType* node, T* s, std::string* error) const {
451*70a7ec85SAndroid Build Coastguard Worker bool (*parser)(const std::string&, T*) = ::android::vintf::parse;
452*70a7ec85SAndroid Build Coastguard Worker return parseText(node, s, {parser}, error);
453*70a7ec85SAndroid Build Coastguard Worker }
454*70a7ec85SAndroid Build Coastguard Worker
455*70a7ec85SAndroid Build Coastguard Worker template <typename T>
parseTextandroid::vintf::XmlNodeConverter456*70a7ec85SAndroid Build Coastguard Worker inline bool parseText(NodeType* node, T* s,
457*70a7ec85SAndroid Build Coastguard Worker const std::function<bool(const std::string&, T*)>& parse,
458*70a7ec85SAndroid Build Coastguard Worker std::string* error) const {
459*70a7ec85SAndroid Build Coastguard Worker std::string text = getText(node);
460*70a7ec85SAndroid Build Coastguard Worker bool ret = parse(text, s);
461*70a7ec85SAndroid Build Coastguard Worker if (!ret) {
462*70a7ec85SAndroid Build Coastguard Worker *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
463*70a7ec85SAndroid Build Coastguard Worker }
464*70a7ec85SAndroid Build Coastguard Worker return ret;
465*70a7ec85SAndroid Build Coastguard Worker }
466*70a7ec85SAndroid Build Coastguard Worker };
467*70a7ec85SAndroid Build Coastguard Worker
468*70a7ec85SAndroid Build Coastguard Worker template<typename Object>
469*70a7ec85SAndroid Build Coastguard Worker struct XmlTextConverter : public XmlNodeConverter<Object> {
mutateNodeandroid::vintf::XmlTextConverter470*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const Object& object, NodeType* root,
471*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
472*70a7ec85SAndroid Build Coastguard Worker appendText(root, ::android::vintf::to_string(object), param.d);
473*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::XmlTextConverter474*70a7ec85SAndroid Build Coastguard Worker bool buildObject(Object* object, NodeType* root, const BuildObjectParam& param) const override {
475*70a7ec85SAndroid Build Coastguard Worker return this->parseText(root, object, param.error);
476*70a7ec85SAndroid Build Coastguard Worker }
477*70a7ec85SAndroid Build Coastguard Worker };
478*70a7ec85SAndroid Build Coastguard Worker
479*70a7ec85SAndroid Build Coastguard Worker template <typename Pair, typename FirstConverter, typename SecondConverter>
480*70a7ec85SAndroid Build Coastguard Worker struct XmlPairConverter : public XmlNodeConverter<Pair> {
mutateNodeandroid::vintf::XmlPairConverter481*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const Pair& object, NodeType* root,
482*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
483*70a7ec85SAndroid Build Coastguard Worker appendChild(root, FirstConverter{}(object.first, param));
484*70a7ec85SAndroid Build Coastguard Worker appendChild(root, SecondConverter{}(object.second, param));
485*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::XmlPairConverter486*70a7ec85SAndroid Build Coastguard Worker bool buildObject(Pair* object, NodeType* root, const BuildObjectParam& param) const override {
487*70a7ec85SAndroid Build Coastguard Worker return this->parseChild(root, FirstConverter{}, &object->first, param) &&
488*70a7ec85SAndroid Build Coastguard Worker this->parseChild(root, SecondConverter{}, &object->second, param);
489*70a7ec85SAndroid Build Coastguard Worker }
490*70a7ec85SAndroid Build Coastguard Worker };
491*70a7ec85SAndroid Build Coastguard Worker
492*70a7ec85SAndroid Build Coastguard Worker // ---------------------- XmlNodeConverter definitions end
493*70a7ec85SAndroid Build Coastguard Worker
494*70a7ec85SAndroid Build Coastguard Worker struct VersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::VersionConverter495*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
496*70a7ec85SAndroid Build Coastguard Worker };
497*70a7ec85SAndroid Build Coastguard Worker
498*70a7ec85SAndroid Build Coastguard Worker struct SepolicyVersionConverter : public XmlTextConverter<SepolicyVersion> {
elementNameandroid::vintf::SepolicyVersionConverter499*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
500*70a7ec85SAndroid Build Coastguard Worker };
501*70a7ec85SAndroid Build Coastguard Worker
502*70a7ec85SAndroid Build Coastguard Worker struct VersionRangeConverter : public XmlTextConverter<VersionRange> {
elementNameandroid::vintf::VersionRangeConverter503*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
504*70a7ec85SAndroid Build Coastguard Worker };
505*70a7ec85SAndroid Build Coastguard Worker
506*70a7ec85SAndroid Build Coastguard Worker struct SepolicyVersionRangeConverter : public XmlTextConverter<SepolicyVersionRange> {
elementNameandroid::vintf::SepolicyVersionRangeConverter507*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "sepolicy-version"; }
508*70a7ec85SAndroid Build Coastguard Worker };
509*70a7ec85SAndroid Build Coastguard Worker
510*70a7ec85SAndroid Build Coastguard Worker // <version>100</version> <=> Version{kFakeAidlMajorVersion, 100}
511*70a7ec85SAndroid Build Coastguard Worker struct AidlVersionConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AidlVersionConverter512*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionConverter513*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const Version& object, NodeType* root,
514*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
515*70a7ec85SAndroid Build Coastguard Worker appendText(root, aidlVersionToString(object), param.d);
516*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::AidlVersionConverter517*70a7ec85SAndroid Build Coastguard Worker bool buildObject(Version* object, NodeType* root,
518*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
519*70a7ec85SAndroid Build Coastguard Worker return parseText(root, object, {parseAidlVersion}, param.error);
520*70a7ec85SAndroid Build Coastguard Worker }
521*70a7ec85SAndroid Build Coastguard Worker };
522*70a7ec85SAndroid Build Coastguard Worker
523*70a7ec85SAndroid Build Coastguard Worker // <version>100</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 100}
524*70a7ec85SAndroid Build Coastguard Worker // <version>100-105</version> <=> VersionRange{kFakeAidlMajorVersion, 100, 105}
525*70a7ec85SAndroid Build Coastguard Worker struct AidlVersionRangeConverter : public XmlNodeConverter<VersionRange> {
elementNameandroid::vintf::AidlVersionRangeConverter526*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
mutateNodeandroid::vintf::AidlVersionRangeConverter527*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const VersionRange& object, NodeType* root,
528*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
529*70a7ec85SAndroid Build Coastguard Worker appendText(root, aidlVersionRangeToString(object), param.d);
530*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::AidlVersionRangeConverter531*70a7ec85SAndroid Build Coastguard Worker bool buildObject(VersionRange* object, NodeType* root,
532*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
533*70a7ec85SAndroid Build Coastguard Worker return parseText(root, object, {parseAidlVersionRange}, param.error);
534*70a7ec85SAndroid Build Coastguard Worker }
535*70a7ec85SAndroid Build Coastguard Worker };
536*70a7ec85SAndroid Build Coastguard Worker
537*70a7ec85SAndroid Build Coastguard Worker struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
elementNameandroid::vintf::TransportArchConverter538*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "transport"; }
mutateNodeandroid::vintf::TransportArchConverter539*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const TransportArch& object, NodeType* root,
540*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
541*70a7ec85SAndroid Build Coastguard Worker if (object.arch != Arch::ARCH_EMPTY) {
542*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "arch", object.arch);
543*70a7ec85SAndroid Build Coastguard Worker }
544*70a7ec85SAndroid Build Coastguard Worker if (object.ip.has_value()) {
545*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "ip", *object.ip);
546*70a7ec85SAndroid Build Coastguard Worker }
547*70a7ec85SAndroid Build Coastguard Worker if (object.port.has_value()) {
548*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "port", *object.port);
549*70a7ec85SAndroid Build Coastguard Worker }
550*70a7ec85SAndroid Build Coastguard Worker appendText(root, ::android::vintf::to_string(object.transport), param.d);
551*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::TransportArchConverter552*70a7ec85SAndroid Build Coastguard Worker bool buildObject(TransportArch* object, NodeType* root,
553*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
554*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, param) ||
555*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "ip", {}, &object->ip, param) ||
556*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "port", {}, &object->port, param) ||
557*70a7ec85SAndroid Build Coastguard Worker !parseText(root, &object->transport, param.error)) {
558*70a7ec85SAndroid Build Coastguard Worker return false;
559*70a7ec85SAndroid Build Coastguard Worker }
560*70a7ec85SAndroid Build Coastguard Worker if (!object->isValid(param.error)) {
561*70a7ec85SAndroid Build Coastguard Worker return false;
562*70a7ec85SAndroid Build Coastguard Worker }
563*70a7ec85SAndroid Build Coastguard Worker return true;
564*70a7ec85SAndroid Build Coastguard Worker }
565*70a7ec85SAndroid Build Coastguard Worker };
566*70a7ec85SAndroid Build Coastguard Worker
567*70a7ec85SAndroid Build Coastguard Worker struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
elementNameandroid::vintf::KernelConfigTypedValueConverter568*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "value"; }
mutateNodeandroid::vintf::KernelConfigTypedValueConverter569*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const KernelConfigTypedValue& object, NodeType* root,
570*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
571*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "type", object.mType);
572*70a7ec85SAndroid Build Coastguard Worker appendText(root, ::android::vintf::to_string(object), param.d);
573*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::KernelConfigTypedValueConverter574*70a7ec85SAndroid Build Coastguard Worker bool buildObject(KernelConfigTypedValue* object, NodeType* root,
575*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
576*70a7ec85SAndroid Build Coastguard Worker std::string stringValue;
577*70a7ec85SAndroid Build Coastguard Worker if (!parseAttr(root, "type", &object->mType, param.error) ||
578*70a7ec85SAndroid Build Coastguard Worker !parseText(root, &stringValue, param.error)) {
579*70a7ec85SAndroid Build Coastguard Worker return false;
580*70a7ec85SAndroid Build Coastguard Worker }
581*70a7ec85SAndroid Build Coastguard Worker if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
582*70a7ec85SAndroid Build Coastguard Worker *param.error = "Could not parse kernel config value \"" + stringValue + "\"";
583*70a7ec85SAndroid Build Coastguard Worker return false;
584*70a7ec85SAndroid Build Coastguard Worker }
585*70a7ec85SAndroid Build Coastguard Worker return true;
586*70a7ec85SAndroid Build Coastguard Worker }
587*70a7ec85SAndroid Build Coastguard Worker };
588*70a7ec85SAndroid Build Coastguard Worker
589*70a7ec85SAndroid Build Coastguard Worker struct KernelConfigKeyConverter : public XmlTextConverter<KernelConfigKey> {
elementNameandroid::vintf::KernelConfigKeyConverter590*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "key"; }
591*70a7ec85SAndroid Build Coastguard Worker };
592*70a7ec85SAndroid Build Coastguard Worker
593*70a7ec85SAndroid Build Coastguard Worker struct MatrixKernelConfigConverter : public XmlPairConverter<KernelConfig, KernelConfigKeyConverter,
594*70a7ec85SAndroid Build Coastguard Worker KernelConfigTypedValueConverter> {
elementNameandroid::vintf::MatrixKernelConfigConverter595*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "config"; }
596*70a7ec85SAndroid Build Coastguard Worker };
597*70a7ec85SAndroid Build Coastguard Worker
598*70a7ec85SAndroid Build Coastguard Worker struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
elementNameandroid::vintf::HalInterfaceConverter599*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "interface"; }
mutateNodeandroid::vintf::HalInterfaceConverter600*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const HalInterface& object, NodeType* root,
601*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
602*70a7ec85SAndroid Build Coastguard Worker if (!object.name().empty()) {
603*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "name", object.name(), param.d);
604*70a7ec85SAndroid Build Coastguard Worker }
605*70a7ec85SAndroid Build Coastguard Worker appendTextElements(root, "instance", object.mInstances, param.d);
606*70a7ec85SAndroid Build Coastguard Worker appendTextElements(root, "regex-instance", object.mRegexes, param.d);
607*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::HalInterfaceConverter608*70a7ec85SAndroid Build Coastguard Worker bool buildObject(HalInterface* object, NodeType* root,
609*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
610*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string> instances;
611*70a7ec85SAndroid Build Coastguard Worker std::vector<std::string> regexes;
612*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalTextElement(root, "name", {}, &object->mName, param.error) ||
613*70a7ec85SAndroid Build Coastguard Worker !parseTextElements(root, "instance", &instances, param.error) ||
614*70a7ec85SAndroid Build Coastguard Worker !parseTextElements(root, "regex-instance", ®exes, param.error)) {
615*70a7ec85SAndroid Build Coastguard Worker return false;
616*70a7ec85SAndroid Build Coastguard Worker }
617*70a7ec85SAndroid Build Coastguard Worker bool success = true;
618*70a7ec85SAndroid Build Coastguard Worker for (const auto& e : instances) {
619*70a7ec85SAndroid Build Coastguard Worker if (!object->insertInstance(e, false /* isRegex */)) {
620*70a7ec85SAndroid Build Coastguard Worker if (!param.error->empty()) *param.error += "\n";
621*70a7ec85SAndroid Build Coastguard Worker *param.error += "Duplicated instance '" + e + "' in " + object->name();
622*70a7ec85SAndroid Build Coastguard Worker success = false;
623*70a7ec85SAndroid Build Coastguard Worker }
624*70a7ec85SAndroid Build Coastguard Worker }
625*70a7ec85SAndroid Build Coastguard Worker for (const auto& e : regexes) {
626*70a7ec85SAndroid Build Coastguard Worker details::Regex regex;
627*70a7ec85SAndroid Build Coastguard Worker if (!regex.compile(e)) {
628*70a7ec85SAndroid Build Coastguard Worker if (!param.error->empty()) *param.error += "\n";
629*70a7ec85SAndroid Build Coastguard Worker *param.error += "Invalid regular expression '" + e + "' in " + object->name();
630*70a7ec85SAndroid Build Coastguard Worker success = false;
631*70a7ec85SAndroid Build Coastguard Worker }
632*70a7ec85SAndroid Build Coastguard Worker if (!object->insertInstance(e, true /* isRegex */)) {
633*70a7ec85SAndroid Build Coastguard Worker if (!param.error->empty()) *param.error += "\n";
634*70a7ec85SAndroid Build Coastguard Worker *param.error += "Duplicated regex-instance '" + e + "' in " + object->name();
635*70a7ec85SAndroid Build Coastguard Worker success = false;
636*70a7ec85SAndroid Build Coastguard Worker }
637*70a7ec85SAndroid Build Coastguard Worker }
638*70a7ec85SAndroid Build Coastguard Worker return success;
639*70a7ec85SAndroid Build Coastguard Worker }
640*70a7ec85SAndroid Build Coastguard Worker };
641*70a7ec85SAndroid Build Coastguard Worker
642*70a7ec85SAndroid Build Coastguard Worker struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
elementNameandroid::vintf::MatrixHalConverter643*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::MatrixHalConverter644*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const MatrixHal& object, NodeType* root,
645*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
646*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "format", object.format);
647*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "optional", object.optional);
648*70a7ec85SAndroid Build Coastguard Worker // Only include if it is not the default empty value
649*70a7ec85SAndroid Build Coastguard Worker if (object.exclusiveTo != ExclusiveTo::EMPTY) {
650*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "exclusive-to", object.exclusiveTo);
651*70a7ec85SAndroid Build Coastguard Worker }
652*70a7ec85SAndroid Build Coastguard Worker // Only include update-via-apex if enabled
653*70a7ec85SAndroid Build Coastguard Worker if (object.updatableViaApex) {
654*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "updatable-via-apex", object.updatableViaApex);
655*70a7ec85SAndroid Build Coastguard Worker }
656*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "name", object.name, param.d);
657*70a7ec85SAndroid Build Coastguard Worker if (object.format == HalFormat::AIDL) {
658*70a7ec85SAndroid Build Coastguard Worker // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
659*70a7ec85SAndroid Build Coastguard Worker // is specified. Don't output any <version> tag if there's only one <version>0</version>
660*70a7ec85SAndroid Build Coastguard Worker // tag.
661*70a7ec85SAndroid Build Coastguard Worker if (object.versionRanges.size() != 1 ||
662*70a7ec85SAndroid Build Coastguard Worker object.versionRanges[0] != details::kDefaultAidlVersionRange) {
663*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, AidlVersionRangeConverter{}, object.versionRanges, param);
664*70a7ec85SAndroid Build Coastguard Worker }
665*70a7ec85SAndroid Build Coastguard Worker } else {
666*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, VersionRangeConverter{}, object.versionRanges, param);
667*70a7ec85SAndroid Build Coastguard Worker }
668*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, HalInterfaceConverter{}, iterateValues(object.interfaces), param);
669*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::MatrixHalConverter670*70a7ec85SAndroid Build Coastguard Worker bool buildObject(MatrixHal* object, NodeType* root,
671*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
672*70a7ec85SAndroid Build Coastguard Worker std::vector<HalInterface> interfaces;
673*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param) ||
674*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "optional", true /* defaultValue */, &object->optional,
675*70a7ec85SAndroid Build Coastguard Worker param) ||
676*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "exclusive-to", ExclusiveTo::EMPTY, &object->exclusiveTo,
677*70a7ec85SAndroid Build Coastguard Worker param) ||
678*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "updatable-via-apex", false /* defaultValue */,
679*70a7ec85SAndroid Build Coastguard Worker &object->updatableViaApex, param) ||
680*70a7ec85SAndroid Build Coastguard Worker !parseTextElement(root, "name", &object->name, param.error) ||
681*70a7ec85SAndroid Build Coastguard Worker !parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
682*70a7ec85SAndroid Build Coastguard Worker return false;
683*70a7ec85SAndroid Build Coastguard Worker }
684*70a7ec85SAndroid Build Coastguard Worker if (object->format == HalFormat::AIDL) {
685*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, AidlVersionRangeConverter{}, &object->versionRanges, param)) {
686*70a7ec85SAndroid Build Coastguard Worker return false;
687*70a7ec85SAndroid Build Coastguard Worker }
688*70a7ec85SAndroid Build Coastguard Worker // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
689*70a7ec85SAndroid Build Coastguard Worker // HAL formats can be unified.
690*70a7ec85SAndroid Build Coastguard Worker if (object->versionRanges.empty()) {
691*70a7ec85SAndroid Build Coastguard Worker object->versionRanges.push_back(details::kDefaultAidlVersionRange);
692*70a7ec85SAndroid Build Coastguard Worker }
693*70a7ec85SAndroid Build Coastguard Worker } else {
694*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, VersionRangeConverter{}, &object->versionRanges, param)) {
695*70a7ec85SAndroid Build Coastguard Worker return false;
696*70a7ec85SAndroid Build Coastguard Worker }
697*70a7ec85SAndroid Build Coastguard Worker }
698*70a7ec85SAndroid Build Coastguard Worker for (auto&& interface : interfaces) {
699*70a7ec85SAndroid Build Coastguard Worker std::string name{interface.name()};
700*70a7ec85SAndroid Build Coastguard Worker auto res = object->interfaces.emplace(std::move(name), std::move(interface));
701*70a7ec85SAndroid Build Coastguard Worker if (!res.second) {
702*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated interface entry \"" + res.first->first +
703*70a7ec85SAndroid Build Coastguard Worker "\"; if additional instances are needed, add them to the "
704*70a7ec85SAndroid Build Coastguard Worker "existing <interface> node.";
705*70a7ec85SAndroid Build Coastguard Worker return false;
706*70a7ec85SAndroid Build Coastguard Worker }
707*70a7ec85SAndroid Build Coastguard Worker }
708*70a7ec85SAndroid Build Coastguard Worker if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
709*70a7ec85SAndroid Build Coastguard Worker return false;
710*70a7ec85SAndroid Build Coastguard Worker }
711*70a7ec85SAndroid Build Coastguard Worker
712*70a7ec85SAndroid Build Coastguard Worker if (!object->isValid(param.error)) {
713*70a7ec85SAndroid Build Coastguard Worker param.error->insert(0, "'" + object->name + "' is not a valid Matrix HAL: ");
714*70a7ec85SAndroid Build Coastguard Worker return false;
715*70a7ec85SAndroid Build Coastguard Worker }
716*70a7ec85SAndroid Build Coastguard Worker return true;
717*70a7ec85SAndroid Build Coastguard Worker }
718*70a7ec85SAndroid Build Coastguard Worker
719*70a7ec85SAndroid Build Coastguard Worker private:
checkAdditionalRestrictionsOnHalandroid::vintf::MatrixHalConverter720*70a7ec85SAndroid Build Coastguard Worker bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
721*70a7ec85SAndroid Build Coastguard Worker // Do not check for target-side libvintf to avoid restricting ability for upgrade
722*70a7ec85SAndroid Build Coastguard Worker // accidentally.
723*70a7ec85SAndroid Build Coastguard Worker if constexpr (kDevice) {
724*70a7ec85SAndroid Build Coastguard Worker return true;
725*70a7ec85SAndroid Build Coastguard Worker }
726*70a7ec85SAndroid Build Coastguard Worker if (hal.getName() == "netutils-wrapper") {
727*70a7ec85SAndroid Build Coastguard Worker if (hal.versionRanges.size() != 1) {
728*70a7ec85SAndroid Build Coastguard Worker *error =
729*70a7ec85SAndroid Build Coastguard Worker "netutils-wrapper HAL must specify exactly one version x.0, "
730*70a7ec85SAndroid Build Coastguard Worker "but multiple <version> element is specified.";
731*70a7ec85SAndroid Build Coastguard Worker return false;
732*70a7ec85SAndroid Build Coastguard Worker }
733*70a7ec85SAndroid Build Coastguard Worker const VersionRange& v = hal.versionRanges.at(0);
734*70a7ec85SAndroid Build Coastguard Worker if (!v.isSingleVersion()) {
735*70a7ec85SAndroid Build Coastguard Worker *error =
736*70a7ec85SAndroid Build Coastguard Worker "netutils-wrapper HAL must specify exactly one version x.0, "
737*70a7ec85SAndroid Build Coastguard Worker "but a range is provided. Perhaps you mean '" +
738*70a7ec85SAndroid Build Coastguard Worker to_string(Version{v.majorVer, 0}) + "'?";
739*70a7ec85SAndroid Build Coastguard Worker return false;
740*70a7ec85SAndroid Build Coastguard Worker }
741*70a7ec85SAndroid Build Coastguard Worker if (v.minMinor != 0) {
742*70a7ec85SAndroid Build Coastguard Worker *error =
743*70a7ec85SAndroid Build Coastguard Worker "netutils-wrapper HAL must specify exactly one version x.0, "
744*70a7ec85SAndroid Build Coastguard Worker "but minor version is not 0. Perhaps you mean '" +
745*70a7ec85SAndroid Build Coastguard Worker to_string(Version{v.majorVer, 0}) + "'?";
746*70a7ec85SAndroid Build Coastguard Worker return false;
747*70a7ec85SAndroid Build Coastguard Worker }
748*70a7ec85SAndroid Build Coastguard Worker }
749*70a7ec85SAndroid Build Coastguard Worker return true;
750*70a7ec85SAndroid Build Coastguard Worker }
751*70a7ec85SAndroid Build Coastguard Worker };
752*70a7ec85SAndroid Build Coastguard Worker
753*70a7ec85SAndroid Build Coastguard Worker struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
elementNameandroid::vintf::MatrixKernelConditionsConverter754*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "conditions"; }
mutateNodeandroid::vintf::MatrixKernelConditionsConverter755*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const std::vector<KernelConfig>& object, NodeType* root,
756*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
757*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, MatrixKernelConfigConverter{}, object, param);
758*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::MatrixKernelConditionsConverter759*70a7ec85SAndroid Build Coastguard Worker bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
760*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
761*70a7ec85SAndroid Build Coastguard Worker return parseChildren(root, MatrixKernelConfigConverter{}, object, param);
762*70a7ec85SAndroid Build Coastguard Worker }
763*70a7ec85SAndroid Build Coastguard Worker };
764*70a7ec85SAndroid Build Coastguard Worker
765*70a7ec85SAndroid Build Coastguard Worker struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
elementNameandroid::vintf::MatrixKernelConverter766*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::MatrixKernelConverter767*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const MatrixKernel& object, NodeType* root,
768*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
769*70a7ec85SAndroid Build Coastguard Worker KernelVersion kv = object.mMinLts;
770*70a7ec85SAndroid Build Coastguard Worker if (!param.flags.isKernelMinorRevisionEnabled()) {
771*70a7ec85SAndroid Build Coastguard Worker kv.minorRev = 0u;
772*70a7ec85SAndroid Build Coastguard Worker }
773*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "version", kv);
774*70a7ec85SAndroid Build Coastguard Worker
775*70a7ec85SAndroid Build Coastguard Worker if (object.getSourceMatrixLevel() != Level::UNSPECIFIED) {
776*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "level", object.getSourceMatrixLevel());
777*70a7ec85SAndroid Build Coastguard Worker }
778*70a7ec85SAndroid Build Coastguard Worker
779*70a7ec85SAndroid Build Coastguard Worker if (!object.mConditions.empty()) {
780*70a7ec85SAndroid Build Coastguard Worker appendChild(root, MatrixKernelConditionsConverter{}(object.mConditions, param));
781*70a7ec85SAndroid Build Coastguard Worker }
782*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isKernelConfigsEnabled()) {
783*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, MatrixKernelConfigConverter{}, object.mConfigs, param);
784*70a7ec85SAndroid Build Coastguard Worker }
785*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::MatrixKernelConverter786*70a7ec85SAndroid Build Coastguard Worker bool buildObject(MatrixKernel* object, NodeType* root,
787*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
788*70a7ec85SAndroid Build Coastguard Worker Level sourceMatrixLevel = Level::UNSPECIFIED;
789*70a7ec85SAndroid Build Coastguard Worker if (!parseAttr(root, "version", &object->mMinLts, param.error) ||
790*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, param) ||
791*70a7ec85SAndroid Build Coastguard Worker !parseOptionalChild(root, MatrixKernelConditionsConverter{}, {}, &object->mConditions,
792*70a7ec85SAndroid Build Coastguard Worker param) ||
793*70a7ec85SAndroid Build Coastguard Worker !parseChildren(root, MatrixKernelConfigConverter{}, &object->mConfigs, param)) {
794*70a7ec85SAndroid Build Coastguard Worker return false;
795*70a7ec85SAndroid Build Coastguard Worker }
796*70a7ec85SAndroid Build Coastguard Worker object->setSourceMatrixLevel(sourceMatrixLevel);
797*70a7ec85SAndroid Build Coastguard Worker return true;
798*70a7ec85SAndroid Build Coastguard Worker }
799*70a7ec85SAndroid Build Coastguard Worker };
800*70a7ec85SAndroid Build Coastguard Worker
801*70a7ec85SAndroid Build Coastguard Worker struct FqInstanceConverter : public XmlTextConverter<FqInstance> {
elementNameandroid::vintf::FqInstanceConverter802*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "fqname"; }
803*70a7ec85SAndroid Build Coastguard Worker };
804*70a7ec85SAndroid Build Coastguard Worker
805*70a7ec85SAndroid Build Coastguard Worker // Convert ManifestHal from and to XML. Returned object is guaranteed to have
806*70a7ec85SAndroid Build Coastguard Worker // .isValid() == true.
807*70a7ec85SAndroid Build Coastguard Worker struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
elementNameandroid::vintf::ManifestHalConverter808*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "hal"; }
mutateNodeandroid::vintf::ManifestHalConverter809*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const ManifestHal& object, NodeType* root,
810*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
811*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "format", object.format);
812*70a7ec85SAndroid Build Coastguard Worker // Only include if it is not the default empty value
813*70a7ec85SAndroid Build Coastguard Worker if (object.exclusiveTo != ExclusiveTo::EMPTY) {
814*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "exclusive-to", object.exclusiveTo);
815*70a7ec85SAndroid Build Coastguard Worker }
816*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "name", object.name, param.d);
817*70a7ec85SAndroid Build Coastguard Worker if (!object.transportArch.empty()) {
818*70a7ec85SAndroid Build Coastguard Worker appendChild(root, TransportArchConverter{}(object.transportArch, param));
819*70a7ec85SAndroid Build Coastguard Worker }
820*70a7ec85SAndroid Build Coastguard Worker if (object.format == HalFormat::AIDL) {
821*70a7ec85SAndroid Build Coastguard Worker // By default, buildObject() assumes a <version>0</version> tag if no <version> tag
822*70a7ec85SAndroid Build Coastguard Worker // is specified. Don't output any <version> tag if there's only one <version>0</version>
823*70a7ec85SAndroid Build Coastguard Worker // tag.
824*70a7ec85SAndroid Build Coastguard Worker if (object.versions.size() != 1 || object.versions[0] != details::kDefaultAidlVersion) {
825*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, AidlVersionConverter{}, object.versions, param);
826*70a7ec85SAndroid Build Coastguard Worker }
827*70a7ec85SAndroid Build Coastguard Worker } else {
828*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, VersionConverter{}, object.versions, param);
829*70a7ec85SAndroid Build Coastguard Worker }
830*70a7ec85SAndroid Build Coastguard Worker if (object.isOverride()) {
831*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "override", object.isOverride());
832*70a7ec85SAndroid Build Coastguard Worker }
833*70a7ec85SAndroid Build Coastguard Worker if (const auto& apex = object.updatableViaApex(); apex.has_value()) {
834*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "updatable-via-apex", apex.value());
835*70a7ec85SAndroid Build Coastguard Worker }
836*70a7ec85SAndroid Build Coastguard Worker // Only include update-via-system if enabled
837*70a7ec85SAndroid Build Coastguard Worker if (object.updatableViaSystem()) {
838*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "updatable-via-system", object.updatableViaSystem());
839*70a7ec85SAndroid Build Coastguard Worker }
840*70a7ec85SAndroid Build Coastguard Worker if (const auto& accessor = object.accessor(); accessor.has_value()) {
841*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "accessor", accessor.value(), param.d);
842*70a7ec85SAndroid Build Coastguard Worker }
843*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isFqnameEnabled()) {
844*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> simpleFqInstances;
845*70a7ec85SAndroid Build Coastguard Worker object.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
846*70a7ec85SAndroid Build Coastguard Worker simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
847*70a7ec85SAndroid Build Coastguard Worker return true;
848*70a7ec85SAndroid Build Coastguard Worker });
849*70a7ec85SAndroid Build Coastguard Worker appendTextElements(root, FqInstanceConverter{}.elementName(), simpleFqInstances,
850*70a7ec85SAndroid Build Coastguard Worker param.d);
851*70a7ec85SAndroid Build Coastguard Worker }
852*70a7ec85SAndroid Build Coastguard Worker if (object.getMaxLevel() != Level::UNSPECIFIED) {
853*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "max-level", object.getMaxLevel());
854*70a7ec85SAndroid Build Coastguard Worker }
855*70a7ec85SAndroid Build Coastguard Worker if (object.getMinLevel() != Level::UNSPECIFIED) {
856*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "min-level", object.getMinLevel());
857*70a7ec85SAndroid Build Coastguard Worker }
858*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::ManifestHalConverter859*70a7ec85SAndroid Build Coastguard Worker bool buildObject(ManifestHal* object, NodeType* root,
860*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
861*70a7ec85SAndroid Build Coastguard Worker std::vector<HalInterface> interfaces;
862*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, param) ||
863*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "override", false, &object->mIsOverride, param) ||
864*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "exclusive-to", ExclusiveTo::EMPTY, &object->exclusiveTo,
865*70a7ec85SAndroid Build Coastguard Worker param) ||
866*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "updatable-via-apex", {}, &object->mUpdatableViaApex, param) ||
867*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "updatable-via-system", false /* defaultValue */,
868*70a7ec85SAndroid Build Coastguard Worker &object->mUpdatableViaSystem, param) ||
869*70a7ec85SAndroid Build Coastguard Worker !parseOptionalTextElement(root, "accessor", {}, &object->mAccessor, param.error) ||
870*70a7ec85SAndroid Build Coastguard Worker !parseTextElement(root, "name", &object->name, param.error) ||
871*70a7ec85SAndroid Build Coastguard Worker !parseOptionalChild(root, TransportArchConverter{}, {}, &object->transportArch,
872*70a7ec85SAndroid Build Coastguard Worker param) ||
873*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "max-level", Level::UNSPECIFIED, &object->mMaxLevel, param) ||
874*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "min-level", Level::UNSPECIFIED, &object->mMinLevel, param)) {
875*70a7ec85SAndroid Build Coastguard Worker return false;
876*70a7ec85SAndroid Build Coastguard Worker }
877*70a7ec85SAndroid Build Coastguard Worker if (getChildren(root, "accessor").size() > 1) {
878*70a7ec85SAndroid Build Coastguard Worker *param.error = "No more than one <accessor> is allowed in <hal>";
879*70a7ec85SAndroid Build Coastguard Worker return false;
880*70a7ec85SAndroid Build Coastguard Worker }
881*70a7ec85SAndroid Build Coastguard Worker
882*70a7ec85SAndroid Build Coastguard Worker std::string_view apexName = parseApexName(param.fileName);
883*70a7ec85SAndroid Build Coastguard Worker if (!apexName.empty()) {
884*70a7ec85SAndroid Build Coastguard Worker if (object->mUpdatableViaApex.has_value()) {
885*70a7ec85SAndroid Build Coastguard Worker // When defined in APEX, updatable-via-apex can be either
886*70a7ec85SAndroid Build Coastguard Worker // - ""(empty) : the HAL isn't updatable even if it's in APEX
887*70a7ec85SAndroid Build Coastguard Worker // - {apex name}: the HAL is updtable via the current APEX
888*70a7ec85SAndroid Build Coastguard Worker const std::string& updatableViaApex = object->mUpdatableViaApex.value();
889*70a7ec85SAndroid Build Coastguard Worker if (!updatableViaApex.empty() && apexName.compare(updatableViaApex) != 0) {
890*70a7ec85SAndroid Build Coastguard Worker *param.error = "Invalid APEX HAL " + object->name + ": updatable-via-apex " +
891*70a7ec85SAndroid Build Coastguard Worker updatableViaApex + " doesn't match with the defining APEX " +
892*70a7ec85SAndroid Build Coastguard Worker std::string(apexName) + "\n";
893*70a7ec85SAndroid Build Coastguard Worker return false;
894*70a7ec85SAndroid Build Coastguard Worker }
895*70a7ec85SAndroid Build Coastguard Worker } else {
896*70a7ec85SAndroid Build Coastguard Worker // Set updatable-via-apex to the defining APEX when it's not set explicitly.
897*70a7ec85SAndroid Build Coastguard Worker // This should be set before calling insertInstances() which copies the current
898*70a7ec85SAndroid Build Coastguard Worker // value to ManifestInstance.
899*70a7ec85SAndroid Build Coastguard Worker object->mUpdatableViaApex = apexName;
900*70a7ec85SAndroid Build Coastguard Worker }
901*70a7ec85SAndroid Build Coastguard Worker }
902*70a7ec85SAndroid Build Coastguard Worker
903*70a7ec85SAndroid Build Coastguard Worker switch (object->format) {
904*70a7ec85SAndroid Build Coastguard Worker case HalFormat::HIDL: {
905*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, VersionConverter{}, &object->versions, param))
906*70a7ec85SAndroid Build Coastguard Worker return false;
907*70a7ec85SAndroid Build Coastguard Worker if (object->transportArch.empty()) {
908*70a7ec85SAndroid Build Coastguard Worker *param.error =
909*70a7ec85SAndroid Build Coastguard Worker "HIDL HAL '" + object->name + "' should have <transport> defined.";
910*70a7ec85SAndroid Build Coastguard Worker return false;
911*70a7ec85SAndroid Build Coastguard Worker }
912*70a7ec85SAndroid Build Coastguard Worker if (object->transportArch.transport == Transport::INET ||
913*70a7ec85SAndroid Build Coastguard Worker object->transportArch.ip.has_value() ||
914*70a7ec85SAndroid Build Coastguard Worker object->transportArch.port.has_value()) {
915*70a7ec85SAndroid Build Coastguard Worker *param.error = "HIDL HAL '" + object->name +
916*70a7ec85SAndroid Build Coastguard Worker "' should not have <transport> \"inet\" " +
917*70a7ec85SAndroid Build Coastguard Worker "or ip or port attributes defined.";
918*70a7ec85SAndroid Build Coastguard Worker return false;
919*70a7ec85SAndroid Build Coastguard Worker }
920*70a7ec85SAndroid Build Coastguard Worker } break;
921*70a7ec85SAndroid Build Coastguard Worker case HalFormat::NATIVE: {
922*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, VersionConverter{}, &object->versions, param))
923*70a7ec85SAndroid Build Coastguard Worker return false;
924*70a7ec85SAndroid Build Coastguard Worker if (!object->transportArch.empty()) {
925*70a7ec85SAndroid Build Coastguard Worker *param.error =
926*70a7ec85SAndroid Build Coastguard Worker "Native HAL '" + object->name + "' should not have <transport> defined.";
927*70a7ec85SAndroid Build Coastguard Worker return false;
928*70a7ec85SAndroid Build Coastguard Worker }
929*70a7ec85SAndroid Build Coastguard Worker } break;
930*70a7ec85SAndroid Build Coastguard Worker case HalFormat::AIDL: {
931*70a7ec85SAndroid Build Coastguard Worker if (!object->transportArch.empty() &&
932*70a7ec85SAndroid Build Coastguard Worker object->transportArch.transport != Transport::INET) {
933*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion >= kMetaVersionAidlInet) {
934*70a7ec85SAndroid Build Coastguard Worker *param.error = "AIDL HAL '" + object->name +
935*70a7ec85SAndroid Build Coastguard Worker R"(' only supports "inet" or empty <transport>, found ")" +
936*70a7ec85SAndroid Build Coastguard Worker to_string(object->transportArch) + "\"";
937*70a7ec85SAndroid Build Coastguard Worker return false;
938*70a7ec85SAndroid Build Coastguard Worker }
939*70a7ec85SAndroid Build Coastguard Worker LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
940*70a7ec85SAndroid Build Coastguard Worker << object->name << ". Only \"inet\" supported.";
941*70a7ec85SAndroid Build Coastguard Worker object->transportArch = {};
942*70a7ec85SAndroid Build Coastguard Worker }
943*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, AidlVersionConverter{}, &object->versions, param)) {
944*70a7ec85SAndroid Build Coastguard Worker return false;
945*70a7ec85SAndroid Build Coastguard Worker }
946*70a7ec85SAndroid Build Coastguard Worker // Insert fake version for AIDL HALs so that forEachInstance works.
947*70a7ec85SAndroid Build Coastguard Worker if (object->versions.empty()) {
948*70a7ec85SAndroid Build Coastguard Worker object->versions.push_back(details::kDefaultAidlVersion);
949*70a7ec85SAndroid Build Coastguard Worker }
950*70a7ec85SAndroid Build Coastguard Worker } break;
951*70a7ec85SAndroid Build Coastguard Worker default: {
952*70a7ec85SAndroid Build Coastguard Worker LOG(FATAL) << "Unhandled HalFormat "
953*70a7ec85SAndroid Build Coastguard Worker << static_cast<typename std::underlying_type<HalFormat>::type>(
954*70a7ec85SAndroid Build Coastguard Worker object->format);
955*70a7ec85SAndroid Build Coastguard Worker } break;
956*70a7ec85SAndroid Build Coastguard Worker }
957*70a7ec85SAndroid Build Coastguard Worker if (!object->transportArch.isValid(param.error)) return false;
958*70a7ec85SAndroid Build Coastguard Worker
959*70a7ec85SAndroid Build Coastguard Worker // Parse <fqname> into fqInstances list
960*70a7ec85SAndroid Build Coastguard Worker std::set<FqInstance> fqInstances;
961*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, FqInstanceConverter{}, &fqInstances, param)) {
962*70a7ec85SAndroid Build Coastguard Worker return false;
963*70a7ec85SAndroid Build Coastguard Worker }
964*70a7ec85SAndroid Build Coastguard Worker
965*70a7ec85SAndroid Build Coastguard Worker // Handle deprecated <interface> x <instance>
966*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, HalInterfaceConverter{}, &interfaces, param)) {
967*70a7ec85SAndroid Build Coastguard Worker return false;
968*70a7ec85SAndroid Build Coastguard Worker }
969*70a7ec85SAndroid Build Coastguard Worker // Check duplicated <interface><name>
970*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> interface_names;
971*70a7ec85SAndroid Build Coastguard Worker for (auto &&interface : interfaces) {
972*70a7ec85SAndroid Build Coastguard Worker auto res = interface_names.emplace(interface.name());
973*70a7ec85SAndroid Build Coastguard Worker if (!res.second) {
974*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated interface entry \"" + *res.first +
975*70a7ec85SAndroid Build Coastguard Worker "\"; if additional instances are needed, add them to the "
976*70a7ec85SAndroid Build Coastguard Worker "existing <interface> node.";
977*70a7ec85SAndroid Build Coastguard Worker return false;
978*70a7ec85SAndroid Build Coastguard Worker }
979*70a7ec85SAndroid Build Coastguard Worker }
980*70a7ec85SAndroid Build Coastguard Worker // Turn <version> x <interface> x <instance> into <fqname>s; insert into
981*70a7ec85SAndroid Build Coastguard Worker // fqInstances list.
982*70a7ec85SAndroid Build Coastguard Worker bool convertedInstancesIntoFqnames = false;
983*70a7ec85SAndroid Build Coastguard Worker for (const auto& v : object->versions) {
984*70a7ec85SAndroid Build Coastguard Worker for (const auto& intf : interfaces) {
985*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance &&
986*70a7ec85SAndroid Build Coastguard Worker (object->format == HalFormat::HIDL || object->format == HalFormat::AIDL) &&
987*70a7ec85SAndroid Build Coastguard Worker !intf.hasAnyInstance()) {
988*70a7ec85SAndroid Build Coastguard Worker *param.error +=
989*70a7ec85SAndroid Build Coastguard Worker "<hal> " + object->name + " <interface> " + intf.name() +
990*70a7ec85SAndroid Build Coastguard Worker " has no <instance>. Either specify <instance> or, "
991*70a7ec85SAndroid Build Coastguard Worker "preferably, specify <fqname> and delete <version> and <interface>.";
992*70a7ec85SAndroid Build Coastguard Worker return false;
993*70a7ec85SAndroid Build Coastguard Worker }
994*70a7ec85SAndroid Build Coastguard Worker bool cont = intf.forEachInstance(
995*70a7ec85SAndroid Build Coastguard Worker [&v, &fqInstances, &convertedInstancesIntoFqnames, &object, ¶m](
996*70a7ec85SAndroid Build Coastguard Worker const auto& interface, const auto& instance, bool /* isRegex */) {
997*70a7ec85SAndroid Build Coastguard Worker auto fqInstance = details::convertLegacyInstanceIntoFqInstance(
998*70a7ec85SAndroid Build Coastguard Worker object->name, v, interface, instance, object->format, param.error);
999*70a7ec85SAndroid Build Coastguard Worker
1000*70a7ec85SAndroid Build Coastguard Worker if (!fqInstance.has_value()) {
1001*70a7ec85SAndroid Build Coastguard Worker return false;
1002*70a7ec85SAndroid Build Coastguard Worker }
1003*70a7ec85SAndroid Build Coastguard Worker
1004*70a7ec85SAndroid Build Coastguard Worker // Check for duplication in fqInstances.
1005*70a7ec85SAndroid Build Coastguard Worker // Before kMetaVersionNoHalInterfaceInstance: It is okay to have duplication
1006*70a7ec85SAndroid Build Coastguard Worker // between <interface> and <fqname>.
1007*70a7ec85SAndroid Build Coastguard Worker // After kMetaVersionNoHalInterfaceInstance: Duplication between
1008*70a7ec85SAndroid Build Coastguard Worker // <interface> and <fqname> is not allowed.
1009*70a7ec85SAndroid Build Coastguard Worker auto&& [it, inserted] = fqInstances.emplace(std::move(fqInstance.value()));
1010*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance && !inserted) {
1011*70a7ec85SAndroid Build Coastguard Worker std::string debugString =
1012*70a7ec85SAndroid Build Coastguard Worker object->format == HalFormat::AIDL
1013*70a7ec85SAndroid Build Coastguard Worker ? toAidlFqnameString(object->name, interface, instance)
1014*70a7ec85SAndroid Build Coastguard Worker : toFQNameString(object->name, v, interface, instance);
1015*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated " + debugString +
1016*70a7ec85SAndroid Build Coastguard Worker " in <interface><instance> and <fqname>. ";
1017*70a7ec85SAndroid Build Coastguard Worker if constexpr (kDevice) {
1018*70a7ec85SAndroid Build Coastguard Worker *param.error +=
1019*70a7ec85SAndroid Build Coastguard Worker "(Did you copy source manifests to the device directly "
1020*70a7ec85SAndroid Build Coastguard Worker "without going through assemble_vintf, e.g. not using "
1021*70a7ec85SAndroid Build Coastguard Worker "DEVICE_MANIFEST_FILE or ODM_MANIFEST_FILES?)";
1022*70a7ec85SAndroid Build Coastguard Worker } else {
1023*70a7ec85SAndroid Build Coastguard Worker *param.error += "Remove deprecated <interface>.";
1024*70a7ec85SAndroid Build Coastguard Worker }
1025*70a7ec85SAndroid Build Coastguard Worker return false;
1026*70a7ec85SAndroid Build Coastguard Worker }
1027*70a7ec85SAndroid Build Coastguard Worker
1028*70a7ec85SAndroid Build Coastguard Worker convertedInstancesIntoFqnames = true;
1029*70a7ec85SAndroid Build Coastguard Worker return true; // continue
1030*70a7ec85SAndroid Build Coastguard Worker });
1031*70a7ec85SAndroid Build Coastguard Worker if (!cont) {
1032*70a7ec85SAndroid Build Coastguard Worker return false;
1033*70a7ec85SAndroid Build Coastguard Worker }
1034*70a7ec85SAndroid Build Coastguard Worker }
1035*70a7ec85SAndroid Build Coastguard Worker }
1036*70a7ec85SAndroid Build Coastguard Worker
1037*70a7ec85SAndroid Build Coastguard Worker if (!checkAdditionalRestrictionsOnHal(*object, param.error)) {
1038*70a7ec85SAndroid Build Coastguard Worker return false;
1039*70a7ec85SAndroid Build Coastguard Worker }
1040*70a7ec85SAndroid Build Coastguard Worker
1041*70a7ec85SAndroid Build Coastguard Worker // For HIDL, if any <version> x <interface> x <instance> tuple, all <version>
1042*70a7ec85SAndroid Build Coastguard Worker // tags can be cleared. <version> information is already in <fqname>'s.
1043*70a7ec85SAndroid Build Coastguard Worker // For AIDL, <version> information is not in <fqname>, so don't clear them.
1044*70a7ec85SAndroid Build Coastguard Worker // For HALs with only <version> but no <interface>
1045*70a7ec85SAndroid Build Coastguard Worker // (e.g. native HALs like netutils-wrapper), <version> is kept.
1046*70a7ec85SAndroid Build Coastguard Worker if (convertedInstancesIntoFqnames && object->format != HalFormat::AIDL) {
1047*70a7ec85SAndroid Build Coastguard Worker object->versions.clear();
1048*70a7ec85SAndroid Build Coastguard Worker }
1049*70a7ec85SAndroid Build Coastguard Worker
1050*70a7ec85SAndroid Build Coastguard Worker std::set<FqInstance> fqInstancesToInsert;
1051*70a7ec85SAndroid Build Coastguard Worker for (auto& e : fqInstances) {
1052*70a7ec85SAndroid Build Coastguard Worker if (e.hasPackage()) {
1053*70a7ec85SAndroid Build Coastguard Worker *param.error = "Should not specify package: \"" + e.string() + "\"";
1054*70a7ec85SAndroid Build Coastguard Worker return false;
1055*70a7ec85SAndroid Build Coastguard Worker }
1056*70a7ec85SAndroid Build Coastguard Worker if (object->format == HalFormat::AIDL) {
1057*70a7ec85SAndroid Build Coastguard Worker // <fqname> in AIDL HALs should not contain version.
1058*70a7ec85SAndroid Build Coastguard Worker if (e.hasVersion()) {
1059*70a7ec85SAndroid Build Coastguard Worker *param.error = "Should not specify version in <fqname> for AIDL HAL: \"" +
1060*70a7ec85SAndroid Build Coastguard Worker e.string() + "\"";
1061*70a7ec85SAndroid Build Coastguard Worker return false;
1062*70a7ec85SAndroid Build Coastguard Worker }
1063*70a7ec85SAndroid Build Coastguard Worker // Put in the fake kDefaultAidlVersion so that HalManifest can
1064*70a7ec85SAndroid Build Coastguard Worker // store it in an FqInstance object with a non-empty package.
1065*70a7ec85SAndroid Build Coastguard Worker FqInstance withFakeVersion;
1066*70a7ec85SAndroid Build Coastguard Worker if (!withFakeVersion.setTo(details::kDefaultAidlVersion.majorVer,
1067*70a7ec85SAndroid Build Coastguard Worker details::kDefaultAidlVersion.minorVer, e.getInterface(),
1068*70a7ec85SAndroid Build Coastguard Worker e.getInstance())) {
1069*70a7ec85SAndroid Build Coastguard Worker return false;
1070*70a7ec85SAndroid Build Coastguard Worker }
1071*70a7ec85SAndroid Build Coastguard Worker fqInstancesToInsert.emplace(std::move(withFakeVersion));
1072*70a7ec85SAndroid Build Coastguard Worker } else {
1073*70a7ec85SAndroid Build Coastguard Worker fqInstancesToInsert.emplace(std::move(e));
1074*70a7ec85SAndroid Build Coastguard Worker }
1075*70a7ec85SAndroid Build Coastguard Worker }
1076*70a7ec85SAndroid Build Coastguard Worker
1077*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion >= kMetaVersionNoHalInterfaceInstance &&
1078*70a7ec85SAndroid Build Coastguard Worker (object->format == HalFormat::HIDL || object->format == HalFormat::AIDL) &&
1079*70a7ec85SAndroid Build Coastguard Worker fqInstancesToInsert.empty() && !object->isOverride()) {
1080*70a7ec85SAndroid Build Coastguard Worker *param.error = "<hal> " + object->name + " has no instance. Fix by adding <fqname>.";
1081*70a7ec85SAndroid Build Coastguard Worker return false;
1082*70a7ec85SAndroid Build Coastguard Worker }
1083*70a7ec85SAndroid Build Coastguard Worker
1084*70a7ec85SAndroid Build Coastguard Worker bool allowMajorVersionDup = param.metaVersion < kMetaVersionNoHalInterfaceInstance;
1085*70a7ec85SAndroid Build Coastguard Worker if (!object->insertInstances(fqInstancesToInsert, allowMajorVersionDup, param.error)) {
1086*70a7ec85SAndroid Build Coastguard Worker return false;
1087*70a7ec85SAndroid Build Coastguard Worker }
1088*70a7ec85SAndroid Build Coastguard Worker
1089*70a7ec85SAndroid Build Coastguard Worker if (!object->isValid(param.error)) {
1090*70a7ec85SAndroid Build Coastguard Worker param.error->insert(0, "'" + object->name + "' is not a valid Manifest HAL: ");
1091*70a7ec85SAndroid Build Coastguard Worker return false;
1092*70a7ec85SAndroid Build Coastguard Worker }
1093*70a7ec85SAndroid Build Coastguard Worker
1094*70a7ec85SAndroid Build Coastguard Worker return true;
1095*70a7ec85SAndroid Build Coastguard Worker }
1096*70a7ec85SAndroid Build Coastguard Worker
1097*70a7ec85SAndroid Build Coastguard Worker private:
checkAdditionalRestrictionsOnHalandroid::vintf::ManifestHalConverter1098*70a7ec85SAndroid Build Coastguard Worker bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
1099*70a7ec85SAndroid Build Coastguard Worker // Do not check for target-side libvintf to avoid restricting upgrade accidentally.
1100*70a7ec85SAndroid Build Coastguard Worker if constexpr (kDevice) {
1101*70a7ec85SAndroid Build Coastguard Worker return true;
1102*70a7ec85SAndroid Build Coastguard Worker }
1103*70a7ec85SAndroid Build Coastguard Worker if (hal.getName() == "netutils-wrapper") {
1104*70a7ec85SAndroid Build Coastguard Worker for (const Version& v : hal.versions) {
1105*70a7ec85SAndroid Build Coastguard Worker if (v.minorVer != 0) {
1106*70a7ec85SAndroid Build Coastguard Worker *error =
1107*70a7ec85SAndroid Build Coastguard Worker "netutils-wrapper HAL must specify exactly one version x.0, "
1108*70a7ec85SAndroid Build Coastguard Worker "but minor version is not 0. Perhaps you mean '" +
1109*70a7ec85SAndroid Build Coastguard Worker to_string(Version{v.majorVer, 0}) + "'?";
1110*70a7ec85SAndroid Build Coastguard Worker return false;
1111*70a7ec85SAndroid Build Coastguard Worker }
1112*70a7ec85SAndroid Build Coastguard Worker }
1113*70a7ec85SAndroid Build Coastguard Worker }
1114*70a7ec85SAndroid Build Coastguard Worker return true;
1115*70a7ec85SAndroid Build Coastguard Worker }
1116*70a7ec85SAndroid Build Coastguard Worker };
1117*70a7ec85SAndroid Build Coastguard Worker
1118*70a7ec85SAndroid Build Coastguard Worker struct KernelSepolicyVersionConverter : public XmlTextConverter<KernelSepolicyVersion> {
elementNameandroid::vintf::KernelSepolicyVersionConverter1119*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "kernel-sepolicy-version"; }
1120*70a7ec85SAndroid Build Coastguard Worker };
1121*70a7ec85SAndroid Build Coastguard Worker
1122*70a7ec85SAndroid Build Coastguard Worker struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
elementNameandroid::vintf::SepolicyConverter1123*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::SepolicyConverter1124*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const Sepolicy& object, NodeType* root,
1125*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1126*70a7ec85SAndroid Build Coastguard Worker appendChild(root, KernelSepolicyVersionConverter{}(object.kernelSepolicyVersion(), param));
1127*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, SepolicyVersionRangeConverter{}, object.sepolicyVersions(), param);
1128*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::SepolicyConverter1129*70a7ec85SAndroid Build Coastguard Worker bool buildObject(Sepolicy* object, NodeType* root,
1130*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1131*70a7ec85SAndroid Build Coastguard Worker if (!parseChild(root, KernelSepolicyVersionConverter{}, &object->mKernelSepolicyVersion,
1132*70a7ec85SAndroid Build Coastguard Worker param) ||
1133*70a7ec85SAndroid Build Coastguard Worker !parseChildren(root, SepolicyVersionRangeConverter{}, &object->mSepolicyVersionRanges,
1134*70a7ec85SAndroid Build Coastguard Worker param)) {
1135*70a7ec85SAndroid Build Coastguard Worker return false;
1136*70a7ec85SAndroid Build Coastguard Worker }
1137*70a7ec85SAndroid Build Coastguard Worker return true;
1138*70a7ec85SAndroid Build Coastguard Worker }
1139*70a7ec85SAndroid Build Coastguard Worker };
1140*70a7ec85SAndroid Build Coastguard Worker
1141*70a7ec85SAndroid Build Coastguard Worker struct [[deprecated]] VndkVersionRangeConverter : public XmlTextConverter<VndkVersionRange> {
elementNameandroid::vintf::VndkVersionRangeConverter1142*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
1143*70a7ec85SAndroid Build Coastguard Worker };
1144*70a7ec85SAndroid Build Coastguard Worker
1145*70a7ec85SAndroid Build Coastguard Worker struct VndkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkVersionConverter1146*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
1147*70a7ec85SAndroid Build Coastguard Worker };
1148*70a7ec85SAndroid Build Coastguard Worker
1149*70a7ec85SAndroid Build Coastguard Worker struct VndkLibraryConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::VndkLibraryConverter1150*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "library"; }
1151*70a7ec85SAndroid Build Coastguard Worker };
1152*70a7ec85SAndroid Build Coastguard Worker
1153*70a7ec85SAndroid Build Coastguard Worker struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
elementNameandroid::vintf::VndkConverter1154*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "vndk"; }
mutateNodeandroid::vintf::VndkConverter1155*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const Vndk& object, NodeType* root,
1156*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1157*70a7ec85SAndroid Build Coastguard Worker appendChild(root, VndkVersionRangeConverter{}(object.mVersionRange, param));
1158*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
1159*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::VndkConverter1160*70a7ec85SAndroid Build Coastguard Worker bool buildObject(Vndk* object, NodeType* root, const BuildObjectParam& param) const override {
1161*70a7ec85SAndroid Build Coastguard Worker if (!parseChild(root, VndkVersionRangeConverter{}, &object->mVersionRange, param) ||
1162*70a7ec85SAndroid Build Coastguard Worker !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
1163*70a7ec85SAndroid Build Coastguard Worker return false;
1164*70a7ec85SAndroid Build Coastguard Worker }
1165*70a7ec85SAndroid Build Coastguard Worker return true;
1166*70a7ec85SAndroid Build Coastguard Worker }
1167*70a7ec85SAndroid Build Coastguard Worker };
1168*70a7ec85SAndroid Build Coastguard Worker
1169*70a7ec85SAndroid Build Coastguard Worker struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
elementNameandroid::vintf::VendorNdkConverter1170*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "vendor-ndk"; }
mutateNodeandroid::vintf::VendorNdkConverter1171*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const VendorNdk& object, NodeType* root,
1172*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1173*70a7ec85SAndroid Build Coastguard Worker appendChild(root, VndkVersionConverter{}(object.mVersion, param));
1174*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, VndkLibraryConverter{}, object.mLibraries, param);
1175*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::VendorNdkConverter1176*70a7ec85SAndroid Build Coastguard Worker bool buildObject(VendorNdk* object, NodeType* root,
1177*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1178*70a7ec85SAndroid Build Coastguard Worker if (!parseChild(root, VndkVersionConverter{}, &object->mVersion, param) ||
1179*70a7ec85SAndroid Build Coastguard Worker !parseChildren(root, VndkLibraryConverter{}, &object->mLibraries, param)) {
1180*70a7ec85SAndroid Build Coastguard Worker return false;
1181*70a7ec85SAndroid Build Coastguard Worker }
1182*70a7ec85SAndroid Build Coastguard Worker return true;
1183*70a7ec85SAndroid Build Coastguard Worker }
1184*70a7ec85SAndroid Build Coastguard Worker };
1185*70a7ec85SAndroid Build Coastguard Worker
1186*70a7ec85SAndroid Build Coastguard Worker struct SystemSdkVersionConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::SystemSdkVersionConverter1187*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "version"; }
1188*70a7ec85SAndroid Build Coastguard Worker };
1189*70a7ec85SAndroid Build Coastguard Worker
1190*70a7ec85SAndroid Build Coastguard Worker struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
elementNameandroid::vintf::SystemSdkConverter1191*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "system-sdk"; }
mutateNodeandroid::vintf::SystemSdkConverter1192*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const SystemSdk& object, NodeType* root,
1193*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1194*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, SystemSdkVersionConverter{}, object.versions(), param);
1195*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::SystemSdkConverter1196*70a7ec85SAndroid Build Coastguard Worker bool buildObject(SystemSdk* object, NodeType* root,
1197*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1198*70a7ec85SAndroid Build Coastguard Worker return parseChildren(root, SystemSdkVersionConverter{}, &object->mVersions, param);
1199*70a7ec85SAndroid Build Coastguard Worker }
1200*70a7ec85SAndroid Build Coastguard Worker };
1201*70a7ec85SAndroid Build Coastguard Worker
1202*70a7ec85SAndroid Build Coastguard Worker struct HalManifestSepolicyConverter : public XmlNodeConverter<SepolicyVersion> {
elementNameandroid::vintf::HalManifestSepolicyConverter1203*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "sepolicy"; }
mutateNodeandroid::vintf::HalManifestSepolicyConverter1204*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const SepolicyVersion& object, NodeType* root,
1205*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1206*70a7ec85SAndroid Build Coastguard Worker appendChild(root, SepolicyVersionConverter{}(object, param));
1207*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::HalManifestSepolicyConverter1208*70a7ec85SAndroid Build Coastguard Worker bool buildObject(SepolicyVersion* object, NodeType* root,
1209*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1210*70a7ec85SAndroid Build Coastguard Worker return parseChild(root, SepolicyVersionConverter{}, object, param);
1211*70a7ec85SAndroid Build Coastguard Worker }
1212*70a7ec85SAndroid Build Coastguard Worker };
1213*70a7ec85SAndroid Build Coastguard Worker
1214*70a7ec85SAndroid Build Coastguard Worker struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
elementNameandroid::vintf::ManifestXmlFileConverter1215*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::ManifestXmlFileConverter1216*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const ManifestXmlFile& object, NodeType* root,
1217*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1218*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "name", object.name(), param.d);
1219*70a7ec85SAndroid Build Coastguard Worker appendChild(root, VersionConverter{}(object.version(), param));
1220*70a7ec85SAndroid Build Coastguard Worker if (!object.overriddenPath().empty()) {
1221*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "path", object.overriddenPath(), param.d);
1222*70a7ec85SAndroid Build Coastguard Worker }
1223*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::ManifestXmlFileConverter1224*70a7ec85SAndroid Build Coastguard Worker bool buildObject(ManifestXmlFile* object, NodeType* root,
1225*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1226*70a7ec85SAndroid Build Coastguard Worker if (!parseTextElement(root, "name", &object->mName, param.error) ||
1227*70a7ec85SAndroid Build Coastguard Worker !parseChild(root, VersionConverter{}, &object->mVersion, param) ||
1228*70a7ec85SAndroid Build Coastguard Worker !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
1229*70a7ec85SAndroid Build Coastguard Worker return false;
1230*70a7ec85SAndroid Build Coastguard Worker }
1231*70a7ec85SAndroid Build Coastguard Worker return true;
1232*70a7ec85SAndroid Build Coastguard Worker }
1233*70a7ec85SAndroid Build Coastguard Worker };
1234*70a7ec85SAndroid Build Coastguard Worker
1235*70a7ec85SAndroid Build Coastguard Worker struct StringKernelConfigKeyConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::StringKernelConfigKeyConverter1236*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "key"; }
1237*70a7ec85SAndroid Build Coastguard Worker };
1238*70a7ec85SAndroid Build Coastguard Worker
1239*70a7ec85SAndroid Build Coastguard Worker struct KernelConfigValueConverter : public XmlTextConverter<std::string> {
elementNameandroid::vintf::KernelConfigValueConverter1240*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "value"; }
1241*70a7ec85SAndroid Build Coastguard Worker };
1242*70a7ec85SAndroid Build Coastguard Worker
1243*70a7ec85SAndroid Build Coastguard Worker struct StringKernelConfigConverter
1244*70a7ec85SAndroid Build Coastguard Worker : public XmlPairConverter<std::pair<std::string, std::string>, StringKernelConfigKeyConverter,
1245*70a7ec85SAndroid Build Coastguard Worker KernelConfigValueConverter> {
elementNameandroid::vintf::StringKernelConfigConverter1246*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "config"; }
1247*70a7ec85SAndroid Build Coastguard Worker };
1248*70a7ec85SAndroid Build Coastguard Worker
1249*70a7ec85SAndroid Build Coastguard Worker struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
elementNameandroid::vintf::KernelInfoConverter1250*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "kernel"; }
mutateNodeandroid::vintf::KernelInfoConverter1251*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const KernelInfo& object, NodeType* root,
1252*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1253*70a7ec85SAndroid Build Coastguard Worker if (object.version() != KernelVersion{}) {
1254*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "version", object.version());
1255*70a7ec85SAndroid Build Coastguard Worker }
1256*70a7ec85SAndroid Build Coastguard Worker if (object.level() != Level::UNSPECIFIED) {
1257*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "target-level", object.level());
1258*70a7ec85SAndroid Build Coastguard Worker }
1259*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isKernelConfigsEnabled()) {
1260*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, StringKernelConfigConverter{}, object.configs(), param);
1261*70a7ec85SAndroid Build Coastguard Worker }
1262*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::KernelInfoConverter1263*70a7ec85SAndroid Build Coastguard Worker bool buildObject(KernelInfo* object, NodeType* root,
1264*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1265*70a7ec85SAndroid Build Coastguard Worker return parseOptionalAttr(root, "version", {}, &object->mVersion, param) &&
1266*70a7ec85SAndroid Build Coastguard Worker parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1267*70a7ec85SAndroid Build Coastguard Worker param) &&
1268*70a7ec85SAndroid Build Coastguard Worker parseChildren(root, StringKernelConfigConverter{}, &object->mConfigs, param);
1269*70a7ec85SAndroid Build Coastguard Worker }
1270*70a7ec85SAndroid Build Coastguard Worker };
1271*70a7ec85SAndroid Build Coastguard Worker
1272*70a7ec85SAndroid Build Coastguard Worker struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
elementNameandroid::vintf::HalManifestConverter1273*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "manifest"; }
mutateNodeandroid::vintf::HalManifestConverter1274*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const HalManifest& object, NodeType* root,
1275*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1276*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isMetaVersionEnabled()) {
1277*70a7ec85SAndroid Build Coastguard Worker // Append the current metaversion of libvintf because the XML file
1278*70a7ec85SAndroid Build Coastguard Worker // is generated with libvintf @ current meta version.
1279*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "version", kMetaVersion);
1280*70a7ec85SAndroid Build Coastguard Worker }
1281*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isSchemaTypeEnabled()) {
1282*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "type", object.mType);
1283*70a7ec85SAndroid Build Coastguard Worker }
1284*70a7ec85SAndroid Build Coastguard Worker
1285*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isHalsEnabled()) {
1286*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, ManifestHalConverter{}, object.getHals(), param);
1287*70a7ec85SAndroid Build Coastguard Worker }
1288*70a7ec85SAndroid Build Coastguard Worker if (object.mType == SchemaType::DEVICE) {
1289*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isSepolicyEnabled()) {
1290*70a7ec85SAndroid Build Coastguard Worker if (object.device.mSepolicyVersion != SepolicyVersion{}) {
1291*70a7ec85SAndroid Build Coastguard Worker appendChild(root, HalManifestSepolicyConverter{}(object.device.mSepolicyVersion,
1292*70a7ec85SAndroid Build Coastguard Worker param));
1293*70a7ec85SAndroid Build Coastguard Worker }
1294*70a7ec85SAndroid Build Coastguard Worker }
1295*70a7ec85SAndroid Build Coastguard Worker if (object.mLevel != Level::UNSPECIFIED) {
1296*70a7ec85SAndroid Build Coastguard Worker this->appendAttr(root, "target-level", object.mLevel);
1297*70a7ec85SAndroid Build Coastguard Worker }
1298*70a7ec85SAndroid Build Coastguard Worker
1299*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isKernelEnabled()) {
1300*70a7ec85SAndroid Build Coastguard Worker if (!!object.kernel()) {
1301*70a7ec85SAndroid Build Coastguard Worker appendChild(root, KernelInfoConverter{}(*object.kernel(), param));
1302*70a7ec85SAndroid Build Coastguard Worker }
1303*70a7ec85SAndroid Build Coastguard Worker }
1304*70a7ec85SAndroid Build Coastguard Worker } else if (object.mType == SchemaType::FRAMEWORK) {
1305*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isVndkEnabled()) {
1306*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic push
1307*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1308*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, VndkConverter{}, object.framework.mVndks, param);
1309*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic pop
1310*70a7ec85SAndroid Build Coastguard Worker
1311*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, VendorNdkConverter{}, object.framework.mVendorNdks, param);
1312*70a7ec85SAndroid Build Coastguard Worker }
1313*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isSsdkEnabled()) {
1314*70a7ec85SAndroid Build Coastguard Worker if (!object.framework.mSystemSdk.empty()) {
1315*70a7ec85SAndroid Build Coastguard Worker appendChild(root, SystemSdkConverter{}(object.framework.mSystemSdk, param));
1316*70a7ec85SAndroid Build Coastguard Worker }
1317*70a7ec85SAndroid Build Coastguard Worker }
1318*70a7ec85SAndroid Build Coastguard Worker }
1319*70a7ec85SAndroid Build Coastguard Worker
1320*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isXmlFilesEnabled()) {
1321*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, ManifestXmlFileConverter{}, object.getXmlFiles(), param);
1322*70a7ec85SAndroid Build Coastguard Worker }
1323*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::HalManifestConverter1324*70a7ec85SAndroid Build Coastguard Worker bool buildObject(HalManifest* object, NodeType* root,
1325*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& constParam) const override {
1326*70a7ec85SAndroid Build Coastguard Worker BuildObjectParam param = constParam;
1327*70a7ec85SAndroid Build Coastguard Worker if (!parseAttr(root, "version", ¶m.metaVersion, param.error)) return false;
1328*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion > kMetaVersion) {
1329*70a7ec85SAndroid Build Coastguard Worker *param.error = "Unrecognized manifest.version " + to_string(param.metaVersion) +
1330*70a7ec85SAndroid Build Coastguard Worker " (libvintf@" + to_string(kMetaVersion) + ")";
1331*70a7ec85SAndroid Build Coastguard Worker return false;
1332*70a7ec85SAndroid Build Coastguard Worker }
1333*70a7ec85SAndroid Build Coastguard Worker object->mSourceMetaVersion = param.metaVersion;
1334*70a7ec85SAndroid Build Coastguard Worker
1335*70a7ec85SAndroid Build Coastguard Worker if (!parseAttr(root, "type", &object->mType, param.error)) {
1336*70a7ec85SAndroid Build Coastguard Worker return false;
1337*70a7ec85SAndroid Build Coastguard Worker }
1338*70a7ec85SAndroid Build Coastguard Worker
1339*70a7ec85SAndroid Build Coastguard Worker std::vector<ManifestHal> hals;
1340*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, ManifestHalConverter{}, &hals, param)) {
1341*70a7ec85SAndroid Build Coastguard Worker return false;
1342*70a7ec85SAndroid Build Coastguard Worker }
1343*70a7ec85SAndroid Build Coastguard Worker for (auto&& hal : hals) {
1344*70a7ec85SAndroid Build Coastguard Worker hal.setFileName(object->fileName());
1345*70a7ec85SAndroid Build Coastguard Worker }
1346*70a7ec85SAndroid Build Coastguard Worker
1347*70a7ec85SAndroid Build Coastguard Worker if (object->mType == SchemaType::DEVICE) {
1348*70a7ec85SAndroid Build Coastguard Worker // tags for device hal manifest only.
1349*70a7ec85SAndroid Build Coastguard Worker // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1350*70a7ec85SAndroid Build Coastguard Worker // in the XML file.
1351*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalChild(root, HalManifestSepolicyConverter{}, {},
1352*70a7ec85SAndroid Build Coastguard Worker &object->device.mSepolicyVersion, param)) {
1353*70a7ec85SAndroid Build Coastguard Worker return false;
1354*70a7ec85SAndroid Build Coastguard Worker }
1355*70a7ec85SAndroid Build Coastguard Worker
1356*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1357*70a7ec85SAndroid Build Coastguard Worker param)) {
1358*70a7ec85SAndroid Build Coastguard Worker return false;
1359*70a7ec85SAndroid Build Coastguard Worker }
1360*70a7ec85SAndroid Build Coastguard Worker
1361*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalChild(root, KernelInfoConverter{}, &object->device.mKernel, param)) {
1362*70a7ec85SAndroid Build Coastguard Worker return false;
1363*70a7ec85SAndroid Build Coastguard Worker }
1364*70a7ec85SAndroid Build Coastguard Worker } else if (object->mType == SchemaType::FRAMEWORK) {
1365*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic push
1366*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1367*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, VndkConverter{}, &object->framework.mVndks, param)) {
1368*70a7ec85SAndroid Build Coastguard Worker return false;
1369*70a7ec85SAndroid Build Coastguard Worker }
1370*70a7ec85SAndroid Build Coastguard Worker for (const auto& vndk : object->framework.mVndks) {
1371*70a7ec85SAndroid Build Coastguard Worker if (!vndk.mVersionRange.isSingleVersion()) {
1372*70a7ec85SAndroid Build Coastguard Worker *param.error = "vndk.version " + to_string(vndk.mVersionRange) +
1373*70a7ec85SAndroid Build Coastguard Worker " cannot be a range for manifests";
1374*70a7ec85SAndroid Build Coastguard Worker return false;
1375*70a7ec85SAndroid Build Coastguard Worker }
1376*70a7ec85SAndroid Build Coastguard Worker }
1377*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic pop
1378*70a7ec85SAndroid Build Coastguard Worker
1379*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, VendorNdkConverter{}, &object->framework.mVendorNdks, param)) {
1380*70a7ec85SAndroid Build Coastguard Worker return false;
1381*70a7ec85SAndroid Build Coastguard Worker }
1382*70a7ec85SAndroid Build Coastguard Worker
1383*70a7ec85SAndroid Build Coastguard Worker std::set<std::string> vendorNdkVersions;
1384*70a7ec85SAndroid Build Coastguard Worker for (const auto& vendorNdk : object->framework.mVendorNdks) {
1385*70a7ec85SAndroid Build Coastguard Worker if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
1386*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
1387*70a7ec85SAndroid Build Coastguard Worker return false;
1388*70a7ec85SAndroid Build Coastguard Worker }
1389*70a7ec85SAndroid Build Coastguard Worker vendorNdkVersions.insert(vendorNdk.version());
1390*70a7ec85SAndroid Build Coastguard Worker }
1391*70a7ec85SAndroid Build Coastguard Worker
1392*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->framework.mSystemSdk,
1393*70a7ec85SAndroid Build Coastguard Worker param)) {
1394*70a7ec85SAndroid Build Coastguard Worker return false;
1395*70a7ec85SAndroid Build Coastguard Worker }
1396*70a7ec85SAndroid Build Coastguard Worker }
1397*70a7ec85SAndroid Build Coastguard Worker for (auto &&hal : hals) {
1398*70a7ec85SAndroid Build Coastguard Worker std::string description{hal.name};
1399*70a7ec85SAndroid Build Coastguard Worker if (!object->add(std::move(hal), param.error)) {
1400*70a7ec85SAndroid Build Coastguard Worker param.error->insert(0, "Duplicated manifest.hal entry " + description + ": ");
1401*70a7ec85SAndroid Build Coastguard Worker return false;
1402*70a7ec85SAndroid Build Coastguard Worker }
1403*70a7ec85SAndroid Build Coastguard Worker }
1404*70a7ec85SAndroid Build Coastguard Worker
1405*70a7ec85SAndroid Build Coastguard Worker std::vector<ManifestXmlFile> xmlFiles;
1406*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, ManifestXmlFileConverter{}, &xmlFiles, param)) {
1407*70a7ec85SAndroid Build Coastguard Worker return false;
1408*70a7ec85SAndroid Build Coastguard Worker }
1409*70a7ec85SAndroid Build Coastguard Worker for (auto&& xmlFile : xmlFiles) {
1410*70a7ec85SAndroid Build Coastguard Worker std::string description{xmlFile.name()};
1411*70a7ec85SAndroid Build Coastguard Worker if (!object->addXmlFile(std::move(xmlFile))) {
1412*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated manifest.xmlfile entry " + description +
1413*70a7ec85SAndroid Build Coastguard Worker "; entries cannot have duplicated name and version";
1414*70a7ec85SAndroid Build Coastguard Worker return false;
1415*70a7ec85SAndroid Build Coastguard Worker }
1416*70a7ec85SAndroid Build Coastguard Worker }
1417*70a7ec85SAndroid Build Coastguard Worker
1418*70a7ec85SAndroid Build Coastguard Worker return true;
1419*70a7ec85SAndroid Build Coastguard Worker }
1420*70a7ec85SAndroid Build Coastguard Worker };
1421*70a7ec85SAndroid Build Coastguard Worker
1422*70a7ec85SAndroid Build Coastguard Worker struct AvbVersionConverter : public XmlTextConverter<Version> {
elementNameandroid::vintf::AvbVersionConverter1423*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "vbmeta-version"; }
1424*70a7ec85SAndroid Build Coastguard Worker };
1425*70a7ec85SAndroid Build Coastguard Worker
1426*70a7ec85SAndroid Build Coastguard Worker struct AvbConverter : public XmlNodeConverter<Version> {
elementNameandroid::vintf::AvbConverter1427*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "avb"; }
mutateNodeandroid::vintf::AvbConverter1428*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const Version& object, NodeType* root,
1429*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1430*70a7ec85SAndroid Build Coastguard Worker appendChild(root, AvbVersionConverter{}(object, param));
1431*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::AvbConverter1432*70a7ec85SAndroid Build Coastguard Worker bool buildObject(Version* object, NodeType* root,
1433*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1434*70a7ec85SAndroid Build Coastguard Worker return parseChild(root, AvbVersionConverter{}, object, param);
1435*70a7ec85SAndroid Build Coastguard Worker }
1436*70a7ec85SAndroid Build Coastguard Worker };
1437*70a7ec85SAndroid Build Coastguard Worker
1438*70a7ec85SAndroid Build Coastguard Worker struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
elementNameandroid::vintf::MatrixXmlFileConverter1439*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "xmlfile"; }
mutateNodeandroid::vintf::MatrixXmlFileConverter1440*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const MatrixXmlFile& object, NodeType* root,
1441*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1442*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "name", object.name(), param.d);
1443*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "format", object.format());
1444*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "optional", object.optional());
1445*70a7ec85SAndroid Build Coastguard Worker appendChild(root, VersionRangeConverter{}(object.versionRange(), param));
1446*70a7ec85SAndroid Build Coastguard Worker if (!object.overriddenPath().empty()) {
1447*70a7ec85SAndroid Build Coastguard Worker appendTextElement(root, "path", object.overriddenPath(), param.d);
1448*70a7ec85SAndroid Build Coastguard Worker }
1449*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::MatrixXmlFileConverter1450*70a7ec85SAndroid Build Coastguard Worker bool buildObject(MatrixXmlFile* object, NodeType* root,
1451*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& param) const override {
1452*70a7ec85SAndroid Build Coastguard Worker if (!parseTextElement(root, "name", &object->mName, param.error) ||
1453*70a7ec85SAndroid Build Coastguard Worker !parseAttr(root, "format", &object->mFormat, param.error) ||
1454*70a7ec85SAndroid Build Coastguard Worker !parseOptionalAttr(root, "optional", false, &object->mOptional, param) ||
1455*70a7ec85SAndroid Build Coastguard Worker !parseChild(root, VersionRangeConverter{}, &object->mVersionRange, param) ||
1456*70a7ec85SAndroid Build Coastguard Worker !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, param.error)) {
1457*70a7ec85SAndroid Build Coastguard Worker return false;
1458*70a7ec85SAndroid Build Coastguard Worker }
1459*70a7ec85SAndroid Build Coastguard Worker return true;
1460*70a7ec85SAndroid Build Coastguard Worker }
1461*70a7ec85SAndroid Build Coastguard Worker };
1462*70a7ec85SAndroid Build Coastguard Worker
1463*70a7ec85SAndroid Build Coastguard Worker struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
elementNameandroid::vintf::CompatibilityMatrixConverter1464*70a7ec85SAndroid Build Coastguard Worker std::string elementName() const override { return "compatibility-matrix"; }
mutateNodeandroid::vintf::CompatibilityMatrixConverter1465*70a7ec85SAndroid Build Coastguard Worker void mutateNode(const CompatibilityMatrix& object, NodeType* root,
1466*70a7ec85SAndroid Build Coastguard Worker const MutateNodeParam& param) const override {
1467*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isMetaVersionEnabled()) {
1468*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "version", kMetaVersion);
1469*70a7ec85SAndroid Build Coastguard Worker }
1470*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isSchemaTypeEnabled()) {
1471*70a7ec85SAndroid Build Coastguard Worker appendAttr(root, "type", object.mType);
1472*70a7ec85SAndroid Build Coastguard Worker }
1473*70a7ec85SAndroid Build Coastguard Worker
1474*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isHalsEnabled()) {
1475*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, MatrixHalConverter{}, iterateValues(object.mHals), param);
1476*70a7ec85SAndroid Build Coastguard Worker }
1477*70a7ec85SAndroid Build Coastguard Worker if (object.mType == SchemaType::FRAMEWORK) {
1478*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isKernelEnabled()) {
1479*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, MatrixKernelConverter{}, object.framework.mKernels, param);
1480*70a7ec85SAndroid Build Coastguard Worker }
1481*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isSepolicyEnabled()) {
1482*70a7ec85SAndroid Build Coastguard Worker if (!(object.framework.mSepolicy == Sepolicy{})) {
1483*70a7ec85SAndroid Build Coastguard Worker appendChild(root, SepolicyConverter{}(object.framework.mSepolicy, param));
1484*70a7ec85SAndroid Build Coastguard Worker }
1485*70a7ec85SAndroid Build Coastguard Worker }
1486*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isAvbEnabled()) {
1487*70a7ec85SAndroid Build Coastguard Worker if (!(object.framework.mAvbMetaVersion == Version{})) {
1488*70a7ec85SAndroid Build Coastguard Worker appendChild(root, AvbConverter{}(object.framework.mAvbMetaVersion, param));
1489*70a7ec85SAndroid Build Coastguard Worker }
1490*70a7ec85SAndroid Build Coastguard Worker }
1491*70a7ec85SAndroid Build Coastguard Worker if (object.mLevel != Level::UNSPECIFIED) {
1492*70a7ec85SAndroid Build Coastguard Worker this->appendAttr(root, "level", object.mLevel);
1493*70a7ec85SAndroid Build Coastguard Worker }
1494*70a7ec85SAndroid Build Coastguard Worker } else if (object.mType == SchemaType::DEVICE) {
1495*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isVndkEnabled()) {
1496*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic push
1497*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1498*70a7ec85SAndroid Build Coastguard Worker if (!(object.device.mVndk == Vndk{})) {
1499*70a7ec85SAndroid Build Coastguard Worker appendChild(root, VndkConverter{}(object.device.mVndk, param));
1500*70a7ec85SAndroid Build Coastguard Worker }
1501*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic pop
1502*70a7ec85SAndroid Build Coastguard Worker
1503*70a7ec85SAndroid Build Coastguard Worker if (!(object.device.mVendorNdk == VendorNdk{})) {
1504*70a7ec85SAndroid Build Coastguard Worker appendChild(root, VendorNdkConverter{}(object.device.mVendorNdk, param));
1505*70a7ec85SAndroid Build Coastguard Worker }
1506*70a7ec85SAndroid Build Coastguard Worker }
1507*70a7ec85SAndroid Build Coastguard Worker
1508*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isSsdkEnabled()) {
1509*70a7ec85SAndroid Build Coastguard Worker if (!object.device.mSystemSdk.empty()) {
1510*70a7ec85SAndroid Build Coastguard Worker appendChild(root, SystemSdkConverter{}(object.device.mSystemSdk, param));
1511*70a7ec85SAndroid Build Coastguard Worker }
1512*70a7ec85SAndroid Build Coastguard Worker }
1513*70a7ec85SAndroid Build Coastguard Worker }
1514*70a7ec85SAndroid Build Coastguard Worker
1515*70a7ec85SAndroid Build Coastguard Worker if (param.flags.isXmlFilesEnabled()) {
1516*70a7ec85SAndroid Build Coastguard Worker appendChildren(root, MatrixXmlFileConverter{}, object.getXmlFiles(), param);
1517*70a7ec85SAndroid Build Coastguard Worker }
1518*70a7ec85SAndroid Build Coastguard Worker }
buildObjectandroid::vintf::CompatibilityMatrixConverter1519*70a7ec85SAndroid Build Coastguard Worker bool buildObject(CompatibilityMatrix* object, NodeType* root,
1520*70a7ec85SAndroid Build Coastguard Worker const BuildObjectParam& constParam) const override {
1521*70a7ec85SAndroid Build Coastguard Worker BuildObjectParam param = constParam;
1522*70a7ec85SAndroid Build Coastguard Worker if (!parseAttr(root, "version", ¶m.metaVersion, param.error)) return false;
1523*70a7ec85SAndroid Build Coastguard Worker if (param.metaVersion > kMetaVersion) {
1524*70a7ec85SAndroid Build Coastguard Worker *param.error = "Unrecognized compatibility-matrix.version " +
1525*70a7ec85SAndroid Build Coastguard Worker to_string(param.metaVersion) + " (libvintf@" + to_string(kMetaVersion) +
1526*70a7ec85SAndroid Build Coastguard Worker ")";
1527*70a7ec85SAndroid Build Coastguard Worker return false;
1528*70a7ec85SAndroid Build Coastguard Worker }
1529*70a7ec85SAndroid Build Coastguard Worker
1530*70a7ec85SAndroid Build Coastguard Worker std::vector<MatrixHal> hals;
1531*70a7ec85SAndroid Build Coastguard Worker if (!parseAttr(root, "type", &object->mType, param.error) ||
1532*70a7ec85SAndroid Build Coastguard Worker !parseChildren(root, MatrixHalConverter{}, &hals, param)) {
1533*70a7ec85SAndroid Build Coastguard Worker return false;
1534*70a7ec85SAndroid Build Coastguard Worker }
1535*70a7ec85SAndroid Build Coastguard Worker
1536*70a7ec85SAndroid Build Coastguard Worker if (object->mType == SchemaType::FRAMEWORK) {
1537*70a7ec85SAndroid Build Coastguard Worker // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1538*70a7ec85SAndroid Build Coastguard Worker // hard-coded in the XML file.
1539*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, MatrixKernelConverter{}, &object->framework.mKernels, param) ||
1540*70a7ec85SAndroid Build Coastguard Worker !parseOptionalChild(root, SepolicyConverter{}, {}, &object->framework.mSepolicy,
1541*70a7ec85SAndroid Build Coastguard Worker param) ||
1542*70a7ec85SAndroid Build Coastguard Worker !parseOptionalChild(root, AvbConverter{}, {}, &object->framework.mAvbMetaVersion,
1543*70a7ec85SAndroid Build Coastguard Worker param)) {
1544*70a7ec85SAndroid Build Coastguard Worker return false;
1545*70a7ec85SAndroid Build Coastguard Worker }
1546*70a7ec85SAndroid Build Coastguard Worker
1547*70a7ec85SAndroid Build Coastguard Worker std::set<Version> seenKernelVersions;
1548*70a7ec85SAndroid Build Coastguard Worker for (const auto& kernel : object->framework.mKernels) {
1549*70a7ec85SAndroid Build Coastguard Worker Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1550*70a7ec85SAndroid Build Coastguard Worker if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1551*70a7ec85SAndroid Build Coastguard Worker continue;
1552*70a7ec85SAndroid Build Coastguard Worker }
1553*70a7ec85SAndroid Build Coastguard Worker if (!kernel.conditions().empty()) {
1554*70a7ec85SAndroid Build Coastguard Worker *param.error = "First <kernel> for version " + to_string(minLts) +
1555*70a7ec85SAndroid Build Coastguard Worker " must have empty <conditions> for backwards compatibility.";
1556*70a7ec85SAndroid Build Coastguard Worker return false;
1557*70a7ec85SAndroid Build Coastguard Worker }
1558*70a7ec85SAndroid Build Coastguard Worker seenKernelVersions.insert(minLts);
1559*70a7ec85SAndroid Build Coastguard Worker }
1560*70a7ec85SAndroid Build Coastguard Worker
1561*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, param)) {
1562*70a7ec85SAndroid Build Coastguard Worker return false;
1563*70a7ec85SAndroid Build Coastguard Worker }
1564*70a7ec85SAndroid Build Coastguard Worker
1565*70a7ec85SAndroid Build Coastguard Worker } else if (object->mType == SchemaType::DEVICE) {
1566*70a7ec85SAndroid Build Coastguard Worker // <vndk> can be missing because it can be determined at build time, not hard-coded
1567*70a7ec85SAndroid Build Coastguard Worker // in the XML file.
1568*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic push
1569*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1570*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalChild(root, VndkConverter{}, {}, &object->device.mVndk, param)) {
1571*70a7ec85SAndroid Build Coastguard Worker return false;
1572*70a7ec85SAndroid Build Coastguard Worker }
1573*70a7ec85SAndroid Build Coastguard Worker #pragma clang diagnostic pop
1574*70a7ec85SAndroid Build Coastguard Worker
1575*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalChild(root, VendorNdkConverter{}, {}, &object->device.mVendorNdk,
1576*70a7ec85SAndroid Build Coastguard Worker param)) {
1577*70a7ec85SAndroid Build Coastguard Worker return false;
1578*70a7ec85SAndroid Build Coastguard Worker }
1579*70a7ec85SAndroid Build Coastguard Worker
1580*70a7ec85SAndroid Build Coastguard Worker if (!parseOptionalChild(root, SystemSdkConverter{}, {}, &object->device.mSystemSdk,
1581*70a7ec85SAndroid Build Coastguard Worker param)) {
1582*70a7ec85SAndroid Build Coastguard Worker return false;
1583*70a7ec85SAndroid Build Coastguard Worker }
1584*70a7ec85SAndroid Build Coastguard Worker }
1585*70a7ec85SAndroid Build Coastguard Worker
1586*70a7ec85SAndroid Build Coastguard Worker for (auto &&hal : hals) {
1587*70a7ec85SAndroid Build Coastguard Worker if (!object->add(std::move(hal))) {
1588*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated compatibility-matrix.hal entry";
1589*70a7ec85SAndroid Build Coastguard Worker return false;
1590*70a7ec85SAndroid Build Coastguard Worker }
1591*70a7ec85SAndroid Build Coastguard Worker }
1592*70a7ec85SAndroid Build Coastguard Worker
1593*70a7ec85SAndroid Build Coastguard Worker std::vector<MatrixXmlFile> xmlFiles;
1594*70a7ec85SAndroid Build Coastguard Worker if (!parseChildren(root, MatrixXmlFileConverter{}, &xmlFiles, param)) {
1595*70a7ec85SAndroid Build Coastguard Worker return false;
1596*70a7ec85SAndroid Build Coastguard Worker }
1597*70a7ec85SAndroid Build Coastguard Worker for (auto&& xmlFile : xmlFiles) {
1598*70a7ec85SAndroid Build Coastguard Worker if (!xmlFile.optional()) {
1599*70a7ec85SAndroid Build Coastguard Worker *param.error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1600*70a7ec85SAndroid Build Coastguard Worker " has to be optional for compatibility matrix version 1.0";
1601*70a7ec85SAndroid Build Coastguard Worker return false;
1602*70a7ec85SAndroid Build Coastguard Worker }
1603*70a7ec85SAndroid Build Coastguard Worker std::string description{xmlFile.name()};
1604*70a7ec85SAndroid Build Coastguard Worker if (!object->addXmlFile(std::move(xmlFile))) {
1605*70a7ec85SAndroid Build Coastguard Worker *param.error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1606*70a7ec85SAndroid Build Coastguard Worker return false;
1607*70a7ec85SAndroid Build Coastguard Worker }
1608*70a7ec85SAndroid Build Coastguard Worker }
1609*70a7ec85SAndroid Build Coastguard Worker
1610*70a7ec85SAndroid Build Coastguard Worker return true;
1611*70a7ec85SAndroid Build Coastguard Worker }
1612*70a7ec85SAndroid Build Coastguard Worker };
1613*70a7ec85SAndroid Build Coastguard Worker
1614*70a7ec85SAndroid Build Coastguard Worker #define CREATE_CONVERT_FN(type) \
1615*70a7ec85SAndroid Build Coastguard Worker std::string toXml(const type& o, SerializeFlags::Type flags) { \
1616*70a7ec85SAndroid Build Coastguard Worker return type##Converter{}.toXml(o, flags); \
1617*70a7ec85SAndroid Build Coastguard Worker } \
1618*70a7ec85SAndroid Build Coastguard Worker bool fromXml(type* o, const std::string& xml, std::string* error) { \
1619*70a7ec85SAndroid Build Coastguard Worker return type##Converter{}.fromXml(o, xml, error); \
1620*70a7ec85SAndroid Build Coastguard Worker }
1621*70a7ec85SAndroid Build Coastguard Worker
1622*70a7ec85SAndroid Build Coastguard Worker // Create convert functions for public usage.
1623*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(HalManifest)
1624*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(CompatibilityMatrix)
1625*70a7ec85SAndroid Build Coastguard Worker
1626*70a7ec85SAndroid Build Coastguard Worker // Create convert functions for internal usage.
1627*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(KernelInfo)
1628*70a7ec85SAndroid Build Coastguard Worker
1629*70a7ec85SAndroid Build Coastguard Worker // Create convert functions for testing.
1630*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(Version)
1631*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(SepolicyVersion)
1632*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(KernelConfigTypedValue)
1633*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(MatrixHal)
1634*70a7ec85SAndroid Build Coastguard Worker CREATE_CONVERT_FN(ManifestHal)
1635*70a7ec85SAndroid Build Coastguard Worker
1636*70a7ec85SAndroid Build Coastguard Worker #undef CREATE_CONVERT_FN
1637*70a7ec85SAndroid Build Coastguard Worker
1638*70a7ec85SAndroid Build Coastguard Worker } // namespace vintf
1639*70a7ec85SAndroid Build Coastguard Worker } // namespace android
1640