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 "Interface.h"
     18 
     19 #include "Annotation.h"
     20 #include "ArrayType.h"
     21 #include "ConstantExpression.h"
     22 #include "DeathRecipientType.h"
     23 #include "Method.h"
     24 #include "ScalarType.h"
     25 #include "StringType.h"
     26 #include "VectorType.h"
     27 
     28 #include <unistd.h>
     29 
     30 #include <iostream>
     31 #include <sstream>
     32 
     33 #include <android-base/logging.h>
     34 #include <hidl-hash/Hash.h>
     35 #include <hidl-util/Formatter.h>
     36 #include <hidl-util/StringHelper.h>
     37 
     38 namespace android {
     39 
     40 #define B_PACK_CHARS(c1, c2, c3, c4) \
     41          ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
     42 
     43 /* It is very important that these values NEVER change. These values
     44  * must remain unchanged over the lifetime of android. This is
     45  * because the framework on a device will be updated independently of
     46  * the hals on a device. If the hals are compiled with one set of
     47  * transaction values, and the framework with another, then the
     48  * interface between them will be destroyed, and the device will not
     49  * work.
     50  */
     51 enum {
     52     /////////////////// User defined transactions
     53     FIRST_CALL_TRANSACTION  = 0x00000001,
     54     LAST_CALL_TRANSACTION   = 0x0effffff,
     55     /////////////////// HIDL reserved
     56     FIRST_HIDL_TRANSACTION  = 0x0f000000,
     57     HIDL_PING_TRANSACTION                     = B_PACK_CHARS(0x0f, 'P', 'N', 'G'),
     58     HIDL_DESCRIPTOR_CHAIN_TRANSACTION         = B_PACK_CHARS(0x0f, 'C', 'H', 'N'),
     59     HIDL_GET_DESCRIPTOR_TRANSACTION           = B_PACK_CHARS(0x0f, 'D', 'S', 'C'),
     60     HIDL_SYSPROPS_CHANGED_TRANSACTION         = B_PACK_CHARS(0x0f, 'S', 'Y', 'S'),
     61     HIDL_LINK_TO_DEATH_TRANSACTION            = B_PACK_CHARS(0x0f, 'L', 'T', 'D'),
     62     HIDL_UNLINK_TO_DEATH_TRANSACTION          = B_PACK_CHARS(0x0f, 'U', 'T', 'D'),
     63     HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION  = B_PACK_CHARS(0x0f, 'I', 'N', 'T'),
     64     HIDL_GET_REF_INFO_TRANSACTION             = B_PACK_CHARS(0x0f, 'R', 'E', 'F'),
     65     HIDL_DEBUG_TRANSACTION                    = B_PACK_CHARS(0x0f, 'D', 'B', 'G'),
     66     HIDL_HASH_CHAIN_TRANSACTION               = B_PACK_CHARS(0x0f, 'H', 'S', 'H'),
     67     LAST_HIDL_TRANSACTION   = 0x0fffffff,
     68 };
     69 
     70 Interface::Interface(const char* localName, const Location& location, Scope* parent,
     71                      Interface* super)
     72     : Scope(localName, location, parent), mSuperType(super), mIsJavaCompatibleInProgress(false) {}
     73 
     74 std::string Interface::typeName() const {
     75     return "interface " + localName();
     76 }
     77 
     78 bool Interface::fillPingMethod(Method *method) const {
     79     if (method->name() != "ping") {
     80         return false;
     81     }
     82 
     83     method->fillImplementation(
     84         HIDL_PING_TRANSACTION,
     85         {
     86             {IMPL_INTERFACE,
     87                 [](auto &out) {
     88                     out << "return ::android::hardware::Void();\n";
     89                 }
     90             },
     91             {IMPL_STUB_IMPL,
     92                 [](auto &out) {
     93                     out << "return ::android::hardware::Void();\n";
     94                 }
     95             }
     96         }, /*cppImpl*/
     97         {
     98             {IMPL_INTERFACE,
     99                 [](auto &out) {
    100                     out << "return;\n";
    101                 }
    102             },
    103             {IMPL_STUB, nullptr /* don't generate code */}
    104         } /*javaImpl*/
    105     );
    106 
    107     return true;
    108 }
    109 
    110 bool Interface::fillLinkToDeathMethod(Method *method) const {
    111     if (method->name() != "linkToDeath") {
    112         return false;
    113     }
    114 
    115     method->fillImplementation(
    116             HIDL_LINK_TO_DEATH_TRANSACTION,
    117             {
    118                 {IMPL_INTERFACE,
    119                     [](auto &out) {
    120                         out << "(void)cookie;\n"
    121                             << "return (recipient != nullptr);\n";
    122                     }
    123                 },
    124                 {IMPL_PROXY,
    125                     [](auto &out) {
    126                         out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
    127                         out << "::android::hardware::hidl_binder_death_recipient *binder_recipient"
    128                             << " = new ::android::hardware::hidl_binder_death_recipient(recipient, cookie, this);\n"
    129                             << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
    130                             << "_hidl_mDeathRecipients.push_back(binder_recipient);\n"
    131                             << "return (remote()->linkToDeath(binder_recipient)"
    132                             << " == ::android::OK);\n";
    133                     }
    134                 },
    135                 {IMPL_STUB, nullptr}
    136             }, /*cppImpl*/
    137             {
    138                 {IMPL_INTERFACE,
    139                     [](auto &out) {
    140                         out << "return true;";
    141                     }
    142                 },
    143                 {IMPL_PROXY,
    144                     [](auto &out) {
    145                         out << "return mRemote.linkToDeath(recipient, cookie);\n";
    146                     }
    147                 },
    148                 {IMPL_STUB, nullptr}
    149             } /*javaImpl*/
    150     );
    151     return true;
    152 }
    153 
    154 bool Interface::fillUnlinkToDeathMethod(Method *method) const {
    155     if (method->name() != "unlinkToDeath") {
    156         return false;
    157     }
    158 
    159     method->fillImplementation(
    160             HIDL_UNLINK_TO_DEATH_TRANSACTION,
    161             {
    162                 {IMPL_INTERFACE,
    163                     [](auto &out) {
    164                         out << "return (recipient != nullptr);\n";
    165                     }
    166                 },
    167                 {IMPL_PROXY,
    168                     [](auto &out) {
    169                         out << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
    170                             << "for (auto it = _hidl_mDeathRecipients.begin();"
    171                             << "it != _hidl_mDeathRecipients.end();"
    172                             << "++it) {\n";
    173                         out.indent([&] {
    174                             out.sIf("(*it)->getRecipient() == recipient", [&] {
    175                                 out << "::android::status_t status = remote()->unlinkToDeath(*it);\n"
    176                                     << "_hidl_mDeathRecipients.erase(it);\n"
    177                                     << "return status == ::android::OK;\n";
    178                                 });
    179                             });
    180                         out << "}\n";
    181                         out << "return false;\n";
    182                     }
    183                 },
    184                 {IMPL_STUB, nullptr /* don't generate code */}
    185             }, /*cppImpl*/
    186             {
    187                 {IMPL_INTERFACE,
    188                     [](auto &out) {
    189                         out << "return true;\n";
    190                     }
    191                 },
    192                 {IMPL_PROXY,
    193                     [](auto &out) {
    194                         out << "return mRemote.unlinkToDeath(recipient);\n";
    195                     }
    196                 },
    197                 {IMPL_STUB, nullptr /* don't generate code */}
    198             } /*javaImpl*/
    199     );
    200     return true;
    201 }
    202 bool Interface::fillSyspropsChangedMethod(Method *method) const {
    203     if (method->name() != "notifySyspropsChanged") {
    204         return false;
    205     }
    206 
    207     method->fillImplementation(
    208             HIDL_SYSPROPS_CHANGED_TRANSACTION,
    209             { { IMPL_INTERFACE, [](auto &out) {
    210                 out << "::android::report_sysprop_change();\n";
    211                 out << "return ::android::hardware::Void();";
    212             } } }, /*cppImpl */
    213             { { IMPL_INTERFACE, [](auto &out) { /* javaImpl */
    214                 out << "android.os.SystemProperties.reportSyspropChanged();";
    215             } } } /*javaImpl */
    216     );
    217     return true;
    218 }
    219 
    220 bool Interface::fillSetHALInstrumentationMethod(Method *method) const {
    221     if (method->name() != "setHALInstrumentation") {
    222         return false;
    223     }
    224 
    225     method->fillImplementation(
    226             HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION,
    227             {
    228                 {IMPL_INTERFACE,
    229                     [](auto &out) {
    230                         // do nothing for base class.
    231                         out << "return ::android::hardware::Void();\n";
    232                     }
    233                 },
    234                 {IMPL_STUB,
    235                     [](auto &out) {
    236                         out << "configureInstrumentation();\n";
    237                     }
    238                 },
    239                 {IMPL_PASSTHROUGH,
    240                     [](auto &out) {
    241                         out << "configureInstrumentation();\n";
    242                         out << "return ::android::hardware::Void();\n";
    243                     }
    244                 },
    245             }, /*cppImpl */
    246             { { IMPL_INTERFACE, [](auto & /*out*/) { /* javaImpl */
    247                 // Not support for Java Impl for now.
    248             } } } /*javaImpl */
    249     );
    250     return true;
    251 }
    252 
    253 bool Interface::fillDescriptorChainMethod(Method *method) const {
    254     if (method->name() != "interfaceChain") {
    255         return false;
    256     }
    257 
    258     method->fillImplementation(
    259         HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
    260         { { IMPL_INTERFACE, [this](auto &out) {
    261             std::vector<const Interface *> chain = typeChain();
    262             out << "_hidl_cb(";
    263             out.block([&] {
    264                 for (const Interface *iface : chain) {
    265                     out << iface->fullName() << "::descriptor,\n";
    266                 }
    267             });
    268             out << ");\n";
    269             out << "return ::android::hardware::Void();";
    270         } } }, /* cppImpl */
    271         { { IMPL_INTERFACE, [this](auto &out) {
    272             std::vector<const Interface *> chain = typeChain();
    273             out << "return new java.util.ArrayList<String>(java.util.Arrays.asList(\n";
    274             out.indent(); out.indent();
    275             for (size_t i = 0; i < chain.size(); ++i) {
    276                 if (i != 0)
    277                     out << ",\n";
    278                 out << chain[i]->fullJavaName() << ".kInterfaceName";
    279             }
    280             out << "));";
    281             out.unindent(); out.unindent();
    282         } } } /* javaImpl */
    283     );
    284     return true;
    285 }
    286 
    287 static void emitDigestChain(
    288         Formatter &out,
    289         const std::string &prefix,
    290         const std::vector<const Interface *> &chain,
    291         std::function<std::string(const ConstantExpression &)> byteToString) {
    292     out.join(chain.begin(), chain.end(), ",\n", [&] (const auto &iface) {
    293         const Hash &hash = Hash::getHash(iface->location().begin().filename());
    294         out << prefix;
    295         out << "{";
    296         out.join(hash.raw().begin(), hash.raw().end(), ",", [&](const auto &e) {
    297             // Use ConstantExpression::cppValue / javaValue
    298             // because Java used signed byte for uint8_t.
    299             out << byteToString(ConstantExpression::ValueOf(ScalarType::Kind::KIND_UINT8, e));
    300         });
    301         out << "} /* ";
    302         out << hash.hexString();
    303         out << " */";
    304     });
    305 }
    306 
    307 bool Interface::fillHashChainMethod(Method *method) const {
    308     if (method->name() != "getHashChain") {
    309         return false;
    310     }
    311     const VectorType *chainType = static_cast<const VectorType *>(&method->results()[0]->type());
    312     const ArrayType *digestType = static_cast<const ArrayType *>(chainType->getElementType());
    313 
    314     method->fillImplementation(
    315         HIDL_HASH_CHAIN_TRANSACTION,
    316         { { IMPL_INTERFACE, [this, digestType](auto &out) {
    317             std::vector<const Interface *> chain = typeChain();
    318             out << "_hidl_cb(";
    319             out.block([&] {
    320                 emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")",
    321                     chain, [](const auto &e){return e.cppValue();});
    322             });
    323             out << ");\n";
    324             out << "return ::android::hardware::Void();\n";
    325         } } }, /* cppImpl */
    326         { { IMPL_INTERFACE, [this, digestType, chainType](auto &out) {
    327             std::vector<const Interface *> chain = typeChain();
    328             out << "return new "
    329                 << chainType->getJavaType(false /* forInitializer */)
    330                 << "(java.util.Arrays.asList(\n";
    331             out.indent(2, [&] {
    332                 // No need for dimensions when elements are explicitly provided.
    333                 emitDigestChain(out, "new " + digestType->getJavaType(false /* forInitializer */),
    334                     chain, [](const auto &e){return e.javaValue();});
    335             });
    336             out << "));\n";
    337         } } } /* javaImpl */
    338     );
    339     return true;
    340 }
    341 
    342 bool Interface::fillGetDescriptorMethod(Method *method) const {
    343     if (method->name() != "interfaceDescriptor") {
    344         return false;
    345     }
    346 
    347     method->fillImplementation(
    348         HIDL_GET_DESCRIPTOR_TRANSACTION,
    349         { { IMPL_INTERFACE, [this](auto &out) {
    350             out << "_hidl_cb("
    351                 << fullName()
    352                 << "::descriptor);\n"
    353                 << "return ::android::hardware::Void();";
    354         } } }, /* cppImpl */
    355         { { IMPL_INTERFACE, [this](auto &out) {
    356             out << "return "
    357                 << fullJavaName()
    358                 << ".kInterfaceName;\n";
    359         } } } /* javaImpl */
    360     );
    361     return true;
    362 }
    363 
    364 bool Interface::fillGetDebugInfoMethod(Method *method) const {
    365     if (method->name() != "getDebugInfo") {
    366         return false;
    367     }
    368 
    369     static const std::string sArch =
    370             "#if defined(__LP64__)\n"
    371             "::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT\n"
    372             "#else\n"
    373             "::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT\n"
    374             "#endif\n";
    375 
    376     method->fillImplementation(
    377         HIDL_GET_REF_INFO_TRANSACTION,
    378         {
    379             {IMPL_INTERFACE,
    380                 [](auto &out) {
    381                     // getDebugInfo returns N/A for local objects.
    382                     out << "_hidl_cb({ -1 /* pid */, 0 /* ptr */, \n"
    383                         << sArch
    384                         << "});\n"
    385                         << "return ::android::hardware::Void();";
    386                 }
    387             },
    388             {IMPL_STUB_IMPL,
    389                 [](auto &out) {
    390                     out << "_hidl_cb(";
    391                     out.block([&] {
    392                         out << "::android::hardware::details::debuggable()"
    393                             << "? getpid() : -1 /* pid */,\n"
    394                             << "::android::hardware::details::debuggable()"
    395                             << "? reinterpret_cast<uint64_t>(this) : 0 /* ptr */,\n"
    396                             << sArch << "\n";
    397                     });
    398                     out << ");\n"
    399                         << "return ::android::hardware::Void();";
    400                 }
    401             }
    402         }, /* cppImpl */
    403         { { IMPL_INTERFACE, [method](auto &out) {
    404             const Type &refInfo = method->results().front()->type();
    405             out << refInfo.getJavaType(false /* forInitializer */) << " info = new "
    406                 << refInfo.getJavaType(true /* forInitializer */) << "();\n"
    407                 // TODO(b/34777099): PID for java.
    408                 << "info.pid = -1;\n"
    409                 << "info.ptr = 0;\n"
    410                 << "info.arch = android.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;"
    411                 << "return info;";
    412         } } } /* javaImpl */
    413     );
    414 
    415     return true;
    416 }
    417 
    418 bool Interface::fillDebugMethod(Method *method) const {
    419     if (method->name() != "debug") {
    420         return false;
    421     }
    422 
    423     method->fillImplementation(
    424         HIDL_DEBUG_TRANSACTION,
    425         {
    426             {IMPL_INTERFACE,
    427                 [](auto &out) {
    428                     out << "(void)fd;\n"
    429                         << "(void)options;\n"
    430                         << "return ::android::hardware::Void();";
    431                 }
    432             },
    433         }, /* cppImpl */
    434         {
    435             /* unused, as the debug method is hidden from Java */
    436         } /* javaImpl */
    437     );
    438 
    439     return true;
    440 }
    441 
    442 static std::map<std::string, Method *> gAllReservedMethods;
    443 
    444 bool Interface::addMethod(Method *method) {
    445     if (isIBase()) {
    446         if (!gAllReservedMethods.emplace(method->name(), method).second) {
    447             LOG(ERROR) << "ERROR: hidl-gen encountered duplicated reserved method "
    448                        << method->name();
    449             return false;
    450         }
    451         // will add it in addAllReservedMethods
    452         return true;
    453     }
    454 
    455     CHECK(!method->isHidlReserved());
    456     if (lookupMethod(method->name()) != nullptr) {
    457         LOG(ERROR) << "Redefinition of method " << method->name();
    458         return false;
    459     }
    460     size_t serial = FIRST_CALL_TRANSACTION;
    461 
    462     serial += userDefinedMethods().size();
    463 
    464     const Interface *ancestor = mSuperType;
    465     while (ancestor != nullptr) {
    466         serial += ancestor->userDefinedMethods().size();
    467         ancestor = ancestor->superType();
    468     }
    469 
    470     CHECK(serial <= LAST_CALL_TRANSACTION) << "More than "
    471             << LAST_CALL_TRANSACTION << " methods are not allowed.";
    472     method->setSerialId(serial);
    473     mUserMethods.push_back(method);
    474 
    475     return true;
    476 }
    477 
    478 bool Interface::addAllReservedMethods() {
    479     // use a sorted map to insert them in serial ID order.
    480     std::map<int32_t, Method *> reservedMethodsById;
    481     for (const auto &pair : gAllReservedMethods) {
    482         Method *method = pair.second->copySignature();
    483         bool fillSuccess = fillPingMethod(method)
    484             || fillDescriptorChainMethod(method)
    485             || fillGetDescriptorMethod(method)
    486             || fillHashChainMethod(method)
    487             || fillSyspropsChangedMethod(method)
    488             || fillLinkToDeathMethod(method)
    489             || fillUnlinkToDeathMethod(method)
    490             || fillSetHALInstrumentationMethod(method)
    491             || fillGetDebugInfoMethod(method)
    492             || fillDebugMethod(method);
    493 
    494         if (!fillSuccess) {
    495             LOG(ERROR) << "ERROR: hidl-gen does not recognize a reserved method "
    496                        << method->name();
    497             return false;
    498         }
    499         if (!reservedMethodsById.emplace(method->getSerialId(), method).second) {
    500             LOG(ERROR) << "ERROR: hidl-gen uses duplicated serial id for "
    501                        << method->name() << " and "
    502                        << reservedMethodsById[method->getSerialId()]->name()
    503                        << ", serialId = " << method->getSerialId();
    504             return false;
    505         }
    506     }
    507     for (const auto &pair : reservedMethodsById) {
    508         this->mReservedMethods.push_back(pair.second);
    509     }
    510     return true;
    511 }
    512 
    513 const Interface *Interface::superType() const {
    514     return mSuperType;
    515 }
    516 
    517 std::vector<const Interface *> Interface::typeChain() const {
    518     std::vector<const Interface *> v;
    519     const Interface *iface = this;
    520     while (iface != nullptr) {
    521         v.push_back(iface);
    522         iface = iface->mSuperType;
    523     }
    524     return v;
    525 }
    526 
    527 std::vector<const Interface *> Interface::superTypeChain() const {
    528     return superType()->typeChain(); // should work even if superType is nullptr
    529 }
    530 
    531 bool Interface::isElidableType() const {
    532     return true;
    533 }
    534 
    535 bool Interface::isInterface() const {
    536     return true;
    537 }
    538 
    539 bool Interface::isBinder() const {
    540     return true;
    541 }
    542 
    543 const std::vector<Method *> &Interface::userDefinedMethods() const {
    544     return mUserMethods;
    545 }
    546 
    547 const std::vector<Method *> &Interface::hidlReservedMethods() const {
    548     return mReservedMethods;
    549 }
    550 
    551 std::vector<Method *> Interface::methods() const {
    552     std::vector<Method *> v(mUserMethods);
    553     v.insert(v.end(), mReservedMethods.begin(), mReservedMethods.end());
    554     return v;
    555 }
    556 
    557 std::vector<InterfaceAndMethod> Interface::allMethodsFromRoot() const {
    558     std::vector<InterfaceAndMethod> v;
    559     std::vector<const Interface *> chain = typeChain();
    560     for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
    561         const Interface *iface = *it;
    562         for (Method *userMethod : iface->userDefinedMethods()) {
    563             v.push_back(InterfaceAndMethod(iface, userMethod));
    564         }
    565     }
    566     for (Method *reservedMethod : hidlReservedMethods()) {
    567         v.push_back(InterfaceAndMethod(
    568                 *chain.rbegin(), // IBase
    569                 reservedMethod));
    570     }
    571     return v;
    572 }
    573 
    574 Method *Interface::lookupMethod(std::string name) const {
    575     for (const auto &tuple : allMethodsFromRoot()) {
    576         Method *method = tuple.method();
    577         if (method->name() == name) {
    578             return method;
    579         }
    580     }
    581 
    582     return nullptr;
    583 }
    584 
    585 std::string Interface::getBaseName() const {
    586     return fqName().getInterfaceBaseName();
    587 }
    588 
    589 std::string Interface::getProxyName() const {
    590     return fqName().getInterfaceProxyName();
    591 }
    592 
    593 std::string Interface::getStubName() const {
    594     return fqName().getInterfaceStubName();
    595 }
    596 
    597 std::string Interface::getHwName() const {
    598     return fqName().getInterfaceHwName();
    599 }
    600 
    601 std::string Interface::getPassthroughName() const {
    602     return fqName().getInterfacePassthroughName();
    603 }
    604 
    605 FQName Interface::getProxyFqName() const {
    606     return fqName().getInterfaceProxyFqName();
    607 }
    608 
    609 FQName Interface::getStubFqName() const {
    610     return fqName().getInterfaceStubFqName();
    611 }
    612 
    613 FQName Interface::getPassthroughFqName() const {
    614     return fqName().getInterfacePassthroughFqName();
    615 }
    616 
    617 std::string Interface::getCppType(StorageMode mode,
    618                                   bool specifyNamespaces) const {
    619     const std::string base =
    620           std::string(specifyNamespaces ? "::android::" : "")
    621         + "sp<"
    622         + fullName()
    623         + ">";
    624 
    625     switch (mode) {
    626         case StorageMode_Stack:
    627         case StorageMode_Result:
    628             return base;
    629 
    630         case StorageMode_Argument:
    631             return "const " + base + "&";
    632     }
    633 }
    634 
    635 std::string Interface::getJavaType(bool /* forInitializer */) const {
    636     return fullJavaName();
    637 }
    638 
    639 std::string Interface::getVtsType() const {
    640     if (StringHelper::EndsWith(localName(), "Callback")) {
    641         return "TYPE_HIDL_CALLBACK";
    642     } else {
    643         return "TYPE_HIDL_INTERFACE";
    644     }
    645 }
    646 
    647 void Interface::emitReaderWriter(
    648         Formatter &out,
    649         const std::string &name,
    650         const std::string &parcelObj,
    651         bool parcelObjIsPointer,
    652         bool isReader,
    653         ErrorMode mode) const {
    654     const std::string parcelObjDeref =
    655         parcelObj + (parcelObjIsPointer ? "->" : ".");
    656 
    657     if (isReader) {
    658         out << "{\n";
    659         out.indent();
    660 
    661         const std::string binderName = "_hidl_" + name + "_binder";
    662 
    663         out << "::android::sp<::android::hardware::IBinder> "
    664             << binderName << ";\n";
    665 
    666         out << "_hidl_err = ";
    667         out << parcelObjDeref
    668             << "readNullableStrongBinder(&"
    669             << binderName
    670             << ");\n";
    671 
    672         handleError(out, mode);
    673 
    674         out << name
    675             << " = "
    676             << "::android::hardware::fromBinder<"
    677             << fqName().cppName()
    678             << ","
    679             << getProxyFqName().cppName()
    680             << ","
    681             << getStubFqName().cppName()
    682             << ">("
    683             << binderName
    684             << ");\n";
    685 
    686         out.unindent();
    687         out << "}\n\n";
    688     } else {
    689         out << "if (" << name << " == nullptr) {\n";
    690         out.indent();
    691         out << "_hidl_err = ";
    692         out << parcelObjDeref
    693             << "writeStrongBinder(nullptr);\n";
    694         out.unindent();
    695         out << "} else {\n";
    696         out.indent();
    697         out << "::android::sp<::android::hardware::IBinder> _hidl_binder = "
    698             << "::android::hardware::toBinder<\n";
    699         out.indent(2, [&] {
    700             out << fqName().cppName()
    701                 << ">("
    702                 << name
    703                 << ");\n";
    704         });
    705         out << "if (_hidl_binder.get() != nullptr) {\n";
    706         out.indent([&] {
    707             out << "_hidl_err = "
    708                 << parcelObjDeref
    709                 << "writeStrongBinder(_hidl_binder);\n";
    710         });
    711         out << "} else {\n";
    712         out.indent([&] {
    713             out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
    714         });
    715         out << "}\n";
    716         out.unindent();
    717         out << "}\n";
    718 
    719         handleError(out, mode);
    720     }
    721 }
    722 
    723 status_t Interface::emitGlobalTypeDeclarations(Formatter &out) const {
    724     status_t status = Scope::emitGlobalTypeDeclarations(out);
    725     if (status != OK) {
    726         return status;
    727     }
    728     out << "std::string toString("
    729         << getCppArgumentType()
    730         << ");\n";
    731     return OK;
    732 }
    733 
    734 
    735 status_t Interface::emitTypeDefinitions(
    736         Formatter &out, const std::string prefix) const {
    737     std::string space = prefix.empty() ? "" : (prefix + "::");
    738     status_t err = Scope::emitTypeDefinitions(out, space + localName());
    739     if (err != OK) {
    740         return err;
    741     }
    742 
    743     out << "std::string toString("
    744         << getCppArgumentType()
    745         << " o) ";
    746 
    747     out.block([&] {
    748         out << "std::string os = \"[class or subclass of \";\n"
    749             << "os += " << fullName() << "::descriptor;\n"
    750             << "os += \"]\";\n"
    751             << "os += o->isRemote() ? \"@remote\" : \"@local\";\n"
    752             << "return os;\n";
    753     }).endl().endl();
    754 
    755     return OK;
    756 }
    757 
    758 void Interface::emitJavaReaderWriter(
    759         Formatter &out,
    760         const std::string &parcelObj,
    761         const std::string &argName,
    762         bool isReader) const {
    763     if (isReader) {
    764         out << fullJavaName()
    765             << ".asInterface("
    766             << parcelObj
    767             << ".readStrongBinder());\n";
    768     } else {
    769         out << parcelObj
    770             << ".writeStrongBinder("
    771             << argName
    772             << " == null ? null : "
    773             << argName
    774             << ".asBinder());\n";
    775     }
    776 }
    777 
    778 status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
    779     for (const auto &type : getSubTypes()) {
    780         // Skip for TypeDef as it is just an alias of a defined type.
    781         if (type->isTypeDef()) {
    782             continue;
    783         }
    784         out << "attribute: {\n";
    785         out.indent();
    786         status_t status = type->emitVtsTypeDeclarations(out);
    787         if (status != OK) {
    788             return status;
    789         }
    790         out.unindent();
    791         out << "}\n\n";
    792     }
    793     return OK;
    794 }
    795 
    796 status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
    797     for (const auto &method : methods()) {
    798         if (method->isHidlReserved()) {
    799             continue;
    800         }
    801 
    802         out << "api: {\n";
    803         out.indent();
    804         out << "name: \"" << method->name() << "\"\n";
    805         // Generate declaration for each return value.
    806         for (const auto &result : method->results()) {
    807             out << "return_type_hidl: {\n";
    808             out.indent();
    809             status_t status = result->type().emitVtsAttributeType(out);
    810             if (status != OK) {
    811                 return status;
    812             }
    813             out.unindent();
    814             out << "}\n";
    815         }
    816         // Generate declaration for each input argument
    817         for (const auto &arg : method->args()) {
    818             out << "arg: {\n";
    819             out.indent();
    820             status_t status = arg->type().emitVtsAttributeType(out);
    821             if (status != OK) {
    822                 return status;
    823             }
    824             out.unindent();
    825             out << "}\n";
    826         }
    827         // Generate declaration for each annotation.
    828         for (const auto &annotation : method->annotations()) {
    829             out << "callflow: {\n";
    830             out.indent();
    831             std::string name = annotation->name();
    832             if (name == "entry") {
    833                 out << "entry: true\n";
    834             } else if (name == "exit") {
    835                 out << "exit: true\n";
    836             } else if (name == "callflow") {
    837                 const AnnotationParam *param =
    838                         annotation->getParam("next");
    839                 if (param != nullptr) {
    840                     for (auto value : *param->getValues()) {
    841                         out << "next: " << value << "\n";
    842                     }
    843                 }
    844             } else {
    845                 std::cerr << "Unrecognized annotation '"
    846                           << name << "' for method: " << method->name()
    847                           << ". A VTS annotation should be one of: "
    848                           << "entry, exit, callflow. \n";
    849             }
    850             out.unindent();
    851             out << "}\n";
    852         }
    853         out.unindent();
    854         out << "}\n\n";
    855     }
    856     return OK;
    857 }
    858 
    859 status_t Interface::emitVtsAttributeType(Formatter &out) const {
    860     out << "type: " << getVtsType() << "\n"
    861         << "predefined_type: \""
    862         << fullName()
    863         << "\"\n";
    864     return OK;
    865 }
    866 
    867 bool Interface::hasOnewayMethods() const {
    868     for (auto const &method : methods()) {
    869         if (method->isOneway()) {
    870             return true;
    871         }
    872     }
    873 
    874     const Interface* superClass = superType();
    875 
    876     if (superClass != nullptr) {
    877         return superClass->hasOnewayMethods();
    878     }
    879 
    880     return false;
    881 }
    882 
    883 bool Interface::isJavaCompatible() const {
    884     if (mIsJavaCompatibleInProgress) {
    885         // We're currently trying to determine if this Interface is
    886         // java-compatible and something is referencing this interface through
    887         // one of its methods. Assume we'll ultimately succeed, if we were wrong
    888         // the original invocation of Interface::isJavaCompatible() will then
    889         // return the correct "false" result.
    890         return true;
    891     }
    892 
    893     if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
    894         mIsJavaCompatibleInProgress = false;
    895         return false;
    896     }
    897 
    898     mIsJavaCompatibleInProgress = true;
    899 
    900     if (!Scope::isJavaCompatible()) {
    901         mIsJavaCompatibleInProgress = false;
    902         return false;
    903     }
    904 
    905     for (const auto &method : methods()) {
    906         if (!method->isJavaCompatible()) {
    907             mIsJavaCompatibleInProgress = false;
    908             return false;
    909         }
    910     }
    911 
    912     mIsJavaCompatibleInProgress = false;
    913 
    914     return true;
    915 }
    916 
    917 }  // namespace android
    918 
    919