summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'parse_xml.cpp')
-rw-r--r--parse_xml.cpp444
1 files changed, 230 insertions, 214 deletions
diff --git a/parse_xml.cpp b/parse_xml.cpp
index 7abbc55..739e344 100644
--- a/parse_xml.cpp
+++ b/parse_xml.cpp
@@ -143,50 +143,59 @@ struct XmlNodeConverter : public XmlConverter<Object> {
143 virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const { 143 virtual void mutateNode(const Object& o, NodeType* n, DocType* d, SerializeFlags) const {
144 mutateNode(o, n, d); 144 mutateNode(o, n, d);
145 } 145 }
146 virtual bool buildObject(Object *o, NodeType *n) const = 0; 146 virtual bool buildObject(Object* o, NodeType* n, std::string* error) const = 0;
147 virtual std::string elementName() const = 0; 147 virtual std::string elementName() const = 0;
148 148
149 // convenience methods for user 149 // convenience methods for user
150 inline const std::string &lastError() const { return mLastError; } 150 inline const std::string& lastError() const override { return mLastError; }
151 inline NodeType* serialize(const Object& o, DocType* d, 151 inline NodeType* serialize(const Object& o, DocType* d,
152 SerializeFlags flags = EVERYTHING) const { 152 SerializeFlags flags = EVERYTHING) const {
153 NodeType *root = createNode(this->elementName(), d); 153 NodeType *root = createNode(this->elementName(), d);
154 this->mutateNode(o, root, d, flags); 154 this->mutateNode(o, root, d, flags);
155 return root; 155 return root;
156 } 156 }
157 inline std::string serialize(const Object& o, SerializeFlags flags) const { 157 inline std::string serialize(const Object& o, SerializeFlags flags) const override {
158 DocType *doc = createDocument(); 158 DocType *doc = createDocument();
159 appendChild(doc, serialize(o, doc, flags)); 159 appendChild(doc, serialize(o, doc, flags));
160 std::string s = printDocument(doc); 160 std::string s = printDocument(doc);
161 deleteDocument(doc); 161 deleteDocument(doc);
162 return s; 162 return s;
163 } 163 }
164 inline bool deserialize(Object *object, NodeType *root) const { 164 inline bool deserialize(Object* object, NodeType* root) {
165 bool ret = deserialize(object, root, &mLastError);
166 return ret;
167 }
168 inline bool deserialize(Object* o, const std::string& xml) override {
169 bool ret = (*this)(o, xml, &mLastError);
170 return ret;
171 }
172 inline bool deserialize(Object* object, NodeType* root, std::string* error) const {
165 if (nameOf(root) != this->elementName()) { 173 if (nameOf(root) != this->elementName()) {
166 return false; 174 return false;
167 } 175 }
168 return this->buildObject(object, root); 176 return this->buildObject(object, root, error);
169 } 177 }
170 inline bool deserialize(Object *o, const std::string &xml) const { 178 inline bool operator()(Object* o, const std::string& xml, std::string* error) const override {
171 DocType *doc = createDocument(xml); 179 std::string errorBuffer;
180 if (error == nullptr) error = &errorBuffer;
181
182 auto doc = createDocument(xml);
172 if (doc == nullptr) { 183 if (doc == nullptr) {
173 this->mLastError = "Not a valid XML"; 184 *error = "Not a valid XML";
174 return false; 185 return false;
175 } 186 }
176 bool ret = deserialize(o, getRootChild(doc)); 187 bool ret = deserialize(o, getRootChild(doc), error);
177 deleteDocument(doc); 188 deleteDocument(doc);
178 return ret; 189 return ret;
179 } 190 }
180 inline NodeType *operator()(const Object &o, DocType *d) const { 191 inline NodeType *operator()(const Object &o, DocType *d) const {
181 return serialize(o, d); 192 return serialize(o, d);
182 } 193 }
183 inline std::string operator()(const Object& o, SerializeFlags flags) const { 194 inline std::string operator()(const Object& o, SerializeFlags flags) const override {
184 return serialize(o, flags); 195 return serialize(o, flags);
185 } 196 }
186 inline bool operator()(Object *o, NodeType *node) const { 197 inline bool operator()(Object* o, NodeType* node) { return deserialize(o, node); }
187 return deserialize(o, node); 198 inline bool operator()(Object* o, const std::string& xml) override {
188 }
189 inline bool operator()(Object *o, const std::string &xml) const {
190 return deserialize(o, xml); 199 return deserialize(o, xml);
191 } 200 }
192 201
@@ -230,11 +239,11 @@ struct XmlNodeConverter : public XmlConverter<Object> {
230 } 239 }
231 240
232 // All parse* functions helps buildObject() to deserialize XML to the object. Returns 241 // All parse* functions helps buildObject() to deserialize XML to the object. Returns
233 // true if deserialization is successful, false if any error, and mLastError will be 242 // true if deserialization is successful, false if any error, and "error" will be
234 // set to error message. 243 // set to error message.
235 template <typename T> 244 template <typename T>
236 inline bool parseOptionalAttr(NodeType *root, const std::string &attrName, 245 inline bool parseOptionalAttr(NodeType* root, const std::string& attrName, T&& defaultValue,
237 T &&defaultValue, T *attr) const { 246 T* attr, std::string* /* error */) const {
238 std::string attrText; 247 std::string attrText;
239 bool success = getAttr(root, attrName, &attrText) && 248 bool success = getAttr(root, attrName, &attrText) &&
240 ::android::vintf::parse(attrText, attr); 249 ::android::vintf::parse(attrText, attr);
@@ -245,31 +254,33 @@ struct XmlNodeConverter : public XmlConverter<Object> {
245 } 254 }
246 255
247 template <typename T> 256 template <typename T>
248 inline bool parseAttr(NodeType *root, const std::string &attrName, T *attr) const { 257 inline bool parseAttr(NodeType* root, const std::string& attrName, T* attr,
258 std::string* error) const {
249 std::string attrText; 259 std::string attrText;
250 bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr); 260 bool ret = getAttr(root, attrName, &attrText) && ::android::vintf::parse(attrText, attr);
251 if (!ret) { 261 if (!ret) {
252 mLastError = "Could not find/parse attr with name \"" + attrName + "\" and value \"" + 262 *error = "Could not find/parse attr with name \"" + attrName + "\" and value \"" +
253 attrText + "\" for element <" + elementName() + ">"; 263 attrText + "\" for element <" + elementName() + ">";
254 } 264 }
255 return ret; 265 return ret;
256 } 266 }
257 267
258 inline bool parseAttr(NodeType *root, const std::string &attrName, std::string *attr) const { 268 inline bool parseAttr(NodeType* root, const std::string& attrName, std::string* attr,
269 std::string* error) const {
259 bool ret = getAttr(root, attrName, attr); 270 bool ret = getAttr(root, attrName, attr);
260 if (!ret) { 271 if (!ret) {
261 mLastError = "Could not find attr with name \"" + attrName + "\" for element <" 272 *error = "Could not find attr with name \"" + attrName + "\" for element <" +
262 + elementName() + ">"; 273 elementName() + ">";
263 } 274 }
264 return ret; 275 return ret;
265 } 276 }
266 277
267 inline bool parseTextElement(NodeType *root, 278 inline bool parseTextElement(NodeType* root, const std::string& elementName, std::string* s,
268 const std::string &elementName, std::string *s) const { 279 std::string* error) const {
269 NodeType *child = getChild(root, elementName); 280 NodeType *child = getChild(root, elementName);
270 if (child == nullptr) { 281 if (child == nullptr) {
271 mLastError = "Could not find element with name <" + elementName + "> in element <" 282 *error = "Could not find element with name <" + elementName + "> in element <" +
272 + this->elementName() + ">"; 283 this->elementName() + ">";
273 return false; 284 return false;
274 } 285 }
275 *s = getText(child); 286 *s = getText(child);
@@ -277,14 +288,15 @@ struct XmlNodeConverter : public XmlConverter<Object> {
277 } 288 }
278 289
279 inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName, 290 inline bool parseOptionalTextElement(NodeType* root, const std::string& elementName,
280 std::string&& defaultValue, std::string* s) const { 291 std::string&& defaultValue, std::string* s,
292 std::string* /* error */) const {
281 NodeType* child = getChild(root, elementName); 293 NodeType* child = getChild(root, elementName);
282 *s = child == nullptr ? std::move(defaultValue) : getText(child); 294 *s = child == nullptr ? std::move(defaultValue) : getText(child);
283 return true; 295 return true;
284 } 296 }
285 297
286 inline bool parseTextElements(NodeType *root, const std::string &elementName, 298 inline bool parseTextElements(NodeType* root, const std::string& elementName,
287 std::vector<std::string> *v) const { 299 std::vector<std::string>* v, std::string* /* error */) const {
288 auto nodes = getChildren(root, elementName); 300 auto nodes = getChildren(root, elementName);
289 v->resize(nodes.size()); 301 v->resize(nodes.size());
290 for (size_t i = 0; i < nodes.size(); ++i) { 302 for (size_t i = 0; i < nodes.size(); ++i) {
@@ -294,43 +306,37 @@ struct XmlNodeConverter : public XmlConverter<Object> {
294 } 306 }
295 307
296 template <typename T> 308 template <typename T>
297 inline bool parseChild(NodeType *root, const XmlNodeConverter<T> &conv, T *t) const { 309 inline bool parseChild(NodeType* root, const XmlNodeConverter<T>& conv, T* t,
310 std::string* error) const {
298 NodeType *child = getChild(root, conv.elementName()); 311 NodeType *child = getChild(root, conv.elementName());
299 if (child == nullptr) { 312 if (child == nullptr) {
300 mLastError = "Could not find element with name <" + conv.elementName() + "> in element <" 313 *error = "Could not find element with name <" + conv.elementName() + "> in element <" +
301 + this->elementName() + ">"; 314 this->elementName() + ">";
302 return false; 315 return false;
303 } 316 }
304 bool success = conv.deserialize(t, child); 317 return conv.deserialize(t, child, error);
305 if (!success) {
306 mLastError = conv.lastError();
307 }
308 return success;
309 } 318 }
310 319
311 template <typename T> 320 template <typename T>
312 inline bool parseOptionalChild(NodeType *root, const XmlNodeConverter<T> &conv, 321 inline bool parseOptionalChild(NodeType* root, const XmlNodeConverter<T>& conv,
313 T &&defaultValue, T *t) const { 322 T&& defaultValue, T* t, std::string* error) const {
314 NodeType *child = getChild(root, conv.elementName()); 323 NodeType *child = getChild(root, conv.elementName());
315 if (child == nullptr) { 324 if (child == nullptr) {
316 *t = std::move(defaultValue); 325 *t = std::move(defaultValue);
317 return true; 326 return true;
318 } 327 }
319 bool success = conv.deserialize(t, child); 328 return conv.deserialize(t, child, error);
320 if (!success) {
321 mLastError = conv.lastError();
322 }
323 return success;
324 } 329 }
325 330
326 template <typename T> 331 template <typename T>
327 inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::vector<T> *v) const { 332 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::vector<T>* v,
333 std::string* error) const {
328 auto nodes = getChildren(root, conv.elementName()); 334 auto nodes = getChildren(root, conv.elementName());
329 v->resize(nodes.size()); 335 v->resize(nodes.size());
330 for (size_t i = 0; i < nodes.size(); ++i) { 336 for (size_t i = 0; i < nodes.size(); ++i) {
331 if (!conv.deserialize(&v->at(i), nodes[i])) { 337 if (!conv.deserialize(&v->at(i), nodes[i], error)) {
332 mLastError = "Could not parse element with name <" + conv.elementName() 338 *error = "Could not parse element with name <" + conv.elementName() +
333 + "> in element <" + this->elementName() + ">: " + conv.lastError(); 339 "> in element <" + this->elementName() + ">: " + *error;
334 return false; 340 return false;
335 } 341 }
336 } 342 }
@@ -338,37 +344,39 @@ struct XmlNodeConverter : public XmlConverter<Object> {
338 } 344 }
339 345
340 template <typename T> 346 template <typename T>
341 inline bool parseChildren(NodeType *root, const XmlNodeConverter<T> &conv, std::set<T> *s) const { 347 inline bool parseChildren(NodeType* root, const XmlNodeConverter<T>& conv, std::set<T>* s,
348 std::string* error) const {
342 std::vector<T> vec; 349 std::vector<T> vec;
343 if (!parseChildren(root, conv, &vec)) { 350 if (!parseChildren(root, conv, &vec, error)) {
344 return false; 351 return false;
345 } 352 }
346 s->clear(); 353 s->clear();
347 s->insert(vec.begin(), vec.end()); 354 s->insert(vec.begin(), vec.end());
348 if (s->size() != vec.size()) { 355 if (s->size() != vec.size()) {
349 mLastError = "Duplicated elements <" + conv.elementName() + "> in element <" 356 *error = "Duplicated elements <" + conv.elementName() + "> in element <" +
350 + this->elementName() + ">"; 357 this->elementName() + ">";
351 s->clear(); 358 s->clear();
352 return false; 359 return false;
353 } 360 }
354 return true; 361 return true;
355 } 362 }
356 363
357 inline bool parseText(NodeType *node, std::string *s) const { 364 inline bool parseText(NodeType* node, std::string* s, std::string* /* error */) const {
358 *s = getText(node); 365 *s = getText(node);
359 return true; 366 return true;
360 } 367 }
361 368
362 template <typename T> 369 template <typename T>
363 inline bool parseText(NodeType *node, T *s) const { 370 inline bool parseText(NodeType* node, T* s, std::string* error) const {
364 std::string text = getText(node); 371 std::string text = getText(node);
365 bool ret = ::android::vintf::parse(text, s); 372 bool ret = ::android::vintf::parse(text, s);
366 if (!ret) { 373 if (!ret) {
367 mLastError = "Could not parse text \"" + text + "\" in element <" + elementName() + ">"; 374 *error = "Could not parse text \"" + text + "\" in element <" + elementName() + ">";
368 } 375 }
369 return ret; 376 return ret;
370 } 377 }
371protected: 378
379 private:
372 mutable std::string mLastError; 380 mutable std::string mLastError;
373}; 381};
374 382
@@ -380,8 +388,8 @@ struct XmlTextConverter : public XmlNodeConverter<Object> {
380 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override { 388 virtual void mutateNode(const Object &object, NodeType *root, DocType *d) const override {
381 appendText(root, ::android::vintf::to_string(object), d); 389 appendText(root, ::android::vintf::to_string(object), d);
382 } 390 }
383 virtual bool buildObject(Object *object, NodeType *root) const override { 391 virtual bool buildObject(Object* object, NodeType* root, std::string* error) const override {
384 return this->parseText(root, object); 392 return this->parseText(root, object, error);
385 } 393 }
386 virtual std::string elementName() const { return mElementName; }; 394 virtual std::string elementName() const { return mElementName; };
387private: 395private:
@@ -390,11 +398,11 @@ private:
390 398
391// ---------------------- XmlNodeConverter definitions end 399// ---------------------- XmlNodeConverter definitions end
392 400
393const XmlTextConverter<Version> versionConverter{"version"}; 401XmlTextConverter<Version> versionConverter{"version"};
394 402
395const XmlTextConverter<VersionRange> versionRangeConverter{"version"}; 403XmlTextConverter<VersionRange> versionRangeConverter{"version"};
396 404
397const XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"}; 405XmlTextConverter<KernelConfigKey> kernelConfigKeyConverter{"key"};
398 406
399struct TransportArchConverter : public XmlNodeConverter<TransportArch> { 407struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
400 std::string elementName() const override { return "transport"; } 408 std::string elementName() const override { return "transport"; }
@@ -404,22 +412,22 @@ struct TransportArchConverter : public XmlNodeConverter<TransportArch> {
404 } 412 }
405 appendText(root, ::android::vintf::to_string(object.transport), d); 413 appendText(root, ::android::vintf::to_string(object.transport), d);
406 } 414 }
407 bool buildObject(TransportArch *object, NodeType *root) const override { 415 bool buildObject(TransportArch* object, NodeType* root, std::string* error) const override {
408 if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch) || 416 if (!parseOptionalAttr(root, "arch", Arch::ARCH_EMPTY, &object->arch, error) ||
409 !parseText(root, &object->transport)) { 417 !parseText(root, &object->transport, error)) {
410 return false; 418 return false;
411 } 419 }
412 if (!object->isValid()) { 420 if (!object->isValid()) {
413 this->mLastError = "transport == " + ::android::vintf::to_string(object->transport) + 421 *error = "transport == " + ::android::vintf::to_string(object->transport) +
414 " and arch == " + ::android::vintf::to_string(object->arch) + 422 " and arch == " + ::android::vintf::to_string(object->arch) +
415 " is not a valid combination."; 423 " is not a valid combination.";
416 return false; 424 return false;
417 } 425 }
418 return true; 426 return true;
419 } 427 }
420}; 428};
421 429
422const TransportArchConverter transportArchConverter{}; 430TransportArchConverter transportArchConverter{};
423 431
424struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> { 432struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTypedValue> {
425 std::string elementName() const override { return "value"; } 433 std::string elementName() const override { return "value"; }
@@ -427,21 +435,22 @@ struct KernelConfigTypedValueConverter : public XmlNodeConverter<KernelConfigTyp
427 appendAttr(root, "type", object.mType); 435 appendAttr(root, "type", object.mType);
428 appendText(root, ::android::vintf::to_string(object), d); 436 appendText(root, ::android::vintf::to_string(object), d);
429 } 437 }
430 bool buildObject(KernelConfigTypedValue *object, NodeType *root) const override { 438 bool buildObject(KernelConfigTypedValue* object, NodeType* root,
439 std::string* error) const override {
431 std::string stringValue; 440 std::string stringValue;
432 if (!parseAttr(root, "type", &object->mType) || 441 if (!parseAttr(root, "type", &object->mType, error) ||
433 !parseText(root, &stringValue)) { 442 !parseText(root, &stringValue, error)) {
434 return false; 443 return false;
435 } 444 }
436 if (!::android::vintf::parseKernelConfigValue(stringValue, object)) { 445 if (!::android::vintf::parseKernelConfigValue(stringValue, object)) {
437 this->mLastError = "Could not parse kernel config value \"" + stringValue + "\""; 446 *error = "Could not parse kernel config value \"" + stringValue + "\"";
438 return false; 447 return false;
439 } 448 }
440 return true; 449 return true;
441 } 450 }
442}; 451};
443 452
444const KernelConfigTypedValueConverter kernelConfigTypedValueConverter{}; 453KernelConfigTypedValueConverter kernelConfigTypedValueConverter{};
445 454
446struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> { 455struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
447 std::string elementName() const override { return "config"; } 456 std::string elementName() const override { return "config"; }
@@ -449,16 +458,16 @@ struct KernelConfigConverter : public XmlNodeConverter<KernelConfig> {
449 appendChild(root, kernelConfigKeyConverter(object.first, d)); 458 appendChild(root, kernelConfigKeyConverter(object.first, d));
450 appendChild(root, kernelConfigTypedValueConverter(object.second, d)); 459 appendChild(root, kernelConfigTypedValueConverter(object.second, d));
451 } 460 }
452 bool buildObject(KernelConfig *object, NodeType *root) const override { 461 bool buildObject(KernelConfig* object, NodeType* root, std::string* error) const override {
453 if ( !parseChild(root, kernelConfigKeyConverter, &object->first) 462 if (!parseChild(root, kernelConfigKeyConverter, &object->first, error) ||
454 || !parseChild(root, kernelConfigTypedValueConverter, &object->second)) { 463 !parseChild(root, kernelConfigTypedValueConverter, &object->second, error)) {
455 return false; 464 return false;
456 } 465 }
457 return true; 466 return true;
458 } 467 }
459}; 468};
460 469
461const KernelConfigConverter kernelConfigConverter{}; 470KernelConfigConverter kernelConfigConverter{};
462 471
463struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> { 472struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
464 std::string elementName() const override { return "interface"; } 473 std::string elementName() const override { return "interface"; }
@@ -466,23 +475,23 @@ struct HalInterfaceConverter : public XmlNodeConverter<HalInterface> {
466 appendTextElement(root, "name", intf.name, d); 475 appendTextElement(root, "name", intf.name, d);
467 appendTextElements(root, "instance", intf.instances, d); 476 appendTextElements(root, "instance", intf.instances, d);
468 } 477 }
469 bool buildObject(HalInterface *intf, NodeType *root) const override { 478 bool buildObject(HalInterface* intf, NodeType* root, std::string* error) const override {
470 std::vector<std::string> instances; 479 std::vector<std::string> instances;
471 if (!parseTextElement(root, "name", &intf->name) || 480 if (!parseTextElement(root, "name", &intf->name, error) ||
472 !parseTextElements(root, "instance", &instances)) { 481 !parseTextElements(root, "instance", &instances, error)) {
473 return false; 482 return false;
474 } 483 }
475 intf->instances.clear(); 484 intf->instances.clear();
476 intf->instances.insert(instances.begin(), instances.end()); 485 intf->instances.insert(instances.begin(), instances.end());
477 if (intf->instances.size() != instances.size()) { 486 if (intf->instances.size() != instances.size()) {
478 this->mLastError = "Duplicated instances in " + intf->name; 487 *error = "Duplicated instances in " + intf->name;
479 return false; 488 return false;
480 } 489 }
481 return true; 490 return true;
482 } 491 }
483}; 492};
484 493
485const HalInterfaceConverter halInterfaceConverter{}; 494HalInterfaceConverter halInterfaceConverter{};
486 495
487struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> { 496struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
488 std::string elementName() const override { return "hal"; } 497 std::string elementName() const override { return "hal"; }
@@ -493,28 +502,29 @@ struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
493 appendChildren(root, versionRangeConverter, hal.versionRanges, d); 502 appendChildren(root, versionRangeConverter, hal.versionRanges, d);
494 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d); 503 appendChildren(root, halInterfaceConverter, iterateValues(hal.interfaces), d);
495 } 504 }
496 bool buildObject(MatrixHal *object, NodeType *root) const override { 505 bool buildObject(MatrixHal* object, NodeType* root, std::string* error) const override {
497 std::vector<HalInterface> interfaces; 506 std::vector<HalInterface> interfaces;
498 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) || 507 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
499 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional) || 508 !parseOptionalAttr(root, "optional", false /* defaultValue */, &object->optional,
500 !parseTextElement(root, "name", &object->name) || 509 error) ||
501 !parseChildren(root, versionRangeConverter, &object->versionRanges) || 510 !parseTextElement(root, "name", &object->name, error) ||
502 !parseChildren(root, halInterfaceConverter, &interfaces)) { 511 !parseChildren(root, versionRangeConverter, &object->versionRanges, error) ||
512 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
503 return false; 513 return false;
504 } 514 }
505 for (auto&& interface : interfaces) { 515 for (auto&& interface : interfaces) {
506 std::string name{interface.name}; 516 std::string name{interface.name};
507 auto res = object->interfaces.emplace(std::move(name), std::move(interface)); 517 auto res = object->interfaces.emplace(std::move(name), std::move(interface));
508 if (!res.second) { 518 if (!res.second) {
509 this->mLastError = "Duplicated interface entry \"" + res.first->first + 519 *error = "Duplicated interface entry \"" + res.first->first +
510 "\"; if additional instances are needed, add them to the " 520 "\"; if additional instances are needed, add them to the "
511 "existing <interface> node."; 521 "existing <interface> node.";
512 return false; 522 return false;
513 } 523 }
514 } 524 }
515// Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally. 525// Do not check for target-side libvintf to avoid restricting ability for upgrade accidentally.
516#ifndef LIBVINTF_TARGET 526#ifndef LIBVINTF_TARGET
517 if (!checkAdditionalRestrictionsOnHal(*object)) { 527 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
518 return false; 528 return false;
519 } 529 }
520#endif 530#endif
@@ -523,24 +533,24 @@ struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
523 533
524#ifndef LIBVINTF_TARGET 534#ifndef LIBVINTF_TARGET
525 private: 535 private:
526 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal) const { 536 bool checkAdditionalRestrictionsOnHal(const MatrixHal& hal, std::string* error) const {
527 if (hal.getName() == "netutils-wrapper") { 537 if (hal.getName() == "netutils-wrapper") {
528 if (hal.versionRanges.size() != 1) { 538 if (hal.versionRanges.size() != 1) {
529 this->mLastError = 539 *error =
530 "netutils-wrapper HAL must specify exactly one version x.0, " 540 "netutils-wrapper HAL must specify exactly one version x.0, "
531 "but multiple <version> element is specified."; 541 "but multiple <version> element is specified.";
532 return false; 542 return false;
533 } 543 }
534 const VersionRange& v = hal.versionRanges.at(0); 544 const VersionRange& v = hal.versionRanges.at(0);
535 if (!v.isSingleVersion()) { 545 if (!v.isSingleVersion()) {
536 this->mLastError = 546 *error =
537 "netutils-wrapper HAL must specify exactly one version x.0, " 547 "netutils-wrapper HAL must specify exactly one version x.0, "
538 "but a range is provided. Perhaps you mean '" + 548 "but a range is provided. Perhaps you mean '" +
539 to_string(Version{v.majorVer, 0}) + "'?"; 549 to_string(Version{v.majorVer, 0}) + "'?";
540 return false; 550 return false;
541 } 551 }
542 if (v.minMinor != 0) { 552 if (v.minMinor != 0) {
543 this->mLastError = 553 *error =
544 "netutils-wrapper HAL must specify exactly one version x.0, " 554 "netutils-wrapper HAL must specify exactly one version x.0, "
545 "but minor version is not 0. Perhaps you mean '" + 555 "but minor version is not 0. Perhaps you mean '" +
546 to_string(Version{v.majorVer, 0}) + "'?"; 556 to_string(Version{v.majorVer, 0}) + "'?";
@@ -552,7 +562,7 @@ struct MatrixHalConverter : public XmlNodeConverter<MatrixHal> {
552#endif 562#endif
553}; 563};
554 564
555const MatrixHalConverter matrixHalConverter{}; 565MatrixHalConverter matrixHalConverter{};
556 566
557struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> { 567struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<KernelConfig>> {
558 std::string elementName() const override { return "conditions"; } 568 std::string elementName() const override { return "conditions"; }
@@ -560,12 +570,13 @@ struct MatrixKernelConditionsConverter : public XmlNodeConverter<std::vector<Ker
560 DocType* d) const override { 570 DocType* d) const override {
561 appendChildren(root, kernelConfigConverter, conds, d); 571 appendChildren(root, kernelConfigConverter, conds, d);
562 } 572 }
563 bool buildObject(std::vector<KernelConfig>* object, NodeType* root) const override { 573 bool buildObject(std::vector<KernelConfig>* object, NodeType* root,
564 return parseChildren(root, kernelConfigConverter, object); 574 std::string* error) const override {
575 return parseChildren(root, kernelConfigConverter, object, error);
565 } 576 }
566}; 577};
567 578
568const MatrixKernelConditionsConverter matrixKernelConditionsConverter{}; 579MatrixKernelConditionsConverter matrixKernelConditionsConverter{};
569 580
570struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> { 581struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
571 std::string elementName() const override { return "kernel"; } 582 std::string elementName() const override { return "kernel"; }
@@ -576,17 +587,18 @@ struct MatrixKernelConverter : public XmlNodeConverter<MatrixKernel> {
576 } 587 }
577 appendChildren(root, kernelConfigConverter, kernel.mConfigs, d); 588 appendChildren(root, kernelConfigConverter, kernel.mConfigs, d);
578 } 589 }
579 bool buildObject(MatrixKernel *object, NodeType *root) const override { 590 bool buildObject(MatrixKernel* object, NodeType* root, std::string* error) const override {
580 if (!parseAttr(root, "version", &object->mMinLts) || 591 if (!parseAttr(root, "version", &object->mMinLts, error) ||
581 !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions) || 592 !parseOptionalChild(root, matrixKernelConditionsConverter, {}, &object->mConditions,
582 !parseChildren(root, kernelConfigConverter, &object->mConfigs)) { 593 error) ||
594 !parseChildren(root, kernelConfigConverter, &object->mConfigs, error)) {
583 return false; 595 return false;
584 } 596 }
585 return true; 597 return true;
586 } 598 }
587}; 599};
588 600
589const MatrixKernelConverter matrixKernelConverter{}; 601MatrixKernelConverter matrixKernelConverter{};
590 602
591struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> { 603struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
592 std::string elementName() const override { return "hal"; } 604 std::string elementName() const override { return "hal"; }
@@ -600,28 +612,27 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
600 appendAttr(root, "override", hal.isOverride); 612 appendAttr(root, "override", hal.isOverride);
601 } 613 }
602 } 614 }
603 bool buildObject(ManifestHal *object, NodeType *root) const override { 615 bool buildObject(ManifestHal* object, NodeType* root, std::string* error) const override {
604 std::vector<HalInterface> interfaces; 616 std::vector<HalInterface> interfaces;
605 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format) || 617 if (!parseOptionalAttr(root, "format", HalFormat::HIDL, &object->format, error) ||
606 !parseOptionalAttr(root, "override", false, &object->isOverride) || 618 !parseOptionalAttr(root, "override", false, &object->isOverride, error) ||
607 !parseTextElement(root, "name", &object->name) || 619 !parseTextElement(root, "name", &object->name, error) ||
608 !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch) || 620 !parseOptionalChild(root, transportArchConverter, {}, &object->transportArch, error) ||
609 !parseChildren(root, versionConverter, &object->versions) || 621 !parseChildren(root, versionConverter, &object->versions, error) ||
610 !parseChildren(root, halInterfaceConverter, &interfaces)) { 622 !parseChildren(root, halInterfaceConverter, &interfaces, error)) {
611 return false; 623 return false;
612 } 624 }
613 625
614 switch (object->format) { 626 switch (object->format) {
615 case HalFormat::HIDL: { 627 case HalFormat::HIDL: {
616 if (object->transportArch.empty()) { 628 if (object->transportArch.empty()) {
617 this->mLastError = 629 *error = "HIDL HAL '" + object->name + "' should have <transport> defined.";
618 "HIDL HAL '" + object->name + "' should have <transport> defined.";
619 return false; 630 return false;
620 } 631 }
621 } break; 632 } break;
622 case HalFormat::NATIVE: { 633 case HalFormat::NATIVE: {
623 if (!object->transportArch.empty()) { 634 if (!object->transportArch.empty()) {
624 this->mLastError = 635 *error =
625 "Native HAL '" + object->name + "' should not have <transport> defined."; 636 "Native HAL '" + object->name + "' should not have <transport> defined.";
626 return false; 637 return false;
627 } 638 }
@@ -639,19 +650,19 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
639 auto res = object->interfaces.emplace(interface.name, 650 auto res = object->interfaces.emplace(interface.name,
640 std::move(interface)); 651 std::move(interface));
641 if (!res.second) { 652 if (!res.second) {
642 this->mLastError = "Duplicated interface entry \"" + res.first->first + 653 *error = "Duplicated interface entry \"" + res.first->first +
643 "\"; if additional instances are needed, add them to the " 654 "\"; if additional instances are needed, add them to the "
644 "existing <interface> node."; 655 "existing <interface> node.";
645 return false; 656 return false;
646 } 657 }
647 } 658 }
648 if (!object->isValid()) { 659 if (!object->isValid()) {
649 this->mLastError = "'" + object->name + "' is not a valid Manifest HAL."; 660 *error = "'" + object->name + "' is not a valid Manifest HAL.";
650 return false; 661 return false;
651 } 662 }
652// Do not check for target-side libvintf to avoid restricting upgrade accidentally. 663// Do not check for target-side libvintf to avoid restricting upgrade accidentally.
653#ifndef LIBVINTF_TARGET 664#ifndef LIBVINTF_TARGET
654 if (!checkAdditionalRestrictionsOnHal(*object)) { 665 if (!checkAdditionalRestrictionsOnHal(*object, error)) {
655 return false; 666 return false;
656 } 667 }
657#endif 668#endif
@@ -660,11 +671,11 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
660 671
661#ifndef LIBVINTF_TARGET 672#ifndef LIBVINTF_TARGET
662 private: 673 private:
663 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal) const { 674 bool checkAdditionalRestrictionsOnHal(const ManifestHal& hal, std::string* error) const {
664 if (hal.getName() == "netutils-wrapper") { 675 if (hal.getName() == "netutils-wrapper") {
665 for (const Version& v : hal.versions) { 676 for (const Version& v : hal.versions) {
666 if (v.minorVer != 0) { 677 if (v.minorVer != 0) {
667 this->mLastError = 678 *error =
668 "netutils-wrapper HAL must specify exactly one version x.0, " 679 "netutils-wrapper HAL must specify exactly one version x.0, "
669 "but minor version is not 0. Perhaps you mean '" + 680 "but minor version is not 0. Perhaps you mean '" +
670 to_string(Version{v.majorVer, 0}) + "'?"; 681 to_string(Version{v.majorVer, 0}) + "'?";
@@ -679,10 +690,10 @@ struct ManifestHalConverter : public XmlNodeConverter<ManifestHal> {
679 690
680// Convert ManifestHal from and to XML. Returned object is guaranteed to have 691// Convert ManifestHal from and to XML. Returned object is guaranteed to have
681// .isValid() == true. 692// .isValid() == true.
682const ManifestHalConverter manifestHalConverter{}; 693ManifestHalConverter manifestHalConverter{};
683 694
684const XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"}; 695XmlTextConverter<KernelSepolicyVersion> kernelSepolicyVersionConverter{"kernel-sepolicy-version"};
685const XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"}; 696XmlTextConverter<VersionRange> sepolicyVersionConverter{"sepolicy-version"};
686 697
687struct SepolicyConverter : public XmlNodeConverter<Sepolicy> { 698struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
688 std::string elementName() const override { return "sepolicy"; } 699 std::string elementName() const override { return "sepolicy"; }
@@ -690,21 +701,22 @@ struct SepolicyConverter : public XmlNodeConverter<Sepolicy> {
690 appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d)); 701 appendChild(root, kernelSepolicyVersionConverter(object.kernelSepolicyVersion(), d));
691 appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d); 702 appendChildren(root, sepolicyVersionConverter, object.sepolicyVersions(), d);
692 } 703 }
693 bool buildObject(Sepolicy *object, NodeType *root) const override { 704 bool buildObject(Sepolicy* object, NodeType* root, std::string* error) const override {
694 if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion) || 705 if (!parseChild(root, kernelSepolicyVersionConverter, &object->mKernelSepolicyVersion,
695 !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges)) { 706 error) ||
707 !parseChildren(root, sepolicyVersionConverter, &object->mSepolicyVersionRanges,
708 error)) {
696 return false; 709 return false;
697 } 710 }
698 return true; 711 return true;
699 } 712 }
700}; 713};
701const SepolicyConverter sepolicyConverter{}; 714SepolicyConverter sepolicyConverter{};
702 715
703[[deprecated]] 716[[deprecated]] XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
704const XmlTextConverter<VndkVersionRange> vndkVersionRangeConverter{"version"};
705 717
706const XmlTextConverter<std::string> vndkVersionConverter{"version"}; 718XmlTextConverter<std::string> vndkVersionConverter{"version"};
707const XmlTextConverter<std::string> vndkLibraryConverter{"library"}; 719XmlTextConverter<std::string> vndkLibraryConverter{"library"};
708 720
709struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> { 721struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
710 std::string elementName() const override { return "vndk"; } 722 std::string elementName() const override { return "vndk"; }
@@ -712,17 +724,16 @@ struct [[deprecated]] VndkConverter : public XmlNodeConverter<Vndk> {
712 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d)); 724 appendChild(root, vndkVersionRangeConverter(object.mVersionRange, d));
713 appendChildren(root, vndkLibraryConverter, object.mLibraries, d); 725 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
714 } 726 }
715 bool buildObject(Vndk *object, NodeType *root) const override { 727 bool buildObject(Vndk* object, NodeType* root, std::string* error) const override {
716 if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange) || 728 if (!parseChild(root, vndkVersionRangeConverter, &object->mVersionRange, error) ||
717 !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) { 729 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
718 return false; 730 return false;
719 } 731 }
720 return true; 732 return true;
721 } 733 }
722}; 734};
723 735
724[[deprecated]] 736[[deprecated]] VndkConverter vndkConverter{};
725const VndkConverter vndkConverter{};
726 737
727struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> { 738struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
728 std::string elementName() const override { return "vendor-ndk"; } 739 std::string elementName() const override { return "vendor-ndk"; }
@@ -730,41 +741,41 @@ struct VendorNdkConverter : public XmlNodeConverter<VendorNdk> {
730 appendChild(root, vndkVersionConverter(object.mVersion, d)); 741 appendChild(root, vndkVersionConverter(object.mVersion, d));
731 appendChildren(root, vndkLibraryConverter, object.mLibraries, d); 742 appendChildren(root, vndkLibraryConverter, object.mLibraries, d);
732 } 743 }
733 bool buildObject(VendorNdk* object, NodeType* root) const override { 744 bool buildObject(VendorNdk* object, NodeType* root, std::string* error) const override {
734 if (!parseChild(root, vndkVersionConverter, &object->mVersion) || 745 if (!parseChild(root, vndkVersionConverter, &object->mVersion, error) ||
735 !parseChildren(root, vndkLibraryConverter, &object->mLibraries)) { 746 !parseChildren(root, vndkLibraryConverter, &object->mLibraries, error)) {
736 return false; 747 return false;
737 } 748 }
738 return true; 749 return true;
739 } 750 }
740}; 751};
741 752
742const VendorNdkConverter vendorNdkConverter{}; 753VendorNdkConverter vendorNdkConverter{};
743 754
744const XmlTextConverter<std::string> systemSdkVersionConverter{"version"}; 755XmlTextConverter<std::string> systemSdkVersionConverter{"version"};
745 756
746struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> { 757struct SystemSdkConverter : public XmlNodeConverter<SystemSdk> {
747 std::string elementName() const override { return "system-sdk"; } 758 std::string elementName() const override { return "system-sdk"; }
748 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override { 759 void mutateNode(const SystemSdk& object, NodeType* root, DocType* d) const override {
749 appendChildren(root, systemSdkVersionConverter, object.versions(), d); 760 appendChildren(root, systemSdkVersionConverter, object.versions(), d);
750 } 761 }
751 bool buildObject(SystemSdk* object, NodeType* root) const override { 762 bool buildObject(SystemSdk* object, NodeType* root, std::string* error) const override {
752 return parseChildren(root, systemSdkVersionConverter, &object->mVersions); 763 return parseChildren(root, systemSdkVersionConverter, &object->mVersions, error);
753 } 764 }
754}; 765};
755 766
756const SystemSdkConverter systemSdkConverter{}; 767SystemSdkConverter systemSdkConverter{};
757 768
758struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> { 769struct HalManifestSepolicyConverter : public XmlNodeConverter<Version> {
759 std::string elementName() const override { return "sepolicy"; } 770 std::string elementName() const override { return "sepolicy"; }
760 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 771 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
761 appendChild(root, versionConverter(m, d)); 772 appendChild(root, versionConverter(m, d));
762 } 773 }
763 bool buildObject(Version *object, NodeType *root) const override { 774 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
764 return parseChild(root, versionConverter, object); 775 return parseChild(root, versionConverter, object, error);
765 } 776 }
766}; 777};
767const HalManifestSepolicyConverter halManifestSepolicyConverter{}; 778HalManifestSepolicyConverter halManifestSepolicyConverter{};
768 779
769struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> { 780struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
770 std::string elementName() const override { return "xmlfile"; } 781 std::string elementName() const override { return "xmlfile"; }
@@ -775,16 +786,16 @@ struct ManifestXmlFileConverter : public XmlNodeConverter<ManifestXmlFile> {
775 appendTextElement(root, "path", f.overriddenPath(), d); 786 appendTextElement(root, "path", f.overriddenPath(), d);
776 } 787 }
777 } 788 }
778 bool buildObject(ManifestXmlFile* object, NodeType* root) const override { 789 bool buildObject(ManifestXmlFile* object, NodeType* root, std::string* error) const override {
779 if (!parseTextElement(root, "name", &object->mName) || 790 if (!parseTextElement(root, "name", &object->mName, error) ||
780 !parseChild(root, versionConverter, &object->mVersion) || 791 !parseChild(root, versionConverter, &object->mVersion, error) ||
781 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) { 792 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
782 return false; 793 return false;
783 } 794 }
784 return true; 795 return true;
785 } 796 }
786}; 797};
787const ManifestXmlFileConverter manifestXmlFileConverter{}; 798ManifestXmlFileConverter manifestXmlFileConverter{};
788 799
789struct HalManifestConverter : public XmlNodeConverter<HalManifest> { 800struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
790 std::string elementName() const override { return "manifest"; } 801 std::string elementName() const override { return "manifest"; }
@@ -826,17 +837,17 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
826 appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d); 837 appendChildren(root, manifestXmlFileConverter, m.getXmlFiles(), d);
827 } 838 }
828 } 839 }
829 bool buildObject(HalManifest *object, NodeType *root) const override { 840 bool buildObject(HalManifest* object, NodeType* root, std::string* error) const override {
830 std::vector<ManifestHal> hals; 841 std::vector<ManifestHal> hals;
831 if (!parseAttr(root, "version", &object->mMetaVersion) || 842 if (!parseAttr(root, "version", &object->mMetaVersion, error) ||
832 !parseAttr(root, "type", &object->mType) || 843 !parseAttr(root, "type", &object->mType, error) ||
833 !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel) || 844 !parseOptionalAttr(root, "target-level", Level::UNSPECIFIED, &object->mLevel, error) ||
834 !parseChildren(root, manifestHalConverter, &hals)) { 845 !parseChildren(root, manifestHalConverter, &hals, error)) {
835 return false; 846 return false;
836 } 847 }
837 if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) { 848 if (!kMetaVersion.minorAtLeast(object->mMetaVersion)) {
838 this->mLastError = "Unrecognized manifest.version " + to_string(object->mMetaVersion) + 849 *error = "Unrecognized manifest.version " + to_string(object->mMetaVersion) +
839 " (libvintf@" + to_string(kMetaVersion) + ")"; 850 " (libvintf@" + to_string(kMetaVersion) + ")";
840 return false; 851 return false;
841 } 852 }
842 if (object->mType == SchemaType::DEVICE) { 853 if (object->mType == SchemaType::DEVICE) {
@@ -844,59 +855,59 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
844 // <sepolicy> can be missing because it can be determined at build time, not hard-coded 855 // <sepolicy> can be missing because it can be determined at build time, not hard-coded
845 // in the XML file. 856 // in the XML file.
846 if (!parseOptionalChild(root, halManifestSepolicyConverter, {}, 857 if (!parseOptionalChild(root, halManifestSepolicyConverter, {},
847 &object->device.mSepolicyVersion)) { 858 &object->device.mSepolicyVersion, error)) {
848 return false; 859 return false;
849 } 860 }
850 } else if (object->mType == SchemaType::FRAMEWORK) { 861 } else if (object->mType == SchemaType::FRAMEWORK) {
851#pragma clang diagnostic push 862#pragma clang diagnostic push
852#pragma clang diagnostic ignored "-Wdeprecated-declarations" 863#pragma clang diagnostic ignored "-Wdeprecated-declarations"
853 if (!parseChildren(root, vndkConverter, &object->framework.mVndks)) { 864 if (!parseChildren(root, vndkConverter, &object->framework.mVndks, error)) {
854 return false; 865 return false;
855 } 866 }
856 for (const auto &vndk : object->framework.mVndks) { 867 for (const auto &vndk : object->framework.mVndks) {
857 if (!vndk.mVersionRange.isSingleVersion()) { 868 if (!vndk.mVersionRange.isSingleVersion()) {
858 this->mLastError = "vndk.version " + to_string(vndk.mVersionRange) 869 *error = "vndk.version " + to_string(vndk.mVersionRange) +
859 + " cannot be a range for manifests"; 870 " cannot be a range for manifests";
860 return false; 871 return false;
861 } 872 }
862 } 873 }
863#pragma clang diagnostic pop 874#pragma clang diagnostic pop
864 875
865 if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks)) { 876 if (!parseChildren(root, vendorNdkConverter, &object->framework.mVendorNdks, error)) {
866 return false; 877 return false;
867 } 878 }
868 879
869 std::set<std::string> vendorNdkVersions; 880 std::set<std::string> vendorNdkVersions;
870 for (const auto& vendorNdk : object->framework.mVendorNdks) { 881 for (const auto& vendorNdk : object->framework.mVendorNdks) {
871 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) { 882 if (vendorNdkVersions.find(vendorNdk.version()) != vendorNdkVersions.end()) {
872 this->mLastError = 883 *error = "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
873 "Duplicated manifest.vendor-ndk.version " + vendorNdk.version();
874 return false; 884 return false;
875 } 885 }
876 vendorNdkVersions.insert(vendorNdk.version()); 886 vendorNdkVersions.insert(vendorNdk.version());
877 } 887 }
878 888
879 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk)) { 889 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->framework.mSystemSdk,
890 error)) {
880 return false; 891 return false;
881 } 892 }
882 } 893 }
883 for (auto &&hal : hals) { 894 for (auto &&hal : hals) {
884 std::string description{hal.name}; 895 std::string description{hal.name};
885 if (!object->add(std::move(hal))) { 896 if (!object->add(std::move(hal))) {
886 this->mLastError = "Duplicated manifest.hal entry " + description; 897 *error = "Duplicated manifest.hal entry " + description;
887 return false; 898 return false;
888 } 899 }
889 } 900 }
890 901
891 std::vector<ManifestXmlFile> xmlFiles; 902 std::vector<ManifestXmlFile> xmlFiles;
892 if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles)) { 903 if (!parseChildren(root, manifestXmlFileConverter, &xmlFiles, error)) {
893 return false; 904 return false;
894 } 905 }
895 for (auto&& xmlFile : xmlFiles) { 906 for (auto&& xmlFile : xmlFiles) {
896 std::string description{xmlFile.name()}; 907 std::string description{xmlFile.name()};
897 if (!object->addXmlFile(std::move(xmlFile))) { 908 if (!object->addXmlFile(std::move(xmlFile))) {
898 this->mLastError = "Duplicated manifest.xmlfile entry " + description + 909 *error = "Duplicated manifest.xmlfile entry " + description +
899 "; entries cannot have duplicated name and version"; 910 "; entries cannot have duplicated name and version";
900 return false; 911 return false;
901 } 912 }
902 } 913 }
@@ -905,19 +916,19 @@ struct HalManifestConverter : public XmlNodeConverter<HalManifest> {
905 } 916 }
906}; 917};
907 918
908const HalManifestConverter halManifestConverter{}; 919HalManifestConverter halManifestConverter{};
909 920
910const XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"}; 921XmlTextConverter<Version> avbVersionConverter{"vbmeta-version"};
911struct AvbConverter : public XmlNodeConverter<Version> { 922struct AvbConverter : public XmlNodeConverter<Version> {
912 std::string elementName() const override { return "avb"; } 923 std::string elementName() const override { return "avb"; }
913 void mutateNode(const Version &m, NodeType *root, DocType *d) const override { 924 void mutateNode(const Version &m, NodeType *root, DocType *d) const override {
914 appendChild(root, avbVersionConverter(m, d)); 925 appendChild(root, avbVersionConverter(m, d));
915 } 926 }
916 bool buildObject(Version *object, NodeType *root) const override { 927 bool buildObject(Version* object, NodeType* root, std::string* error) const override {
917 return parseChild(root, avbVersionConverter, object); 928 return parseChild(root, avbVersionConverter, object, error);
918 } 929 }
919}; 930};
920const AvbConverter avbConverter{}; 931AvbConverter avbConverter{};
921 932
922struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> { 933struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
923 std::string elementName() const override { return "xmlfile"; } 934 std::string elementName() const override { return "xmlfile"; }
@@ -930,18 +941,18 @@ struct MatrixXmlFileConverter : public XmlNodeConverter<MatrixXmlFile> {
930 appendTextElement(root, "path", f.overriddenPath(), d); 941 appendTextElement(root, "path", f.overriddenPath(), d);
931 } 942 }
932 } 943 }
933 bool buildObject(MatrixXmlFile* object, NodeType* root) const override { 944 bool buildObject(MatrixXmlFile* object, NodeType* root, std::string* error) const override {
934 if (!parseTextElement(root, "name", &object->mName) || 945 if (!parseTextElement(root, "name", &object->mName, error) ||
935 !parseAttr(root, "format", &object->mFormat) || 946 !parseAttr(root, "format", &object->mFormat, error) ||
936 !parseOptionalAttr(root, "optional", false, &object->mOptional) || 947 !parseOptionalAttr(root, "optional", false, &object->mOptional, error) ||
937 !parseChild(root, versionRangeConverter, &object->mVersionRange) || 948 !parseChild(root, versionRangeConverter, &object->mVersionRange, error) ||
938 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath)) { 949 !parseOptionalTextElement(root, "path", {}, &object->mOverriddenPath, error)) {
939 return false; 950 return false;
940 } 951 }
941 return true; 952 return true;
942 } 953 }
943}; 954};
944const MatrixXmlFileConverter matrixXmlFileConverter{}; 955MatrixXmlFileConverter matrixXmlFileConverter{};
945 956
946struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> { 957struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatrix> {
947 std::string elementName() const override { return "compatibility-matrix"; } 958 std::string elementName() const override { return "compatibility-matrix"; }
@@ -998,21 +1009,25 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri
998 appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d); 1009 appendChildren(root, matrixXmlFileConverter, m.getXmlFiles(), d);
999 } 1010 }
1000 } 1011 }
1001 bool buildObject(CompatibilityMatrix *object, NodeType *root) const override { 1012 bool buildObject(CompatibilityMatrix* object, NodeType* root,
1013 std::string* error) const override {
1002 Version version; 1014 Version version;
1003 std::vector<MatrixHal> hals; 1015 std::vector<MatrixHal> hals;
1004 if (!parseAttr(root, "version", &version) || !parseAttr(root, "type", &object->mType) || 1016 if (!parseAttr(root, "version", &version, error) ||
1005 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel) || 1017 !parseAttr(root, "type", &object->mType, error) ||
1006 !parseChildren(root, matrixHalConverter, &hals)) { 1018 !parseOptionalAttr(root, "level", Level::UNSPECIFIED, &object->mLevel, error) ||
1019 !parseChildren(root, matrixHalConverter, &hals, error)) {
1007 return false; 1020 return false;
1008 } 1021 }
1009 1022
1010 if (object->mType == SchemaType::FRAMEWORK) { 1023 if (object->mType == SchemaType::FRAMEWORK) {
1011 // <avb> and <sepolicy> can be missing because it can be determined at build time, not 1024 // <avb> and <sepolicy> can be missing because it can be determined at build time, not
1012 // hard-coded in the XML file. 1025 // hard-coded in the XML file.
1013 if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels) || 1026 if (!parseChildren(root, matrixKernelConverter, &object->framework.mKernels, error) ||
1014 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy) || 1027 !parseOptionalChild(root, sepolicyConverter, {}, &object->framework.mSepolicy,
1015 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion)) { 1028 error) ||
1029 !parseOptionalChild(root, avbConverter, {}, &object->framework.mAvbMetaVersion,
1030 error)) {
1016 return false; 1031 return false;
1017 } 1032 }
1018 1033
@@ -1023,8 +1038,8 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri
1023 continue; 1038 continue;
1024 } 1039 }
1025 if (!kernel.conditions().empty()) { 1040 if (!kernel.conditions().empty()) {
1026 this->mLastError = "First <kernel> for version " + to_string(minLts) + 1041 *error = "First <kernel> for version " + to_string(minLts) +
1027 " must have empty <conditions> for backwards compatibility."; 1042 " must have empty <conditions> for backwards compatibility.";
1028 return false; 1043 return false;
1029 } 1044 }
1030 seenKernelVersions.insert(minLts); 1045 seenKernelVersions.insert(minLts);
@@ -1035,45 +1050,47 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri
1035 // in the XML file. 1050 // in the XML file.
1036#pragma clang diagnostic push 1051#pragma clang diagnostic push
1037#pragma clang diagnostic ignored "-Wdeprecated-declarations" 1052#pragma clang diagnostic ignored "-Wdeprecated-declarations"
1038 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk)) { 1053 if (!parseOptionalChild(root, vndkConverter, {}, &object->device.mVndk, error)) {
1039 return false; 1054 return false;
1040 } 1055 }
1041#pragma clang diagnostic pop 1056#pragma clang diagnostic pop
1042 1057
1043 if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk)) { 1058 if (!parseOptionalChild(root, vendorNdkConverter, {}, &object->device.mVendorNdk,
1059 error)) {
1044 return false; 1060 return false;
1045 } 1061 }
1046 1062
1047 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk)) { 1063 if (!parseOptionalChild(root, systemSdkConverter, {}, &object->device.mSystemSdk,
1064 error)) {
1048 return false; 1065 return false;
1049 } 1066 }
1050 } 1067 }
1051 1068
1052 if (!kMetaVersion.minorAtLeast(version)) { 1069 if (!kMetaVersion.minorAtLeast(version)) {
1053 this->mLastError = "Unrecognized compatibility-matrix.version " + to_string(version) + 1070 *error = "Unrecognized compatibility-matrix.version " + to_string(version) +
1054 " (libvintf@" + to_string(kMetaVersion) + ")"; 1071 " (libvintf@" + to_string(kMetaVersion) + ")";
1055 return false; 1072 return false;
1056 } 1073 }
1057 for (auto &&hal : hals) { 1074 for (auto &&hal : hals) {
1058 if (!object->add(std::move(hal))) { 1075 if (!object->add(std::move(hal))) {
1059 this->mLastError = "Duplicated compatibility-matrix.hal entry"; 1076 *error = "Duplicated compatibility-matrix.hal entry";
1060 return false; 1077 return false;
1061 } 1078 }
1062 } 1079 }
1063 1080
1064 std::vector<MatrixXmlFile> xmlFiles; 1081 std::vector<MatrixXmlFile> xmlFiles;
1065 if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles)) { 1082 if (!parseChildren(root, matrixXmlFileConverter, &xmlFiles, error)) {
1066 return false; 1083 return false;
1067 } 1084 }
1068 for (auto&& xmlFile : xmlFiles) { 1085 for (auto&& xmlFile : xmlFiles) {
1069 if (!xmlFile.optional()) { 1086 if (!xmlFile.optional()) {
1070 this->mLastError = "compatibility-matrix.xmlfile entry " + xmlFile.name() + 1087 *error = "compatibility-matrix.xmlfile entry " + xmlFile.name() +
1071 " has to be optional for compatibility matrix version 1.0"; 1088 " has to be optional for compatibility matrix version 1.0";
1072 return false; 1089 return false;
1073 } 1090 }
1074 std::string description{xmlFile.name()}; 1091 std::string description{xmlFile.name()};
1075 if (!object->addXmlFile(std::move(xmlFile))) { 1092 if (!object->addXmlFile(std::move(xmlFile))) {
1076 this->mLastError = "Duplicated compatibility-matrix.xmlfile entry " + description; 1093 *error = "Duplicated compatibility-matrix.xmlfile entry " + description;
1077 return false; 1094 return false;
1078 } 1095 }
1079 } 1096 }
@@ -1082,19 +1099,18 @@ struct CompatibilityMatrixConverter : public XmlNodeConverter<CompatibilityMatri
1082 } 1099 }
1083}; 1100};
1084 1101
1085const CompatibilityMatrixConverter compatibilityMatrixConverter{}; 1102CompatibilityMatrixConverter compatibilityMatrixConverter{};
1086 1103
1087// Publicly available as in parse_xml.h 1104// Publicly available as in parse_xml.h
1088const XmlConverter<HalManifest> &gHalManifestConverter = halManifestConverter; 1105XmlConverter<HalManifest>& gHalManifestConverter = halManifestConverter;
1089const XmlConverter<CompatibilityMatrix> &gCompatibilityMatrixConverter 1106XmlConverter<CompatibilityMatrix>& gCompatibilityMatrixConverter = compatibilityMatrixConverter;
1090 = compatibilityMatrixConverter;
1091 1107
1092// For testing in LibVintfTest 1108// For testing in LibVintfTest
1093const XmlConverter<Version> &gVersionConverter = versionConverter; 1109XmlConverter<Version>& gVersionConverter = versionConverter;
1094const XmlConverter<KernelConfigTypedValue> &gKernelConfigTypedValueConverter 1110XmlConverter<KernelConfigTypedValue>& gKernelConfigTypedValueConverter =
1095 = kernelConfigTypedValueConverter; 1111 kernelConfigTypedValueConverter;
1096const XmlConverter<MatrixHal> &gMatrixHalConverter = matrixHalConverter; 1112XmlConverter<MatrixHal>& gMatrixHalConverter = matrixHalConverter;
1097const XmlConverter<ManifestHal> &gManifestHalConverter = manifestHalConverter; 1113XmlConverter<ManifestHal>& gManifestHalConverter = manifestHalConverter;
1098 1114
1099} // namespace vintf 1115} // namespace vintf
1100} // namespace android 1116} // namespace android