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 "AST.h"
     18 
     19 #include "Coordinator.h"
     20 #include "Interface.h"
     21 #include "Method.h"
     22 #include "Scope.h"
     23 
     24 #include <hidl-util/Formatter.h>
     25 #include <android-base/logging.h>
     26 
     27 namespace android {
     28 
     29 void AST::emitJavaReaderWriter(
     30         Formatter &out,
     31         const std::string &parcelObj,
     32         const TypedVar *arg,
     33         bool isReader,
     34         bool addPrefixToName) const {
     35     if (isReader) {
     36         out << arg->type().getJavaType()
     37             << " "
     38             << (addPrefixToName ? "_hidl_out_" : "")
     39             << arg->name()
     40             << " = ";
     41     }
     42 
     43     arg->type().emitJavaReaderWriter(out, parcelObj,
     44             (addPrefixToName ? "_hidl_out_" : "") + arg->name(),
     45             isReader);
     46 }
     47 
     48 status_t AST::generateJavaTypes(
     49         const std::string &outputPath, const std::string &limitToType) const {
     50     // Splits types.hal up into one java file per declared type.
     51 
     52     for (const auto& type : mRootScope.getSubTypes()) {
     53         std::string typeName = type->localName();
     54 
     55         if (type->isTypeDef()) {
     56             continue;
     57         }
     58 
     59         if (!limitToType.empty() && typeName != limitToType) {
     60             continue;
     61         }
     62 
     63         std::string path = outputPath;
     64         path.append(mCoordinator->convertPackageRootToPath(mPackage));
     65         path.append(mCoordinator->getPackagePath(mPackage, true /* relative */,
     66                 true /* sanitized */));
     67         path.append(typeName);
     68         path.append(".java");
     69 
     70         CHECK(Coordinator::MakeParentHierarchy(path)) << path;
     71         FILE *file = fopen(path.c_str(), "w");
     72 
     73         if (file == NULL) {
     74             return -errno;
     75         }
     76 
     77         Formatter out(file);
     78 
     79         std::vector<std::string> packageComponents;
     80         getPackageAndVersionComponents(
     81                 &packageComponents, true /* cpp_compatible */);
     82 
     83         out << "package " << mPackage.javaPackage() << ";\n\n";
     84 
     85         out << "\n";
     86 
     87         status_t err =
     88             type->emitJavaTypeDeclarations(out, true /* atTopLevel */);
     89 
     90         if (err != OK) {
     91             return err;
     92         }
     93     }
     94 
     95     return OK;
     96 }
     97 
     98 status_t AST::generateJava(
     99         const std::string &outputPath, const std::string &limitToType) const {
    100     if (!isJavaCompatible()) {
    101         fprintf(stderr,
    102                 "ERROR: This interface is not Java compatible. The Java backend"
    103                 " does NOT support union types nor native handles. "
    104                 "In addition, vectors of arrays are limited to at most "
    105                 "one-dimensional arrays and vectors of {vectors,interfaces} are"
    106                 " not supported.\n");
    107 
    108         return UNKNOWN_ERROR;
    109     }
    110 
    111     if (!AST::isInterface()) {
    112         return generateJavaTypes(outputPath, limitToType);
    113     }
    114 
    115     const Interface* iface = mRootScope.getInterface();
    116     std::string ifaceName = iface->localName();
    117 
    118     const std::string baseName = iface->getBaseName();
    119 
    120     std::string path = outputPath;
    121     path.append(mCoordinator->convertPackageRootToPath(mPackage));
    122     path.append(mCoordinator->getPackagePath(mPackage, true /* relative */,
    123             true /* sanitized */));
    124     path.append(ifaceName);
    125     path.append(".java");
    126 
    127     CHECK(Coordinator::MakeParentHierarchy(path));
    128     FILE *file = fopen(path.c_str(), "w");
    129 
    130     if (file == NULL) {
    131         return -errno;
    132     }
    133 
    134     Formatter out(file);
    135 
    136     std::vector<std::string> packageComponents;
    137     getPackageAndVersionComponents(
    138             &packageComponents, true /* cpp_compatible */);
    139 
    140     out << "package " << mPackage.javaPackage() << ";\n\n";
    141 
    142     out.setNamespace(mPackage.javaPackage() + ".");
    143 
    144     const Interface *superType = iface->superType();
    145 
    146     out << "public interface " << ifaceName << " extends ";
    147 
    148     if (superType != NULL) {
    149         out << superType->fullJavaName();
    150     } else {
    151         out << "android.os.IHwInterface";
    152     }
    153 
    154     out << " {\n";
    155     out.indent();
    156 
    157     out << "public static final String kInterfaceName = \""
    158         << mPackage.string()
    159         << "::"
    160         << ifaceName
    161         << "\";\n\n";
    162 
    163     out << "/* package private */ static "
    164         << ifaceName
    165         << " asInterface(android.os.IHwBinder binder) {\n";
    166 
    167     out.indent();
    168 
    169     out << "if (binder == null) {\n";
    170     out.indent();
    171     out << "return null;\n";
    172     out.unindent();
    173     out << "}\n\n";
    174 
    175     out << "android.os.IHwInterface iface =\n";
    176     out.indent();
    177     out.indent();
    178     out << "binder.queryLocalInterface(kInterfaceName);\n\n";
    179     out.unindent();
    180     out.unindent();
    181 
    182     out << "if ((iface != null) && (iface instanceof "
    183         << ifaceName
    184         << ")) {\n";
    185 
    186     out.indent();
    187     out << "return (" << ifaceName << ")iface;\n";
    188     out.unindent();
    189     out << "}\n\n";
    190 
    191     out << ifaceName << " proxy = new " << ifaceName << ".Proxy(binder);\n\n";
    192     out << "try {\n";
    193     out.indent();
    194     out << "for (String descriptor : proxy.interfaceChain()) {\n";
    195     out.indent();
    196     out << "if (descriptor.equals(kInterfaceName)) {\n";
    197     out.indent();
    198     out << "return proxy;\n";
    199     out.unindent();
    200     out << "}\n";
    201     out.unindent();
    202     out << "}\n";
    203     out.unindent();
    204     out << "} catch (android.os.RemoteException e) {\n";
    205     out.indent();
    206     out.unindent();
    207     out << "}\n\n";
    208 
    209     out << "return null;\n";
    210 
    211     out.unindent();
    212     out << "}\n\n";
    213 
    214     out << "public static "
    215         << ifaceName
    216         << " castFrom(android.os.IHwInterface iface) {\n";
    217     out.indent();
    218 
    219     out << "return (iface == null) ? null : "
    220         << ifaceName
    221         << ".asInterface(iface.asBinder());\n";
    222 
    223     out.unindent();
    224     out << "}\n\n";
    225 
    226     out << "@Override\npublic android.os.IHwBinder asBinder();\n\n";
    227 
    228     out << "public static "
    229         << ifaceName
    230         << " getService(String serviceName) throws android.os.RemoteException {\n";
    231 
    232     out.indent();
    233 
    234     out << "return "
    235         << ifaceName
    236         << ".asInterface(android.os.HwBinder.getService(\""
    237         << iface->fqName().string()
    238         << "\",serviceName));\n";
    239 
    240     out.unindent();
    241 
    242     out << "}\n\n";
    243 
    244     out << "public static "
    245         << ifaceName
    246         << " getService() throws android.os.RemoteException {\n";
    247 
    248     out.indent();
    249 
    250     out << "return "
    251         << ifaceName
    252         << ".asInterface(android.os.HwBinder.getService(\""
    253         << iface->fqName().string()
    254         << "\",\"default\"));\n";
    255 
    256     out.unindent();
    257 
    258     out << "}\n\n";
    259 
    260     status_t err = emitJavaTypeDeclarations(out);
    261 
    262     if (err != OK) {
    263         return err;
    264     }
    265 
    266     for (const auto &method : iface->methods()) {
    267         if (method->isHiddenFromJava()) {
    268             continue;
    269         }
    270 
    271         const bool returnsValue = !method->results().empty();
    272         const bool needsCallback = method->results().size() > 1;
    273 
    274         if (needsCallback) {
    275             out << "\n (at) java.lang.FunctionalInterface\npublic interface " << method->name()
    276                 << "Callback {\n";
    277 
    278             out.indent();
    279 
    280             out << "public void onValues(";
    281             method->emitJavaResultSignature(out);
    282             out << ");\n";
    283 
    284             out.unindent();
    285             out << "}\n\n";
    286         }
    287 
    288         if (returnsValue && !needsCallback) {
    289             out << method->results()[0]->type().getJavaType();
    290         } else {
    291             out << "void";
    292         }
    293 
    294         out << " "
    295             << method->name()
    296             << "(";
    297         method->emitJavaArgSignature(out);
    298 
    299         if (needsCallback) {
    300             if (!method->args().empty()) {
    301                 out << ", ";
    302             }
    303 
    304             out << method->name()
    305                 << "Callback _hidl_cb";
    306         }
    307 
    308         out << ")\n";
    309         out.indent();
    310         out << "throws android.os.RemoteException;\n";
    311         out.unindent();
    312     }
    313 
    314     out << "\npublic static final class Proxy implements "
    315         << ifaceName
    316         << " {\n";
    317 
    318     out.indent();
    319 
    320     out << "private android.os.IHwBinder mRemote;\n\n";
    321     out << "public Proxy(android.os.IHwBinder remote) {\n";
    322     out.indent();
    323     out << "mRemote = java.util.Objects.requireNonNull(remote);\n";
    324     out.unindent();
    325     out << "}\n\n";
    326 
    327     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
    328     out.indent();
    329     out << "return mRemote;\n";
    330     out.unindent();
    331     out << "}\n\n";
    332 
    333 
    334     out << "@Override\npublic String toString() ";
    335     out.block([&] {
    336         out.sTry([&] {
    337             out << "return this.interfaceDescriptor() + \"@Proxy\";\n";
    338         }).sCatch("android.os.RemoteException ex", [&] {
    339             out << "/* ignored; handled below. */\n";
    340         }).endl();
    341         out << "return \"[class or subclass of \" + "
    342             << ifaceName << ".kInterfaceName + \"]@Proxy\";\n";
    343     }).endl().endl();
    344 
    345     const Interface *prevInterface = nullptr;
    346     for (const auto &tuple : iface->allMethodsFromRoot()) {
    347         const Method *method = tuple.method();
    348 
    349         if (method->isHiddenFromJava()) {
    350             continue;
    351         }
    352 
    353         const Interface *superInterface = tuple.interface();
    354         if (prevInterface != superInterface) {
    355             out << "// Methods from "
    356                 << superInterface->fullName()
    357                 << " follow.\n";
    358             prevInterface = superInterface;
    359         }
    360         const bool returnsValue = !method->results().empty();
    361         const bool needsCallback = method->results().size() > 1;
    362 
    363         out << "@Override\npublic ";
    364         if (returnsValue && !needsCallback) {
    365             out << method->results()[0]->type().getJavaType();
    366         } else {
    367             out << "void";
    368         }
    369 
    370         out << " "
    371             << method->name()
    372             << "(";
    373         method->emitJavaArgSignature(out);
    374 
    375         if (needsCallback) {
    376             if (!method->args().empty()) {
    377                 out << ", ";
    378             }
    379 
    380             out << method->name()
    381                 << "Callback _hidl_cb";
    382         }
    383 
    384         out << ")\n";
    385         out.indent();
    386         out.indent();
    387         out << "throws android.os.RemoteException {\n";
    388         out.unindent();
    389 
    390         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_PROXY)) {
    391             method->javaImpl(IMPL_PROXY, out);
    392             out.unindent();
    393             out << "}\n";
    394             continue;
    395         }
    396         out << "android.os.HwParcel _hidl_request = new android.os.HwParcel();\n";
    397         out << "_hidl_request.writeInterfaceToken("
    398             << superInterface->fullJavaName()
    399             << ".kInterfaceName);\n";
    400 
    401         for (const auto &arg : method->args()) {
    402             emitJavaReaderWriter(
    403                     out,
    404                     "_hidl_request",
    405                     arg,
    406                     false /* isReader */,
    407                     false /* addPrefixToName */);
    408         }
    409 
    410         out << "\nandroid.os.HwParcel _hidl_reply = new android.os.HwParcel();\n";
    411 
    412         out.sTry([&] {
    413             out << "mRemote.transact("
    414                 << method->getSerialId()
    415                 << " /* "
    416                 << method->name()
    417                 << " */, _hidl_request, _hidl_reply, ";
    418 
    419             if (method->isOneway()) {
    420                 out << "android.os.IHwBinder.FLAG_ONEWAY";
    421             } else {
    422                 out << "0 /* flags */";
    423             }
    424 
    425             out << ");\n";
    426 
    427             if (!method->isOneway()) {
    428                 out << "_hidl_reply.verifySuccess();\n";
    429             } else {
    430                 CHECK(!returnsValue);
    431             }
    432 
    433             out << "_hidl_request.releaseTemporaryStorage();\n";
    434 
    435             if (returnsValue) {
    436                 out << "\n";
    437 
    438                 for (const auto &arg : method->results()) {
    439                     emitJavaReaderWriter(
    440                             out,
    441                             "_hidl_reply",
    442                             arg,
    443                             true /* isReader */,
    444                             true /* addPrefixToName */);
    445                 }
    446 
    447                 if (needsCallback) {
    448                     out << "_hidl_cb.onValues(";
    449 
    450                     bool firstField = true;
    451                     for (const auto &arg : method->results()) {
    452                         if (!firstField) {
    453                             out << ", ";
    454                         }
    455 
    456                         out << "_hidl_out_" << arg->name();
    457                         firstField = false;
    458                     }
    459 
    460                     out << ");\n";
    461                 } else {
    462                     const std::string returnName = method->results()[0]->name();
    463                     out << "return _hidl_out_" << returnName << ";\n";
    464                 }
    465             }
    466         }).sFinally([&] {
    467             out << "_hidl_reply.release();\n";
    468         }).endl();
    469 
    470         out.unindent();
    471         out << "}\n\n";
    472     }
    473 
    474     out.unindent();
    475     out << "}\n";
    476 
    477     ////////////////////////////////////////////////////////////////////////////
    478 
    479     out << "\npublic static abstract class Stub extends android.os.HwBinder "
    480         << "implements "
    481         << ifaceName << " {\n";
    482 
    483     out.indent();
    484 
    485     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
    486     out.indent();
    487     out << "return this;\n";
    488     out.unindent();
    489     out << "}\n\n";
    490 
    491     for (Method *method : iface->hidlReservedMethods()) {
    492         if (method->isHiddenFromJava()) {
    493             continue;
    494         }
    495 
    496         // b/32383557 this is a hack. We need to change this if we have more reserved methods.
    497         CHECK_LE(method->results().size(), 1u);
    498         std::string resultType = method->results().size() == 0 ? "void" :
    499                 method->results()[0]->type().getJavaType();
    500         out << "@Override\npublic final "
    501             << resultType
    502             << " "
    503             << method->name()
    504             << "(";
    505         method->emitJavaArgSignature(out);
    506         out << ") {\n";
    507 
    508         out.indent();
    509         method->javaImpl(IMPL_INTERFACE, out);
    510         out.unindent();
    511         out << "\n}\n\n";
    512     }
    513 
    514     out << "@Override\n"
    515         << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
    516     out.indent();
    517     // XXX what about potential superClasses?
    518     out << "if (kInterfaceName.equals(descriptor)) {\n";
    519     out.indent();
    520     out << "return this;\n";
    521     out.unindent();
    522     out << "}\n";
    523     out << "return null;\n";
    524     out.unindent();
    525     out << "}\n\n";
    526 
    527     out << "public void registerAsService(String serviceName) throws android.os.RemoteException {\n";
    528     out.indent();
    529 
    530     out << "registerService(serviceName);\n";
    531 
    532     out.unindent();
    533     out << "}\n\n";
    534 
    535     out << "@Override\npublic String toString() ";
    536     out.block([&] {
    537         out << "return this.interfaceDescriptor() + \"@Stub\";\n";
    538     }).endl().endl();
    539 
    540     out << "@Override\n"
    541         << "public void onTransact("
    542         << "int _hidl_code, "
    543         << "android.os.HwParcel _hidl_request, "
    544         << "final android.os.HwParcel _hidl_reply, "
    545         << "int _hidl_flags)\n";
    546     out.indent();
    547     out.indent();
    548     out << "throws android.os.RemoteException {\n";
    549     out.unindent();
    550 
    551     out << "switch (_hidl_code) {\n";
    552 
    553     out.indent();
    554 
    555     for (const auto &tuple : iface->allMethodsFromRoot()) {
    556         const Method *method = tuple.method();
    557 
    558         const Interface *superInterface = tuple.interface();
    559         const bool returnsValue = !method->results().empty();
    560         const bool needsCallback = method->results().size() > 1;
    561 
    562         out << "case "
    563             << method->getSerialId()
    564             << " /* "
    565             << method->name()
    566             << " */:\n{\n";
    567 
    568         out.indent();
    569 
    570         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) {
    571             method->javaImpl(IMPL_STUB, out);
    572             out.unindent();
    573             out << "break;\n";
    574             out << "}\n\n";
    575             continue;
    576         }
    577 
    578         out << "_hidl_request.enforceInterface("
    579             << superInterface->fullJavaName()
    580             << ".kInterfaceName);\n\n";
    581 
    582         if (method->isHiddenFromJava()) {
    583             // This is a method hidden from the Java side of things, it must not
    584             // return any value and will simply signal success.
    585             CHECK(!returnsValue);
    586 
    587             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
    588             out << "_hidl_reply.send();\n";
    589             out << "break;\n";
    590             out.unindent();
    591             out << "}\n\n";
    592             continue;
    593         }
    594 
    595         for (const auto &arg : method->args()) {
    596             emitJavaReaderWriter(
    597                     out,
    598                     "_hidl_request",
    599                     arg,
    600                     true /* isReader */,
    601                     false /* addPrefixToName */);
    602         }
    603 
    604         if (!needsCallback && returnsValue) {
    605             const TypedVar *returnArg = method->results()[0];
    606 
    607             out << returnArg->type().getJavaType()
    608                 << " _hidl_out_"
    609                 << returnArg->name()
    610                 << " = ";
    611         }
    612 
    613         out << method->name()
    614             << "(";
    615 
    616         bool firstField = true;
    617         for (const auto &arg : method->args()) {
    618             if (!firstField) {
    619                 out << ", ";
    620             }
    621 
    622             out << arg->name();
    623 
    624             firstField = false;
    625         }
    626 
    627         if (needsCallback) {
    628             if (!firstField) {
    629                 out << ", ";
    630             }
    631 
    632             out << "new " << method->name() << "Callback() {\n";
    633             out.indent();
    634 
    635             out << "@Override\n"
    636                 << "public void onValues(";
    637             method->emitJavaResultSignature(out);
    638             out << ") {\n";
    639 
    640             out.indent();
    641             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
    642 
    643             for (const auto &arg : method->results()) {
    644                 emitJavaReaderWriter(
    645                         out,
    646                         "_hidl_reply",
    647                         arg,
    648                         false /* isReader */,
    649                         false /* addPrefixToName */);
    650                 // no need to add _hidl_out because out vars are are scoped
    651             }
    652 
    653             out << "_hidl_reply.send();\n"
    654                       << "}}";
    655 
    656             out.unindent();
    657             out.unindent();
    658         }
    659 
    660         out << ");\n";
    661 
    662         if (!needsCallback && !method->isOneway()) {
    663             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
    664 
    665             if (returnsValue) {
    666                 const TypedVar *returnArg = method->results()[0];
    667 
    668                 emitJavaReaderWriter(
    669                         out,
    670                         "_hidl_reply",
    671                         returnArg,
    672                         false /* isReader */,
    673                         true /* addPrefixToName */);
    674             }
    675 
    676             out << "_hidl_reply.send();\n";
    677         }
    678 
    679         out << "break;\n";
    680         out.unindent();
    681         out << "}\n\n";
    682     }
    683 
    684     out.unindent();
    685     out << "}\n";
    686 
    687     out.unindent();
    688     out << "}\n";
    689 
    690     out.unindent();
    691     out << "}\n";
    692 
    693     out.unindent();
    694     out << "}\n";
    695 
    696     return OK;
    697 }
    698 
    699 status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
    700     return mRootScope.emitJavaTypeDeclarations(out, false /* atTopLevel */);
    701 }
    702 
    703 }  // namespace android
    704