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));
     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     std::string ifaceName;
    112     if (!AST::isInterface(&ifaceName)) {
    113         return generateJavaTypes(outputPath, limitToType);
    114     }
    115 
    116     const Interface *iface = mRootScope->getInterface();
    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 << "\npublic interface "
    276                 << method->name()
    277                 << "Callback {\n";
    278 
    279             out.indent();
    280 
    281             out << "public void onValues(";
    282             method->emitJavaResultSignature(out);
    283             out << ");\n";
    284 
    285             out.unindent();
    286             out << "}\n\n";
    287         }
    288 
    289         if (returnsValue && !needsCallback) {
    290             out << method->results()[0]->type().getJavaType();
    291         } else {
    292             out << "void";
    293         }
    294 
    295         out << " "
    296             << method->name()
    297             << "(";
    298         method->emitJavaArgSignature(out);
    299 
    300         if (needsCallback) {
    301             if (!method->args().empty()) {
    302                 out << ", ";
    303             }
    304 
    305             out << method->name()
    306                 << "Callback cb";
    307         }
    308 
    309         out << ")\n";
    310         out.indent();
    311         out << "throws android.os.RemoteException;\n";
    312         out.unindent();
    313     }
    314 
    315     out << "\npublic static final class Proxy implements "
    316         << ifaceName
    317         << " {\n";
    318 
    319     out.indent();
    320 
    321     out << "private android.os.IHwBinder mRemote;\n\n";
    322     out << "public Proxy(android.os.IHwBinder remote) {\n";
    323     out.indent();
    324     out << "mRemote = java.util.Objects.requireNonNull(remote);\n";
    325     out.unindent();
    326     out << "}\n\n";
    327 
    328     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
    329     out.indent();
    330     out << "return mRemote;\n";
    331     out.unindent();
    332     out << "}\n\n";
    333 
    334 
    335     out << "@Override\npublic String toString() ";
    336     out.block([&] {
    337         out.sTry([&] {
    338             out << "return this.interfaceDescriptor() + \"@Proxy\";\n";
    339         }).sCatch("android.os.RemoteException ex", [&] {
    340             out << "/* ignored; handled below. */\n";
    341         }).endl();
    342         out << "return \"[class or subclass of \" + "
    343             << ifaceName << ".kInterfaceName + \"]@Proxy\";\n";
    344     }).endl().endl();
    345 
    346     const Interface *prevInterface = nullptr;
    347     for (const auto &tuple : iface->allMethodsFromRoot()) {
    348         const Method *method = tuple.method();
    349 
    350         if (method->isHiddenFromJava()) {
    351             continue;
    352         }
    353 
    354         const Interface *superInterface = tuple.interface();
    355         if (prevInterface != superInterface) {
    356             out << "// Methods from "
    357                 << superInterface->fullName()
    358                 << " follow.\n";
    359             prevInterface = superInterface;
    360         }
    361         const bool returnsValue = !method->results().empty();
    362         const bool needsCallback = method->results().size() > 1;
    363 
    364         out << "@Override\npublic ";
    365         if (returnsValue && !needsCallback) {
    366             out << method->results()[0]->type().getJavaType();
    367         } else {
    368             out << "void";
    369         }
    370 
    371         out << " "
    372             << method->name()
    373             << "(";
    374         method->emitJavaArgSignature(out);
    375 
    376         if (needsCallback) {
    377             if (!method->args().empty()) {
    378                 out << ", ";
    379             }
    380 
    381             out << method->name()
    382                 << "Callback cb";
    383         }
    384 
    385         out << ")\n";
    386         out.indent();
    387         out.indent();
    388         out << "throws android.os.RemoteException {\n";
    389         out.unindent();
    390 
    391         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_PROXY)) {
    392             method->javaImpl(IMPL_PROXY, out);
    393             out.unindent();
    394             out << "}\n";
    395             continue;
    396         }
    397         out << "android.os.HwParcel _hidl_request = new android.os.HwParcel();\n";
    398         out << "_hidl_request.writeInterfaceToken("
    399             << superInterface->fullJavaName()
    400             << ".kInterfaceName);\n";
    401 
    402         for (const auto &arg : method->args()) {
    403             emitJavaReaderWriter(
    404                     out,
    405                     "_hidl_request",
    406                     arg,
    407                     false /* isReader */,
    408                     false /* addPrefixToName */);
    409         }
    410 
    411         out << "\nandroid.os.HwParcel _hidl_reply = new android.os.HwParcel();\n";
    412 
    413         out.sTry([&] {
    414             out << "mRemote.transact("
    415                 << method->getSerialId()
    416                 << " /* "
    417                 << method->name()
    418                 << " */, _hidl_request, _hidl_reply, ";
    419 
    420             if (method->isOneway()) {
    421                 out << "android.os.IHwBinder.FLAG_ONEWAY";
    422             } else {
    423                 out << "0 /* flags */";
    424             }
    425 
    426             out << ");\n";
    427 
    428             if (!method->isOneway()) {
    429                 out << "_hidl_reply.verifySuccess();\n";
    430             } else {
    431                 CHECK(!returnsValue);
    432             }
    433 
    434             out << "_hidl_request.releaseTemporaryStorage();\n";
    435 
    436             if (returnsValue) {
    437                 out << "\n";
    438 
    439                 for (const auto &arg : method->results()) {
    440                     emitJavaReaderWriter(
    441                             out,
    442                             "_hidl_reply",
    443                             arg,
    444                             true /* isReader */,
    445                             true /* addPrefixToName */);
    446                 }
    447 
    448                 if (needsCallback) {
    449                     out << "cb.onValues(";
    450 
    451                     bool firstField = true;
    452                     for (const auto &arg : method->results()) {
    453                         if (!firstField) {
    454                             out << ", ";
    455                         }
    456 
    457                         out << "_hidl_out_" << arg->name();
    458                         firstField = false;
    459                     }
    460 
    461                     out << ");\n";
    462                 } else {
    463                     const std::string returnName = method->results()[0]->name();
    464                     out << "return _hidl_out_" << returnName << ";\n";
    465                 }
    466             }
    467         }).sFinally([&] {
    468             out << "_hidl_reply.release();\n";
    469         }).endl();
    470 
    471         out.unindent();
    472         out << "}\n\n";
    473     }
    474 
    475     out.unindent();
    476     out << "}\n";
    477 
    478     ////////////////////////////////////////////////////////////////////////////
    479 
    480     out << "\npublic static abstract class Stub extends android.os.HwBinder "
    481         << "implements "
    482         << ifaceName << " {\n";
    483 
    484     out.indent();
    485 
    486     out << "@Override\npublic android.os.IHwBinder asBinder() {\n";
    487     out.indent();
    488     out << "return this;\n";
    489     out.unindent();
    490     out << "}\n\n";
    491 
    492     for (Method *method : iface->hidlReservedMethods()) {
    493         if (method->isHiddenFromJava()) {
    494             continue;
    495         }
    496 
    497         // b/32383557 this is a hack. We need to change this if we have more reserved methods.
    498         CHECK_LE(method->results().size(), 1u);
    499         std::string resultType = method->results().size() == 0 ? "void" :
    500                 method->results()[0]->type().getJavaType();
    501         out << "@Override\npublic final "
    502             << resultType
    503             << " "
    504             << method->name()
    505             << "(";
    506         method->emitJavaArgSignature(out);
    507         out << ") {\n";
    508 
    509         out.indent();
    510         method->javaImpl(IMPL_INTERFACE, out);
    511         out.unindent();
    512         out << "\n}\n\n";
    513     }
    514 
    515     out << "@Override\n"
    516         << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n";
    517     out.indent();
    518     // XXX what about potential superClasses?
    519     out << "if (kInterfaceName.equals(descriptor)) {\n";
    520     out.indent();
    521     out << "return this;\n";
    522     out.unindent();
    523     out << "}\n";
    524     out << "return null;\n";
    525     out.unindent();
    526     out << "}\n\n";
    527 
    528     out << "public void registerAsService(String serviceName) throws android.os.RemoteException {\n";
    529     out.indent();
    530 
    531     out << "registerService(serviceName);\n";
    532 
    533     out.unindent();
    534     out << "}\n\n";
    535 
    536     out << "@Override\npublic String toString() ";
    537     out.block([&] {
    538         out << "return this.interfaceDescriptor() + \"@Stub\";\n";
    539     }).endl().endl();
    540 
    541     out << "@Override\n"
    542         << "public void onTransact("
    543         << "int _hidl_code, "
    544         << "android.os.HwParcel _hidl_request, "
    545         << "final android.os.HwParcel _hidl_reply, "
    546         << "int _hidl_flags)\n";
    547     out.indent();
    548     out.indent();
    549     out << "throws android.os.RemoteException {\n";
    550     out.unindent();
    551 
    552     out << "switch (_hidl_code) {\n";
    553 
    554     out.indent();
    555 
    556     for (const auto &tuple : iface->allMethodsFromRoot()) {
    557         const Method *method = tuple.method();
    558 
    559         const Interface *superInterface = tuple.interface();
    560         const bool returnsValue = !method->results().empty();
    561         const bool needsCallback = method->results().size() > 1;
    562 
    563         out << "case "
    564             << method->getSerialId()
    565             << " /* "
    566             << method->name()
    567             << " */:\n{\n";
    568 
    569         out.indent();
    570 
    571         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) {
    572             method->javaImpl(IMPL_STUB, out);
    573             out.unindent();
    574             out << "break;\n";
    575             out << "}\n\n";
    576             continue;
    577         }
    578 
    579         out << "_hidl_request.enforceInterface("
    580             << superInterface->fullJavaName()
    581             << ".kInterfaceName);\n\n";
    582 
    583         if (method->isHiddenFromJava()) {
    584             // This is a method hidden from the Java side of things, it must not
    585             // return any value and will simply signal success.
    586             CHECK(!returnsValue);
    587 
    588             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
    589             out << "_hidl_reply.send();\n";
    590             out << "break;\n";
    591             out.unindent();
    592             out << "}\n\n";
    593             continue;
    594         }
    595 
    596         for (const auto &arg : method->args()) {
    597             emitJavaReaderWriter(
    598                     out,
    599                     "_hidl_request",
    600                     arg,
    601                     true /* isReader */,
    602                     false /* addPrefixToName */);
    603         }
    604 
    605         if (!needsCallback && returnsValue) {
    606             const TypedVar *returnArg = method->results()[0];
    607 
    608             out << returnArg->type().getJavaType()
    609                 << " _hidl_out_"
    610                 << returnArg->name()
    611                 << " = ";
    612         }
    613 
    614         out << method->name()
    615             << "(";
    616 
    617         bool firstField = true;
    618         for (const auto &arg : method->args()) {
    619             if (!firstField) {
    620                 out << ", ";
    621             }
    622 
    623             out << arg->name();
    624 
    625             firstField = false;
    626         }
    627 
    628         if (needsCallback) {
    629             if (!firstField) {
    630                 out << ", ";
    631             }
    632 
    633             out << "new " << method->name() << "Callback() {\n";
    634             out.indent();
    635 
    636             out << "@Override\n"
    637                 << "public void onValues(";
    638             method->emitJavaResultSignature(out);
    639             out << ") {\n";
    640 
    641             out.indent();
    642             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
    643 
    644             for (const auto &arg : method->results()) {
    645                 emitJavaReaderWriter(
    646                         out,
    647                         "_hidl_reply",
    648                         arg,
    649                         false /* isReader */,
    650                         false /* addPrefixToName */);
    651                 // no need to add _hidl_out because out vars are are scoped
    652             }
    653 
    654             out << "_hidl_reply.send();\n"
    655                       << "}}";
    656 
    657             out.unindent();
    658             out.unindent();
    659         }
    660 
    661         out << ");\n";
    662 
    663         if (!needsCallback && !method->isOneway()) {
    664             out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
    665 
    666             if (returnsValue) {
    667                 const TypedVar *returnArg = method->results()[0];
    668 
    669                 emitJavaReaderWriter(
    670                         out,
    671                         "_hidl_reply",
    672                         returnArg,
    673                         false /* isReader */,
    674                         true /* addPrefixToName */);
    675             }
    676 
    677             out << "_hidl_reply.send();\n";
    678         }
    679 
    680         out << "break;\n";
    681         out.unindent();
    682         out << "}\n\n";
    683     }
    684 
    685     out.unindent();
    686     out << "}\n";
    687 
    688     out.unindent();
    689     out << "}\n";
    690 
    691     out.unindent();
    692     out << "}\n";
    693 
    694     out.unindent();
    695     out << "}\n";
    696 
    697     return OK;
    698 }
    699 
    700 status_t AST::emitJavaTypeDeclarations(Formatter &out) const {
    701     return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */);
    702 }
    703 
    704 }  // namespace android
    705