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 "EnumType.h" 18 19#include "Annotation.h" 20#include "ScalarType.h" 21 22#include <inttypes.h> 23#include <hidl-util/Formatter.h> 24#include <android-base/logging.h> 25 26namespace android { 27 28EnumType::EnumType(const char* localName, const Location& location, Type* storageType, 29 Scope* parent) 30 : Scope(localName, location, parent), mValues(), mStorageType(storageType) { 31 mBitfieldType = new BitFieldType(); 32 mBitfieldType->setElementType(this); 33} 34 35const Type *EnumType::storageType() const { 36 return mStorageType; 37} 38 39const std::vector<EnumValue *> &EnumType::values() const { 40 return mValues; 41} 42 43void EnumType::addValue(EnumValue *value) { 44 CHECK(value != nullptr); 45 46 EnumValue *prev = nullptr; 47 std::vector<const EnumType *> chain; 48 getTypeChain(&chain); 49 for (auto it = chain.begin(); it != chain.end(); ++it) { 50 const auto &type = *it; 51 if(!type->values().empty()) { 52 prev = type->values().back(); 53 break; 54 } 55 } 56 57 value->autofill(prev, resolveToScalarType()); 58 mValues.push_back(value); 59} 60 61bool EnumType::isElidableType() const { 62 return mStorageType->isElidableType(); 63} 64 65const ScalarType *EnumType::resolveToScalarType() const { 66 return mStorageType->resolveToScalarType(); 67} 68 69std::string EnumType::typeName() const { 70 return "enum " + localName(); 71} 72 73bool EnumType::isEnum() const { 74 return true; 75} 76 77bool EnumType::canCheckEquality() const { 78 return true; 79} 80 81std::string EnumType::getCppType(StorageMode, 82 bool /* specifyNamespaces */) const { 83 return fullName(); 84} 85 86std::string EnumType::getJavaType(bool forInitializer) const { 87 return mStorageType->resolveToScalarType()->getJavaType(forInitializer); 88} 89 90std::string EnumType::getJavaSuffix() const { 91 return mStorageType->resolveToScalarType()->getJavaSuffix(); 92} 93 94std::string EnumType::getJavaWrapperType() const { 95 return mStorageType->resolveToScalarType()->getJavaWrapperType(); 96} 97 98std::string EnumType::getVtsType() const { 99 return "TYPE_ENUM"; 100} 101 102BitFieldType *EnumType::getBitfieldType() const { 103 return mBitfieldType; 104} 105 106LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const { 107 std::vector<const EnumType *> chain; 108 getTypeChain(&chain); 109 for (auto it = chain.begin(); it != chain.end(); ++it) { 110 const auto &type = *it; 111 for(EnumValue *v : type->values()) { 112 if(v->name() == name) { 113 return v; 114 } 115 } 116 } 117 return nullptr; 118} 119 120void EnumType::emitReaderWriter( 121 Formatter &out, 122 const std::string &name, 123 const std::string &parcelObj, 124 bool parcelObjIsPointer, 125 bool isReader, 126 ErrorMode mode) const { 127 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 128 CHECK(scalarType != NULL); 129 130 scalarType->emitReaderWriterWithCast( 131 out, 132 name, 133 parcelObj, 134 parcelObjIsPointer, 135 isReader, 136 mode, 137 true /* needsCast */); 138} 139 140void EnumType::emitJavaFieldReaderWriter( 141 Formatter &out, 142 size_t depth, 143 const std::string &parcelName, 144 const std::string &blobName, 145 const std::string &fieldName, 146 const std::string &offset, 147 bool isReader) const { 148 return mStorageType->emitJavaFieldReaderWriter( 149 out, depth, parcelName, blobName, fieldName, offset, isReader); 150} 151 152status_t EnumType::emitTypeDeclarations(Formatter &out) const { 153 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 154 CHECK(scalarType != nullptr); 155 156 const std::string storageType = scalarType->getCppStackType(); 157 158 out << "enum class " 159 << localName() 160 << " : " 161 << storageType 162 << " {\n"; 163 164 out.indent(); 165 166 std::vector<const EnumType *> chain; 167 getTypeChain(&chain); 168 169 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 170 const auto &type = *it; 171 172 for (const auto &entry : type->values()) { 173 out << entry->name(); 174 175 std::string value = entry->cppValue(scalarType->getKind()); 176 CHECK(!value.empty()); // use autofilled values for c++. 177 out << " = " << value; 178 179 out << ","; 180 181 std::string comment = entry->comment(); 182 if (!comment.empty() && comment != value) { 183 out << " // " << comment; 184 } 185 186 out << "\n"; 187 } 188 } 189 190 out.unindent(); 191 out << "};\n\n"; 192 193 return OK; 194} 195 196void EnumType::emitEnumBitwiseOperator( 197 Formatter &out, 198 bool lhsIsEnum, 199 bool rhsIsEnum, 200 const std::string &op) const { 201 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 202 CHECK(scalarType != nullptr); 203 204 const std::string storageType = scalarType->getCppStackType(); 205 206 out << "constexpr " 207 << storageType 208 << " operator" 209 << op 210 << "(const " 211 << (lhsIsEnum ? fullName() : storageType) 212 << " lhs, const " 213 << (rhsIsEnum ? fullName() : storageType) 214 << " rhs) {\n"; 215 216 out.indent([&] { 217 out << "return static_cast<" 218 << storageType 219 << ">("; 220 221 if (lhsIsEnum) { 222 out << "static_cast<" 223 << storageType 224 << ">(lhs)"; 225 } else { 226 out << "lhs"; 227 } 228 out << " " << op << " "; 229 if (rhsIsEnum) { 230 out << "static_cast<" 231 << storageType 232 << ">(rhs)"; 233 } else { 234 out << "rhs"; 235 } 236 out << ");\n"; 237 }); 238 239 out << "}\n\n"; 240} 241 242void EnumType::emitBitFieldBitwiseAssignmentOperator( 243 Formatter &out, 244 const std::string &op) const { 245 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 246 CHECK(scalarType != nullptr); 247 248 const std::string storageType = scalarType->getCppStackType(); 249 250 out << "constexpr " << storageType << " &operator" << op << "=(" 251 << storageType << "& v, const " << fullName() << " e) {\n"; 252 253 out.indent([&] { 254 out << "v " << op << "= static_cast<" << storageType << ">(e);\n"; 255 out << "return v;\n"; 256 }); 257 258 out << "}\n\n"; 259} 260 261status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const { 262 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 263 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "|"); 264 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "|"); 265 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 266 emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true /* rhsIsEnum */, "&"); 267 emitEnumBitwiseOperator(out, true /* lhsIsEnum */, false /* rhsIsEnum */, "&"); 268 269 emitBitFieldBitwiseAssignmentOperator(out, "|"); 270 emitBitFieldBitwiseAssignmentOperator(out, "&"); 271 272 // toString for bitfields, equivalent to dumpBitfield in Java 273 out << "template<typename>\n" 274 << "std::string toString(" 275 << resolveToScalarType()->getCppArgumentType() 276 << " o);\n"; 277 out << "template<>\n" 278 << "std::string toString<" << getCppStackType() << ">(" 279 << resolveToScalarType()->getCppArgumentType() 280 << " o);\n\n"; 281 282 // toString for enum itself 283 out << "std::string toString(" 284 << getCppArgumentType() 285 << " o);\n\n"; 286 287 return OK; 288} 289 290status_t EnumType::emitTypeDefinitions(Formatter &out, const std::string /* prefix */) const { 291 292 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 293 CHECK(scalarType != NULL); 294 295 out << "template<>\n" 296 << "std::string toString<" << getCppStackType() << ">(" 297 << scalarType->getCppArgumentType() 298 << " o) "; 299 out.block([&] { 300 // include toHexString for scalar types 301 out << "using ::android::hardware::details::toHexString;\n" 302 << "std::string os;\n" 303 << getBitfieldType()->getCppStackType() << " flipped = 0;\n" 304 << "bool first = true;\n"; 305 for (EnumValue *value : values()) { 306 std::string valueName = fullName() + "::" + value->name(); 307 out.sIf("(o & " + valueName + ")" + 308 " == static_cast<" + scalarType->getCppStackType() + 309 ">(" + valueName + ")", [&] { 310 out << "os += (first ? \"\" : \" | \");\n" 311 << "os += \"" << value->name() << "\";\n" 312 << "first = false;\n" 313 << "flipped |= " << valueName << ";\n"; 314 }).endl(); 315 } 316 // put remaining bits 317 out.sIf("o != flipped", [&] { 318 out << "os += (first ? \"\" : \" | \");\n"; 319 scalarType->emitHexDump(out, "os", "o & (~flipped)"); 320 }); 321 out << "os += \" (\";\n"; 322 scalarType->emitHexDump(out, "os", "o"); 323 out << "os += \")\";\n"; 324 325 out << "return os;\n"; 326 }).endl().endl(); 327 328 out << "std::string toString(" 329 << getCppArgumentType() 330 << " o) "; 331 332 out.block([&] { 333 out << "using ::android::hardware::details::toHexString;\n"; 334 for (EnumValue *value : values()) { 335 out.sIf("o == " + fullName() + "::" + value->name(), [&] { 336 out << "return \"" << value->name() << "\";\n"; 337 }).endl(); 338 } 339 out << "std::string os;\n"; 340 scalarType->emitHexDump(out, "os", 341 "static_cast<" + scalarType->getCppStackType() + ">(o)"); 342 out << "return os;\n"; 343 }).endl().endl(); 344 345 return OK; 346} 347 348status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const { 349 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 350 CHECK(scalarType != NULL); 351 352 out << "public " 353 << (atTopLevel ? "" : "static ") 354 << "final class " 355 << localName() 356 << " {\n"; 357 358 out.indent(); 359 360 const std::string typeName = 361 scalarType->getJavaType(false /* forInitializer */); 362 363 std::vector<const EnumType *> chain; 364 getTypeChain(&chain); 365 366 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 367 const auto &type = *it; 368 369 for (const auto &entry : type->values()) { 370 out << "public static final " 371 << typeName 372 << " " 373 << entry->name() 374 << " = "; 375 376 // javaValue will make the number signed. 377 std::string value = entry->javaValue(scalarType->getKind()); 378 CHECK(!value.empty()); // use autofilled values for java. 379 out << value; 380 381 out << ";"; 382 383 std::string comment = entry->comment(); 384 if (!comment.empty() && comment != value) { 385 out << " // " << comment; 386 } 387 388 out << "\n"; 389 } 390 } 391 392 out << "public static final String toString(" 393 << typeName << " o) "; 394 out.block([&] { 395 for (EnumValue *value : values()) { 396 out.sIf("o == " + value->name(), [&] { 397 out << "return \"" << value->name() << "\";\n"; 398 }).endl(); 399 } 400 out << "return \"0x\" + "; 401 scalarType->emitConvertToJavaHexString(out, "o"); 402 out << ";\n"; 403 }).endl(); 404 405 auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */); 406 auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType(); 407 out << "\n" 408 << "public static final String dumpBitfield(" 409 << bitfieldType << " o) "; 410 out.block([&] { 411 out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n"; 412 out << bitfieldType << " flipped = 0;\n"; 413 for (EnumValue *value : values()) { 414 if (value->constExpr()->castSizeT() == 0) { 415 out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n"; 416 continue; 417 } 418 out.sIf("(o & " + value->name() + ") == " + value->name(), [&] { 419 out << "list.add(\"" << value->name() << "\");\n"; 420 out << "flipped |= " << value->name() << ";\n"; 421 }).endl(); 422 } 423 // put remaining bits 424 out.sIf("o != flipped", [&] { 425 out << "list.add(\"0x\" + "; 426 scalarType->emitConvertToJavaHexString(out, "o & (~flipped)"); 427 out << ");\n"; 428 }).endl(); 429 out << "return String.join(\" | \", list);\n"; 430 }).endl().endl(); 431 432 out.unindent(); 433 out << "};\n\n"; 434 435 return OK; 436} 437 438status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const { 439 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 440 441 out << "name: \"" << fullName() << "\"\n"; 442 out << "type: " << getVtsType() << "\n"; 443 out << "enum_value: {\n"; 444 out.indent(); 445 446 out << "scalar_type: \"" 447 << scalarType->getVtsScalarType() 448 << "\"\n\n"; 449 std::vector<const EnumType *> chain; 450 getTypeChain(&chain); 451 452 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 453 const auto &type = *it; 454 455 for (const auto &entry : type->values()) { 456 out << "enumerator: \"" << entry->name() << "\"\n"; 457 out << "scalar_value: {\n"; 458 out.indent(); 459 // use autofilled values for vts. 460 std::string value = entry->value(scalarType->getKind()); 461 CHECK(!value.empty()); 462 out << mStorageType->resolveToScalarType()->getVtsScalarType() 463 << ": " 464 << value 465 << "\n"; 466 out.unindent(); 467 out << "}\n"; 468 } 469 } 470 471 out.unindent(); 472 out << "}\n"; 473 return OK; 474} 475 476status_t EnumType::emitVtsAttributeType(Formatter &out) const { 477 out << "type: " << getVtsType() << "\n"; 478 out << "predefined_type: \"" << fullName() << "\"\n"; 479 return OK; 480} 481 482void EnumType::emitJavaDump( 483 Formatter &out, 484 const std::string &streamName, 485 const std::string &name) const { 486 out << streamName << ".append(" << fqName().javaName() << ".toString(" 487 << name << "));\n"; 488} 489 490void EnumType::getTypeChain(std::vector<const EnumType *> *out) const { 491 out->clear(); 492 const EnumType *type = this; 493 for (;;) { 494 out->push_back(type); 495 496 const Type *superType = type->storageType(); 497 if (superType == NULL || !superType->isEnum()) { 498 break; 499 } 500 501 type = static_cast<const EnumType *>(superType); 502 } 503} 504 505void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const { 506 mStorageType->getAlignmentAndSize(align, size); 507} 508 509const Annotation *EnumType::findExportAnnotation() const { 510 for (const auto &annotation : annotations()) { 511 if (annotation->name() == "export") { 512 return annotation; 513 } 514 } 515 516 return nullptr; 517} 518 519void EnumType::appendToExportedTypesVector( 520 std::vector<const Type *> *exportedTypes) const { 521 if (findExportAnnotation() != nullptr) { 522 exportedTypes->push_back(this); 523 } 524} 525 526status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const { 527 const Annotation *annotation = findExportAnnotation(); 528 CHECK(annotation != nullptr); 529 530 std::string name = localName(); 531 532 const AnnotationParam *nameParam = annotation->getParam("name"); 533 if (nameParam != nullptr) { 534 name = nameParam->getSingleString(); 535 } 536 537 bool exportParent = true; 538 const AnnotationParam *exportParentParam = annotation->getParam("export_parent"); 539 if (exportParentParam != nullptr) { 540 exportParent = exportParentParam->getSingleBool(); 541 } 542 543 std::string valuePrefix; 544 const AnnotationParam *prefixParam = annotation->getParam("value_prefix"); 545 if (prefixParam != nullptr) { 546 valuePrefix = prefixParam->getSingleString(); 547 } 548 549 std::string valueSuffix; 550 const AnnotationParam *suffixParam = annotation->getParam("value_suffix"); 551 if (suffixParam != nullptr) { 552 valueSuffix = suffixParam->getSingleString(); 553 } 554 555 const ScalarType *scalarType = mStorageType->resolveToScalarType(); 556 CHECK(scalarType != nullptr); 557 558 std::vector<const EnumType *> chain; 559 if (exportParent) { 560 getTypeChain(&chain); 561 } else { 562 chain = { this }; 563 } 564 565 if (forJava) { 566 if (!name.empty()) { 567 out << "public final class " 568 << name 569 << " {\n"; 570 571 out.indent(); 572 } else { 573 out << "// Values declared in " << localName() << " follow.\n"; 574 } 575 576 const std::string typeName = 577 scalarType->getJavaType(false /* forInitializer */); 578 579 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 580 const auto &type = *it; 581 582 for (const auto &entry : type->values()) { 583 out << "public static final " 584 << typeName 585 << " " 586 << valuePrefix 587 << entry->name() 588 << valueSuffix 589 << " = "; 590 591 // javaValue will make the number signed. 592 std::string value = entry->javaValue(scalarType->getKind()); 593 CHECK(!value.empty()); // use autofilled values for java. 594 out << value; 595 596 out << ";"; 597 598 std::string comment = entry->comment(); 599 if (!comment.empty() && comment != value) { 600 out << " // " << comment; 601 } 602 603 out << "\n"; 604 } 605 } 606 607 if (!name.empty()) { 608 out.unindent(); 609 out << "};\n"; 610 } 611 out << "\n"; 612 613 return OK; 614 } 615 616 if (!name.empty()) { 617 out << "typedef "; 618 } 619 620 out << "enum {\n"; 621 622 out.indent(); 623 624 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 625 const auto &type = *it; 626 627 for (const auto &entry : type->values()) { 628 out << valuePrefix << entry->name() << valueSuffix; 629 630 std::string value = entry->cppValue(scalarType->getKind()); 631 CHECK(!value.empty()); // use autofilled values for c++. 632 out << " = " << value; 633 634 out << ","; 635 636 std::string comment = entry->comment(); 637 if (!comment.empty() && comment != value) { 638 out << " // " << comment; 639 } 640 641 out << "\n"; 642 } 643 } 644 645 out.unindent(); 646 out << "}"; 647 648 if (!name.empty()) { 649 out << " " << name; 650 } 651 652 out << ";\n\n"; 653 654 return OK; 655} 656 657//////////////////////////////////////////////////////////////////////////////// 658 659EnumValue::EnumValue(const char *name, ConstantExpression *value) 660 : mName(name), 661 mValue(value), 662 mIsAutoFill(false) { 663} 664 665std::string EnumValue::name() const { 666 return mName; 667} 668 669std::string EnumValue::value(ScalarType::Kind castKind) const { 670 CHECK(mValue != nullptr); 671 return mValue->value(castKind); 672} 673 674std::string EnumValue::cppValue(ScalarType::Kind castKind) const { 675 CHECK(mValue != nullptr); 676 return mValue->cppValue(castKind); 677} 678std::string EnumValue::javaValue(ScalarType::Kind castKind) const { 679 CHECK(mValue != nullptr); 680 return mValue->javaValue(castKind); 681} 682 683std::string EnumValue::comment() const { 684 CHECK(mValue != nullptr); 685 return mValue->description(); 686} 687 688ConstantExpression *EnumValue::constExpr() const { 689 CHECK(mValue != nullptr); 690 return mValue; 691} 692 693void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) { 694 if(mValue != nullptr) 695 return; 696 mIsAutoFill = true; 697 ConstantExpression *value = new ConstantExpression(); 698 if(prev == nullptr) { 699 *value = ConstantExpression::Zero(type->getKind()); 700 } else { 701 CHECK(prev->mValue != nullptr); 702 *value = prev->mValue->addOne(); 703 } 704 mValue = value; 705} 706 707bool EnumValue::isAutoFill() const { 708 return mIsAutoFill; 709} 710 711bool EnumValue::isEnumValue() const { 712 return true; 713} 714 715//////////////////////////////////////////////////////////////////////////////// 716 717bool BitFieldType::isBitField() const { 718 return true; 719} 720 721std::string BitFieldType::typeName() const { 722 return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName())); 723} 724 725bool BitFieldType::isCompatibleElementType(Type *elementType) const { 726 return elementType->isEnum(); 727} 728 729const ScalarType *BitFieldType::resolveToScalarType() const { 730 return mElementType->resolveToScalarType(); 731} 732 733std::string BitFieldType::getCppType(StorageMode mode, 734 bool specifyNamespaces) const { 735 return resolveToScalarType()->getCppType(mode, specifyNamespaces); 736} 737 738std::string BitFieldType::getJavaType(bool forInitializer) const { 739 return resolveToScalarType()->getJavaType(forInitializer); 740} 741 742std::string BitFieldType::getJavaSuffix() const { 743 return resolveToScalarType()->getJavaSuffix(); 744} 745 746std::string BitFieldType::getJavaWrapperType() const { 747 return resolveToScalarType()->getJavaWrapperType(); 748} 749 750std::string BitFieldType::getVtsType() const { 751 return "TYPE_MASK"; 752} 753 754bool BitFieldType::isElidableType() const { 755 return resolveToScalarType()->isElidableType(); 756} 757 758bool BitFieldType::canCheckEquality() const { 759 return resolveToScalarType()->canCheckEquality(); 760} 761 762status_t BitFieldType::emitVtsAttributeType(Formatter &out) const { 763 out << "type: " << getVtsType() << "\n"; 764 out << "scalar_type: \"" 765 << mElementType->resolveToScalarType()->getVtsScalarType() 766 << "\"\n"; 767 out << "predefined_type: \"" 768 << static_cast<NamedType *>(mElementType)->fullName() << "\"\n"; 769 return OK; 770} 771 772void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const { 773 resolveToScalarType()->getAlignmentAndSize(align, size); 774} 775 776void BitFieldType::emitReaderWriter( 777 Formatter &out, 778 const std::string &name, 779 const std::string &parcelObj, 780 bool parcelObjIsPointer, 781 bool isReader, 782 ErrorMode mode) const { 783 resolveToScalarType()->emitReaderWriterWithCast( 784 out, 785 name, 786 parcelObj, 787 parcelObjIsPointer, 788 isReader, 789 mode, 790 true /* needsCast */); 791} 792 793EnumType *BitFieldType::getEnumType() const { 794 CHECK(mElementType->isEnum()); 795 return static_cast<EnumType *>(mElementType); 796} 797 798// a bitfield maps to the underlying scalar type in C++, so operator<< is 799// already defined. We can still emit useful information if the bitfield is 800// in a struct / union by overriding emitDump as below. 801void BitFieldType::emitDump( 802 Formatter &out, 803 const std::string &streamName, 804 const std::string &name) const { 805 out << streamName << " += "<< getEnumType()->fqName().cppNamespace() 806 << "::toString<" << getEnumType()->getCppStackType() 807 << ">(" << name << ");\n"; 808} 809 810void BitFieldType::emitJavaDump( 811 Formatter &out, 812 const std::string &streamName, 813 const std::string &name) const { 814 out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield(" 815 << name << "));\n"; 816} 817 818void BitFieldType::emitJavaFieldReaderWriter( 819 Formatter &out, 820 size_t depth, 821 const std::string &parcelName, 822 const std::string &blobName, 823 const std::string &fieldName, 824 const std::string &offset, 825 bool isReader) const { 826 return resolveToScalarType()->emitJavaFieldReaderWriter( 827 out, depth, parcelName, blobName, fieldName, offset, isReader); 828} 829 830} // namespace android 831 832