Home | History | Annotate | Download | only in aidl
      1 /*
      2  * Copyright (C) 2015, 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 "generate_cpp.h"
     18 
     19 #include <cctype>
     20 #include <cstring>
     21 #include <memory>
     22 #include <random>
     23 #include <set>
     24 #include <string>
     25 
     26 #include <android-base/stringprintf.h>
     27 
     28 #include "aidl_language.h"
     29 #include "ast_cpp.h"
     30 #include "code_writer.h"
     31 #include "logging.h"
     32 #include "os.h"
     33 
     34 using android::base::StringPrintf;
     35 using std::string;
     36 using std::unique_ptr;
     37 using std::vector;
     38 using std::set;
     39 
     40 namespace android {
     41 namespace aidl {
     42 namespace cpp {
     43 namespace internals {
     44 namespace {
     45 
     46 const char kAndroidStatusVarName[] = "_aidl_ret_status";
     47 const char kCodeVarName[] = "_aidl_code";
     48 const char kFlagsVarName[] = "_aidl_flags";
     49 const char kDataVarName[] = "_aidl_data";
     50 const char kErrorLabel[] = "_aidl_error";
     51 const char kImplVarName[] = "_aidl_impl";
     52 const char kReplyVarName[] = "_aidl_reply";
     53 const char kReturnVarName[] = "_aidl_return";
     54 const char kStatusVarName[] = "_aidl_status";
     55 const char kTraceVarName[] = "_aidl_trace";
     56 const char kAndroidParcelLiteral[] = "::android::Parcel";
     57 const char kAndroidStatusLiteral[] = "::android::status_t";
     58 const char kAndroidStatusOk[] = "::android::OK";
     59 const char kBinderStatusLiteral[] = "::android::binder::Status";
     60 const char kIBinderHeader[] = "binder/IBinder.h";
     61 const char kIInterfaceHeader[] = "binder/IInterface.h";
     62 const char kParcelHeader[] = "binder/Parcel.h";
     63 const char kStatusHeader[] = "binder/Status.h";
     64 const char kString16Header[] = "utils/String16.h";
     65 const char kTraceHeader[] = "utils/Trace.h";
     66 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
     67 
     68 unique_ptr<AstNode> BreakOnStatusNotOk() {
     69   IfStatement* ret = new IfStatement(new Comparison(
     70       new LiteralExpression(kAndroidStatusVarName), "!=",
     71       new LiteralExpression(kAndroidStatusOk)));
     72   ret->OnTrue()->AddLiteral("break");
     73   return unique_ptr<AstNode>(ret);
     74 }
     75 
     76 unique_ptr<AstNode> GotoErrorOnBadStatus() {
     77   IfStatement* ret = new IfStatement(new Comparison(
     78       new LiteralExpression(kAndroidStatusVarName), "!=",
     79       new LiteralExpression(kAndroidStatusOk)));
     80   ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
     81   return unique_ptr<AstNode>(ret);
     82 }
     83 
     84 
     85 unique_ptr<AstNode> ReturnOnStatusNotOk() {
     86   IfStatement* ret = new IfStatement(new Comparison(
     87       new LiteralExpression(kAndroidStatusVarName), "!=",
     88       new LiteralExpression(kAndroidStatusOk)));
     89   ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
     90   return unique_ptr<AstNode>(ret);
     91 }
     92 
     93 string UpperCase(const std::string& s) {
     94   string result = s;
     95   for (char& c : result)
     96     c = toupper(c);
     97   return result;
     98 }
     99 
    100 string BuildVarName(const AidlArgument& a) {
    101   string prefix = "out_";
    102   if (a.GetDirection() & AidlArgument::IN_DIR) {
    103     prefix = "in_";
    104   }
    105   return prefix + a.GetName();
    106 }
    107 
    108 ArgList BuildArgList(const TypeNamespace& types,
    109                      const AidlMethod& method,
    110                      bool for_declaration) {
    111   // Build up the argument list for the server method call.
    112   vector<string> method_arguments;
    113   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
    114     string literal;
    115     if (for_declaration) {
    116       // Method declarations need types, pointers to out params, and variable
    117       // names that match the .aidl specification.
    118       const Type* type = a->GetType().GetLanguageType<Type>();
    119 
    120       literal = type->CppType();
    121 
    122       if (a->IsOut()) {
    123         literal = literal + "*";
    124       } else {
    125         // We pass in parameters that are not primitives by const reference.
    126         // Arrays of primitives are not primitives.
    127         if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
    128           literal = "const " + literal + "&";
    129         }
    130       }
    131 
    132       literal += " " + a->GetName();
    133     } else {
    134       if (a->IsOut()) { literal = "&"; }
    135       literal += BuildVarName(*a);
    136     }
    137     method_arguments.push_back(literal);
    138   }
    139 
    140   const Type* return_type = method.GetType().GetLanguageType<Type>();
    141 
    142   if (return_type != types.VoidType()) {
    143     string literal;
    144     if (for_declaration) {
    145       literal = StringPrintf(
    146           "%s* %s", return_type->CppType().c_str(),
    147           kReturnVarName);
    148     } else {
    149       literal = string{"&"} + kReturnVarName;
    150     }
    151     method_arguments.push_back(literal);
    152   }
    153 
    154   return ArgList(method_arguments);
    155 }
    156 
    157 unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
    158                                         const TypeNamespace& types,
    159                                         bool for_interface) {
    160   uint32_t modifiers = 0;
    161   if (for_interface) {
    162     modifiers |= MethodDecl::IS_VIRTUAL;
    163     modifiers |= MethodDecl::IS_PURE_VIRTUAL;
    164   } else {
    165     modifiers |= MethodDecl::IS_OVERRIDE;
    166   }
    167 
    168   return unique_ptr<Declaration>{
    169       new MethodDecl{kBinderStatusLiteral,
    170                      method.GetName(),
    171                      BuildArgList(types, method, true /* for method decl */),
    172                      modifiers}};
    173 }
    174 
    175 unique_ptr<CppNamespace> NestInNamespaces(
    176     vector<unique_ptr<Declaration>> decls,
    177     const vector<string>& package) {
    178   if (package.empty()) {
    179     // We should also be checking this before we get this far, but do it again
    180     // for the sake of unit tests and meaningful errors.
    181     LOG(FATAL) << "C++ generation requires a package declaration "
    182                   "for namespacing";
    183   }
    184   auto it = package.crbegin();  // Iterate over the namespaces inner to outer
    185   unique_ptr<CppNamespace> inner{new CppNamespace{*it, std::move(decls)}};
    186   ++it;
    187   for (; it != package.crend(); ++it) {
    188     inner.reset(new CppNamespace{*it, std::move(inner)});
    189   }
    190   return inner;
    191 }
    192 
    193 unique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl,
    194                                           const vector<string>& package) {
    195   vector<unique_ptr<Declaration>> decls;
    196   decls.push_back(std::move(decl));
    197   return NestInNamespaces(std::move(decls), package);
    198 }
    199 
    200 bool DeclareLocalVariable(const TypeNamespace& types, const AidlArgument& a,
    201                           StatementBlock* b) {
    202   const Type* cpp_type = a.GetType().GetLanguageType<Type>();
    203   if (!cpp_type) { return false; }
    204 
    205   string type = cpp_type->CppType();
    206 
    207   b->AddLiteral(type + " " + BuildVarName(a));
    208   return true;
    209 }
    210 
    211 string ClassName(const AidlInterface& interface, ClassNames type) {
    212   string c_name = interface.GetName();
    213 
    214   if (c_name.length() >= 2 && c_name[0] == 'I' && isupper(c_name[1]))
    215     c_name = c_name.substr(1);
    216 
    217   switch (type) {
    218     case ClassNames::CLIENT:
    219       c_name = "Bp" + c_name;
    220       break;
    221     case ClassNames::SERVER:
    222       c_name = "Bn" + c_name;
    223       break;
    224     case ClassNames::INTERFACE:
    225       c_name = "I" + c_name;
    226       break;
    227     case ClassNames::BASE:
    228       break;
    229   }
    230   return c_name;
    231 }
    232 
    233 string BuildHeaderGuard(const AidlInterface& interface,
    234                         ClassNames header_type) {
    235   string class_name = ClassName(interface, header_type);
    236   for (size_t i = 1; i < class_name.size(); ++i) {
    237     if (isupper(class_name[i])) {
    238       class_name.insert(i, "_");
    239       ++i;
    240     }
    241   }
    242   string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_",
    243                             interface.GetPackage().c_str(),
    244                             class_name.c_str());
    245   for (char& c : ret) {
    246     if (c == '.') {
    247       c = '_';
    248     }
    249     c = toupper(c);
    250   }
    251   return ret;
    252 }
    253 
    254 unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
    255                                                 const AidlInterface& interface,
    256                                                 const AidlMethod& method) {
    257   const string i_name = ClassName(interface, ClassNames::INTERFACE);
    258   const string bp_name = ClassName(interface, ClassNames::CLIENT);
    259   unique_ptr<MethodImpl> ret{new MethodImpl{
    260       kBinderStatusLiteral, bp_name, method.GetName(),
    261       ArgList{BuildArgList(types, method, true /* for method decl */)}}};
    262   StatementBlock* b = ret->GetStatementBlock();
    263 
    264   // Declare parcels to hold our query and the response.
    265   b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
    266   // Even if we're oneway, the transact method still takes a parcel.
    267   b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
    268 
    269   // Declare the status_t variable we need for error handling.
    270   b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
    271                              kAndroidStatusVarName,
    272                              kAndroidStatusOk));
    273   // We unconditionally return a Status object.
    274   b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
    275 
    276   if (interface.ShouldGenerateTraces()) {
    277     b->AddLiteral(
    278         StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
    279         kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
    280   }
    281 
    282   // Add the name of the interface we're hoping to call.
    283   b->AddStatement(new Assignment(
    284       kAndroidStatusVarName,
    285       new MethodCall(StringPrintf("%s.writeInterfaceToken",
    286                                   kDataVarName),
    287                      "getInterfaceDescriptor()")));
    288   b->AddStatement(GotoErrorOnBadStatus());
    289 
    290   for (const auto& a: method.GetArguments()) {
    291     const Type* type = a->GetType().GetLanguageType<Type>();
    292     string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
    293     var_name = type->WriteCast(var_name);
    294 
    295     if (a->IsIn()) {
    296       // Serialization looks roughly like:
    297       //     _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
    298       //     if (_aidl_ret_status != ::android::OK) { goto error; }
    299       const string& method = type->WriteToParcelMethod();
    300       b->AddStatement(new Assignment(
    301           kAndroidStatusVarName,
    302           new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
    303                          ArgList(var_name))));
    304       b->AddStatement(GotoErrorOnBadStatus());
    305     } else if (a->IsOut() && a->GetType().IsArray()) {
    306       // Special case, the length of the out array is written into the parcel.
    307       //     _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
    308       //     if (_aidl_ret_status != ::android::OK) { goto error; }
    309       b->AddStatement(new Assignment(
    310           kAndroidStatusVarName,
    311           new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
    312                          ArgList(var_name))));
    313       b->AddStatement(GotoErrorOnBadStatus());
    314     }
    315   }
    316 
    317   // Invoke the transaction on the remote binder and confirm status.
    318   string transaction_code = StringPrintf(
    319       "%s::%s", i_name.c_str(), UpperCase(method.GetName()).c_str());
    320 
    321   vector<string> args = {transaction_code, kDataVarName,
    322                          StringPrintf("&%s", kReplyVarName)};
    323 
    324   if (interface.IsOneway() || method.IsOneway()) {
    325     args.push_back("::android::IBinder::FLAG_ONEWAY");
    326   }
    327 
    328   b->AddStatement(new Assignment(
    329       kAndroidStatusVarName,
    330       new MethodCall("remote()->transact",
    331                      ArgList(args))));
    332   b->AddStatement(GotoErrorOnBadStatus());
    333 
    334   if (!interface.IsOneway() && !method.IsOneway()) {
    335     // Strip off the exception header and fail if we see a remote exception.
    336     // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
    337     // if (_aidl_ret_status != ::android::OK) { goto error; }
    338     // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
    339     b->AddStatement(new Assignment(
    340         kAndroidStatusVarName,
    341         StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
    342     b->AddStatement(GotoErrorOnBadStatus());
    343     IfStatement* exception_check = new IfStatement(
    344         new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
    345     b->AddStatement(exception_check);
    346     exception_check->OnTrue()->AddLiteral(
    347         StringPrintf("return %s", kStatusVarName));
    348   }
    349 
    350   // Type checking should guarantee that nothing below emits code until "return
    351   // status" if we are a oneway method, so no more fear of accessing reply.
    352 
    353   // If the method is expected to return something, read it first by convention.
    354   const Type* return_type = method.GetType().GetLanguageType<Type>();
    355   if (return_type != types.VoidType()) {
    356     const string& method_call = return_type->ReadFromParcelMethod();
    357     b->AddStatement(new Assignment(
    358         kAndroidStatusVarName,
    359         new MethodCall(StringPrintf("%s.%s", kReplyVarName,
    360                                     method_call.c_str()),
    361                        ArgList(kReturnVarName))));
    362     b->AddStatement(GotoErrorOnBadStatus());
    363   }
    364 
    365   for (const AidlArgument* a : method.GetOutArguments()) {
    366     // Deserialization looks roughly like:
    367     //     _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
    368     //     if (_aidl_status != ::android::OK) { goto _aidl_error; }
    369     string method =
    370       a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
    371 
    372     b->AddStatement(new Assignment(
    373         kAndroidStatusVarName,
    374         new MethodCall(StringPrintf("%s.%s", kReplyVarName,
    375                                     method.c_str()),
    376                        ArgList(a->GetName()))));
    377     b->AddStatement(GotoErrorOnBadStatus());
    378   }
    379 
    380   // If we've gotten to here, one of two things is true:
    381   //   1) We've read some bad status_t
    382   //   2) We've only read status_t == OK and there was no exception in the
    383   //      response.
    384   // In both cases, we're free to set Status from the status_t and return.
    385   b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
    386   b->AddLiteral(
    387       StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
    388                    kAndroidStatusVarName));
    389 
    390   b->AddLiteral(StringPrintf("return %s", kStatusVarName));
    391 
    392   return unique_ptr<Declaration>(ret.release());
    393 }
    394 
    395 }  // namespace
    396 
    397 unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
    398                                        const AidlInterface& interface) {
    399   vector<string> include_list = {
    400       HeaderFile(interface, ClassNames::CLIENT, false),
    401       kParcelHeader
    402   };
    403   vector<unique_ptr<Declaration>> file_decls;
    404 
    405   // The constructor just passes the IBinder instance up to the super
    406   // class.
    407   const string i_name = ClassName(interface, ClassNames::INTERFACE);
    408   file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
    409       ClassName(interface, ClassNames::CLIENT),
    410       ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
    411                            kImplVarName)},
    412       { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
    413 
    414   // Clients define a method per transaction.
    415   for (const auto& method : interface.GetMethods()) {
    416     unique_ptr<Declaration> m = DefineClientTransaction(
    417         types, interface, *method);
    418     if (!m) { return nullptr; }
    419     file_decls.push_back(std::move(m));
    420   }
    421   return unique_ptr<Document>{new CppSource{
    422       include_list,
    423       NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
    424 }
    425 
    426 namespace {
    427 
    428 bool HandleServerTransaction(const TypeNamespace& types,
    429                              const AidlInterface& interface,
    430                              const AidlMethod& method,
    431                              StatementBlock* b) {
    432   // Declare all the parameters now.  In the common case, we expect no errors
    433   // in serialization.
    434   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
    435     if (!DeclareLocalVariable(types, *a, b)) { return false; }
    436   }
    437 
    438   // Declare a variable to hold the return value.
    439   const Type* return_type = method.GetType().GetLanguageType<Type>();
    440   if (return_type != types.VoidType()) {
    441     b->AddLiteral(StringPrintf(
    442         "%s %s", return_type->CppType().c_str(),
    443         kReturnVarName));
    444   }
    445 
    446   // Check that the client is calling the correct interface.
    447   IfStatement* interface_check = new IfStatement(
    448       new MethodCall(StringPrintf("%s.checkInterface",
    449                                   kDataVarName), "this"),
    450       true /* invert the check */);
    451   b->AddStatement(interface_check);
    452   interface_check->OnTrue()->AddStatement(
    453       new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
    454   interface_check->OnTrue()->AddLiteral("break");
    455 
    456   // Deserialize each "in" parameter to the transaction.
    457   for (const auto& a: method.GetArguments()) {
    458     // Deserialization looks roughly like:
    459     //     _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
    460     //     if (_aidl_ret_status != ::android::OK) { break; }
    461     const Type* type = a->GetType().GetLanguageType<Type>();
    462     const string& readMethod = type->ReadFromParcelMethod();
    463 
    464     if (a->IsIn()) {
    465       b->AddStatement(new Assignment{
    466           kAndroidStatusVarName,
    467           new MethodCall{string(kDataVarName) + "." + readMethod,
    468                          "&" + BuildVarName(*a)}});
    469       b->AddStatement(BreakOnStatusNotOk());
    470     } else if (a->IsOut() && a->GetType().IsArray()) {
    471       // Special case, the length of the out array is written into the parcel.
    472       //     _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
    473       //     if (_aidl_ret_status != ::android::OK) { break; }
    474       b->AddStatement(new Assignment{
    475           kAndroidStatusVarName,
    476           new MethodCall{string(kDataVarName) + ".resizeOutVector",
    477                          "&" + BuildVarName(*a)}});
    478       b->AddStatement(BreakOnStatusNotOk());
    479     }
    480   }
    481 
    482   if (interface.ShouldGenerateTraces()) {
    483     b->AddStatement(new Statement(new MethodCall("atrace_begin",
    484         ArgList{{"ATRACE_TAG_AIDL",
    485         StringPrintf("\"%s::%s::cppServer\"",
    486                      interface.GetName().c_str(),
    487                      method.GetName().c_str())}})));
    488   }
    489 
    490   // Call the actual method.  This is implemented by the subclass.
    491   vector<unique_ptr<AstNode>> status_args;
    492   status_args.emplace_back(new MethodCall(
    493           method.GetName(),
    494           BuildArgList(types, method, false /* not for method decl */)));
    495   b->AddStatement(new Statement(new MethodCall(
    496       StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
    497       ArgList(std::move(status_args)))));
    498 
    499   if (interface.ShouldGenerateTraces()) {
    500     b->AddStatement(new Statement(new MethodCall("atrace_end",
    501                                                  "ATRACE_TAG_AIDL")));
    502   }
    503 
    504   // Write exceptions during transaction handling to parcel.
    505   if (!method.IsOneway()) {
    506     b->AddStatement(new Assignment(
    507         kAndroidStatusVarName,
    508         StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
    509     b->AddStatement(BreakOnStatusNotOk());
    510     IfStatement* exception_check = new IfStatement(
    511         new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
    512     b->AddStatement(exception_check);
    513     exception_check->OnTrue()->AddLiteral("break");
    514   }
    515 
    516   // If we have a return value, write it first.
    517   if (return_type != types.VoidType()) {
    518     string writeMethod =
    519         string(kReplyVarName) + "->" +
    520         return_type->WriteToParcelMethod();
    521     b->AddStatement(new Assignment{
    522         kAndroidStatusVarName, new MethodCall{writeMethod,
    523         ArgList{return_type->WriteCast(kReturnVarName)}}});
    524     b->AddStatement(BreakOnStatusNotOk());
    525   }
    526 
    527   // Write each out parameter to the reply parcel.
    528   for (const AidlArgument* a : method.GetOutArguments()) {
    529     // Serialization looks roughly like:
    530     //     _aidl_ret_status = data.WriteInt32(out_param_name);
    531     //     if (_aidl_ret_status != ::android::OK) { break; }
    532     const Type* type = a->GetType().GetLanguageType<Type>();
    533     const string& writeMethod = type->WriteToParcelMethod();
    534 
    535     b->AddStatement(new Assignment{
    536         kAndroidStatusVarName,
    537         new MethodCall{string(kReplyVarName) + "->" + writeMethod,
    538                        type->WriteCast(BuildVarName(*a))}});
    539     b->AddStatement(BreakOnStatusNotOk());
    540   }
    541 
    542   return true;
    543 }
    544 
    545 }  // namespace
    546 
    547 unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
    548                                        const AidlInterface& interface) {
    549   const string bn_name = ClassName(interface, ClassNames::SERVER);
    550   vector<string> include_list{
    551       HeaderFile(interface, ClassNames::SERVER, false),
    552       kParcelHeader
    553   };
    554   unique_ptr<MethodImpl> on_transact{new MethodImpl{
    555       kAndroidStatusLiteral, bn_name, "onTransact",
    556       ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
    557                StringPrintf("const %s& %s", kAndroidParcelLiteral,
    558                             kDataVarName),
    559                StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
    560                StringPrintf("uint32_t %s", kFlagsVarName)}}
    561       }};
    562 
    563   // Declare the status_t variable
    564   on_transact->GetStatementBlock()->AddLiteral(
    565       StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
    566                    kAndroidStatusOk));
    567 
    568   // Add the all important switch statement, but retain a pointer to it.
    569   SwitchStatement* s = new SwitchStatement{kCodeVarName};
    570   on_transact->GetStatementBlock()->AddStatement(s);
    571 
    572   // The switch statement has a case statement for each transaction code.
    573   for (const auto& method : interface.GetMethods()) {
    574     StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
    575     if (!b) { return nullptr; }
    576 
    577     if (!HandleServerTransaction(types, interface, *method, b)) { return nullptr; }
    578   }
    579 
    580   // The switch statement has a default case which defers to the super class.
    581   // The superclass handles a few pre-defined transactions.
    582   StatementBlock* b = s->AddCase("");
    583   b->AddLiteral(StringPrintf(
    584                 "%s = ::android::BBinder::onTransact(%s, %s, "
    585                 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
    586                 kDataVarName, kReplyVarName, kFlagsVarName));
    587 
    588   // If we saw a null reference, we can map that to an appropriate exception.
    589   IfStatement* null_check = new IfStatement(
    590       new LiteralExpression(string(kAndroidStatusVarName) +
    591                             " == ::android::UNEXPECTED_NULL"));
    592   on_transact->GetStatementBlock()->AddStatement(null_check);
    593   null_check->OnTrue()->AddStatement(new Assignment(
    594       kAndroidStatusVarName,
    595       StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
    596                    ".writeToParcel(%s)",
    597                    kBinderStatusLiteral, kBinderStatusLiteral,
    598                    kReplyVarName)));
    599 
    600   // Finally, the server's onTransact method just returns a status code.
    601   on_transact->GetStatementBlock()->AddLiteral(
    602       StringPrintf("return %s", kAndroidStatusVarName));
    603 
    604   return unique_ptr<Document>{new CppSource{
    605       include_list,
    606       NestInNamespaces(std::move(on_transact), interface.GetSplitPackage())}};
    607 }
    608 
    609 unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& /* types */,
    610                                           const AidlInterface& interface) {
    611   vector<string> include_list{
    612       HeaderFile(interface, ClassNames::INTERFACE, false),
    613       HeaderFile(interface, ClassNames::CLIENT, false),
    614   };
    615 
    616   string fq_name = ClassName(interface, ClassNames::INTERFACE);
    617   if (!interface.GetPackage().empty()) {
    618     fq_name = interface.GetPackage() + "." + fq_name;
    619   }
    620 
    621   vector<unique_ptr<Declaration>> decls;
    622 
    623   unique_ptr<MacroDecl> meta_if{new MacroDecl{
    624       "IMPLEMENT_META_INTERFACE",
    625       ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
    626                              '"' + fq_name + '"'}}}};
    627   decls.push_back(std::move(meta_if));
    628 
    629   for (const auto& constant: interface.GetStringConstants()) {
    630     unique_ptr<MethodImpl> getter(new MethodImpl(
    631         "const ::android::String16&",
    632         ClassName(interface, ClassNames::INTERFACE),
    633         constant->GetName(),
    634         {}));
    635     getter->GetStatementBlock()->AddLiteral(
    636         StringPrintf("static const ::android::String16 value(%s)",
    637                      constant->GetValue().c_str()));
    638     getter->GetStatementBlock()->AddLiteral("return value");
    639     decls.push_back(std::move(getter));
    640   }
    641 
    642   return unique_ptr<Document>{new CppSource{
    643       include_list,
    644       NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
    645 }
    646 
    647 unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
    648                                        const AidlInterface& interface) {
    649   const string i_name = ClassName(interface, ClassNames::INTERFACE);
    650   const string bp_name = ClassName(interface, ClassNames::CLIENT);
    651 
    652   unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
    653       bp_name,
    654       ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
    655                            kImplVarName)},
    656       ConstructorDecl::IS_EXPLICIT
    657   }};
    658   unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
    659       "~" + bp_name,
    660       ArgList{},
    661       ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
    662 
    663   vector<unique_ptr<Declaration>> publics;
    664   publics.push_back(std::move(constructor));
    665   publics.push_back(std::move(destructor));
    666 
    667   for (const auto& method: interface.GetMethods()) {
    668     publics.push_back(BuildMethodDecl(*method, types, false));
    669   }
    670 
    671   unique_ptr<ClassDecl> bp_class{
    672       new ClassDecl{bp_name,
    673                     "::android::BpInterface<" + i_name + ">",
    674                     std::move(publics),
    675                     {}
    676       }};
    677 
    678   return unique_ptr<Document>{new CppHeader{
    679       BuildHeaderGuard(interface, ClassNames::CLIENT),
    680       {kIBinderHeader,
    681        kIInterfaceHeader,
    682        "utils/Errors.h",
    683        HeaderFile(interface, ClassNames::INTERFACE, false)},
    684       NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
    685 }
    686 
    687 unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
    688                                        const AidlInterface& interface) {
    689   const string i_name = ClassName(interface, ClassNames::INTERFACE);
    690   const string bn_name = ClassName(interface, ClassNames::SERVER);
    691 
    692   unique_ptr<Declaration> on_transact{new MethodDecl{
    693       kAndroidStatusLiteral, "onTransact",
    694       ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
    695                StringPrintf("const %s& %s", kAndroidParcelLiteral,
    696                             kDataVarName),
    697                StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
    698                StringPrintf("uint32_t %s = 0", kFlagsVarName)}},
    699       MethodDecl::IS_OVERRIDE
    700   }};
    701 
    702   std::vector<unique_ptr<Declaration>> publics;
    703   publics.push_back(std::move(on_transact));
    704 
    705   unique_ptr<ClassDecl> bn_class{
    706       new ClassDecl{bn_name,
    707                     "::android::BnInterface<" + i_name + ">",
    708                     std::move(publics),
    709                     {}
    710       }};
    711 
    712   return unique_ptr<Document>{new CppHeader{
    713       BuildHeaderGuard(interface, ClassNames::SERVER),
    714       {"binder/IInterface.h",
    715        HeaderFile(interface, ClassNames::INTERFACE, false)},
    716       NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
    717 }
    718 
    719 unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
    720                                           const AidlInterface& interface) {
    721   set<string> includes = { kIBinderHeader, kIInterfaceHeader,
    722                            kStatusHeader, kStrongPointerHeader };
    723 
    724   for (const auto& method : interface.GetMethods()) {
    725     for (const auto& argument : method->GetArguments()) {
    726       const Type* type = argument->GetType().GetLanguageType<Type>();
    727       type->GetHeaders(&includes);
    728     }
    729 
    730     const Type* return_type = method->GetType().GetLanguageType<Type>();
    731     return_type->GetHeaders(&includes);
    732   }
    733 
    734   unique_ptr<ClassDecl> if_class{
    735       new ClassDecl{ClassName(interface, ClassNames::INTERFACE),
    736                     "::android::IInterface"}};
    737   if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
    738       "DECLARE_META_INTERFACE",
    739       ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
    740 
    741   unique_ptr<Enum> constant_enum{new Enum{"", "int32_t"}};
    742   for (const auto& constant : interface.GetIntConstants()) {
    743     constant_enum->AddValue(
    744         constant->GetName(), std::to_string(constant->GetValue()));
    745   }
    746   if (constant_enum->HasValues()) {
    747     if_class->AddPublic(std::move(constant_enum));
    748   }
    749 
    750   if (!interface.GetStringConstants().empty()) {
    751     includes.insert(kString16Header);
    752   }
    753 
    754   if (interface.ShouldGenerateTraces()) {
    755     includes.insert(kTraceHeader);
    756   }
    757 
    758   for (const auto& constant : interface.GetStringConstants()) {
    759     unique_ptr<MethodDecl> getter(new MethodDecl(
    760           "const ::android::String16&", constant->GetName(),
    761           {}, MethodDecl::IS_STATIC));
    762     if_class->AddPublic(std::move(getter));
    763   }
    764 
    765   if (!interface.GetMethods().empty()) {
    766     unique_ptr<Enum> call_enum{new Enum{"Call"}};
    767     for (const auto& method : interface.GetMethods()) {
    768       // Each method gets an enum entry and pure virtual declaration.
    769       if_class->AddPublic(BuildMethodDecl(*method, types, true));
    770       call_enum->AddValue(
    771           UpperCase(method->GetName()),
    772           StringPrintf("::android::IBinder::FIRST_CALL_TRANSACTION + %d",
    773                        method->GetId()));
    774     }
    775     if_class->AddPublic(std::move(call_enum));
    776   }
    777 
    778   return unique_ptr<Document>{new CppHeader{
    779       BuildHeaderGuard(interface, ClassNames::INTERFACE),
    780       vector<string>(includes.begin(), includes.end()),
    781       NestInNamespaces(std::move(if_class), interface.GetSplitPackage())}};
    782 }
    783 
    784 bool WriteHeader(const CppOptions& options,
    785                  const TypeNamespace& types,
    786                  const AidlInterface& interface,
    787                  const IoDelegate& io_delegate,
    788                  ClassNames header_type) {
    789   unique_ptr<Document> header;
    790   switch (header_type) {
    791     case ClassNames::INTERFACE:
    792       header = BuildInterfaceHeader(types, interface);
    793       break;
    794     case ClassNames::CLIENT:
    795       header = BuildClientHeader(types, interface);
    796       break;
    797     case ClassNames::SERVER:
    798       header = BuildServerHeader(types, interface);
    799       break;
    800     default:
    801       LOG(FATAL) << "aidl internal error";
    802   }
    803   if (!header) {
    804     LOG(ERROR) << "aidl internal error: Failed to generate header.";
    805     return false;
    806   }
    807 
    808   const string header_path = options.OutputHeaderDir() + OS_PATH_SEPARATOR +
    809                              HeaderFile(interface, header_type);
    810   unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
    811   header->Write(code_writer.get());
    812 
    813   const bool success = code_writer->Close();
    814   if (!success) {
    815     io_delegate.RemovePath(header_path);
    816   }
    817 
    818   return success;
    819 }
    820 
    821 }  // namespace internals
    822 
    823 using namespace internals;
    824 
    825 string HeaderFile(const AidlInterface& interface,
    826                   ClassNames class_type,
    827                   bool use_os_sep) {
    828   string file_path = interface.GetPackage();
    829   for (char& c: file_path) {
    830     if (c == '.') {
    831       c = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
    832     }
    833   }
    834   if (!file_path.empty()) {
    835     file_path += (use_os_sep) ? OS_PATH_SEPARATOR : '/';
    836   }
    837   file_path += ClassName(interface, class_type);
    838   file_path += ".h";
    839 
    840   return file_path;
    841 }
    842 
    843 bool GenerateCpp(const CppOptions& options,
    844                  const TypeNamespace& types,
    845                  const AidlInterface& interface,
    846                  const IoDelegate& io_delegate) {
    847   auto interface_src = BuildInterfaceSource(types, interface);
    848   auto client_src = BuildClientSource(types, interface);
    849   auto server_src = BuildServerSource(types, interface);
    850 
    851   if (!interface_src || !client_src || !server_src) {
    852     return false;
    853   }
    854 
    855   if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(),
    856                                      interface.GetSplitPackage())) {
    857     LOG(ERROR) << "Failed to create directory structure for headers.";
    858     return false;
    859   }
    860 
    861   if (!WriteHeader(options, types, interface, io_delegate,
    862                    ClassNames::INTERFACE) ||
    863       !WriteHeader(options, types, interface, io_delegate,
    864                    ClassNames::CLIENT) ||
    865       !WriteHeader(options, types, interface, io_delegate,
    866                    ClassNames::SERVER)) {
    867     return false;
    868   }
    869 
    870   unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(
    871       options.OutputCppFilePath());
    872   interface_src->Write(writer.get());
    873   client_src->Write(writer.get());
    874   server_src->Write(writer.get());
    875 
    876   const bool success = writer->Close();
    877   if (!success) {
    878     io_delegate.RemovePath(options.OutputCppFilePath());
    879   }
    880 
    881   return success;
    882 }
    883 
    884 }  // namespace cpp
    885 }  // namespace aidl
    886 }  // namespace android
    887