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