Home | History | Annotate | Download | only in hidl
      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 
     26 namespace android {
     27 
     28 EnumType::EnumType(
     29         const char *localName,
     30         const Location &location,
     31         Type *storageType)
     32     : Scope(localName, location),
     33       mValues(),
     34       mStorageType(storageType) {
     35     mBitfieldType = new BitFieldType();
     36     mBitfieldType->setElementType(this);
     37 }
     38 
     39 const Type *EnumType::storageType() const {
     40     return mStorageType;
     41 }
     42 
     43 const std::vector<EnumValue *> &EnumType::values() const {
     44     return mValues;
     45 }
     46 
     47 void EnumType::addValue(EnumValue *value) {
     48     CHECK(value != nullptr);
     49 
     50     EnumValue *prev = nullptr;
     51     std::vector<const EnumType *> chain;
     52     getTypeChain(&chain);
     53     for (auto it = chain.begin(); it != chain.end(); ++it) {
     54         const auto &type = *it;
     55         if(!type->values().empty()) {
     56             prev = type->values().back();
     57             break;
     58         }
     59     }
     60 
     61     value->autofill(prev, resolveToScalarType());
     62     mValues.push_back(value);
     63 }
     64 
     65 bool EnumType::isElidableType() const {
     66     return mStorageType->isElidableType();
     67 }
     68 
     69 const ScalarType *EnumType::resolveToScalarType() const {
     70     return mStorageType->resolveToScalarType();
     71 }
     72 
     73 std::string EnumType::typeName() const {
     74     return "enum " + localName();
     75 }
     76 
     77 bool EnumType::isEnum() const {
     78     return true;
     79 }
     80 
     81 bool EnumType::canCheckEquality() const {
     82     return true;
     83 }
     84 
     85 std::string EnumType::getCppType(StorageMode,
     86                                  bool specifyNamespaces) const {
     87     return specifyNamespaces ? fullName() : partialCppName();
     88 }
     89 
     90 std::string EnumType::getJavaType(bool forInitializer) const {
     91     return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
     92 }
     93 
     94 std::string EnumType::getJavaSuffix() const {
     95     return mStorageType->resolveToScalarType()->getJavaSuffix();
     96 }
     97 
     98 std::string EnumType::getJavaWrapperType() const {
     99     return mStorageType->resolveToScalarType()->getJavaWrapperType();
    100 }
    101 
    102 std::string EnumType::getVtsType() const {
    103     return "TYPE_ENUM";
    104 }
    105 
    106 BitFieldType *EnumType::getBitfieldType() const {
    107     return mBitfieldType;
    108 }
    109 
    110 LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
    111     std::vector<const EnumType *> chain;
    112     getTypeChain(&chain);
    113     for (auto it = chain.begin(); it != chain.end(); ++it) {
    114         const auto &type = *it;
    115         for(EnumValue *v : type->values()) {
    116             if(v->name() == name) {
    117                 return v;
    118             }
    119         }
    120     }
    121     return nullptr;
    122 }
    123 
    124 void EnumType::emitReaderWriter(
    125         Formatter &out,
    126         const std::string &name,
    127         const std::string &parcelObj,
    128         bool parcelObjIsPointer,
    129         bool isReader,
    130         ErrorMode mode) const {
    131     const ScalarType *scalarType = mStorageType->resolveToScalarType();
    132     CHECK(scalarType != NULL);
    133 
    134     scalarType->emitReaderWriterWithCast(
    135             out,
    136             name,
    137             parcelObj,
    138             parcelObjIsPointer,
    139             isReader,
    140             mode,
    141             true /* needsCast */);
    142 }
    143 
    144 void EnumType::emitJavaFieldReaderWriter(
    145         Formatter &out,
    146         size_t depth,
    147         const std::string &parcelName,
    148         const std::string &blobName,
    149         const std::string &fieldName,
    150         const std::string &offset,
    151         bool isReader) const {
    152     return mStorageType->emitJavaFieldReaderWriter(
    153             out, depth, parcelName, blobName, fieldName, offset, isReader);
    154 }
    155 
    156 status_t EnumType::emitTypeDeclarations(Formatter &out) const {
    157     const ScalarType *scalarType = mStorageType->resolveToScalarType();
    158     CHECK(scalarType != nullptr);
    159 
    160     const std::string storageType = scalarType->getCppStackType();
    161 
    162     out << "enum class "
    163         << localName()
    164         << " : "
    165         << storageType
    166         << " {\n";
    167 
    168     out.indent();
    169 
    170     std::vector<const EnumType *> chain;
    171     getTypeChain(&chain);
    172 
    173     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
    174         const auto &type = *it;
    175 
    176         for (const auto &entry : type->values()) {
    177             out << entry->name();
    178 
    179             std::string value = entry->cppValue(scalarType->getKind());
    180             CHECK(!value.empty()); // use autofilled values for c++.
    181             out << " = " << value;
    182 
    183             out << ",";
    184 
    185             std::string comment = entry->comment();
    186             if (!comment.empty() && comment != value) {
    187                 out << " // " << comment;
    188             }
    189 
    190             out << "\n";
    191         }
    192     }
    193 
    194     out.unindent();
    195     out << "};\n\n";
    196 
    197     return OK;
    198 }
    199 
    200 void EnumType::emitEnumBitwiseOperator(
    201         Formatter &out,
    202         bool lhsIsEnum,
    203         bool rhsIsEnum,
    204         const std::string &op) const {
    205     const ScalarType *scalarType = mStorageType->resolveToScalarType();
    206     CHECK(scalarType != nullptr);
    207 
    208     const std::string storageType = scalarType->getCppStackType();
    209 
    210     out << "constexpr "
    211         << storageType
    212         << " operator"
    213         << op
    214         << "(const "
    215         << (lhsIsEnum ? fullName() : storageType)
    216         << " lhs, const "
    217         << (rhsIsEnum ? fullName() : storageType)
    218         << " rhs) {\n";
    219 
    220     out.indent([&] {
    221         out << "return static_cast<"
    222             << storageType
    223             << ">(";
    224 
    225         if (lhsIsEnum) {
    226             out << "static_cast<"
    227                 << storageType
    228                 << ">(lhs)";
    229         } else {
    230             out << "lhs";
    231         }
    232         out << " " << op << " ";
    233         if (rhsIsEnum) {
    234             out << "static_cast<"
    235                 << storageType
    236                 << ">(rhs)";
    237         } else {
    238             out << "rhs";
    239         }
    240         out << ");\n";
    241     });
    242 
    243     out << "}\n\n";
    244 }
    245 
    246 void EnumType::emitBitFieldBitwiseAssignmentOperator(
    247         Formatter &out,
    248         const std::string &op) const {
    249     const ScalarType *scalarType = mStorageType->resolveToScalarType();
    250     CHECK(scalarType != nullptr);
    251 
    252     const std::string storageType = scalarType->getCppStackType();
    253 
    254     out << "constexpr " << storageType << " &operator" << op << "=("
    255         << storageType << "& v, const " << fullName() << " e) {\n";
    256 
    257     out.indent([&] {
    258         out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
    259         out << "return v;\n";
    260     });
    261 
    262     out << "}\n\n";
    263 }
    264 
    265 status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
    266     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
    267     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
    268     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
    269     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
    270     emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
    271     emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
    272 
    273     emitBitFieldBitwiseAssignmentOperator(out, "|");
    274     emitBitFieldBitwiseAssignmentOperator(out, "&");
    275 
    276     // toString for bitfields, equivalent to dumpBitfield in Java
    277     out << "template<typename>\n"
    278         << "std::string toString("
    279         << resolveToScalarType()->getCppArgumentType()
    280         << " o);\n";
    281     out << "template<>\n"
    282         << "std::string toString<" << getCppStackType() << ">("
    283         << resolveToScalarType()->getCppArgumentType()
    284         << " o);\n\n";
    285 
    286     // toString for enum itself
    287     out << "std::string toString("
    288         << getCppArgumentType()
    289         << " o);\n\n";
    290 
    291     return OK;
    292 }
    293 
    294 status_t EnumType::emitTypeDefinitions(Formatter &out, const std::string /* prefix */) const {
    295 
    296     const ScalarType *scalarType = mStorageType->resolveToScalarType();
    297     CHECK(scalarType != NULL);
    298 
    299     out << "template<>\n"
    300         << "std::string toString<" << getCppStackType() << ">("
    301         << scalarType->getCppArgumentType()
    302         << " o) ";
    303     out.block([&] {
    304         // include toHexString for scalar types
    305         out << "using ::android::hardware::details::toHexString;\n"
    306             << "std::string os;\n"
    307             << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
    308             << "bool first = true;\n";
    309         for (EnumValue *value : values()) {
    310             std::string valueName = fullName() + "::" + value->name();
    311             out.sIf("(o & " + valueName + ")" +
    312                     " == static_cast<" + scalarType->getCppStackType() +
    313                     ">(" + valueName + ")", [&] {
    314                 out << "os += (first ? \"\" : \" | \");\n"
    315                     << "os += \"" << value->name() << "\";\n"
    316                     << "first = false;\n"
    317                     << "flipped |= " << valueName << ";\n";
    318             }).endl();
    319         }
    320         // put remaining bits
    321         out.sIf("o != flipped", [&] {
    322             out << "os += (first ? \"\" : \" | \");\n";
    323             scalarType->emitHexDump(out, "os", "o & (~flipped)");
    324         });
    325         out << "os += \" (\";\n";
    326         scalarType->emitHexDump(out, "os", "o");
    327         out << "os += \")\";\n";
    328 
    329         out << "return os;\n";
    330     }).endl().endl();
    331 
    332     out << "std::string toString("
    333         << getCppArgumentType()
    334         << " o) ";
    335 
    336     out.block([&] {
    337         out << "using ::android::hardware::details::toHexString;\n";
    338         for (EnumValue *value : values()) {
    339             out.sIf("o == " + fullName() + "::" + value->name(), [&] {
    340                 out << "return \"" << value->name() << "\";\n";
    341             }).endl();
    342         }
    343         out << "std::string os;\n";
    344         scalarType->emitHexDump(out, "os",
    345             "static_cast<" + scalarType->getCppStackType() + ">(o)");
    346         out << "return os;\n";
    347     }).endl().endl();
    348 
    349     return OK;
    350 }
    351 
    352 status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
    353     const ScalarType *scalarType = mStorageType->resolveToScalarType();
    354     CHECK(scalarType != NULL);
    355 
    356     out << "public "
    357         << (atTopLevel ? "" : "static ")
    358         << "final class "
    359         << localName()
    360         << " {\n";
    361 
    362     out.indent();
    363 
    364     const std::string typeName =
    365         scalarType->getJavaType(false /* forInitializer */);
    366 
    367     std::vector<const EnumType *> chain;
    368     getTypeChain(&chain);
    369 
    370     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
    371         const auto &type = *it;
    372 
    373         for (const auto &entry : type->values()) {
    374             out << "public static final "
    375                 << typeName
    376                 << " "
    377                 << entry->name()
    378                 << " = ";
    379 
    380             // javaValue will make the number signed.
    381             std::string value = entry->javaValue(scalarType->getKind());
    382             CHECK(!value.empty()); // use autofilled values for java.
    383             out << value;
    384 
    385             out << ";";
    386 
    387             std::string comment = entry->comment();
    388             if (!comment.empty() && comment != value) {
    389                 out << " // " << comment;
    390             }
    391 
    392             out << "\n";
    393         }
    394     }
    395 
    396     out << "public static final String toString("
    397         << typeName << " o) ";
    398     out.block([&] {
    399         for (EnumValue *value : values()) {
    400             out.sIf("o == " + value->name(), [&] {
    401                 out << "return \"" << value->name() << "\";\n";
    402             }).endl();
    403         }
    404         out << "return \"0x\" + ";
    405         scalarType->emitConvertToJavaHexString(out, "o");
    406         out << ";\n";
    407     }).endl();
    408 
    409     auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */);
    410     auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType();
    411     out << "\n"
    412         << "public static final String dumpBitfield("
    413         << bitfieldType << " o) ";
    414     out.block([&] {
    415         out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
    416         out << bitfieldType << " flipped = 0;\n";
    417         for (EnumValue *value : values()) {
    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 
    438 status_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 
    476 status_t EnumType::emitVtsAttributeType(Formatter &out) const {
    477     out << "type: " << getVtsType() << "\n";
    478     out << "predefined_type: \"" << fullName() << "\"\n";
    479     return OK;
    480 }
    481 
    482 void 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 
    490 void 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 
    505 void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
    506     mStorageType->getAlignmentAndSize(align, size);
    507 }
    508 
    509 const 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 
    519 void EnumType::appendToExportedTypesVector(
    520         std::vector<const Type *> *exportedTypes) const {
    521     if (findExportAnnotation() != nullptr) {
    522         exportedTypes->push_back(this);
    523     }
    524 }
    525 
    526 status_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 
    659 EnumValue::EnumValue(const char *name, ConstantExpression *value)
    660     : mName(name),
    661       mValue(value),
    662       mIsAutoFill(false) {
    663 }
    664 
    665 std::string EnumValue::name() const {
    666     return mName;
    667 }
    668 
    669 std::string EnumValue::value(ScalarType::Kind castKind) const {
    670     CHECK(mValue != nullptr);
    671     return mValue->value(castKind);
    672 }
    673 
    674 std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
    675     CHECK(mValue != nullptr);
    676     return mValue->cppValue(castKind);
    677 }
    678 std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
    679     CHECK(mValue != nullptr);
    680     return mValue->javaValue(castKind);
    681 }
    682 
    683 std::string EnumValue::comment() const {
    684     CHECK(mValue != nullptr);
    685     return mValue->description();
    686 }
    687 
    688 ConstantExpression *EnumValue::constExpr() const {
    689     CHECK(mValue != nullptr);
    690     return mValue;
    691 }
    692 
    693 void 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 
    707 bool EnumValue::isAutoFill() const {
    708     return mIsAutoFill;
    709 }
    710 
    711 bool EnumValue::isEnumValue() const {
    712     return true;
    713 }
    714 
    715 ////////////////////////////////////////////////////////////////////////////////
    716 
    717 bool BitFieldType::isBitField() const {
    718     return true;
    719 }
    720 
    721 std::string BitFieldType::typeName() const {
    722     return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
    723 }
    724 
    725 void BitFieldType::addNamedTypesToSet(std::set<const FQName> &) const {
    726 }
    727 
    728 bool BitFieldType::isCompatibleElementType(Type *elementType) const {
    729     return elementType->isEnum();
    730 }
    731 
    732 const ScalarType *BitFieldType::resolveToScalarType() const {
    733     return mElementType->resolveToScalarType();
    734 }
    735 
    736 std::string BitFieldType::getCppType(StorageMode mode,
    737                                  bool specifyNamespaces) const {
    738     return resolveToScalarType()->getCppType(mode, specifyNamespaces);
    739 }
    740 
    741 std::string BitFieldType::getJavaType(bool forInitializer) const {
    742     return resolveToScalarType()->getJavaType(forInitializer);
    743 }
    744 
    745 std::string BitFieldType::getJavaSuffix() const {
    746     return resolveToScalarType()->getJavaSuffix();
    747 }
    748 
    749 std::string BitFieldType::getJavaWrapperType() const {
    750     return resolveToScalarType()->getJavaWrapperType();
    751 }
    752 
    753 std::string BitFieldType::getVtsType() const {
    754     return "TYPE_MASK";
    755 }
    756 
    757 bool BitFieldType::isElidableType() const {
    758     return resolveToScalarType()->isElidableType();
    759 }
    760 
    761 bool BitFieldType::canCheckEquality() const {
    762     return resolveToScalarType()->canCheckEquality();
    763 }
    764 
    765 status_t BitFieldType::emitVtsAttributeType(Formatter &out) const {
    766     out << "type: " << getVtsType() << "\n";
    767     out << "scalar_type: \""
    768         << mElementType->resolveToScalarType()->getVtsScalarType()
    769         << "\"\n";
    770     out << "predefined_type: \""
    771         << static_cast<NamedType *>(mElementType)->fullName() << "\"\n";
    772     return OK;
    773 }
    774 
    775 void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
    776     resolveToScalarType()->getAlignmentAndSize(align, size);
    777 }
    778 
    779 void BitFieldType::emitReaderWriter(
    780         Formatter &out,
    781         const std::string &name,
    782         const std::string &parcelObj,
    783         bool parcelObjIsPointer,
    784         bool isReader,
    785         ErrorMode mode) const {
    786     resolveToScalarType()->emitReaderWriterWithCast(
    787             out,
    788             name,
    789             parcelObj,
    790             parcelObjIsPointer,
    791             isReader,
    792             mode,
    793             true /* needsCast */);
    794 }
    795 
    796 EnumType *BitFieldType::getEnumType() const {
    797     CHECK(mElementType->isEnum());
    798     return static_cast<EnumType *>(mElementType);
    799 }
    800 
    801 // a bitfield maps to the underlying scalar type in C++, so operator<< is
    802 // already defined. We can still emit useful information if the bitfield is
    803 // in a struct / union by overriding emitDump as below.
    804 void BitFieldType::emitDump(
    805         Formatter &out,
    806         const std::string &streamName,
    807         const std::string &name) const {
    808     out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
    809         << "::toString<" << getEnumType()->getCppStackType()
    810         << ">(" << name << ");\n";
    811 }
    812 
    813 void BitFieldType::emitJavaDump(
    814         Formatter &out,
    815         const std::string &streamName,
    816         const std::string &name) const {
    817     out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
    818         << name << "));\n";
    819 }
    820 
    821 void BitFieldType::emitJavaFieldReaderWriter(
    822         Formatter &out,
    823         size_t depth,
    824         const std::string &parcelName,
    825         const std::string &blobName,
    826         const std::string &fieldName,
    827         const std::string &offset,
    828         bool isReader) const {
    829     return resolveToScalarType()->emitJavaFieldReaderWriter(
    830             out, depth, parcelName, blobName, fieldName, offset, isReader);
    831 }
    832 
    833 }  // namespace android
    834 
    835