blob: e42f9f74ce56eba7973411030bf820eb6a41863f [file] [log] [blame]
Yifan Hong676447a2016-11-15 12:57:23 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Convert objects from and to xml.
18
Yifan Honge0bb98d2017-08-07 14:40:19 -070019#define LOG_TAG "libvintf"
20#include <android-base/logging.h>
21
22#include "parse_xml.h"
23
24#include <type_traits>
25
Yifan Hong676447a2016-11-15 12:57:23 -080026#include <tinyxml2.h>
27
Yifan Hong705216b2018-03-21 17:27:47 -070028#include "Regex.h"
Yifan Hong934de622019-08-30 15:28:59 -070029#include "constants-private.h"
Yifan Hongdb127cb2017-09-19 13:36:21 -070030#include "constants.h"
Yifan Hong676447a2016-11-15 12:57:23 -080031#include "parse_string.h"
Yifan Hong676447a2016-11-15 12:57:23 -080032
33namespace android {
34namespace vintf {
35
36// --------------- tinyxml2 details
37
38using NodeType = tinyxml2::XMLElement;
39using DocType = tinyxml2::XMLDocument;
40
41// caller is responsible for deleteDocument() call
42inline DocType *createDocument() {
43 return new tinyxml2::XMLDocument();
44}
45
46// caller is responsible for deleteDocument() call
47inline DocType *createDocument(const std::string &xml) {
48 DocType *doc = new tinyxml2::XMLDocument();
Elliott Hughesa4c0a2e2017-08-08 11:26:24 -070049 if (doc->Parse(xml.c_str()) == tinyxml2::XML_SUCCESS) {
Yifan Hong676447a2016-11-15 12:57:23 -080050 return doc;
51 }
52 delete doc;
53 return nullptr;
54}
55
56inline void deleteDocument(DocType *d) {
57 delete d;
58}
59
60inline std::string printDocument(DocType *d) {
61 tinyxml2::XMLPrinter p;
62 d->Print(&p);
63 return std::string{p.CStr()};
64}
65
66inline NodeType *createNode(const std::string &name, DocType *d) {
67 return d->NewElement(name.c_str());
68}
69
70inline void appendChild(NodeType *parent, NodeType *child) {
71 parent->InsertEndChild(child);
72}
73
74inline void appendChild(DocType *parent, NodeType *child) {
75 parent->InsertEndChild(child);
76}
77
78inline void appendStrAttr(NodeType *e, const std::string &attrName, const std::string &attr) {
79 e->SetAttribute(attrName.c_str(), attr.c_str());
80}
81
82// text -> text
83inline void appendText(NodeType *parent, const std::string &text, DocType *d) {
84 parent->InsertEndChild(d->NewText(text.c_str()));
85}
86
Yifan Hong676447a2016-11-15 12:57:23 -080087inline std::string nameOf(NodeType *root) {
Yifan Hongcd41ffc2017-01-20 13:46:32 -080088 return root->Name() == NULL ? "" : root->Name();
Yifan Hong676447a2016-11-15 12:57:23 -080089}
90
91inline std::string getText(NodeType *root) {
Yifan Hongcd41ffc2017-01-20 13:46:32 -080092 return root->GetText() == NULL ? "" : root->GetText();
Yifan Hong676447a2016-11-15 12:57:23 -080093}
94
95inline NodeType *getChild(NodeType *parent, const std::string &name) {
96 return parent->FirstChildElement(name.c_str());
97}
98
99inline NodeType *getRootChild(DocType *parent) {
100 return parent->FirstChildElement();
101}
102
103inline std::vector<NodeType *> getChildren(NodeType *parent, const std::string &name) {
104 std::vector<NodeType *> v;
105 for (NodeType *child = parent->FirstChildElement(name.c_str());
106 child != nullptr;
107 child = child->NextSiblingElement(name.c_str())) {
108 v.push_back(child);
109 }
110 return v;
111}
112
113inline bool getAttr(NodeType *root, const std::string &attrName, std::string *s) {
114 const char *c = root->Attribute(attrName.c_str());
115 if (c == NULL)
116 return false;
117 *s = c;
118 return true;
119}
120
121// --------------- tinyxml2 details end.
122
Yifan Hong8e9c6692017-02-28 14:07:42 -0800123// Helper functions for XmlConverter
124static bool parse(const std::string &attrText, bool *attr) {
125 if (attrText == "true" || attrText == "1") {
126 *attr = true;
127 return true;
128 }
129 if (attrText == "false" || attrText == "0") {
130 *attr = false;
131 return true;
132 }
133 return false;
134}
135
Yifan Hong676447a2016-11-15 12:57:23 -0800136// ---------------------- XmlNodeConverter definitions
137
138template<typename Object>
139struct XmlNodeConverter : public XmlConverter<Object> {
140 XmlNodeConverter() {}
141 virtual ~XmlNodeConverter() {}
142
143 // sub-types should implement these.
144 virtual void mutateNode(const Object &o, NodeType *n, DocType *d) const = 0;
Yifan Hongba588bc2018-08-08 14:19:41 -0700145 virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags::Type) const {
Yifan Honga2635c42017-12-12 13:20:33 -0800146 mutateNode(o, n, d);
147 }
Yifan Hong94757062018-02-09 16:36:31 -0800148 virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
Yifan Hong676447a2016-11-15 12:57:23 -0800149 virtual std::string elementName() const = 0;
150
151 // convenience methods for user
Yifan Hong94757062018-02-09 16:36:31 -0800152 inline const std::string& lastError() const override { return mLastError; }
Yifan Honga2635c42017-12-12 13:20:33 -0800153 inline NodeType* serialize(const Object& o, DocType* d,
Yifan Hongba588bc2018-08-08 14:19:41 -0700154 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800155 NodeType *root = createNode(this->elementName(), d);
Yifan Honga2635c42017-12-12 13:20:33 -0800156 this->mutateNode(o, root, d, flags);
Yifan Hong676447a2016-11-15 12:57:23 -0800157 return root;
158 }
Yifan Hongba588bc2018-08-08 14:19:41 -0700159 inline std::string serialize(const Object& o, SerializeFlags::Type flags) const override {
Yifan Hong676447a2016-11-15 12:57:23 -0800160 DocType *doc = createDocument();
Yifan Honga2635c42017-12-12 13:20:33 -0800161 appendChild(doc, serialize(o, doc, flags));
Yifan Hong676447a2016-11-15 12:57:23 -0800162 std::string s = printDocument(doc);
163 deleteDocument(doc);
164 return s;
165 }
Yifan Hong94757062018-02-09 16:36:31 -0800166 inline bool deserialize(Object* object, NodeType* root) {
167 bool ret = deserialize(object, root, &mLastError);
168 return ret;
169 }
170 inline bool deserialize(Object* o, const std::string& xml) override {
171 bool ret = (*this)(o, xml, &mLastError);
172 return ret;
173 }
174 inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800175 if (nameOf(root) != this->elementName()) {
176 return false;
177 }
Yifan Hong94757062018-02-09 16:36:31 -0800178 return this->buildObject(object, root, error);
Yifan Hong676447a2016-11-15 12:57:23 -0800179 }
Yifan Hong94757062018-02-09 16:36:31 -0800180 inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
181 std::string errorBuffer;
182 if (error == nullptr) error = &errorBuffer;
183
184 auto doc = createDocument(xml);
Yifan Hong08e984c2017-05-18 12:50:04 -0700185 if (doc == nullptr) {
Yifan Hong94757062018-02-09 16:36:31 -0800186 *error = "Not a valid XML";
Yifan Hong08e984c2017-05-18 12:50:04 -0700187 return false;
188 }
Yifan Hong94757062018-02-09 16:36:31 -0800189 bool ret = deserialize(o, getRootChild(doc), error);
Yifan Hong676447a2016-11-15 12:57:23 -0800190 deleteDocument(doc);
191 return ret;
192 }
193 inline NodeType *operator()(const Object &o, DocType *d) const {
194 return serialize(o, d);
195 }
Yifan Hongba588bc2018-08-08 14:19:41 -0700196 inline std::string operator()(const Object& o, SerializeFlags::Type flags) const override {
Yifan Honga2635c42017-12-12 13:20:33 -0800197 return serialize(o, flags);
Yifan Hong676447a2016-11-15 12:57:23 -0800198 }
Yifan Hong94757062018-02-09 16:36:31 -0800199 inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
200 inline bool operator()(Object* o, const std::string& xml) override {
Yifan Hong676447a2016-11-15 12:57:23 -0800201 return deserialize(o, xml);
202 }
203
204 // convenience methods for implementor.
Yifan Hong8e9c6692017-02-28 14:07:42 -0800205
206 // All append* functions helps mutateNode() to serialize the object into XML.
Yifan Hong676447a2016-11-15 12:57:23 -0800207 template <typename T>
208 inline void appendAttr(NodeType *e, const std::string &attrName, const T &attr) const {
209 return appendStrAttr(e, attrName, ::android::vintf::to_string(attr));
210 }
211
212 inline void appendAttr(NodeType *e, const std::string &attrName, bool attr) const {
213 return appendStrAttr(e, attrName, attr ? "true" : "false");
214 }
215
Yifan Hong33466ad2017-02-24 11:31:37 -0800216 // text -> <name>text</name>
217 inline void appendTextElement(NodeType *parent, const std::string &name,
218 const std::string &text, DocType *d) const {
219 NodeType *c = createNode(name, d);
220 appendText(c, text, d);
221 appendChild(parent, c);
222 }
223
224 // text -> <name>text</name>
225 template<typename Array>
226 inline void appendTextElements(NodeType *parent, const std::string &name,
227 const Array &array, DocType *d) const {
228 for (const std::string &text : array) {
229 NodeType *c = createNode(name, d);
230 appendText(c, text, d);
231 appendChild(parent, c);
232 }
233 }
234
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700235 template <typename T, typename Array>
236 inline void appendChildren(NodeType* parent, const XmlNodeConverter<T>& conv,
237 const Array& array, DocType* d,
Yifan Hongba588bc2018-08-08 14:19:41 -0700238 SerializeFlags::Type flags = SerializeFlags::EVERYTHING) const {
Yifan Hong33466ad2017-02-24 11:31:37 -0800239 for (const T &t : array) {
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700240 appendChild(parent, conv.serialize(t, d, flags));
Yifan Hong33466ad2017-02-24 11:31:37 -0800241 }
242 }
243
Yifan Hong8e9c6692017-02-28 14:07:42 -0800244 // All parse* functions helps buildObject() to deserialize XML to the object. Returns
Yifan Hong94757062018-02-09 16:36:31 -0800245 // true if deserialization is successful, false if any error, and "error" will be
Yifan Hong8e9c6692017-02-28 14:07:42 -0800246 // set to error message.
247 template <typename T>
Yifan Hong94757062018-02-09 16:36:31 -0800248 inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
249 T* attr, std::string* /* error */) const {
Yifan Hong8e9c6692017-02-28 14:07:42 -0800250 std::string attrText;
251 bool success = getAttr(root, attrName, &attrText) &&
252 ::android::vintf::parse(attrText, attr);
253 if (!success) {
254 *attr = std::move(defaultValue);
255 }
256 return true;
257 }
258
Yifan Hong676447a2016-11-15 12:57:23 -0800259 template <typename T>
Yifan Hong94757062018-02-09 16:36:31 -0800260 inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
261 std::string* error) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800262 std::string attrText;
263 bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
264 if (!ret) {
Yifan Hong94757062018-02-09 16:36:31 -0800265 *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
266 attrText + "\" for element <" + elementName() + ">";
Yifan Hong676447a2016-11-15 12:57:23 -0800267 }
268 return ret;
269 }
270
Yifan Hong94757062018-02-09 16:36:31 -0800271 inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
272 std::string* error) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800273 bool ret = getAttr(root, attrName, attr);
274 if (!ret) {
Yifan Hong94757062018-02-09 16:36:31 -0800275 *error = "Could not find attr with name \"" + attrName + "\" for element <" +
276 elementName() + ">";
Yifan Hong676447a2016-11-15 12:57:23 -0800277 }
278 return ret;
279 }
280
Yifan Hong94757062018-02-09 16:36:31 -0800281 inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
282 std::string* error) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800283 NodeType *child = getChild(root, elementName);
284 if (child == nullptr) {
Yifan Hong94757062018-02-09 16:36:31 -0800285 *error = "Could not find element with name <" + elementName + "> in element <" +
286 this->elementName() + ">";
Yifan Hong676447a2016-11-15 12:57:23 -0800287 return false;
288 }
289 *s = getText(child);
290 return true;
291 }
292
Yifan Hongd4857902017-06-13 14:13:56 -0700293 inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
Yifan Hong94757062018-02-09 16:36:31 -0800294 std::string&& defaultValue, std::string* s,
295 std::string* /* error */) const {
Yifan Hongd4857902017-06-13 14:13:56 -0700296 NodeType* child = getChild(root, elementName);
297 *s = child == nullptr ? std::move(defaultValue) : getText(child);
298 return true;
299 }
300
Yifan Hong94757062018-02-09 16:36:31 -0800301 inline bool parseTextElements(NodeType* root, const std::string& elementName,
302 std::vector<std::string>* v, std::string* /* error */) const {
Yifan Hong33466ad2017-02-24 11:31:37 -0800303 auto nodes = getChildren(root, elementName);
304 v->resize(nodes.size());
305 for (size_t i = 0; i < nodes.size(); ++i) {
306 v->at(i) = getText(nodes[i]);
307 }
308 return true;
309 }
310
Yifan Hong676447a2016-11-15 12:57:23 -0800311 template <typename T>
Yifan Hong94757062018-02-09 16:36:31 -0800312 inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
313 std::string* error) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800314 NodeType *child = getChild(root, conv.elementName());
315 if (child == nullptr) {
Yifan Hong94757062018-02-09 16:36:31 -0800316 *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
317 this->elementName() + ">";
Yifan Hong676447a2016-11-15 12:57:23 -0800318 return false;
319 }
Yifan Hong94757062018-02-09 16:36:31 -0800320 return conv.deserialize(t, child, error);
Yifan Hong676447a2016-11-15 12:57:23 -0800321 }
322
323 template <typename T>
Yifan Hong94757062018-02-09 16:36:31 -0800324 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
325 T&& defaultValue, T* t, std::string* error) const {
Yifan Hong8e9c6692017-02-28 14:07:42 -0800326 NodeType *child = getChild(root, conv.elementName());
327 if (child == nullptr) {
328 *t = std::move(defaultValue);
329 return true;
330 }
Yifan Hong94757062018-02-09 16:36:31 -0800331 return conv.deserialize(t, child, error);
Yifan Hong8e9c6692017-02-28 14:07:42 -0800332 }
333
334 template <typename T>
Yifan Honga45f77d2018-12-03 16:42:52 -0800335 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
336 std::optional<T>* t, std::string* error) const {
337 NodeType* child = getChild(root, conv.elementName());
338 if (child == nullptr) {
339 *t = std::nullopt;
340 return true;
341 }
342 *t = std::make_optional<T>();
343 return conv.deserialize(&**t, child, error);
344 }
345
346 template <typename T>
Yifan Hong94757062018-02-09 16:36:31 -0800347 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
348 std::string* error) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800349 auto nodes = getChildren(root, conv.elementName());
350 v->resize(nodes.size());
351 for (size_t i = 0; i < nodes.size(); ++i) {
Yifan Hong94757062018-02-09 16:36:31 -0800352 if (!conv.deserialize(&v->at(i), nodes[i], error)) {
353 *error = "Could not parse element with name <" + conv.elementName() +
354 "> in element <" + this->elementName() + ">: " + *error;
Yifan Hong676447a2016-11-15 12:57:23 -0800355 return false;
356 }
357 }
358 return true;
359 }
360
Yifan Hong180c5102018-11-02 16:26:48 -0700361 template <typename Container, typename T = typename Container::value_type,
362 typename = typename Container::key_compare>
363 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, Container* s,
Yifan Hong94757062018-02-09 16:36:31 -0800364 std::string* error) const {
Yifan Honga04e1472017-04-05 13:15:34 -0700365 std::vector<T> vec;
Yifan Hong94757062018-02-09 16:36:31 -0800366 if (!parseChildren(root, conv, &vec, error)) {
Yifan Honga04e1472017-04-05 13:15:34 -0700367 return false;
368 }
369 s->clear();
370 s->insert(vec.begin(), vec.end());
371 if (s->size() != vec.size()) {
Yifan Hong94757062018-02-09 16:36:31 -0800372 *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
373 this->elementName() + ">";
Yifan Honga04e1472017-04-05 13:15:34 -0700374 s->clear();
375 return false;
376 }
377 return true;
378 }
379
Yifan Hong180c5102018-11-02 16:26:48 -0700380 template <typename K, typename V>
381 inline bool parseChildren(NodeType* root, const XmlNodeConverter<std::pair<K, V>>& conv,
382 std::map<K, V>* s, std::string* error) const {
383 return parseChildren<std::map<K, V>, std::pair<K, V>>(root, conv, s, error);
384 }
385
Yifan Hong94757062018-02-09 16:36:31 -0800386 inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
Yifan Hong676447a2016-11-15 12:57:23 -0800387 *s = getText(node);
388 return true;
389 }
390
Yifan Hongc54d32c2017-03-07 19:12:26 -0800391 template <typename T>
Yifan Hong94757062018-02-09 16:36:31 -0800392 inline bool parseText(NodeType* node, T* s, std::string* error) const {
Yifan Hongc6771f22017-04-05 11:45:18 -0700393 std::string text = getText(node);
394 bool ret = ::android::vintf::parse(text, s);
395 if (!ret) {
Yifan Hong94757062018-02-09 16:36:31 -0800396 *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
Yifan Hongc6771f22017-04-05 11:45:18 -0700397 }
398 return ret;
Yifan Hongc54d32c2017-03-07 19:12:26 -0800399 }
Yifan Hong94757062018-02-09 16:36:31 -0800400
401 private:
Yifan Hong676447a2016-11-15 12:57:23 -0800402 mutable std::string mLastError;
403};
404
405template<typename Object>
406struct XmlTextConverter : public XmlNodeConverter<Object> {
407 XmlTextConverter(const std::string &elementName)
408 : mElementName(elementName) {}
409
410 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
411 appendText(root, ::android::vintf::to_string(object), d);
412 }
Yifan Hong94757062018-02-09 16:36:31 -0800413 virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
414 return this->parseText(root, object, error);
Yifan Hong676447a2016-11-15 12:57:23 -0800415 }
Yifan Hong832e3902018-07-16 15:22:55 -0700416 virtual std::string elementName() const { return mElementName; }
417
418 private:
Yifan Hong676447a2016-11-15 12:57:23 -0800419 std::string mElementName;
420};
421
Yifan Hong180c5102018-11-02 16:26:48 -0700422template <typename Pair>
423struct XmlPairConverter : public XmlNodeConverter<Pair> {
424 XmlPairConverter(
425 const std::string& elementName,
426 std::unique_ptr<XmlNodeConverter<typename Pair::first_type>>&& firstConverter,
427 std::unique_ptr<XmlNodeConverter<typename Pair::second_type>>&& secondConverter)
428 : mElementName(elementName),
429 mFirstConverter(std::move(firstConverter)),
430 mSecondConverter(std::move(secondConverter)) {}
431
432 virtual void mutateNode(const Pair& pair, NodeType* root, DocType* d) const override {
433 appendChild(root, mFirstConverter->serialize(pair.first, d));
434 appendChild(root, mSecondConverter->serialize(pair.second, d));
435 }
436 virtual bool buildObject(Pair* pair, NodeType* root, std::string* error) const override {
437 return this->parseChild(root, *mFirstConverter, &pair->first, error) &&
438 this->parseChild(root, *mSecondConverter, &pair->second, error);
439 }
440 virtual std::string elementName() const { return mElementName; }
441
442 private:
443 std::string mElementName;
444 std::unique_ptr<XmlNodeConverter<typename Pair::first_type>> mFirstConverter;
445 std::unique_ptr<XmlNodeConverter<typename Pair::second_type>> mSecondConverter;
446};
447
Yifan Hong676447a2016-11-15 12:57:23 -0800448// ---------------------- XmlNodeConverter definitions end
449
Yifan Hong94757062018-02-09 16:36:31 -0800450XmlTextConverter<Version> versionConverter{"version"};
Yifan Hong676447a2016-11-15 12:57:23 -0800451
Yifan Hong94757062018-02-09 16:36:31 -0800452XmlTextConverter<VersionRange> versionRangeConverter{"version"};
Yifan Hong676447a2016-11-15 12:57:23 -0800453
Yifan Hongc54d32c2017-03-07 19:12:26 -0800454struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
455 std::string elementName() const override { return "transport"; }
456 void mutateNode(const TransportArch &object, NodeType *root, DocType *d) const override {
457 if (object.arch != Arch::ARCH_EMPTY) {
458 appendAttr(root, "arch", object.arch);
459 }
460 appendText(root, ::android::vintf::to_string(object.transport), d);
461 }
Yifan Hong94757062018-02-09 16:36:31 -0800462 bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
463 if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
464 !parseText(root, &object->transport, error)) {
Yifan Hongc54d32c2017-03-07 19:12:26 -0800465 return false;
466 }
467 if (!object->isValid()) {
Yifan Hong94757062018-02-09 16:36:31 -0800468 *error = "transport == " + ::android::vintf::to_string(object->transport) +
469 " and arch == " + ::android::vintf::to_string(object->arch) +
470 " is not a valid combination.";
Yifan Hongc54d32c2017-03-07 19:12:26 -0800471 return false;
472 }
473 return true;
474 }
475};
476
Yifan Hong94757062018-02-09 16:36:31 -0800477TransportArchConverter transportArchConverter{};
Yifan Hongc54d32c2017-03-07 19:12:26 -0800478
Yifan Hong3f5489a2017-02-08 11:14:21 -0800479struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
480 std::string elementName() const override { return "value"; }
481 void mutateNode(const KernelConfigTypedValue &object, NodeType *root, DocType *d) const override {
482 appendAttr(root, "type", object.mType);
483 appendText(root, ::android::vintf::to_string(object), d);
484 }
Yifan Hong94757062018-02-09 16:36:31 -0800485 bool buildObject(KernelConfigTypedValue* object, NodeType* root,
486 std::string* error) const override {
Yifan Hong3f5489a2017-02-08 11:14:21 -0800487 std::string stringValue;
Yifan Hong94757062018-02-09 16:36:31 -0800488 if (!parseAttr(root, "type", &object->mType, error) ||
489 !parseText(root, &stringValue, error)) {
Yifan Hong3f5489a2017-02-08 11:14:21 -0800490 return false;
491 }
492 if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
Yifan Hong94757062018-02-09 16:36:31 -0800493 *error = "Could not parse kernel config value \"" + stringValue + "\"";
Yifan Hong3f5489a2017-02-08 11:14:21 -0800494 return false;
495 }
496 return true;
497 }
498};
499
Yifan Hong94757062018-02-09 16:36:31 -0800500KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
Yifan Hong3f5489a2017-02-08 11:14:21 -0800501
Yifan Hong180c5102018-11-02 16:26:48 -0700502XmlPairConverter<KernelConfig> matrixKernelConfigConverter{
503 "config", std::make_unique<XmlTextConverter<KernelConfigKey>>("key"),
504 std::make_unique<KernelConfigTypedValueConverter>(kernelConfigTypedValueConverter)};
Yifan Hong3f5489a2017-02-08 11:14:21 -0800505
Yifan Hong476b63f2017-05-17 18:15:01 -0700506struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
507 std::string elementName() const override { return "interface"; }
508 void mutateNode(const HalInterface &intf, NodeType *root, DocType *d) const override {
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700509 appendTextElement(root, "name", intf.name(), d);
510 appendTextElements(root, "instance", intf.mInstances, d);
Yifan Hong705216b2018-03-21 17:27:47 -0700511 appendTextElements(root, "regex-instance", intf.mRegexes, d);
Yifan Hong476b63f2017-05-17 18:15:01 -0700512 }
Yifan Hong94757062018-02-09 16:36:31 -0800513 bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
Yifan Hong476b63f2017-05-17 18:15:01 -0700514 std::vector<std::string> instances;
Yifan Hong705216b2018-03-21 17:27:47 -0700515 std::vector<std::string> regexes;
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700516 if (!parseTextElement(root, "name", &intf->mName, error) ||
Yifan Hong705216b2018-03-21 17:27:47 -0700517 !parseTextElements(root, "instance", &instances, error) ||
518 !parseTextElements(root, "regex-instance", &regexes, error)) {
Yifan Hong476b63f2017-05-17 18:15:01 -0700519 return false;
520 }
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700521 bool success = true;
522 for (const auto& e : instances) {
523 if (!intf->insertInstance(e, false /* isRegex */)) {
524 if (!error->empty()) *error += "\n";
525 *error += "Duplicated instance '" + e + "' in " + intf->name();
526 success = false;
527 }
Yifan Hong476b63f2017-05-17 18:15:01 -0700528 }
Yifan Hong705216b2018-03-21 17:27:47 -0700529 for (const auto& e : regexes) {
530 details::Regex regex;
531 if (!regex.compile(e)) {
532 if (!error->empty()) *error += "\n";
533 *error += "Invalid regular expression '" + e + "' in " + intf->name();
534 success = false;
535 }
536 if (!intf->insertInstance(e, true /* isRegex */)) {
537 if (!error->empty()) *error += "\n";
538 *error += "Duplicated regex-instance '" + e + "' in " + intf->name();
539 success = false;
540 }
541 }
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700542 return success;
Yifan Hong476b63f2017-05-17 18:15:01 -0700543 }
544};
545
Yifan Hong94757062018-02-09 16:36:31 -0800546HalInterfaceConverter halInterfaceConverter{};
Yifan Hong476b63f2017-05-17 18:15:01 -0700547
Yifan Honga9993572017-01-24 19:33:15 -0800548struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
Yifan Hong676447a2016-11-15 12:57:23 -0800549 std::string elementName() const override { return "hal"; }
550 void mutateNode(const MatrixHal &hal, NodeType *root, DocType *d) const override {
551 appendAttr(root, "format", hal.format);
552 appendAttr(root, "optional", hal.optional);
553 appendTextElement(root, "name", hal.name, d);
Yifan Hong934de622019-08-30 15:28:59 -0700554 // Don't write <version> for format="aidl"
555 if (hal.format != HalFormat::AIDL) {
556 appendChildren(root, versionRangeConverter, hal.versionRanges, d);
557 }
Yifan Hong9cd9eb02017-05-17 18:36:08 -0700558 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
Yifan Hong676447a2016-11-15 12:57:23 -0800559 }
Yifan Hong94757062018-02-09 16:36:31 -0800560 bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
Yifan Hong9cd9eb02017-05-17 18:36:08 -0700561 std::vector<HalInterface> interfaces;
Yifan Hong94757062018-02-09 16:36:31 -0800562 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
563 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
564 error) ||
565 !parseTextElement(root, "name", &object->name, error) ||
566 !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
567 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
Yifan Hong676447a2016-11-15 12:57:23 -0800568 return false;
569 }
Yifan Hong934de622019-08-30 15:28:59 -0700570 if (object->format == HalFormat::AIDL) {
571 if (!object->versionRanges.empty()) {
572 LOG(WARNING) << "Ignoring <version> on matrix <hal format=\"aidl\"> "
573 << object->name;
574 object->versionRanges.clear();
575 }
576 // Insert fake version for AIDL HALs so that compatibility check for AIDL and other
577 // HAL formats can be unified.
578 object->versionRanges.push_back(details::kFakeAidlVersionRange);
579 }
Yifan Hong9cd9eb02017-05-17 18:36:08 -0700580 for (auto&& interface : interfaces) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700581 std::string name{interface.name()};
Yifan Hong9cd9eb02017-05-17 18:36:08 -0700582 auto res = object->interfaces.emplace(std::move(name), std::move(interface));
583 if (!res.second) {
Yifan Hong94757062018-02-09 16:36:31 -0800584 *error = "Duplicated interface entry \"" + res.first->first +
585 "\"; if additional instances are needed, add them to the "
586 "existing <interface> node.";
Yifan Hong9cd9eb02017-05-17 18:36:08 -0700587 return false;
588 }
589 }
Yifan Hongd9e46432017-08-15 17:14:52 -0700590// Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
Yifan Hong6bce1a62018-01-31 13:30:04 -0800591#ifndef LIBVINTF_TARGET
Yifan Hong94757062018-02-09 16:36:31 -0800592 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
Yifan Hongd9e46432017-08-15 17:14:52 -0700593 return false;
594 }
595#endif
Yifan Hong676447a2016-11-15 12:57:23 -0800596 return true;
597 }
Yifan Hongd9e46432017-08-15 17:14:52 -0700598
Yifan Hong6bce1a62018-01-31 13:30:04 -0800599#ifndef LIBVINTF_TARGET
Yifan Hongd9e46432017-08-15 17:14:52 -0700600 private:
Yifan Hong94757062018-02-09 16:36:31 -0800601 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
Yifan Hongd9e46432017-08-15 17:14:52 -0700602 if (hal.getName() == "netutils-wrapper") {
603 if (hal.versionRanges.size() != 1) {
Yifan Hong94757062018-02-09 16:36:31 -0800604 *error =
Yifan Hongd9e46432017-08-15 17:14:52 -0700605 "netutils-wrapper HAL must specify exactly one version x.0, "
606 "but multiple <version> element is specified.";
607 return false;
608 }
609 const VersionRange& v = hal.versionRanges.at(0);
610 if (!v.isSingleVersion()) {
Yifan Hong94757062018-02-09 16:36:31 -0800611 *error =
Yifan Hongd9e46432017-08-15 17:14:52 -0700612 "netutils-wrapper HAL must specify exactly one version x.0, "
613 "but a range is provided. Perhaps you mean '" +
614 to_string(Version{v.majorVer, 0}) + "'?";
615 return false;
616 }
617 if (v.minMinor != 0) {
Yifan Hong94757062018-02-09 16:36:31 -0800618 *error =
Yifan Hongd9e46432017-08-15 17:14:52 -0700619 "netutils-wrapper HAL must specify exactly one version x.0, "
620 "but minor version is not 0. Perhaps you mean '" +
621 to_string(Version{v.majorVer, 0}) + "'?";
622 return false;
623 }
624 }
625 return true;
626 }
627#endif
Yifan Hong676447a2016-11-15 12:57:23 -0800628};
629
Yifan Hong94757062018-02-09 16:36:31 -0800630MatrixHalConverter matrixHalConverter{};
Yifan Hong676447a2016-11-15 12:57:23 -0800631
Yifan Hongff0a5632017-08-21 18:39:29 -0700632struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
633 std::string elementName() const override { return "conditions"; }
634 void mutateNode(const std::vector<KernelConfig>& conds, NodeType* root,
635 DocType* d) const override {
Yifan Hong180c5102018-11-02 16:26:48 -0700636 appendChildren(root, matrixKernelConfigConverter, conds, d);
Yifan Hongff0a5632017-08-21 18:39:29 -0700637 }
Yifan Hong94757062018-02-09 16:36:31 -0800638 bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
639 std::string* error) const override {
Yifan Hong180c5102018-11-02 16:26:48 -0700640 return parseChildren(root, matrixKernelConfigConverter, object, error);
Yifan Hongff0a5632017-08-21 18:39:29 -0700641 }
642};
643
Yifan Hong94757062018-02-09 16:36:31 -0800644MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
Yifan Hongff0a5632017-08-21 18:39:29 -0700645
Yifan Honga9993572017-01-24 19:33:15 -0800646struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
Yifan Hong676447a2016-11-15 12:57:23 -0800647 std::string elementName() const override { return "kernel"; }
Yifan Hong86678e42018-07-26 11:38:54 -0700648 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d) const override {
Yifan Hong250b55c2018-08-07 17:41:56 -0700649 mutateNode(kernel, root, d, SerializeFlags::EVERYTHING);
Yifan Hong86678e42018-07-26 11:38:54 -0700650 }
651 void mutateNode(const MatrixKernel& kernel, NodeType* root, DocType* d,
Yifan Hongba588bc2018-08-08 14:19:41 -0700652 SerializeFlags::Type flags) const override {
Yifan Hong86678e42018-07-26 11:38:54 -0700653 KernelVersion kv = kernel.mMinLts;
Yifan Honga1b112d2018-08-07 17:44:10 -0700654 if (!flags.isKernelMinorRevisionEnabled()) {
Yifan Hong86678e42018-07-26 11:38:54 -0700655 kv.minorRev = 0u;
656 }
657 appendAttr(root, "version", kv);
658
Yifan Honga39ecfe2019-12-11 17:55:30 -0800659 if (kernel.getSourceMatrixLevel() != Level::UNSPECIFIED) {
660 appendAttr(root, "level", kernel.getSourceMatrixLevel());
661 }
662
Yifan Hongff0a5632017-08-21 18:39:29 -0700663 if (!kernel.mConditions.empty()) {
664 appendChild(root, matrixKernelConditionsConverter(kernel.mConditions, d));
665 }
Yifan Honga1b112d2018-08-07 17:44:10 -0700666 if (flags.isKernelConfigsEnabled()) {
Yifan Hong180c5102018-11-02 16:26:48 -0700667 appendChildren(root, matrixKernelConfigConverter, kernel.mConfigs, d);
Yifan Hong86678e42018-07-26 11:38:54 -0700668 }
Yifan Hong676447a2016-11-15 12:57:23 -0800669 }
Yifan Hong94757062018-02-09 16:36:31 -0800670 bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
Yifan Honga39ecfe2019-12-11 17:55:30 -0800671 Level sourceMatrixLevel = Level::UNSPECIFIED;
Yifan Hong94757062018-02-09 16:36:31 -0800672 if (!parseAttr(root, "version", &object->mMinLts, error) ||
Yifan Honga39ecfe2019-12-11 17:55:30 -0800673 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &sourceMatrixLevel, error) ||
Yifan Hong94757062018-02-09 16:36:31 -0800674 !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
675 error) ||
Yifan Hong180c5102018-11-02 16:26:48 -0700676 !parseChildren(root, matrixKernelConfigConverter, &object->mConfigs, error)) {
Yifan Hong3f5489a2017-02-08 11:14:21 -0800677 return false;
678 }
Yifan Honga39ecfe2019-12-11 17:55:30 -0800679 object->setSourceMatrixLevel(sourceMatrixLevel);
Yifan Hong676447a2016-11-15 12:57:23 -0800680 return true;
681 }
682};
683
Yifan Hong94757062018-02-09 16:36:31 -0800684MatrixKernelConverter matrixKernelConverter{};
Yifan Hong676447a2016-11-15 12:57:23 -0800685
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700686XmlTextConverter<FqInstance> fqInstanceConverter{"fqname"};
687
Yifan Honga9993572017-01-24 19:33:15 -0800688struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
Yifan Hong676447a2016-11-15 12:57:23 -0800689 std::string elementName() const override { return "hal"; }
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700690 void mutateNode(const ManifestHal& m, NodeType* root, DocType* d) const override {
Yifan Hong250b55c2018-08-07 17:41:56 -0700691 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700692 }
693 void mutateNode(const ManifestHal& hal, NodeType* root, DocType* d,
Yifan Hongba588bc2018-08-08 14:19:41 -0700694 SerializeFlags::Type flags) const override {
Yifan Hong676447a2016-11-15 12:57:23 -0800695 appendAttr(root, "format", hal.format);
696 appendTextElement(root, "name", hal.name, d);
Yifan Hong934de622019-08-30 15:28:59 -0700697 if (!hal.transportArch.empty()) {
698 appendChild(root, transportArchConverter(hal.transportArch, d));
699 }
700 // Don't output <version> for format="aidl"
701 if (hal.format != HalFormat::AIDL) {
702 appendChildren(root, versionConverter, hal.versions, d);
703 }
Yifan Hong476b63f2017-05-17 18:15:01 -0700704 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
Yifan Hongce4289b2018-03-13 12:01:24 -0700705 if (hal.isOverride()) {
706 appendAttr(root, "override", hal.isOverride());
Yifan Hong68d23062018-01-17 16:09:46 -0800707 }
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700708
Yifan Honga1b112d2018-08-07 17:44:10 -0700709 if (flags.isFqnameEnabled()) {
Yifan Hong934de622019-08-30 15:28:59 -0700710 std::set<std::string> simpleFqInstances;
711 hal.forEachInstance([&simpleFqInstances](const auto& manifestInstance) {
712 simpleFqInstances.emplace(manifestInstance.getSimpleFqInstance());
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700713 return true;
714 });
Yifan Hong934de622019-08-30 15:28:59 -0700715 appendTextElements(root, fqInstanceConverter.elementName(), simpleFqInstances, d);
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700716 }
Yifan Hong676447a2016-11-15 12:57:23 -0800717 }
Yifan Hong94757062018-02-09 16:36:31 -0800718 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
Yifan Hong476b63f2017-05-17 18:15:01 -0700719 std::vector<HalInterface> interfaces;
Yifan Hong94757062018-02-09 16:36:31 -0800720 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
Yifan Hongce4289b2018-03-13 12:01:24 -0700721 !parseOptionalAttr(root, "override", false, &object->mIsOverride, error) ||
Yifan Hong94757062018-02-09 16:36:31 -0800722 !parseTextElement(root, "name", &object->name, error) ||
723 !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
724 !parseChildren(root, versionConverter, &object->versions, error) ||
725 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
Yifan Hong676447a2016-11-15 12:57:23 -0800726 return false;
727 }
Yifan Honge0bb98d2017-08-07 14:40:19 -0700728
729 switch (object->format) {
730 case HalFormat::HIDL: {
731 if (object->transportArch.empty()) {
Yifan Hong94757062018-02-09 16:36:31 -0800732 *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
Yifan Honge0bb98d2017-08-07 14:40:19 -0700733 return false;
734 }
735 } break;
736 case HalFormat::NATIVE: {
737 if (!object->transportArch.empty()) {
Yifan Hong94757062018-02-09 16:36:31 -0800738 *error =
Yifan Honge0bb98d2017-08-07 14:40:19 -0700739 "Native HAL '" + object->name + "' should not have <transport> defined.";
740 return false;
741 }
742 } break;
Yifan Hong934de622019-08-30 15:28:59 -0700743 case HalFormat::AIDL: {
744 if (!object->transportArch.empty()) {
745 LOG(WARNING) << "Ignoring <transport> on manifest <hal format=\"aidl\"> "
746 << object->name;
747 object->transportArch = {};
748 }
749 if (!object->versions.empty()) {
750 LOG(WARNING) << "Ignoring <version> on manifest <hal format=\"aidl\"> "
751 << object->name;
752 object->versions.clear();
753 }
754 // Insert fake version for AIDL HALs so that forEachInstance works.
755 object->versions.push_back(details::kFakeAidlVersion);
756 } break;
Yifan Honge0bb98d2017-08-07 14:40:19 -0700757 default: {
758 LOG(FATAL) << "Unhandled HalFormat "
759 << static_cast<typename std::underlying_type<HalFormat>::type>(
760 object->format);
761 } break;
762 }
763 if (!object->transportArch.isValid()) return false;
764
Yifan Hongec3b9b72017-02-23 13:24:42 -0800765 object->interfaces.clear();
766 for (auto &&interface : interfaces) {
Yifan Hong7e9e04d2018-03-20 13:06:00 -0700767 auto res = object->interfaces.emplace(interface.name(), std::move(interface));
Yifan Hongec3b9b72017-02-23 13:24:42 -0800768 if (!res.second) {
Yifan Hong94757062018-02-09 16:36:31 -0800769 *error = "Duplicated interface entry \"" + res.first->first +
770 "\"; if additional instances are needed, add them to the "
771 "existing <interface> node.";
Yifan Hongec3b9b72017-02-23 13:24:42 -0800772 return false;
773 }
774 }
Yifan Hongc54d32c2017-03-07 19:12:26 -0800775 if (!object->isValid()) {
Yifan Hong94757062018-02-09 16:36:31 -0800776 *error = "'" + object->name + "' is not a valid Manifest HAL.";
Yifan Hongc54d32c2017-03-07 19:12:26 -0800777 return false;
778 }
Yifan Hongd9e46432017-08-15 17:14:52 -0700779// Do not check for target-side libvintf to avoid restricting upgrade accidentally.
Yifan Hong6bce1a62018-01-31 13:30:04 -0800780#ifndef LIBVINTF_TARGET
Yifan Hong94757062018-02-09 16:36:31 -0800781 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
Yifan Hongd9e46432017-08-15 17:14:52 -0700782 return false;
783 }
784#endif
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700785
786 std::set<FqInstance> fqInstances;
787 if (!parseChildren(root, fqInstanceConverter, &fqInstances, error)) {
788 return false;
789 }
Yifan Hong934de622019-08-30 15:28:59 -0700790 std::set<FqInstance> fqInstancesToInsert;
791 for (auto& e : fqInstances) {
Yifan Hong55410692018-05-01 19:08:51 -0700792 if (e.hasPackage()) {
793 *error = "Should not specify package: \"" + e.string() + "\"";
794 return false;
795 }
Yifan Hong934de622019-08-30 15:28:59 -0700796 if (object->format == HalFormat::AIDL) {
797 // <fqname> in AIDL HALs should not contain version. Put in the fake
798 // kFakeAidlVersion so that compatibility check works.
799 FqInstance withFakeVersion;
800 if (!withFakeVersion.setTo(details::kFakeAidlVersion.majorVer,
801 details::kFakeAidlVersion.minorVer, e.getInterface(),
802 e.getInstance())) {
803 return false;
804 }
805 fqInstancesToInsert.emplace(std::move(withFakeVersion));
806 } else {
807 fqInstancesToInsert.emplace(std::move(e));
808 }
Yifan Hong55410692018-05-01 19:08:51 -0700809 }
Yifan Hong934de622019-08-30 15:28:59 -0700810 if (!object->insertInstances(fqInstancesToInsert, error)) {
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700811 return false;
812 }
813
Yifan Hongc54d32c2017-03-07 19:12:26 -0800814 return true;
Yifan Hong676447a2016-11-15 12:57:23 -0800815 }
Yifan Hongd9e46432017-08-15 17:14:52 -0700816
Yifan Hong6bce1a62018-01-31 13:30:04 -0800817#ifndef LIBVINTF_TARGET
Yifan Hongd9e46432017-08-15 17:14:52 -0700818 private:
Yifan Hong94757062018-02-09 16:36:31 -0800819 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
Yifan Hongd9e46432017-08-15 17:14:52 -0700820 if (hal.getName() == "netutils-wrapper") {
821 for (const Version& v : hal.versions) {
822 if (v.minorVer != 0) {
Yifan Hong94757062018-02-09 16:36:31 -0800823 *error =
Yifan Hongd9e46432017-08-15 17:14:52 -0700824 "netutils-wrapper HAL must specify exactly one version x.0, "
825 "but minor version is not 0. Perhaps you mean '" +
826 to_string(Version{v.majorVer, 0}) + "'?";
827 return false;
828 }
829 }
830 }
831 return true;
832 }
833#endif
Yifan Hong676447a2016-11-15 12:57:23 -0800834};
835
Yifan Hong4a5eb7b2017-02-16 18:19:26 -0800836// Convert ManifestHal from and to XML. Returned object is guaranteed to have
837// .isValid() == true.
Yifan Hong94757062018-02-09 16:36:31 -0800838ManifestHalConverter manifestHalConverter{};
Yifan Hong676447a2016-11-15 12:57:23 -0800839
Yifan Hong94757062018-02-09 16:36:31 -0800840XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
841XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
Yifan Hong558380a2017-02-09 15:37:32 -0800842
Yifan Honga9993572017-01-24 19:33:15 -0800843struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
Yifan Hong676447a2016-11-15 12:57:23 -0800844 std::string elementName() const override { return "sepolicy"; }
Yifan Hong558380a2017-02-09 15:37:32 -0800845 void mutateNode(const Sepolicy &object, NodeType *root, DocType *d) const override {
846 appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
Yifan Hong9a361582017-04-12 18:56:37 -0700847 appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
Yifan Hong676447a2016-11-15 12:57:23 -0800848 }
Yifan Hong94757062018-02-09 16:36:31 -0800849 bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
850 if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
851 error) ||
852 !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
853 error)) {
Yifan Hong558380a2017-02-09 15:37:32 -0800854 return false;
855 }
Yifan Hong676447a2016-11-15 12:57:23 -0800856 return true;
857 }
858};
Yifan Hong94757062018-02-09 16:36:31 -0800859SepolicyConverter sepolicyConverter{};
Yifan Hong676447a2016-11-15 12:57:23 -0800860
Yifan Hong94757062018-02-09 16:36:31 -0800861[[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
Yifan Hongfeb454e2018-01-09 16:16:40 -0800862
Yifan Hong94757062018-02-09 16:36:31 -0800863XmlTextConverter<std::string> vndkVersionConverter{"version"};
864XmlTextConverter<std::string> vndkLibraryConverter{"library"};
Yifan Honga04e1472017-04-05 13:15:34 -0700865
Yifan Hong0f529fa2018-01-10 14:51:59 -0800866struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
Yifan Honga04e1472017-04-05 13:15:34 -0700867 std::string elementName() const override { return "vndk"; }
868 void mutateNode(const Vndk &object, NodeType *root, DocType *d) const override {
869 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
870 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
871 }
Yifan Hong94757062018-02-09 16:36:31 -0800872 bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
873 if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
874 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
Yifan Honga04e1472017-04-05 13:15:34 -0700875 return false;
876 }
877 return true;
878 }
879};
880
Yifan Hong94757062018-02-09 16:36:31 -0800881[[deprecated]] VndkConverter vndkConverter{};
Yifan Honga04e1472017-04-05 13:15:34 -0700882
Yifan Hongfeb454e2018-01-09 16:16:40 -0800883struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
884 std::string elementName() const override { return "vendor-ndk"; }
885 void mutateNode(const VendorNdk& object, NodeType* root, DocType* d) const override {
886 appendChild(root, vndkVersionConverter(object.mVersion, d));
887 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
888 }
Yifan Hong94757062018-02-09 16:36:31 -0800889 bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
890 if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
891 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
Yifan Hongfeb454e2018-01-09 16:16:40 -0800892 return false;
893 }
894 return true;
895 }
896};
897
Yifan Hong94757062018-02-09 16:36:31 -0800898VendorNdkConverter vendorNdkConverter{};
Yifan Hongfeb454e2018-01-09 16:16:40 -0800899
Yifan Hong94757062018-02-09 16:36:31 -0800900XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
Yifan Honga28729e2018-01-17 13:40:35 -0800901
902struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
903 std::string elementName() const override { return "system-sdk"; }
904 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
905 appendChildren(root, systemSdkVersionConverter, object.versions(), d);
906 }
Yifan Hong94757062018-02-09 16:36:31 -0800907 bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
908 return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
Yifan Honga28729e2018-01-17 13:40:35 -0800909 }
910};
911
Yifan Hong94757062018-02-09 16:36:31 -0800912SystemSdkConverter systemSdkConverter{};
Yifan Honga28729e2018-01-17 13:40:35 -0800913
Yifan Hong2a3dd082017-04-04 17:15:35 -0700914struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
915 std::string elementName() const override { return "sepolicy"; }
916 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
917 appendChild(root, versionConverter(m, d));
918 }
Yifan Hong94757062018-02-09 16:36:31 -0800919 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
920 return parseChild(root, versionConverter, object, error);
Yifan Hong2a3dd082017-04-04 17:15:35 -0700921 }
922};
Yifan Hong94757062018-02-09 16:36:31 -0800923HalManifestSepolicyConverter halManifestSepolicyConverter{};
Yifan Hong2a3dd082017-04-04 17:15:35 -0700924
Yifan Hongd4857902017-06-13 14:13:56 -0700925struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
926 std::string elementName() const override { return "xmlfile"; }
927 void mutateNode(const ManifestXmlFile& f, NodeType* root, DocType* d) const override {
928 appendTextElement(root, "name", f.name(), d);
929 appendChild(root, versionConverter(f.version(), d));
930 if (!f.overriddenPath().empty()) {
931 appendTextElement(root, "path", f.overriddenPath(), d);
932 }
933 }
Yifan Hong94757062018-02-09 16:36:31 -0800934 bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
935 if (!parseTextElement(root, "name", &object->mName, error) ||
936 !parseChild(root, versionConverter, &object->mVersion, error) ||
937 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
Yifan Hongd4857902017-06-13 14:13:56 -0700938 return false;
939 }
940 return true;
941 }
942};
Yifan Hong94757062018-02-09 16:36:31 -0800943ManifestXmlFileConverter manifestXmlFileConverter{};
Yifan Hongd4857902017-06-13 14:13:56 -0700944
Yifan Hong180c5102018-11-02 16:26:48 -0700945XmlPairConverter<std::pair<std::string, std::string>> kernelConfigConverter{
946 "config", std::make_unique<XmlTextConverter<std::string>>("key"),
947 std::make_unique<XmlTextConverter<std::string>>("value")};
948
949struct KernelInfoConverter : public XmlNodeConverter<KernelInfo> {
950 std::string elementName() const override { return "kernel"; }
951 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d) const override {
952 mutateNode(o, root, d, SerializeFlags::EVERYTHING);
953 }
954 void mutateNode(const KernelInfo& o, NodeType* root, DocType* d,
955 SerializeFlags::Type flags) const override {
956 if (o.version() != KernelVersion{}) {
957 appendAttr(root, "version", o.version());
958 }
Yifan Honge6248442019-12-11 13:33:00 -0800959 if (o.level() != Level::UNSPECIFIED) {
960 appendAttr(root, "target-level", o.level());
961 }
Yifan Hong180c5102018-11-02 16:26:48 -0700962 if (flags.isKernelConfigsEnabled()) {
963 appendChildren(root, kernelConfigConverter, o.configs(), d);
964 }
965 }
966 bool buildObject(KernelInfo* o, NodeType* root, std::string* error) const override {
967 return parseOptionalAttr(root, "version", {}, &o->mVersion, error) &&
Yifan Honge6248442019-12-11 13:33:00 -0800968 parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &o->mLevel, error) &&
Yifan Hong180c5102018-11-02 16:26:48 -0700969 parseChildren(root, kernelConfigConverter, &o->mConfigs, error);
970 }
971};
972
973KernelInfoConverter kernelInfoConverter{};
974
Yifan Hongd2b7e642017-02-17 10:15:32 -0800975struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
Yifan Hong676447a2016-11-15 12:57:23 -0800976 std::string elementName() const override { return "manifest"; }
Yifan Hongd2b7e642017-02-17 10:15:32 -0800977 void mutateNode(const HalManifest &m, NodeType *root, DocType *d) const override {
Yifan Hong250b55c2018-08-07 17:41:56 -0700978 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
Yifan Honga2635c42017-12-12 13:20:33 -0800979 }
980 void mutateNode(const HalManifest& m, NodeType* root, DocType* d,
Yifan Hongba588bc2018-08-08 14:19:41 -0700981 SerializeFlags::Type flags) const override {
Yifan Hong304cdab2018-08-02 16:03:59 -0700982 if (flags.isMetaVersionEnabled()) {
983 appendAttr(root, "version", m.getMetaVersion());
984 }
985 if (flags.isSchemaTypeEnabled()) {
986 appendAttr(root, "type", m.mType);
987 }
Yifan Honga2635c42017-12-12 13:20:33 -0800988
Yifan Honga1b112d2018-08-07 17:44:10 -0700989 if (flags.isHalsEnabled()) {
Yifan Hong2b1efaa2018-03-13 12:36:38 -0700990 appendChildren(root, manifestHalConverter, m.getHals(), d, flags);
Yifan Honga2635c42017-12-12 13:20:33 -0800991 }
Yifan Hong2a3dd082017-04-04 17:15:35 -0700992 if (m.mType == SchemaType::DEVICE) {
Yifan Honga1b112d2018-08-07 17:44:10 -0700993 if (flags.isSepolicyEnabled()) {
Yifan Hong304cdab2018-08-02 16:03:59 -0700994 if (m.device.mSepolicyVersion != Version{}) {
995 appendChild(root, halManifestSepolicyConverter(m.device.mSepolicyVersion, d));
996 }
Yifan Honga2635c42017-12-12 13:20:33 -0800997 }
Yifan Hongc393c712018-02-12 13:33:17 -0800998 if (m.mLevel != Level::UNSPECIFIED) {
999 this->appendAttr(root, "target-level", m.mLevel);
1000 }
Yifan Honga45f77d2018-12-03 16:42:52 -08001001
1002 if (flags.isKernelEnabled()) {
1003 if (!!m.kernel()) {
1004 appendChild(root, kernelInfoConverter.serialize(*m.kernel(), d, flags));
1005 }
1006 }
Yifan Honga04e1472017-04-05 13:15:34 -07001007 } else if (m.mType == SchemaType::FRAMEWORK) {
Yifan Honga1b112d2018-08-07 17:44:10 -07001008 if (flags.isVndkEnabled()) {
Yifan Hong0f529fa2018-01-10 14:51:59 -08001009#pragma clang diagnostic push
1010#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Yifan Honga2635c42017-12-12 13:20:33 -08001011 appendChildren(root, vndkConverter, m.framework.mVndks, d);
Yifan Hong0f529fa2018-01-10 14:51:59 -08001012#pragma clang diagnostic pop
Yifan Hongfeb454e2018-01-09 16:16:40 -08001013
1014 appendChildren(root, vendorNdkConverter, m.framework.mVendorNdks, d);
Yifan Honga2635c42017-12-12 13:20:33 -08001015 }
Yifan Honga1b112d2018-08-07 17:44:10 -07001016 if (flags.isSsdkEnabled()) {
Yifan Honga28729e2018-01-17 13:40:35 -08001017 if (!m.framework.mSystemSdk.empty()) {
1018 appendChild(root, systemSdkConverter(m.framework.mSystemSdk, d));
1019 }
1020 }
Yifan Hong2a3dd082017-04-04 17:15:35 -07001021 }
Yifan Hongd4857902017-06-13 14:13:56 -07001022
Yifan Honga1b112d2018-08-07 17:44:10 -07001023 if (flags.isXmlFilesEnabled()) {
Yifan Honga2635c42017-12-12 13:20:33 -08001024 appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
1025 }
Yifan Hong676447a2016-11-15 12:57:23 -08001026 }
Yifan Hong94757062018-02-09 16:36:31 -08001027 bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
Yifan Honga3104112019-08-30 14:25:55 -07001028 Version metaVersion;
1029 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1030 if (metaVersion > kMetaVersion) {
1031 *error = "Unrecognized manifest.version " + to_string(metaVersion) + " (libvintf@" +
1032 to_string(kMetaVersion) + ")";
Yifan Hong7c7d7062017-04-04 16:26:51 -07001033 return false;
1034 }
Yifan Honga3104112019-08-30 14:25:55 -07001035
1036 std::vector<ManifestHal> hals;
1037 if (!parseAttr(root, "type", &object->mType, error) ||
1038 !parseChildren(root, manifestHalConverter, &hals, error)) {
Yifan Hong676447a2016-11-15 12:57:23 -08001039 return false;
1040 }
Yifan Hong2a3dd082017-04-04 17:15:35 -07001041 if (object->mType == SchemaType::DEVICE) {
1042 // tags for device hal manifest only.
Yifan Hong383f9452017-04-17 11:20:41 -07001043 // <sepolicy> can be missing because it can be determined at build time, not hard-coded
1044 // in the XML file.
Yifan Hong2a3dd082017-04-04 17:15:35 -07001045 if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
Yifan Hong94757062018-02-09 16:36:31 -08001046 &object->device.mSepolicyVersion, error)) {
Yifan Hong2a3dd082017-04-04 17:15:35 -07001047 return false;
1048 }
Yifan Hongc393c712018-02-12 13:33:17 -08001049
1050 if (!parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel,
1051 error)) {
1052 return false;
1053 }
Yifan Honga45f77d2018-12-03 16:42:52 -08001054
1055 if (!parseOptionalChild(root, kernelInfoConverter, &object->device.mKernel, error)) {
1056 return false;
1057 }
Yifan Honga04e1472017-04-05 13:15:34 -07001058 } else if (object->mType == SchemaType::FRAMEWORK) {
Yifan Hong0f529fa2018-01-10 14:51:59 -08001059#pragma clang diagnostic push
1060#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Yifan Hong94757062018-02-09 16:36:31 -08001061 if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
Yifan Honga04e1472017-04-05 13:15:34 -07001062 return false;
1063 }
1064 for (const auto &vndk : object->framework.mVndks) {
1065 if (!vndk.mVersionRange.isSingleVersion()) {
Yifan Hong94757062018-02-09 16:36:31 -08001066 *error = "vndk.version " + to_string(vndk.mVersionRange) +
1067 " cannot be a range for manifests";
Yifan Honga04e1472017-04-05 13:15:34 -07001068 return false;
1069 }
1070 }
Yifan Hong0f529fa2018-01-10 14:51:59 -08001071#pragma clang diagnostic pop
Yifan Hongfeb454e2018-01-09 16:16:40 -08001072
Yifan Hong94757062018-02-09 16:36:31 -08001073 if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
Yifan Hongfeb454e2018-01-09 16:16:40 -08001074 return false;
1075 }
Yifan Honga28729e2018-01-17 13:40:35 -08001076
Yifan Hong0bfbc122018-02-02 13:27:29 -08001077 std::set<std::string> vendorNdkVersions;
1078 for (const auto& vendorNdk : object->framework.mVendorNdks) {
1079 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
Yifan Hong94757062018-02-09 16:36:31 -08001080 *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
Yifan Hong0bfbc122018-02-02 13:27:29 -08001081 return false;
1082 }
1083 vendorNdkVersions.insert(vendorNdk.version());
1084 }
1085
Yifan Hong94757062018-02-09 16:36:31 -08001086 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
1087 error)) {
Yifan Honga28729e2018-01-17 13:40:35 -08001088 return false;
1089 }
Yifan Hong2a3dd082017-04-04 17:15:35 -07001090 }
Yifan Hong676447a2016-11-15 12:57:23 -08001091 for (auto &&hal : hals) {
Yifan Hong79dcc1f2017-05-22 14:35:19 -07001092 std::string description{hal.name};
Yifan Hong33466ad2017-02-24 11:31:37 -08001093 if (!object->add(std::move(hal))) {
Yifan Hong94757062018-02-09 16:36:31 -08001094 *error = "Duplicated manifest.hal entry " + description;
Yifan Hong33466ad2017-02-24 11:31:37 -08001095 return false;
1096 }
Yifan Hong676447a2016-11-15 12:57:23 -08001097 }
Yifan Hongd4857902017-06-13 14:13:56 -07001098
1099 std::vector<ManifestXmlFile> xmlFiles;
Yifan Hong94757062018-02-09 16:36:31 -08001100 if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
Yifan Hongd4857902017-06-13 14:13:56 -07001101 return false;
1102 }
1103 for (auto&& xmlFile : xmlFiles) {
1104 std::string description{xmlFile.name()};
1105 if (!object->addXmlFile(std::move(xmlFile))) {
Yifan Hong94757062018-02-09 16:36:31 -08001106 *error = "Duplicated manifest.xmlfile entry " + description +
1107 "; entries cannot have duplicated name and version";
Yifan Hongd4857902017-06-13 14:13:56 -07001108 return false;
1109 }
1110 }
1111
Yifan Hong676447a2016-11-15 12:57:23 -08001112 return true;
1113 }
1114};
1115
Yifan Hong94757062018-02-09 16:36:31 -08001116HalManifestConverter halManifestConverter{};
Yifan Hong676447a2016-11-15 12:57:23 -08001117
Yifan Hong94757062018-02-09 16:36:31 -08001118XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
Yifan Hongf3029302017-04-12 17:23:49 -07001119struct AvbConverter : public XmlNodeConverter<Version> {
1120 std::string elementName() const override { return "avb"; }
1121 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
1122 appendChild(root, avbVersionConverter(m, d));
1123 }
Yifan Hong94757062018-02-09 16:36:31 -08001124 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
1125 return parseChild(root, avbVersionConverter, object, error);
Yifan Hongf3029302017-04-12 17:23:49 -07001126 }
1127};
Yifan Hong94757062018-02-09 16:36:31 -08001128AvbConverter avbConverter{};
Yifan Hongf3029302017-04-12 17:23:49 -07001129
Yifan Hongd4857902017-06-13 14:13:56 -07001130struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
1131 std::string elementName() const override { return "xmlfile"; }
1132 void mutateNode(const MatrixXmlFile& f, NodeType* root, DocType* d) const override {
1133 appendTextElement(root, "name", f.name(), d);
1134 appendAttr(root, "format", f.format());
1135 appendAttr(root, "optional", f.optional());
1136 appendChild(root, versionRangeConverter(f.versionRange(), d));
1137 if (!f.overriddenPath().empty()) {
1138 appendTextElement(root, "path", f.overriddenPath(), d);
1139 }
1140 }
Yifan Hong94757062018-02-09 16:36:31 -08001141 bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
1142 if (!parseTextElement(root, "name", &object->mName, error) ||
1143 !parseAttr(root, "format", &object->mFormat, error) ||
1144 !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
1145 !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
1146 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
Yifan Hongd4857902017-06-13 14:13:56 -07001147 return false;
1148 }
1149 return true;
1150 }
1151};
Yifan Hong94757062018-02-09 16:36:31 -08001152MatrixXmlFileConverter matrixXmlFileConverter{};
Yifan Hongd4857902017-06-13 14:13:56 -07001153
Yifan Honga9993572017-01-24 19:33:15 -08001154struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
Yifan Hong676447a2016-11-15 12:57:23 -08001155 std::string elementName() const override { return "compatibility-matrix"; }
1156 void mutateNode(const CompatibilityMatrix &m, NodeType *root, DocType *d) const override {
Yifan Hong250b55c2018-08-07 17:41:56 -07001157 mutateNode(m, root, d, SerializeFlags::EVERYTHING);
Yifan Honga2635c42017-12-12 13:20:33 -08001158 }
1159 void mutateNode(const CompatibilityMatrix& m, NodeType* root, DocType* d,
Yifan Hongba588bc2018-08-08 14:19:41 -07001160 SerializeFlags::Type flags) const override {
Yifan Hong304cdab2018-08-02 16:03:59 -07001161 if (flags.isMetaVersionEnabled()) {
Yifan Honga3104112019-08-30 14:25:55 -07001162 appendAttr(root, "version", kMetaVersion);
Yifan Hong304cdab2018-08-02 16:03:59 -07001163 }
1164 if (flags.isSchemaTypeEnabled()) {
1165 appendAttr(root, "type", m.mType);
1166 }
Yifan Honga2635c42017-12-12 13:20:33 -08001167
Yifan Honga1b112d2018-08-07 17:44:10 -07001168 if (flags.isHalsEnabled()) {
Yifan Honga2635c42017-12-12 13:20:33 -08001169 appendChildren(root, matrixHalConverter, iterateValues(m.mHals), d);
1170 }
Yifan Hong7c7d7062017-04-04 16:26:51 -07001171 if (m.mType == SchemaType::FRAMEWORK) {
Yifan Honga1b112d2018-08-07 17:44:10 -07001172 if (flags.isKernelEnabled()) {
Yifan Hong86678e42018-07-26 11:38:54 -07001173 appendChildren(root, matrixKernelConverter, m.framework.mKernels, d, flags);
Yifan Honga2635c42017-12-12 13:20:33 -08001174 }
Yifan Honga1b112d2018-08-07 17:44:10 -07001175 if (flags.isSepolicyEnabled()) {
Yifan Hong244970c2018-01-23 15:29:27 -08001176 if (!(m.framework.mSepolicy == Sepolicy{})) {
1177 appendChild(root, sepolicyConverter(m.framework.mSepolicy, d));
1178 }
Yifan Honga2635c42017-12-12 13:20:33 -08001179 }
Yifan Honga1b112d2018-08-07 17:44:10 -07001180 if (flags.isAvbEnabled()) {
Yifan Hong244970c2018-01-23 15:29:27 -08001181 if (!(m.framework.mAvbMetaVersion == Version{})) {
1182 appendChild(root, avbConverter(m.framework.mAvbMetaVersion, d));
1183 }
Yifan Honga2635c42017-12-12 13:20:33 -08001184 }
Yifan Hongc393c712018-02-12 13:33:17 -08001185 if (m.mLevel != Level::UNSPECIFIED) {
1186 this->appendAttr(root, "level", m.mLevel);
1187 }
Yifan Hong03d2d4a2017-04-12 17:34:14 -07001188 } else if (m.mType == SchemaType::DEVICE) {
Yifan Honga1b112d2018-08-07 17:44:10 -07001189 if (flags.isVndkEnabled()) {
Yifan Hong0f529fa2018-01-10 14:51:59 -08001190#pragma clang diagnostic push
1191#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Yifan Hong9e1f9402018-01-09 16:14:24 -08001192 if (!(m.device.mVndk == Vndk{})) {
1193 appendChild(root, vndkConverter(m.device.mVndk, d));
1194 }
Yifan Hong0f529fa2018-01-10 14:51:59 -08001195#pragma clang diagnostic pop
Yifan Hongfeb454e2018-01-09 16:16:40 -08001196
1197 if (!(m.device.mVendorNdk == VendorNdk{})) {
1198 appendChild(root, vendorNdkConverter(m.device.mVendorNdk, d));
1199 }
Yifan Honga2635c42017-12-12 13:20:33 -08001200 }
Yifan Honga28729e2018-01-17 13:40:35 -08001201
Yifan Honga1b112d2018-08-07 17:44:10 -07001202 if (flags.isSsdkEnabled()) {
Yifan Honga28729e2018-01-17 13:40:35 -08001203 if (!m.device.mSystemSdk.empty()) {
1204 appendChild(root, systemSdkConverter(m.device.mSystemSdk, d));
1205 }
1206 }
Yifan Hong7c7d7062017-04-04 16:26:51 -07001207 }
Yifan Hongd4857902017-06-13 14:13:56 -07001208
Yifan Honga1b112d2018-08-07 17:44:10 -07001209 if (flags.isXmlFilesEnabled()) {
Yifan Honga2635c42017-12-12 13:20:33 -08001210 appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
1211 }
Yifan Hong676447a2016-11-15 12:57:23 -08001212 }
Yifan Hong94757062018-02-09 16:36:31 -08001213 bool buildObject(CompatibilityMatrix* object, NodeType* root,
1214 std::string* error) const override {
Yifan Honga3104112019-08-30 14:25:55 -07001215 Version metaVersion;
1216 if (!parseAttr(root, "version", &metaVersion, error)) return false;
1217 if (metaVersion > kMetaVersion) {
1218 *error = "Unrecognized compatibility-matrix.version " + to_string(metaVersion) +
1219 " (libvintf@" + to_string(kMetaVersion) + ")";
1220 return false;
1221 }
1222
Yifan Hong676447a2016-11-15 12:57:23 -08001223 std::vector<MatrixHal> hals;
Yifan Honga3104112019-08-30 14:25:55 -07001224 if (!parseAttr(root, "type", &object->mType, error) ||
Yifan Hong94757062018-02-09 16:36:31 -08001225 !parseChildren(root, matrixHalConverter, &hals, error)) {
Yifan Hong7c7d7062017-04-04 16:26:51 -07001226 return false;
1227 }
1228
1229 if (object->mType == SchemaType::FRAMEWORK) {
Yifan Hong1e5a0542017-04-28 14:37:56 -07001230 // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1231 // hard-coded in the XML file.
Yifan Hong94757062018-02-09 16:36:31 -08001232 if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1233 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1234 error) ||
1235 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1236 error)) {
Yifan Hong7c7d7062017-04-04 16:26:51 -07001237 return false;
1238 }
Yifan Hongf4a27292017-08-23 15:14:02 -07001239
1240 std::set<Version> seenKernelVersions;
1241 for (const auto& kernel : object->framework.mKernels) {
1242 Version minLts(kernel.minLts().version, kernel.minLts().majorRev);
1243 if (seenKernelVersions.find(minLts) != seenKernelVersions.end()) {
1244 continue;
1245 }
1246 if (!kernel.conditions().empty()) {
Yifan Hong94757062018-02-09 16:36:31 -08001247 *error = "First <kernel> for version " + to_string(minLts) +
1248 " must have empty <conditions> for backwards compatibility.";
Yifan Hongf4a27292017-08-23 15:14:02 -07001249 return false;
1250 }
1251 seenKernelVersions.insert(minLts);
1252 }
1253
Yifan Hongc393c712018-02-12 13:33:17 -08001254 if (!parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error)) {
1255 return false;
1256 }
1257
Yifan Honga04e1472017-04-05 13:15:34 -07001258 } else if (object->mType == SchemaType::DEVICE) {
Yifan Hong0f85ac32017-04-28 14:22:16 -07001259 // <vndk> can be missing because it can be determined at build time, not hard-coded
1260 // in the XML file.
Yifan Hong0f529fa2018-01-10 14:51:59 -08001261#pragma clang diagnostic push
1262#pragma clang diagnostic ignored "-Wdeprecated-declarations"
Yifan Hong94757062018-02-09 16:36:31 -08001263 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
Yifan Honga04e1472017-04-05 13:15:34 -07001264 return false;
1265 }
Yifan Hong0f529fa2018-01-10 14:51:59 -08001266#pragma clang diagnostic pop
Yifan Hongfeb454e2018-01-09 16:16:40 -08001267
Yifan Hong94757062018-02-09 16:36:31 -08001268 if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1269 error)) {
Yifan Hongfeb454e2018-01-09 16:16:40 -08001270 return false;
1271 }
Yifan Honga28729e2018-01-17 13:40:35 -08001272
Yifan Hong94757062018-02-09 16:36:31 -08001273 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1274 error)) {
Yifan Honga28729e2018-01-17 13:40:35 -08001275 return false;
1276 }
Yifan Hong7c7d7062017-04-04 16:26:51 -07001277 }
1278
Yifan Hong676447a2016-11-15 12:57:23 -08001279 for (auto &&hal : hals) {
Yifan Hong33466ad2017-02-24 11:31:37 -08001280 if (!object->add(std::move(hal))) {
Yifan Hong94757062018-02-09 16:36:31 -08001281 *error = "Duplicated compatibility-matrix.hal entry";
Yifan Hong33466ad2017-02-24 11:31:37 -08001282 return false;
1283 }
Yifan Hong676447a2016-11-15 12:57:23 -08001284 }
Yifan Hongd4857902017-06-13 14:13:56 -07001285
1286 std::vector<MatrixXmlFile> xmlFiles;
Yifan Hong94757062018-02-09 16:36:31 -08001287 if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
Yifan Hongd4857902017-06-13 14:13:56 -07001288 return false;
1289 }
1290 for (auto&& xmlFile : xmlFiles) {
1291 if (!xmlFile.optional()) {
Yifan Hong94757062018-02-09 16:36:31 -08001292 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1293 " has to be optional for compatibility matrix version 1.0";
Yifan Hongd4857902017-06-13 14:13:56 -07001294 return false;
1295 }
1296 std::string description{xmlFile.name()};
1297 if (!object->addXmlFile(std::move(xmlFile))) {
Yifan Hong94757062018-02-09 16:36:31 -08001298 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
Yifan Hongd4857902017-06-13 14:13:56 -07001299 return false;
1300 }
1301 }
1302
Yifan Hong676447a2016-11-15 12:57:23 -08001303 return true;
1304 }
1305};
1306
Yifan Hong94757062018-02-09 16:36:31 -08001307CompatibilityMatrixConverter compatibilityMatrixConverter{};
Yifan Hong4a5eb7b2017-02-16 18:19:26 -08001308
1309// Publicly available as in parse_xml.h
Yifan Hong94757062018-02-09 16:36:31 -08001310XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1311XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
Yifan Hong676447a2016-11-15 12:57:23 -08001312
Yifan Hong4a5eb7b2017-02-16 18:19:26 -08001313// For testing in LibVintfTest
Yifan Hong94757062018-02-09 16:36:31 -08001314XmlConverter<Version>& gVersionConverter = versionConverter;
1315XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1316 kernelConfigTypedValueConverter;
1317XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1318XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
Yifan Hong180c5102018-11-02 16:26:48 -07001319XmlConverter<KernelInfo>& gKernelInfoConverter = kernelInfoConverter;
Yifan Hong4a5eb7b2017-02-16 18:19:26 -08001320
Yifan Hong676447a2016-11-15 12:57:23 -08001321} // namespace vintf
1322} // namespace android