1 /* 2 * Copyright (C) 2016 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 #include "CompoundType.h" 18 19 #include "ArrayType.h" 20 #include "Reference.h" 21 #include "ScalarType.h" 22 #include "VectorType.h" 23 24 #include <android-base/logging.h> 25 #include <hidl-util/Formatter.h> 26 #include <iostream> 27 #include <set> 28 #include <string> 29 #include <unordered_set> 30 #include <vector> 31 32 namespace android { 33 34 CompoundType::CompoundType(Style style, const std::string& localName, const FQName& fullName, 35 const Location& location, Scope* parent) 36 : Scope(localName, fullName, location, parent), mStyle(style) {} 37 38 CompoundType::Style CompoundType::style() const { 39 return mStyle; 40 } 41 42 void CompoundType::addField(NamedReference<Type>* field) { 43 mFields.push_back(field); 44 } 45 46 std::vector<const NamedReference<Type>*> CompoundType::getFields() const { 47 return std::vector<const NamedReference<Type>*>(mFields.begin(), mFields.end()); 48 } 49 50 std::vector<const Reference<Type>*> CompoundType::getReferences() const { 51 std::vector<const Reference<Type>*> ret; 52 ret.insert(ret.begin(), mFields.begin(), mFields.end()); 53 return ret; 54 } 55 56 status_t CompoundType::validate() const { 57 for (const auto* field : mFields) { 58 const Type& type = field->type(); 59 60 if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) { 61 std::cerr << "ERROR: Struct/union cannot contain vectors of interfaces at " 62 << field->location() << "\n"; 63 return UNKNOWN_ERROR; 64 } 65 66 if (mStyle == STYLE_UNION) { 67 if (type.isInterface()) { 68 std::cerr << "ERROR: Union cannot contain interfaces at " << field->location() 69 << "\n"; 70 return UNKNOWN_ERROR; 71 } 72 73 if (type.needsEmbeddedReadWrite()) { 74 std::cerr << "ERROR: Union must not contain any types that need fixup at " 75 << field->location() << "\n"; 76 return UNKNOWN_ERROR; 77 } 78 } 79 } 80 81 if (mStyle == STYLE_SAFE_UNION && mFields.size() < 2) { 82 std::cerr << "ERROR: Safe union must contain at least two types to be useful at " 83 << location() << "\n"; 84 return UNKNOWN_ERROR; 85 } 86 87 status_t err = validateUniqueNames(); 88 if (err != OK) return err; 89 90 err = validateSubTypeNames(); 91 if (err != OK) return err; 92 93 return Scope::validate(); 94 } 95 96 status_t CompoundType::validateUniqueNames() const { 97 std::unordered_set<std::string> names; 98 99 for (const auto* field : mFields) { 100 if (names.find(field->name()) != names.end()) { 101 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at " 102 << field->location() << "\n"; 103 return UNKNOWN_ERROR; 104 } 105 names.insert(field->name()); 106 } 107 108 return OK; 109 } 110 111 void CompoundType::emitInvalidSubTypeNamesError(const std::string& subTypeName, 112 const Location& location) const { 113 std::cerr << "ERROR: Type name '" << subTypeName << "' defined at " << location 114 << " conflicts with a member function of " 115 << "safe_union " << definedName() << ". Consider renaming or " 116 << "moving its definition outside the safe_union scope.\n"; 117 } 118 119 status_t CompoundType::validateSubTypeNames() const { 120 if (mStyle != STYLE_SAFE_UNION) { return OK; } 121 const auto& subTypes = Scope::getSubTypes(); 122 123 for (const auto& subType : subTypes) { 124 if (subType->definedName() == "getDiscriminator") { 125 emitInvalidSubTypeNamesError(subType->definedName(), subType->location()); 126 return UNKNOWN_ERROR; 127 } 128 } 129 130 return OK; 131 } 132 133 bool CompoundType::isCompoundType() const { 134 return true; 135 } 136 137 bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const { 138 if (mStyle == STYLE_UNION) { 139 return false; 140 } 141 for (const auto* field : mFields) { 142 if (!field->get()->canCheckEquality(visited)) { 143 return false; 144 } 145 } 146 return true; 147 } 148 149 std::string CompoundType::typeName() const { 150 switch (mStyle) { 151 case STYLE_STRUCT: { 152 return "struct " + definedName(); 153 } 154 case STYLE_UNION: { 155 return "union " + definedName(); 156 } 157 case STYLE_SAFE_UNION: { 158 return "safe_union " + definedName(); 159 } 160 } 161 CHECK(!"Should not be here"); 162 } 163 164 std::string CompoundType::getCppType( 165 StorageMode mode, 166 bool /* specifyNamespaces */) const { 167 const std::string base = fullName(); 168 169 switch (mode) { 170 case StorageMode_Stack: 171 return base; 172 173 case StorageMode_Argument: 174 return "const " + base + "&"; 175 176 case StorageMode_Result: 177 return base + (containsInterface()?"":"*"); 178 } 179 CHECK(!"Should not be here"); 180 } 181 182 std::string CompoundType::getJavaType(bool /* forInitializer */) const { 183 return fullJavaName(); 184 } 185 186 std::string CompoundType::getVtsType() const { 187 switch (mStyle) { 188 case STYLE_STRUCT: 189 { 190 return "TYPE_STRUCT"; 191 } 192 case STYLE_UNION: 193 { 194 return "TYPE_UNION"; 195 } 196 case STYLE_SAFE_UNION: 197 { 198 return "TYPE_SAFE_UNION"; 199 } 200 } 201 CHECK(!"Should not be here"); 202 } 203 204 bool CompoundType::containsInterface() const { 205 for (const auto& field : mFields) { 206 if (field->type().isCompoundType()) { 207 const Type& t = field->type(); 208 const CompoundType* ct = static_cast<const CompoundType*>(&t); 209 if (ct->containsInterface()) { 210 return true; 211 } 212 } 213 if (field->type().isInterface()) { 214 return true; 215 } 216 } 217 return false; 218 } 219 220 void CompoundType::emitSafeUnionUnknownDiscriminatorError(Formatter& out, const std::string& value, 221 bool fatal) const { 222 if (fatal) { 223 out << "::android::hardware::details::logAlwaysFatal("; 224 } else { 225 out << "ALOGE(\"%s\", "; 226 } 227 out << "(\n"; 228 out.indent(2, [&] { 229 out << "\"Unknown union discriminator (value: \" +\n" 230 << "std::to_string(" << getUnionDiscriminatorType()->getCppTypeCast(value) 231 << ") + \").\").c_str());\n"; 232 }); 233 } 234 235 void CompoundType::emitSafeUnionReaderWriterForInterfaces( 236 Formatter &out, 237 const std::string &name, 238 const std::string &parcelObj, 239 bool parcelObjIsPointer, 240 bool isReader, 241 ErrorMode mode) const { 242 243 CHECK(mStyle == STYLE_SAFE_UNION); 244 245 out.block([&] { 246 const auto discriminatorType = getUnionDiscriminatorType(); 247 if (isReader) { 248 out << discriminatorType->getCppStackType() 249 << " _hidl_d_primitive;\n"; 250 } else { 251 out << "const " 252 << discriminatorType->getCppStackType() 253 << " _hidl_d_primitive = " 254 << discriminatorType->getCppTypeCast(name + ".getDiscriminator()") 255 << ";\n"; 256 } 257 258 getUnionDiscriminatorType()->emitReaderWriter(out, "_hidl_d_primitive", parcelObj, 259 parcelObjIsPointer, isReader, mode); 260 out << "switch ((" 261 << fullName() 262 << "::hidl_discriminator) _hidl_d_primitive) "; 263 264 out.block([&] { 265 for (const auto& field : mFields) { 266 out << "case " << fullName() << "::hidl_discriminator::" << field->name() 267 << ": "; 268 269 const std::string tempFieldName = "_hidl_temp_" + field->name(); 270 out.block([&] { 271 if (isReader) { 272 out << field->type().getCppResultType() << " " << tempFieldName 273 << ";\n"; 274 275 field->type().emitReaderWriter(out, tempFieldName, parcelObj, 276 parcelObjIsPointer, isReader, mode); 277 278 const std::string derefOperator = 279 field->type().resultNeedsDeref() ? "*" : ""; 280 out << name << "." << field->name() << "(std::move(" << derefOperator 281 << tempFieldName << "));\n"; 282 } else { 283 const std::string fieldValue = name + "." + field->name() + "()"; 284 out << field->type().getCppArgumentType() << " " << tempFieldName 285 << " = " << fieldValue << ";\n"; 286 287 field->type().emitReaderWriter(out, tempFieldName, parcelObj, 288 parcelObjIsPointer, isReader, mode); 289 } 290 out << "break;\n"; 291 }).endl(); 292 } 293 294 out << "default: "; 295 out.block([&] { 296 emitSafeUnionUnknownDiscriminatorError(out, "_hidl_d_primitive", 297 !isReader /*fatal*/); 298 if (isReader) { 299 out << "_hidl_err = BAD_VALUE;\n"; 300 handleError(out, mode); 301 } 302 }).endl(); 303 }).endl(); 304 }).endl(); 305 } 306 307 void CompoundType::emitReaderWriter( 308 Formatter &out, 309 const std::string &name, 310 const std::string &parcelObj, 311 bool parcelObjIsPointer, 312 bool isReader, 313 ErrorMode mode) const { 314 315 const std::string parcelObjDeref = 316 parcelObj + (parcelObjIsPointer ? "->" : "."); 317 318 if(containsInterface()){ 319 if (mStyle == STYLE_SAFE_UNION) { 320 emitSafeUnionReaderWriterForInterfaces(out, name, parcelObj, 321 parcelObjIsPointer, 322 isReader, mode); 323 return; 324 } 325 326 for (const auto& field : mFields) { 327 const std::string tempFieldName = "_hidl_temp_" + field->name(); 328 const std::string fieldValue = name + "." + field->name(); 329 330 out.block([&] { 331 if (isReader) { 332 out << field->type().getCppResultType() 333 << " " 334 << tempFieldName 335 << ";\n"; 336 } else { 337 out << field->type().getCppArgumentType() 338 << " " 339 << tempFieldName 340 << " = " 341 << fieldValue 342 << ";\n"; 343 } 344 345 field->type().emitReaderWriter(out, tempFieldName, parcelObj, 346 parcelObjIsPointer, isReader, mode); 347 if (isReader) { 348 const std::string derefOperator = field->type().resultNeedsDeref() 349 ? "*" : ""; 350 out << fieldValue 351 << " = std::move(" 352 << derefOperator 353 << tempFieldName 354 << ");\n"; 355 } 356 }).endl(); 357 } 358 } else { 359 const std::string parentName = "_hidl_" + name + "_parent"; 360 361 out << "size_t " << parentName << ";\n\n"; 362 363 if (isReader) { 364 out << "_hidl_err = " << parcelObjDeref << "readBuffer(" 365 << "sizeof(*" << name << "), &" << parentName << ", " 366 << " const_cast<const void**>(reinterpret_cast<void **>(" 367 << "&" << name << ")));\n"; 368 handleError(out, mode); 369 } else { 370 out << "_hidl_err = " 371 << parcelObjDeref 372 << "writeBuffer(&" 373 << name 374 << ", sizeof(" 375 << name 376 << "), &" 377 << parentName 378 << ");\n"; 379 handleError(out, mode); 380 } 381 382 bool needEmbeddedReadWrite = needsEmbeddedReadWrite(); 383 CHECK(mStyle != STYLE_UNION || !needEmbeddedReadWrite); 384 385 if (needEmbeddedReadWrite) { 386 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */ 387 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer, 388 isReader, mode, parentName, "0 /* parentOffset */"); 389 } 390 } 391 } 392 393 void CompoundType::emitReaderWriterEmbedded( 394 Formatter &out, 395 size_t /* depth */, 396 const std::string &name, 397 const std::string & /*sanitizedName */, 398 bool nameIsPointer, 399 const std::string &parcelObj, 400 bool parcelObjIsPointer, 401 bool isReader, 402 ErrorMode mode, 403 const std::string &parentName, 404 const std::string &offsetText) const { 405 emitReaderWriterEmbeddedForTypeName( 406 out, 407 name, 408 nameIsPointer, 409 parcelObj, 410 parcelObjIsPointer, 411 isReader, 412 mode, 413 parentName, 414 offsetText, 415 fullName(), 416 "" /* childName */, 417 "" /* namespace */); 418 } 419 420 void CompoundType::emitJavaReaderWriter( 421 Formatter &out, 422 const std::string &parcelObj, 423 const std::string &argName, 424 bool isReader) const { 425 if (isReader) { 426 out << "new " << fullJavaName() << "();\n"; 427 } 428 429 out << "(" << getJavaTypeCast(argName) << ")." 430 << (isReader ? "readFromParcel" : "writeToParcel") << "(" << parcelObj << ");\n"; 431 } 432 433 void CompoundType::emitJavaFieldInitializer( 434 Formatter &out, const std::string &fieldName) const { 435 const std::string fieldDeclaration = fullJavaName() + " " + fieldName; 436 emitJavaFieldDefaultInitialValue(out, fieldDeclaration); 437 } 438 439 void CompoundType::emitJavaFieldDefaultInitialValue( 440 Formatter &out, const std::string &declaredFieldName) const { 441 out << declaredFieldName 442 << " = new " 443 << fullJavaName() 444 << "();\n"; 445 } 446 447 void CompoundType::emitJavaFieldReaderWriter( 448 Formatter &out, 449 size_t /* depth */, 450 const std::string &parcelName, 451 const std::string &blobName, 452 const std::string &fieldName, 453 const std::string &offset, 454 bool isReader) const { 455 if (isReader) { 456 out << "(" 457 << getJavaTypeCast(fieldName) 458 << ").readEmbeddedFromParcel(" 459 << parcelName 460 << ", " 461 << blobName 462 << ", " 463 << offset 464 << ");\n"; 465 466 return; 467 } 468 469 out << fieldName 470 << ".writeEmbeddedToBlob(" 471 << blobName 472 << ", " 473 << offset 474 << ");\n"; 475 } 476 477 void CompoundType::emitLayoutAsserts(Formatter& out, const Layout& layout, 478 const std::string& layoutName) const { 479 out << "static_assert(sizeof(" 480 << fullName() 481 << layoutName 482 << ") == " 483 << layout.size 484 << ", \"wrong size\");\n"; 485 486 out << "static_assert(__alignof(" 487 << fullName() 488 << layoutName 489 << ") == " 490 << layout.align 491 << ", \"wrong alignment\");\n"; 492 } 493 494 void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const { 495 out << "struct " << definedName() << " final {\n"; 496 497 out.indent(); 498 499 Scope::emitTypeDeclarations(out); 500 501 bool hasPointer = containsPointer(); 502 CompoundLayout layout = hasPointer 503 ? CompoundLayout() 504 : getCompoundAlignmentAndSize(); 505 506 out << "enum class hidl_discriminator : " 507 << getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false) 508 << " "; 509 510 out.block([&] { 511 for (size_t idx = 0; idx < mFields.size(); idx++) { 512 const auto& field = mFields.at(idx); 513 514 field->emitDocComment(out); 515 out << field->name() 516 << " = " 517 << idx 518 << ", // " 519 << field->type().getCppStackType(true /*specifyNamespaces*/) 520 << "\n"; 521 } 522 }); 523 out << ";\n\n"; 524 525 out << definedName() << "();\n" // Constructor 526 << "~" << definedName() << "();\n" // Destructor 527 << definedName() << "(" << definedName() << "&&);\n" // Move constructor 528 << definedName() << "(const " << definedName() << "&);\n" // Copy constructor 529 << definedName() << "& operator=(" << definedName() << "&&);\n" // Move assignment 530 << definedName() << "& operator=(const " << definedName() << "&);\n\n"; // Copy assignment 531 532 for (const auto& field : mFields) { 533 // Setter (copy) 534 out << "void " 535 << field->name() 536 << "(" 537 << field->type().getCppArgumentType() 538 << ");\n"; 539 540 if (field->type().resolveToScalarType() == nullptr) { 541 // Setter (move) 542 out << "void " 543 << field->name() 544 << "(" 545 << field->type().getCppStackType() 546 << "&&);\n"; 547 } 548 549 // Getter (mutable) 550 out << field->type().getCppStackType() 551 << "& " 552 << field->name() 553 << "();\n"; 554 555 // Getter (immutable) 556 out << field->type().getCppArgumentType() 557 << " " 558 << field->name() 559 << "() const;\n\n"; 560 } 561 562 out << "// Utility methods\n"; 563 out << "hidl_discriminator getDiscriminator() const;\n\n"; 564 565 out << "constexpr size_t hidl_getUnionOffset() const "; 566 out.block([&] { 567 out << "return offsetof(" << fullName() << ", hidl_u);\n"; 568 }).endl().endl(); 569 570 out.unindent(); 571 out << "private:\n"; 572 out.indent(); 573 574 out << "void hidl_destructUnion();\n\n"; 575 576 out << "hidl_discriminator hidl_d"; 577 if (!hasPointer) { 578 out << " __attribute__ ((aligned(" 579 << layout.discriminator.align << "))) "; 580 } 581 out << ";\n"; 582 out << "union hidl_union final {\n"; 583 out.indent(); 584 585 for (const auto& field : mFields) { 586 size_t fieldAlign, fieldSize; 587 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize); 588 589 out << field->type().getCppStackType() 590 << " " 591 << field->name(); 592 593 if (!hasPointer) { 594 out << " __attribute__ ((aligned(" 595 << fieldAlign 596 << ")))"; 597 } 598 out << ";\n"; 599 } 600 601 out << "\n" 602 << "hidl_union();\n" 603 << "~hidl_union();\n"; 604 605 out.unindent(); 606 out << "} hidl_u;\n"; 607 608 if (!hasPointer) { 609 out << "\n"; 610 611 emitLayoutAsserts(out, layout.innerStruct, "::hidl_union"); 612 emitLayoutAsserts(out, layout.discriminator, "::hidl_discriminator"); 613 } 614 615 out.unindent(); 616 out << "};\n\n"; 617 618 if (!hasPointer) { 619 emitLayoutAsserts(out, layout.overall, ""); 620 out << "\n"; 621 } 622 } 623 624 void CompoundType::emitFieldHidlDefinition(Formatter& out, const NamedReference<Type>& ref) const { 625 if (ref.getDocComment() != nullptr) ref.getDocComment()->emit(out); 626 627 if (ref.definedInline()) { 628 // Same check as above, this is for sanity 629 CHECK(ref.get()->isCompoundType()); 630 static_cast<const CompoundType*>(ref.get())->emitInlineHidlDefinition(out); 631 out << " " << ref.name() << ";\n"; 632 } else { 633 out << ref.localName() << " " << ref.name() << ";\n"; 634 } 635 } 636 637 void CompoundType::emitInlineHidlDefinition(Formatter& out) const { 638 if (getDocComment() != nullptr) getDocComment()->emit(out); 639 out << typeName() << " "; 640 641 std::set<FQName> namesDeclaredInScope; 642 for (const NamedReference<Type>* ref : mFields) { 643 if (ref->definedInline()) { 644 const Type* type = ref->get(); 645 CHECK(type->isCompoundType()) << " only compound types can be defined inline"; 646 namesDeclaredInScope.insert(static_cast<const CompoundType*>(type)->fqName()); 647 } 648 } 649 650 std::vector<const NamedType*> preDeclaredTypes; 651 for (const NamedType* namedType : getSortedDefinedTypes()) { 652 if (namesDeclaredInScope.find(namedType->fqName()) == namesDeclaredInScope.end()) { 653 // have to predeclare it 654 preDeclaredTypes.push_back(namedType); 655 } 656 } 657 658 out << "{"; 659 out.indent([&] { 660 size_t preDeclaredTypesIdx = 0; 661 size_t fieldIdx = 0; 662 while (preDeclaredTypesIdx < preDeclaredTypes.size() && fieldIdx < mFields.size()) { 663 out << "\n"; 664 if (preDeclaredTypes.at(preDeclaredTypesIdx)->location() < 665 mFields.at(fieldIdx)->location()) { 666 preDeclaredTypes.at(preDeclaredTypesIdx++)->emitHidlDefinition(out); 667 } else { 668 emitFieldHidlDefinition(out, *mFields.at(fieldIdx++)); 669 } 670 } 671 672 while (preDeclaredTypesIdx < preDeclaredTypes.size()) { 673 out << "\n"; 674 preDeclaredTypes.at(preDeclaredTypesIdx++)->emitHidlDefinition(out); 675 } 676 677 while (fieldIdx < mFields.size()) { 678 out << "\n"; 679 emitFieldHidlDefinition(out, *mFields.at(fieldIdx++)); 680 } 681 }); 682 out << "}"; 683 } 684 685 void CompoundType::emitHidlDefinition(Formatter& out) const { 686 emitInlineHidlDefinition(out); 687 out << ";\n"; 688 } 689 690 void CompoundType::emitTypeDeclarations(Formatter& out) const { 691 if (mStyle == STYLE_SAFE_UNION) { 692 emitSafeUnionTypeDeclarations(out); 693 return; 694 } 695 696 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union") << " " << definedName() << " final {\n"; 697 698 out.indent(); 699 700 Scope::emitTypeDeclarations(out); 701 702 if (containsPointer()) { 703 for (const auto& field : mFields) { 704 field->emitDocComment(out); 705 out << field->type().getCppStackType() 706 << " " 707 << field->name() 708 << ";\n"; 709 } 710 711 out.unindent(); 712 out << "};\n\n"; 713 714 return; 715 } 716 717 for (int pass = 0; pass < 2; ++pass) { 718 size_t offset = 0; 719 for (const auto& field : mFields) { 720 size_t fieldAlign, fieldSize; 721 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize); 722 723 offset += Layout::getPad(offset, fieldAlign); 724 725 if (pass == 0) { 726 field->emitDocComment(out); 727 out << field->type().getCppStackType() 728 << " " 729 << field->name() 730 << " __attribute__ ((aligned(" 731 << fieldAlign 732 << ")));\n"; 733 } else { 734 out << "static_assert(offsetof(" 735 << fullName() 736 << ", " 737 << field->name() 738 << ") == " 739 << offset 740 << ", \"wrong offset\");\n"; 741 } 742 743 if (mStyle == STYLE_STRUCT) { 744 offset += fieldSize; 745 } 746 } 747 748 if (pass == 0) { 749 out.unindent(); 750 out << "};\n\n"; 751 } 752 } 753 754 CompoundLayout layout = getCompoundAlignmentAndSize(); 755 emitLayoutAsserts(out, layout.overall, ""); 756 out << "\n"; 757 } 758 759 void CompoundType::emitTypeForwardDeclaration(Formatter& out) const { 760 switch (mStyle) { 761 case STYLE_UNION: { 762 out << "union"; 763 break; 764 } 765 case STYLE_STRUCT: 766 case STYLE_SAFE_UNION: { 767 out << "struct"; 768 break; 769 } 770 default: { 771 CHECK(!"Should not be here"); 772 } 773 } 774 out << " " << definedName() << ";\n"; 775 } 776 777 void CompoundType::emitPackageTypeDeclarations(Formatter& out) const { 778 Scope::emitPackageTypeDeclarations(out); 779 780 out << "static inline std::string toString(" << getCppArgumentType() << " o);\n"; 781 out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream*);\n"; 782 783 if (canCheckEquality()) { 784 out << "static inline bool operator==(" 785 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n"; 786 787 out << "static inline bool operator!=(" 788 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n"; 789 } else { 790 out << "// operator== and operator!= are not generated for " << definedName() << "\n"; 791 } 792 793 out.endl(); 794 } 795 796 void CompoundType::emitPackageTypeHeaderDefinitions(Formatter& out) const { 797 Scope::emitPackageTypeHeaderDefinitions(out); 798 799 out << "static inline std::string toString(" << getCppArgumentType() 800 << (mFields.empty() ? "" : " o") << ") "; 801 802 out.block([&] { 803 // include toString for scalar types 804 out << "using ::android::hardware::toString;\n" 805 << "std::string os;\n"; 806 out << "os += \"{\";\n"; 807 808 if (mStyle == STYLE_SAFE_UNION) { 809 out << "\nswitch (o.getDiscriminator()) {\n"; 810 out.indent(); 811 } 812 813 for (const NamedReference<Type>* field : mFields) { 814 if (mStyle == STYLE_SAFE_UNION) { 815 out << "case " 816 << fullName() 817 << "::hidl_discriminator::" 818 << field->name() 819 << ": "; 820 821 out.block([&] { 822 out << "os += \"." 823 << field->name() 824 << " = \";\n" 825 << "os += toString(o." 826 << field->name() 827 << "());\n" 828 << "break;\n"; 829 }).endl(); 830 } else { 831 out << "os += \""; 832 if (field != *(mFields.begin())) { 833 out << ", "; 834 } 835 out << "." << field->name() << " = \";\n"; 836 field->type().emitDump(out, "os", "o." + field->name()); 837 } 838 } 839 840 if (mStyle == STYLE_SAFE_UNION) { 841 out << "default: "; 842 out.block([&] { 843 emitSafeUnionUnknownDiscriminatorError(out, "o.getDiscriminator()", 844 true /*fatal*/); 845 }) 846 .endl(); 847 848 out.unindent(); 849 out << "}\n"; 850 } 851 out << "os += \"}\"; return os;\n"; 852 }).endl().endl(); 853 854 out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os) "; 855 out.block([&] { out << "*os << toString(o);\n"; }).endl().endl(); 856 857 if (canCheckEquality()) { 858 out << "static inline bool operator==(" << getCppArgumentType() << " " 859 << (mFields.empty() ? "/* lhs */" : "lhs") << ", " << getCppArgumentType() << " " 860 << (mFields.empty() ? "/* rhs */" : "rhs") << ") "; 861 out.block([&] { 862 if (mStyle == STYLE_SAFE_UNION) { 863 out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] { 864 out << "return false;\n"; 865 }).endl(); 866 867 out << "switch (lhs.getDiscriminator()) {\n"; 868 out.indent(); 869 } 870 871 for (const auto& field : mFields) { 872 if (mStyle == STYLE_SAFE_UNION) { 873 out << "case " 874 << fullName() 875 << "::hidl_discriminator::" 876 << field->name() 877 << ": "; 878 879 out.block([&] { 880 out << "return (lhs." 881 << field->name() 882 << "() == rhs." 883 << field->name() 884 << "());\n"; 885 }).endl(); 886 } else { 887 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] { 888 out << "return false;\n"; 889 }).endl(); 890 } 891 } 892 893 if (mStyle == STYLE_SAFE_UNION) { 894 out << "default: "; 895 out.block([&] { 896 emitSafeUnionUnknownDiscriminatorError(out, "lhs.getDiscriminator()", 897 true /*fatal*/); 898 }) 899 .endl(); 900 901 out.unindent(); 902 out << "}\n"; 903 } 904 out << "return true;\n"; 905 }).endl().endl(); 906 907 out << "static inline bool operator!=(" 908 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs)"; 909 out.block([&] { 910 out << "return !(lhs == rhs);\n"; 911 }).endl().endl(); 912 } else { 913 out << "// operator== and operator!= are not generated for " << definedName() << "\n\n"; 914 } 915 } 916 917 void CompoundType::emitPackageHwDeclarations(Formatter& out) const { 918 Scope::emitPackageHwDeclarations(out); 919 920 if (needsEmbeddedReadWrite()) { 921 out << "::android::status_t readEmbeddedFromParcel(\n"; 922 923 out.indent(2); 924 925 out << "const " << fullName() << " &obj,\n" 926 << "const ::android::hardware::Parcel &parcel,\n" 927 << "size_t parentHandle,\n" 928 << "size_t parentOffset);\n\n"; 929 930 out.unindent(2); 931 932 out << "::android::status_t writeEmbeddedToParcel(\n"; 933 934 out.indent(2); 935 936 out << "const " << fullName() << " &obj,\n" 937 << "::android::hardware::Parcel *parcel,\n" 938 << "size_t parentHandle,\n" 939 << "size_t parentOffset);\n\n"; 940 941 out.unindent(2); 942 } 943 } 944 945 static void emitSafeUnionFieldConstructor(Formatter& out, 946 const NamedReference<Type>* field, 947 const std::string& initializerObjectName) { 948 out << "new (&hidl_u." 949 << field->name() 950 << ") " 951 << field->type().getCppStackType() 952 << "(" 953 << initializerObjectName 954 << ");\n"; 955 } 956 957 static void emitSafeUnionSetterDefinition(Formatter& out, 958 const NamedReference<Type>* field, 959 const std::string& parameterName, 960 bool usesMoveSemantics) { 961 out.block([&] { 962 out << "if (hidl_d != hidl_discriminator::" 963 << field->name() 964 << ") "; 965 966 const std::string argumentName = usesMoveSemantics 967 ? ("std::move(" + parameterName + ")") 968 : parameterName; 969 out.block([&] { 970 out << "hidl_destructUnion();\n" 971 << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n\n"; 972 973 emitSafeUnionFieldConstructor(out, field, argumentName); 974 out << "hidl_d = hidl_discriminator::" 975 << field->name() 976 << ";\n"; 977 }).endl(); 978 979 out << "else if (&(hidl_u." 980 << field->name() 981 << ") != &" 982 << parameterName 983 << ") "; 984 985 out.block([&] { 986 out << "hidl_u." 987 << field->name() 988 << " = " 989 << argumentName 990 << ";\n"; 991 }).endl(); 992 }).endl().endl(); 993 } 994 995 static void emitSafeUnionGetterDefinition(Formatter& out, const std::string& fieldName) { 996 out.block([&] { 997 out << "if (CC_UNLIKELY(hidl_d != hidl_discriminator::" 998 << fieldName 999 << ")) "; 1000 1001 out.block([&] { 1002 out << "LOG_ALWAYS_FATAL(\"Bad safe_union access: safe_union has discriminator %\" " 1003 << "PRIu64 \" but discriminator %\" PRIu64 \" was accessed.\",\n"; 1004 out.indent(2, [&] { 1005 out << "static_cast<uint64_t>(hidl_d), " 1006 << "static_cast<uint64_t>(hidl_discriminator::" << fieldName << "));"; 1007 }).endl(); 1008 }).endl().endl(); 1009 1010 out << "return hidl_u." 1011 << fieldName 1012 << ";\n"; 1013 }).endl().endl(); 1014 } 1015 1016 void CompoundType::emitSafeUnionCopyAndAssignDefinition(Formatter& out, 1017 const std::string& parameterName, 1018 bool isCopyConstructor, 1019 bool usesMoveSemantics) const { 1020 out.block([&] { 1021 if (!isCopyConstructor) { 1022 out << "if (this == &" 1023 << parameterName 1024 << ") { return *this; }\n\n"; 1025 } 1026 1027 out << "switch (" 1028 << parameterName 1029 << ".hidl_d) "; 1030 1031 out.block([&] { 1032 for (const auto& field : mFields) { 1033 const std::string parameterFieldName = 1034 (parameterName + ".hidl_u." + field->name()); 1035 1036 const std::string argumentName = 1037 usesMoveSemantics ? ("std::move(" + parameterFieldName + ")") 1038 : parameterFieldName; 1039 1040 out << "case hidl_discriminator::" << field->name() << ": "; 1041 1042 if (isCopyConstructor) { 1043 out.block([&] { 1044 emitSafeUnionFieldConstructor(out, field, argumentName); 1045 out << "break;\n"; 1046 }).endl(); 1047 } else { 1048 out.block([&] { 1049 out << field->name() << "(" << argumentName << ");\n" 1050 << "break;\n"; 1051 }).endl(); 1052 } 1053 } 1054 1055 out << "default: "; 1056 out.block([&] { 1057 emitSafeUnionUnknownDiscriminatorError(out, parameterName + ".hidl_d", 1058 true /*fatal*/); 1059 }).endl(); 1060 }).endl(); 1061 1062 if (isCopyConstructor) { 1063 out << "\nhidl_d = " 1064 << parameterName 1065 << ".hidl_d;\n"; 1066 } else { 1067 out << "return *this;\n"; 1068 } 1069 }).endl().endl(); 1070 } 1071 1072 void CompoundType::emitSafeUnionTypeConstructors(Formatter& out) const { 1073 1074 // Default constructor 1075 out << fullName() << "::" << definedName() << "() "; 1076 1077 out.block([&] { 1078 out << "static_assert(offsetof(" 1079 << fullName() 1080 << ", hidl_d) == 0, \"wrong offset\");\n"; 1081 1082 const CompoundLayout layout = getCompoundAlignmentAndSize(); 1083 1084 if (!containsPointer()) { 1085 out << "static_assert(offsetof(" << fullName() 1086 << ", hidl_u) == " << layout.innerStruct.offset << ", \"wrong offset\");\n"; 1087 } 1088 1089 out.endl(); 1090 1091 out << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n"; 1092 1093 // union itself is zero'd when set 1094 // padding after descriminator 1095 size_t dpad = layout.innerStruct.offset - layout.discriminator.size; 1096 emitPaddingZero(out, layout.discriminator.size /*offset*/, dpad /*size*/); 1097 1098 size_t innerStructEnd = layout.innerStruct.offset + layout.innerStruct.size; 1099 // final padding of the struct 1100 size_t fpad = layout.overall.size - innerStructEnd; 1101 emitPaddingZero(out, innerStructEnd /*offset*/, fpad /*size*/); 1102 1103 out.endl(); 1104 1105 CHECK(!mFields.empty()); 1106 out << "hidl_d = hidl_discriminator::" << mFields.at(0)->name() << ";\n"; 1107 emitSafeUnionFieldConstructor(out, mFields.at(0), ""); 1108 }).endl().endl(); 1109 1110 // Destructor 1111 out << fullName() << "::~" << definedName() << "() "; 1112 1113 out.block([&] { 1114 out << "hidl_destructUnion();\n"; 1115 }).endl().endl(); 1116 1117 // Move constructor 1118 out << fullName() << "::" << definedName() << "(" << definedName() 1119 << "&& other) : " << fullName() << "() "; 1120 1121 emitSafeUnionCopyAndAssignDefinition( 1122 out, "other", true /* isCopyConstructor */, true /* usesMoveSemantics */); 1123 1124 // Copy constructor 1125 out << fullName() << "::" << definedName() << "(const " << definedName() 1126 << "& other) : " << fullName() << "() "; 1127 1128 emitSafeUnionCopyAndAssignDefinition( 1129 out, "other", true /* isCopyConstructor */, false /* usesMoveSemantics */); 1130 1131 // Move assignment operator 1132 out << fullName() << "& (" << fullName() << "::operator=)(" << definedName() << "&& other) "; 1133 1134 emitSafeUnionCopyAndAssignDefinition( 1135 out, "other", false /* isCopyConstructor */, true /* usesMoveSemantics */); 1136 1137 // Copy assignment operator 1138 out << fullName() << "& (" << fullName() << "::operator=)(const " << definedName() 1139 << "& other) "; 1140 1141 emitSafeUnionCopyAndAssignDefinition( 1142 out, "other", false /* isCopyConstructor */, false /* usesMoveSemantics */); 1143 } 1144 1145 void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const { 1146 emitSafeUnionTypeConstructors(out); 1147 1148 out << "void " 1149 << fullName() 1150 << "::hidl_destructUnion() "; 1151 1152 out.block([&] { 1153 out << "switch (hidl_d) "; 1154 out.block([&] { 1155 for (const auto& field : mFields) { 1156 out << "case hidl_discriminator::" << field->name() << ": "; 1157 1158 out.block([&] { 1159 out << "::android::hardware::details::destructElement(&(hidl_u." 1160 << field->name() << "));\n" 1161 << "break;\n"; 1162 }).endl(); 1163 } 1164 1165 out << "default: "; 1166 out.block([&] { 1167 emitSafeUnionUnknownDiscriminatorError(out, "hidl_d", true /*fatal*/); 1168 }).endl(); 1169 }) 1170 .endl() 1171 .endl(); 1172 }).endl().endl(); 1173 1174 for (const NamedReference<Type>* field : mFields) { 1175 // Setter (copy) 1176 out << "void " 1177 << fullName() 1178 << "::" 1179 << field->name() 1180 << "(" 1181 << field->type().getCppArgumentType() 1182 << " o) "; 1183 1184 emitSafeUnionSetterDefinition(out, field, "o", false /* usesMoveSemantics */); 1185 1186 if (field->type().resolveToScalarType() == nullptr) { 1187 // Setter (move) 1188 out << "void " 1189 << fullName() 1190 << "::" 1191 << field->name() 1192 << "(" 1193 << field->type().getCppStackType() 1194 << "&& o) "; 1195 1196 emitSafeUnionSetterDefinition(out, field, "o", true /* usesMoveSemantics */); 1197 } 1198 1199 // Getter (mutable) 1200 out << field->type().getCppStackType() 1201 << "& (" 1202 << fullName() 1203 << "::" 1204 << field->name() 1205 << ")() "; 1206 1207 emitSafeUnionGetterDefinition(out, field->name()); 1208 1209 // Getter (immutable) 1210 out << field->type().getCppArgumentType() 1211 << " (" 1212 << fullName() 1213 << "::" 1214 << field->name() 1215 << ")() const "; 1216 1217 emitSafeUnionGetterDefinition(out, field->name()); 1218 } 1219 1220 // Trivial constructor/destructor for internal union 1221 out << fullName() << "::hidl_union::hidl_union() {}\n\n" 1222 << fullName() << "::hidl_union::~hidl_union() {}\n\n"; 1223 1224 // Utility method 1225 out << fullName() << "::hidl_discriminator (" 1226 << fullName() << "::getDiscriminator)() const "; 1227 1228 out.block([&] { 1229 out << "return hidl_d;\n"; 1230 }).endl().endl(); 1231 } 1232 1233 void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const { 1234 std::string space = prefix.empty() ? "" : (prefix + "::"); 1235 Scope::emitTypeDefinitions(out, space + definedName()); 1236 1237 if (needsEmbeddedReadWrite()) { 1238 emitStructReaderWriter(out, prefix, true /* isReader */); 1239 emitStructReaderWriter(out, prefix, false /* isReader */); 1240 } 1241 1242 if (mStyle == STYLE_SAFE_UNION) { 1243 emitSafeUnionTypeDefinitions(out); 1244 } 1245 } 1246 1247 static void emitJavaSafeUnionUnknownDiscriminatorError(Formatter& out, bool fatal) { 1248 out << "throw new "; 1249 1250 if (fatal) { 1251 out << "Error"; 1252 } else { 1253 out << "IllegalStateException"; 1254 } 1255 1256 out << "(\"Unknown union discriminator (value: \" + hidl_d + \").\");\n"; 1257 } 1258 1259 void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const { 1260 out << "public final "; 1261 1262 if (!atTopLevel) { 1263 out << "static "; 1264 } 1265 1266 out << "class " << definedName() << " {\n"; 1267 1268 out.indent(); 1269 1270 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */); 1271 1272 if (mStyle == STYLE_SAFE_UNION) { 1273 out << "public " << definedName() << "() "; 1274 out.block([&] { 1275 CHECK(!mFields.empty()); 1276 mFields.at(0)->type().emitJavaFieldDefaultInitialValue(out, "hidl_o"); 1277 }) 1278 .endl() 1279 .endl(); 1280 1281 const std::string discriminatorStorageType = ( 1282 getUnionDiscriminatorType()->getJavaType(false)); 1283 1284 out << "public static final class hidl_discriminator "; 1285 out.block([&] { 1286 for (size_t idx = 0; idx < mFields.size(); idx++) { 1287 const auto& field = mFields.at(idx); 1288 1289 field->emitDocComment(out); 1290 out << "public static final " << discriminatorStorageType << " " << field->name() 1291 << " = " << idx << "; // " 1292 << field->type().getJavaType(true /* forInitializer */) << "\n"; 1293 } 1294 1295 out << "\n" 1296 << "public static final String getName(" << discriminatorStorageType 1297 << " value) "; 1298 1299 out.block([&] { 1300 out << "switch (value) "; 1301 out.block([&] { 1302 for (size_t idx = 0; idx < mFields.size(); idx++) { 1303 const auto& field = mFields.at(idx); 1304 1305 out << "case " << idx << ": { return \"" << field->name() 1306 << "\"; }\n"; 1307 } 1308 out << "default: { return \"Unknown\"; }\n"; 1309 }).endl(); 1310 }) 1311 .endl() 1312 .endl(); 1313 1314 out << "private hidl_discriminator() {}\n"; 1315 }) 1316 .endl() 1317 .endl(); 1318 1319 out << "private " << discriminatorStorageType << " hidl_d = 0;\n"; 1320 out << "private Object hidl_o = null;\n"; 1321 1322 for (const auto& field : mFields) { 1323 // Setter 1324 out << "public void " 1325 << field->name() 1326 << "(" 1327 << field->type().getJavaType(false) 1328 << " " 1329 << field->name() 1330 << ") "; 1331 1332 out.block([&] { 1333 out << "hidl_d = hidl_discriminator." 1334 << field->name() 1335 << ";\n"; 1336 1337 out << "hidl_o = " 1338 << field->name() 1339 << ";\n"; 1340 }).endl().endl(); 1341 1342 // Getter 1343 out << "public " 1344 << field->type().getJavaType(false) 1345 << " " 1346 << field->name() 1347 << "() "; 1348 1349 out.block([&] { 1350 out << "if (hidl_d != hidl_discriminator." 1351 << field->name() 1352 << ") "; 1353 1354 out.block([&] { 1355 out << "String className = (hidl_o != null) ? " 1356 << "hidl_o.getClass().getName() : \"null\";\n"; 1357 1358 out << "throw new IllegalStateException(\n"; 1359 out.indent(2, [&] { 1360 out << "\"Read access to inactive union components is disallowed. \" +\n" 1361 << "\"Discriminator value is \" + hidl_d + \" (corresponding \" +\n" 1362 << "\"to \" + hidl_discriminator.getName(hidl_d) + \"), and \" +\n" 1363 << "\"hidl_o is of type \" + className + \".\");\n"; 1364 }); 1365 }).endl(); 1366 1367 out << "if (hidl_o != null && !" 1368 << field->type().getJavaTypeClass() 1369 << ".class.isInstance(hidl_o)) "; 1370 1371 out.block([&] { 1372 out << "throw new Error(\"Union is in a corrupted state.\");\n"; 1373 }).endl(); 1374 1375 out << "return (" 1376 << field->type().getJavaTypeCast("hidl_o") 1377 << ");\n"; 1378 }).endl().endl(); 1379 } 1380 1381 out << "// Utility method\n" 1382 << "public " 1383 << discriminatorStorageType 1384 << " getDiscriminator() { return hidl_d; }\n\n"; 1385 1386 } else if (mStyle == STYLE_STRUCT) { 1387 for (const auto& field : mFields) { 1388 field->emitDocComment(out); 1389 1390 out << "public "; 1391 field->type().emitJavaFieldInitializer(out, field->name()); 1392 } 1393 1394 out << "\n"; 1395 } else { 1396 LOG(FATAL) << "Java output doesn't support " << mStyle; 1397 } 1398 1399 //////////////////////////////////////////////////////////////////////////// 1400 1401 if (canCheckEquality()) { 1402 out << "@Override\npublic final boolean equals(Object otherObject) "; 1403 out.block([&] { 1404 out.sIf("this == otherObject", [&] { 1405 out << "return true;\n"; 1406 }).endl(); 1407 out.sIf("otherObject == null", [&] { 1408 out << "return false;\n"; 1409 }).endl(); 1410 // Though class is final, we use getClass instead of instanceof to be explicit. 1411 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] { 1412 out << "return false;\n"; 1413 }).endl(); 1414 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n"; 1415 1416 if (mStyle == STYLE_SAFE_UNION) { 1417 out.sIf("this.hidl_d != other.hidl_d", [&] { 1418 out << "return false;\n"; 1419 }).endl(); 1420 out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] { 1421 out << "return false;\n"; 1422 }).endl(); 1423 } else { 1424 for (const auto& field : mFields) { 1425 std::string condition = (field->type().isScalar() || field->type().isEnum()) 1426 ? "this." + field->name() + " != other." + field->name() 1427 : ("!android.os.HidlSupport.deepEquals(this." + field->name() 1428 + ", other." + field->name() + ")"); 1429 out.sIf(condition, [&] { 1430 out << "return false;\n"; 1431 }).endl(); 1432 } 1433 } 1434 out << "return true;\n"; 1435 }).endl().endl(); 1436 1437 out << "@Override\npublic final int hashCode() "; 1438 out.block([&] { 1439 out << "return java.util.Objects.hash(\n"; 1440 out.indent(2, [&] { 1441 if (mStyle == STYLE_SAFE_UNION) { 1442 out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n" 1443 << "java.util.Objects.hashCode(this.hidl_d)"; 1444 } else { 1445 out.join(mFields.begin(), mFields.end(), ", \n", [&](const auto& field) { 1446 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")"; 1447 }); 1448 } 1449 }); 1450 out << ");\n"; 1451 }).endl().endl(); 1452 } else { 1453 out << "// equals() is not generated for " << definedName() << "\n"; 1454 } 1455 1456 //////////////////////////////////////////////////////////////////////////// 1457 1458 out << "@Override\npublic final String toString() "; 1459 out.block([&] { 1460 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n" 1461 << "builder.append(\"{\");\n"; 1462 1463 if (mStyle == STYLE_SAFE_UNION) { 1464 out << "switch (this.hidl_d) {\n"; 1465 out.indent(); 1466 } 1467 1468 for (const auto& field : mFields) { 1469 if (mStyle == STYLE_SAFE_UNION) { 1470 out << "case hidl_discriminator." 1471 << field->name() 1472 << ": "; 1473 1474 out.block([&] { 1475 out << "builder.append(\"" 1476 << "." 1477 << field->name() 1478 << " = \");\n"; 1479 1480 field->type().emitJavaDump(out, "builder", "this." + field->name() + "()"); 1481 out << "break;\n"; 1482 }).endl(); 1483 } 1484 else { 1485 out << "builder.append(\""; 1486 if (field != *(mFields.begin())) { 1487 out << ", "; 1488 } 1489 out << "." << field->name() << " = \");\n"; 1490 field->type().emitJavaDump(out, "builder", "this." + field->name()); 1491 } 1492 } 1493 1494 if (mStyle == STYLE_SAFE_UNION) { 1495 out << "default: "; 1496 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); }) 1497 .endl(); 1498 1499 out.unindent(); 1500 out << "}\n"; 1501 } 1502 1503 out << "builder.append(\"}\");\nreturn builder.toString();\n"; 1504 }).endl().endl(); 1505 1506 CompoundLayout layout = getCompoundAlignmentAndSize(); 1507 1508 //////////////////////////////////////////////////////////////////////////// 1509 1510 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n"; 1511 out.indent(); 1512 if (containsInterface()) { 1513 1514 if (mStyle == STYLE_SAFE_UNION) { 1515 out << "hidl_d = "; 1516 getUnionDiscriminatorType()->emitJavaReaderWriter( 1517 out, "parcel", "hidl_d", true); 1518 1519 out << "switch (hidl_d) {\n"; 1520 out.indent(); 1521 } 1522 1523 for (const auto& field : mFields) { 1524 if (mStyle == STYLE_SAFE_UNION) { 1525 out << "case hidl_discriminator." 1526 << field->name() 1527 << ": "; 1528 1529 out.block([&] { 1530 out << "hidl_o = "; 1531 field->type().emitJavaReaderWriter(out, "parcel", "hidl_o", true); 1532 1533 out << "break;\n"; 1534 }).endl(); 1535 } else { 1536 out << field->name() << " = "; 1537 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true); 1538 } 1539 } 1540 1541 if (mStyle == STYLE_SAFE_UNION) { 1542 out << "default: "; 1543 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, false /*fatal*/); }) 1544 .endl(); 1545 1546 out.unindent(); 1547 out << "}\n"; 1548 } 1549 } else { 1550 out << "android.os.HwBlob blob = parcel.readBuffer("; 1551 out << layout.overall.size << " /* size */);\n"; 1552 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n"; 1553 } 1554 out.unindent(); 1555 out << "}\n\n"; 1556 1557 //////////////////////////////////////////////////////////////////////////// 1558 1559 size_t vecAlign, vecSize; 1560 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize); 1561 1562 out << "public static final java.util.ArrayList<" << definedName() 1563 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n"; 1564 out.indent(); 1565 1566 out << "java.util.ArrayList<" << definedName() << "> _hidl_vec = new java.util.ArrayList();\n"; 1567 1568 if (containsInterface()) { 1569 out << "int size = parcel.readInt32();\n"; 1570 out << "for(int i = 0 ; i < size; i ++) {\n"; 1571 out.indent(); 1572 out << fullJavaName() << " tmp = "; 1573 emitJavaReaderWriter(out, "parcel", "tmp", true); 1574 out << "_hidl_vec.add(tmp);\n"; 1575 out.unindent(); 1576 out << "}\n"; 1577 } else { 1578 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer("; 1579 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n"; 1580 1581 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel", 1582 "_hidl_blob", "_hidl_vec", "0", 1583 true /* isReader */); 1584 } 1585 out << "\nreturn _hidl_vec;\n"; 1586 out.unindent(); 1587 out << "}\n\n"; 1588 //////////////////////////////////////////////////////////////////////////// 1589 if (containsInterface()) { 1590 out << "// readEmbeddedFromParcel is not generated()\n"; 1591 } else { 1592 out << "public final void readEmbeddedFromParcel(\n"; 1593 out.indent(2); 1594 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n"; 1595 out.unindent(); 1596 1597 if (mStyle == STYLE_SAFE_UNION) { 1598 getUnionDiscriminatorType()->emitJavaFieldReaderWriter( 1599 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d", 1600 "_hidl_offset + " + std::to_string(layout.discriminator.offset), 1601 true /* isReader */); 1602 1603 out << "switch (this.hidl_d) {\n"; 1604 out.indent(); 1605 } 1606 1607 size_t offset = layout.innerStruct.offset; 1608 for (const auto& field : mFields) { 1609 if (mStyle == STYLE_SAFE_UNION) { 1610 out << "case hidl_discriminator." 1611 << field->name() 1612 << ": "; 1613 1614 out.block([&] { 1615 field->type().emitJavaFieldDefaultInitialValue(out, "hidl_o"); 1616 field->type().emitJavaFieldReaderWriter( 1617 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_o", 1618 "_hidl_offset + " + std::to_string(offset), true /* isReader */); 1619 1620 out << "break;\n"; 1621 }).endl(); 1622 } else { 1623 size_t fieldAlign, fieldSize; 1624 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize); 1625 1626 offset += Layout::getPad(offset, fieldAlign); 1627 field->type().emitJavaFieldReaderWriter( 1628 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(), 1629 "_hidl_offset + " + std::to_string(offset), true /* isReader */); 1630 offset += fieldSize; 1631 } 1632 } 1633 1634 if (mStyle == STYLE_SAFE_UNION) { 1635 out << "default: "; 1636 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, false /*fatal*/); }) 1637 .endl(); 1638 1639 out.unindent(); 1640 out << "}\n"; 1641 } 1642 out.unindent(); 1643 out << "}\n\n"; 1644 } 1645 1646 //////////////////////////////////////////////////////////////////////////// 1647 1648 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n"; 1649 out.indent(); 1650 1651 if (containsInterface()) { 1652 if (mStyle == STYLE_SAFE_UNION) { 1653 getUnionDiscriminatorType()->emitJavaReaderWriter( 1654 out, "parcel", "hidl_d", false); 1655 1656 out << "switch (this.hidl_d) {\n"; 1657 out.indent(); 1658 } 1659 1660 for (const auto& field : mFields) { 1661 if (mStyle == STYLE_SAFE_UNION) { 1662 out << "case hidl_discriminator." 1663 << field->name() 1664 << ": "; 1665 1666 out.block([&] { 1667 field->type().emitJavaReaderWriter(out, "parcel", field->name() + "()", false); 1668 out << "break;\n"; 1669 }).endl(); 1670 } else { 1671 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false); 1672 } 1673 } 1674 1675 if (mStyle == STYLE_SAFE_UNION) { 1676 out << "default: "; 1677 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); }) 1678 .endl(); 1679 1680 out.unindent(); 1681 out << "}\n"; 1682 } 1683 } else { 1684 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" 1685 << layout.overall.size 1686 << " /* size */);\n"; 1687 1688 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n" 1689 << "parcel.writeBuffer(_hidl_blob);\n"; 1690 } 1691 out.unindent(); 1692 out << "}\n\n"; 1693 1694 //////////////////////////////////////////////////////////////////////////// 1695 1696 out << "public static final void writeVectorToParcel(\n"; 1697 out.indent(2); 1698 out << "android.os.HwParcel parcel, java.util.ArrayList<" << definedName() 1699 << "> _hidl_vec) {\n"; 1700 out.unindent(); 1701 1702 if (containsInterface()) { 1703 out << "parcel.writeInt32(_hidl_vec.size());\n"; 1704 out << "for(" << fullJavaName() << " tmp: _hidl_vec) "; 1705 out.block([&] { 1706 emitJavaReaderWriter(out, "parcel", "tmp", false); 1707 }).endl(); 1708 } else { 1709 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize 1710 << " /* sizeof(hidl_vec<T>) */);\n"; 1711 1712 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel", 1713 "_hidl_blob", "_hidl_vec", "0", 1714 false /* isReader */); 1715 1716 out << "\nparcel.writeBuffer(_hidl_blob);\n"; 1717 } 1718 out.unindent(); 1719 out << "}\n\n"; 1720 //////////////////////////////////////////////////////////////////////////// 1721 1722 if (containsInterface()) { 1723 out << "// writeEmbeddedToBlob() is not generated\n"; 1724 } else { 1725 out << "public final void writeEmbeddedToBlob(\n"; 1726 out.indent(2); 1727 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n"; 1728 out.unindent(); 1729 1730 if (mStyle == STYLE_SAFE_UNION) { 1731 getUnionDiscriminatorType()->emitJavaFieldReaderWriter( 1732 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d", 1733 "_hidl_offset + " + std::to_string(layout.discriminator.offset), 1734 false /* isReader */); 1735 1736 out << "switch (this.hidl_d) {\n"; 1737 out.indent(); 1738 } 1739 1740 size_t offset = layout.innerStruct.offset; 1741 for (const auto& field : mFields) { 1742 if (mStyle == STYLE_SAFE_UNION) { 1743 out << "case hidl_discriminator." 1744 << field->name() 1745 << ": "; 1746 1747 out.block([&] { 1748 field->type().emitJavaFieldReaderWriter( 1749 out, 0 /* depth */, "parcel", "_hidl_blob", field->name() + "()", 1750 "_hidl_offset + " + std::to_string(offset), false /* isReader */); 1751 1752 out << "break;\n"; 1753 }).endl(); 1754 } else { 1755 size_t fieldAlign, fieldSize; 1756 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize); 1757 1758 offset += Layout::getPad(offset, fieldAlign); 1759 field->type().emitJavaFieldReaderWriter( 1760 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(), 1761 "_hidl_offset + " + std::to_string(offset), false /* isReader */); 1762 offset += fieldSize; 1763 } 1764 } 1765 1766 if (mStyle == STYLE_SAFE_UNION) { 1767 out << "default: "; 1768 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); }) 1769 .endl(); 1770 1771 out.unindent(); 1772 out << "}\n"; 1773 } 1774 out.unindent(); 1775 out << "}\n"; 1776 } 1777 1778 out.unindent(); 1779 out << "};\n\n"; 1780 } 1781 1782 void CompoundType::emitStructReaderWriter( 1783 Formatter &out, const std::string &prefix, bool isReader) const { 1784 1785 std::string space = prefix.empty() ? "" : (prefix + "::"); 1786 1787 out << "::android::status_t " 1788 << (isReader ? "readEmbeddedFromParcel" 1789 : "writeEmbeddedToParcel") 1790 << "(\n"; 1791 1792 out.indent(2); 1793 1794 const std::string name = "obj"; 1795 if (isReader) { 1796 out << "const " << space << definedName() << " &" << name << ",\n"; 1797 out << "const ::android::hardware::Parcel &parcel,\n"; 1798 } else { 1799 out << "const " << space << definedName() << " &" << name << ",\n"; 1800 out << "::android::hardware::Parcel *parcel,\n"; 1801 } 1802 1803 out << "size_t parentHandle,\n" 1804 << "size_t parentOffset)"; 1805 1806 out << " {\n"; 1807 1808 out.unindent(2); 1809 out.indent(); 1810 1811 out << "::android::status_t _hidl_err = ::android::OK;\n\n"; 1812 1813 if (mStyle == STYLE_SAFE_UNION) { 1814 out << "switch (" << name << ".getDiscriminator()) {\n"; 1815 out.indent(); 1816 } 1817 1818 for (const auto& field : mFields) { 1819 if (!field->type().needsEmbeddedReadWrite()) { 1820 continue; 1821 } 1822 1823 if (mStyle == STYLE_SAFE_UNION) { 1824 out << "case " << fullName() << "::hidl_discriminator::" 1825 << field->name() << ": {\n"; 1826 out.indent(); 1827 } 1828 1829 const std::string fieldName = (mStyle == STYLE_SAFE_UNION) 1830 ? (name + "." + field->name() + "()") 1831 : (name + "." + field->name()); 1832 1833 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION) 1834 ? (name + ".hidl_getUnionOffset() " + 1835 "/* safe_union: union offset into struct */") 1836 : ("offsetof(" + fullName() + ", " + field->name() + ")"); 1837 1838 field->type().emitReaderWriterEmbedded( 1839 out, 1840 0 /* depth */, 1841 fieldName, 1842 field->name() /* sanitizedName */, 1843 false /* nameIsPointer */, 1844 "parcel", 1845 !isReader /* parcelObjIsPointer */, 1846 isReader, 1847 ErrorMode_Return, 1848 "parentHandle", 1849 "parentOffset + " + fieldOffset); 1850 1851 if (mStyle == STYLE_SAFE_UNION) { 1852 out << "break;\n"; 1853 out.unindent(); 1854 out << "}\n"; 1855 } 1856 } 1857 1858 if (mStyle == STYLE_SAFE_UNION) { 1859 out << "default: { break; }\n"; 1860 out.unindent(); 1861 out << "}\n"; 1862 } 1863 1864 out << "return _hidl_err;\n"; 1865 1866 out.unindent(); 1867 out << "}\n\n"; 1868 } 1869 1870 bool CompoundType::needsEmbeddedReadWrite() const { 1871 if (mStyle == STYLE_UNION) { 1872 return false; 1873 } 1874 1875 for (const auto& field : mFields) { 1876 if (field->type().needsEmbeddedReadWrite()) { 1877 return true; 1878 } 1879 } 1880 1881 return false; 1882 } 1883 1884 bool CompoundType::resultNeedsDeref() const { 1885 return !containsInterface() ; 1886 } 1887 1888 void CompoundType::emitVtsTypeDeclarations(Formatter& out) const { 1889 out << "name: \"" << fullName() << "\"\n"; 1890 out << "type: " << getVtsType() << "\n"; 1891 1892 // Emit declaration for each subtype. 1893 for (const auto &type : getSubTypes()) { 1894 switch (mStyle) { 1895 case STYLE_STRUCT: 1896 { 1897 out << "sub_struct: {\n"; 1898 break; 1899 } 1900 case STYLE_UNION: 1901 { 1902 out << "sub_union: {\n"; 1903 break; 1904 } 1905 case STYLE_SAFE_UNION: 1906 { 1907 out << "sub_safe_union: {\n"; 1908 break; 1909 } 1910 default: 1911 { 1912 CHECK(!"Should not be here"); 1913 } 1914 } 1915 out.indent(); 1916 type->emitVtsTypeDeclarations(out); 1917 out.unindent(); 1918 out << "}\n"; 1919 } 1920 1921 // Emit declaration for each field. 1922 for (const auto& field : mFields) { 1923 switch (mStyle) { 1924 case STYLE_STRUCT: 1925 { 1926 out << "struct_value: {\n"; 1927 break; 1928 } 1929 case STYLE_UNION: 1930 { 1931 out << "union_value: {\n"; 1932 break; 1933 } 1934 case STYLE_SAFE_UNION: 1935 { 1936 out << "safe_union_value: {\n"; 1937 break; 1938 } 1939 default: 1940 { 1941 CHECK(!"Should not be here"); 1942 } 1943 } 1944 out.indent(); 1945 out << "name: \"" << field->name() << "\"\n"; 1946 field->type().emitVtsAttributeType(out); 1947 out.unindent(); 1948 out << "}\n"; 1949 } 1950 } 1951 1952 void CompoundType::emitVtsAttributeType(Formatter& out) const { 1953 out << "type: " << getVtsType() << "\n"; 1954 out << "predefined_type: \"" << fullName() << "\"\n"; 1955 } 1956 1957 bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const { 1958 if (mStyle == STYLE_UNION) { 1959 return false; 1960 } 1961 1962 for (const auto* field : mFields) { 1963 if (!field->get()->isJavaCompatible(visited)) { 1964 return false; 1965 } 1966 } 1967 1968 return Scope::deepIsJavaCompatible(visited); 1969 } 1970 1971 bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const { 1972 for (const auto* field : mFields) { 1973 if (field->get()->containsPointer(visited)) { 1974 return true; 1975 } 1976 } 1977 1978 return Scope::deepContainsPointer(visited); 1979 } 1980 1981 void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const { 1982 CompoundLayout layout = getCompoundAlignmentAndSize(); 1983 *align = layout.overall.align; 1984 *size = layout.overall.size; 1985 } 1986 1987 CompoundType::CompoundLayout CompoundType::getCompoundAlignmentAndSize() const { 1988 CompoundLayout compoundLayout; 1989 1990 // Local aliases for convenience 1991 Layout& overall = compoundLayout.overall; 1992 Layout& innerStruct = compoundLayout.innerStruct; 1993 Layout& discriminator = compoundLayout.discriminator; 1994 1995 if (mStyle == STYLE_SAFE_UNION) { 1996 getUnionDiscriminatorType()->getAlignmentAndSize( 1997 &(discriminator.align), &(discriminator.size)); 1998 1999 innerStruct.offset = discriminator.size; 2000 } 2001 2002 for (const auto& field : mFields) { 2003 // Each field is aligned according to its alignment requirement. 2004 // The surrounding structure's alignment is the maximum of its 2005 // fields' aligments. 2006 size_t fieldAlign, fieldSize; 2007 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize); 2008 size_t lPad = Layout::getPad(innerStruct.size, fieldAlign); 2009 2010 innerStruct.size = (mStyle == STYLE_STRUCT) 2011 ? (innerStruct.size + lPad + fieldSize) 2012 : std::max(innerStruct.size, fieldSize); 2013 2014 innerStruct.align = std::max(innerStruct.align, fieldAlign); 2015 } 2016 2017 // Pad the inner structure's size 2018 innerStruct.size += Layout::getPad(innerStruct.size, 2019 innerStruct.align); 2020 2021 // Compute its final offset 2022 innerStruct.offset += Layout::getPad(innerStruct.offset, 2023 innerStruct.align); 2024 2025 // An empty struct/union still occupies a byte of space in C++. 2026 if (innerStruct.size == 0) { 2027 innerStruct.size = 1; 2028 } 2029 2030 overall.size = innerStruct.offset + innerStruct.size; 2031 2032 // Pad the overall structure's size 2033 overall.align = std::max(innerStruct.align, discriminator.align); 2034 overall.size += Layout::getPad(overall.size, overall.align); 2035 2036 if (mStyle != STYLE_SAFE_UNION) { 2037 CHECK(overall.offset == innerStruct.offset) << overall.offset << " " << innerStruct.offset; 2038 CHECK(overall.align == innerStruct.align) << overall.align << " " << innerStruct.align; 2039 CHECK(overall.size == innerStruct.size) << overall.size << " " << innerStruct.size; 2040 } 2041 2042 return compoundLayout; 2043 } 2044 2045 void CompoundType::emitPaddingZero(Formatter& out, size_t offset, size_t size) const { 2046 if (size > 0) { 2047 out << "::std::memset(reinterpret_cast<uint8_t*>(this) + " << offset << ", 0, " << size 2048 << ");\n"; 2049 } else { 2050 out << "// no padding to zero starting at offset " << offset << "\n"; 2051 } 2052 } 2053 2054 std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const { 2055 static const std::vector<std::pair<int, ScalarType::Kind> > scalars { 2056 {8, ScalarType::Kind::KIND_UINT8}, 2057 {16, ScalarType::Kind::KIND_UINT16}, 2058 {32, ScalarType::Kind::KIND_UINT32}, 2059 }; 2060 2061 size_t numFields = mFields.size(); 2062 auto kind = ScalarType::Kind::KIND_UINT64; 2063 2064 for (const auto& scalar : scalars) { 2065 if (numFields <= (1ULL << scalar.first)) { 2066 kind = scalar.second; break; 2067 } 2068 } 2069 2070 return std::unique_ptr<ScalarType>(new ScalarType(kind, nullptr)); 2071 } 2072 2073 size_t CompoundType::Layout::getPad(size_t offset, size_t align) { 2074 size_t remainder = offset % align; 2075 return (remainder > 0) ? (align - remainder) : 0; 2076 } 2077 2078 } // namespace android 2079 2080