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 "generate_java.h" 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include <algorithm> 24 #include <unordered_set> 25 26 #include <android-base/macros.h> 27 #include <android-base/stringprintf.h> 28 29 #include "options.h" 30 #include "type_java.h" 31 32 using std::string; 33 34 using android::base::StringPrintf; 35 36 namespace android { 37 namespace aidl { 38 namespace java { 39 40 // ================================================= 41 class StubClass : public Class { 42 public: 43 StubClass(const Type* type, const InterfaceType* interfaceType, 44 JavaTypeNamespace* types); 45 virtual ~StubClass() = default; 46 47 Variable* transact_code; 48 Variable* transact_data; 49 Variable* transact_reply; 50 Variable* transact_flags; 51 SwitchStatement* transact_switch; 52 StatementBlock* transact_statements; 53 54 // Where onTransact cases should be generated as separate methods. 55 bool transact_outline; 56 // Specific methods that should be outlined when transact_outline is true. 57 std::unordered_set<const AidlMethod*> outline_methods; 58 // Number of all methods. 59 size_t all_method_count; 60 61 // Finish generation. This will add a default case to the switch. 62 void finish(); 63 64 Expression* get_transact_descriptor(const JavaTypeNamespace* types, 65 const AidlMethod* method); 66 67 private: 68 void make_as_interface(const InterfaceType* interfaceType, 69 JavaTypeNamespace* types); 70 71 Variable* transact_descriptor; 72 73 DISALLOW_COPY_AND_ASSIGN(StubClass); 74 }; 75 76 StubClass::StubClass(const Type* type, const InterfaceType* interfaceType, 77 JavaTypeNamespace* types) 78 : Class() { 79 transact_descriptor = nullptr; 80 transact_outline = false; 81 all_method_count = 0; // Will be set when outlining may be enabled. 82 83 this->comment = "/** Local-side IPC implementation stub class. */"; 84 this->modifiers = PUBLIC | ABSTRACT | STATIC; 85 this->what = Class::CLASS; 86 this->type = type; 87 this->extends = types->BinderNativeType(); 88 this->interfaces.push_back(interfaceType); 89 90 // descriptor 91 Field* descriptor = 92 new Field(STATIC | FINAL | PRIVATE, 93 new Variable(types->StringType(), "DESCRIPTOR")); 94 descriptor->value = "\"" + interfaceType->JavaType() + "\""; 95 this->elements.push_back(descriptor); 96 97 // ctor 98 Method* ctor = new Method; 99 ctor->modifiers = PUBLIC; 100 ctor->comment = 101 "/** Construct the stub at attach it to the " 102 "interface. */"; 103 ctor->name = "Stub"; 104 ctor->statements = new StatementBlock; 105 MethodCall* attach = 106 new MethodCall(THIS_VALUE, "attachInterface", 2, THIS_VALUE, 107 new LiteralExpression("DESCRIPTOR")); 108 ctor->statements->Add(attach); 109 this->elements.push_back(ctor); 110 111 // asInterface 112 make_as_interface(interfaceType, types); 113 114 // asBinder 115 Method* asBinder = new Method; 116 asBinder->modifiers = PUBLIC | OVERRIDE; 117 asBinder->returnType = types->IBinderType(); 118 asBinder->name = "asBinder"; 119 asBinder->statements = new StatementBlock; 120 asBinder->statements->Add(new ReturnStatement(THIS_VALUE)); 121 this->elements.push_back(asBinder); 122 123 // onTransact 124 this->transact_code = new Variable(types->IntType(), "code"); 125 this->transact_data = new Variable(types->ParcelType(), "data"); 126 this->transact_reply = new Variable(types->ParcelType(), "reply"); 127 this->transact_flags = new Variable(types->IntType(), "flags"); 128 Method* onTransact = new Method; 129 onTransact->modifiers = PUBLIC | OVERRIDE; 130 onTransact->returnType = types->BoolType(); 131 onTransact->name = "onTransact"; 132 onTransact->parameters.push_back(this->transact_code); 133 onTransact->parameters.push_back(this->transact_data); 134 onTransact->parameters.push_back(this->transact_reply); 135 onTransact->parameters.push_back(this->transact_flags); 136 onTransact->statements = new StatementBlock; 137 transact_statements = onTransact->statements; 138 onTransact->exceptions.push_back(types->RemoteExceptionType()); 139 this->elements.push_back(onTransact); 140 this->transact_switch = new SwitchStatement(this->transact_code); 141 } 142 143 void StubClass::finish() { 144 Case* default_case = new Case; 145 146 MethodCall* superCall = new MethodCall( 147 SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data, 148 this->transact_reply, this->transact_flags); 149 default_case->statements->Add(new ReturnStatement(superCall)); 150 transact_switch->cases.push_back(default_case); 151 152 transact_statements->Add(this->transact_switch); 153 } 154 155 // The the expression for the interface's descriptor to be used when 156 // generating code for the given method. Null is acceptable for method 157 // and stands for synthetic cases. 158 Expression* StubClass::get_transact_descriptor(const JavaTypeNamespace* types, 159 const AidlMethod* method) { 160 if (transact_outline) { 161 if (method != nullptr) { 162 // When outlining, each outlined method needs its own literal. 163 if (outline_methods.count(method) != 0) { 164 return new LiteralExpression("DESCRIPTOR"); 165 } 166 } else { 167 // Synthetic case. A small number is assumed. Use its own descriptor 168 // if there are only synthetic cases. 169 if (outline_methods.size() == all_method_count) { 170 return new LiteralExpression("DESCRIPTOR"); 171 } 172 } 173 } 174 175 // When not outlining, store the descriptor literal into a local variable, in 176 // an effort to save const-string instructions in each switch case. 177 if (transact_descriptor == nullptr) { 178 transact_descriptor = new Variable(types->StringType(), "descriptor"); 179 transact_statements->Add( 180 new VariableDeclaration(transact_descriptor, 181 new LiteralExpression("DESCRIPTOR"))); 182 } 183 return transact_descriptor; 184 } 185 186 void StubClass::make_as_interface(const InterfaceType* interfaceType, 187 JavaTypeNamespace* types) { 188 Variable* obj = new Variable(types->IBinderType(), "obj"); 189 190 Method* m = new Method; 191 m->comment = "/**\n * Cast an IBinder object into an "; 192 m->comment += interfaceType->JavaType(); 193 m->comment += " interface,\n"; 194 m->comment += " * generating a proxy if needed.\n */"; 195 m->modifiers = PUBLIC | STATIC; 196 m->returnType = interfaceType; 197 m->name = "asInterface"; 198 m->parameters.push_back(obj); 199 m->statements = new StatementBlock; 200 201 IfStatement* ifstatement = new IfStatement(); 202 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE); 203 ifstatement->statements = new StatementBlock; 204 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE)); 205 m->statements->Add(ifstatement); 206 207 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR) 208 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface"); 209 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR")); 210 IInterfaceType* iinType = new IInterfaceType(types); 211 Variable* iin = new Variable(iinType, "iin"); 212 VariableDeclaration* iinVd = 213 new VariableDeclaration(iin, queryLocalInterface, NULL); 214 m->statements->Add(iinVd); 215 216 // Ensure the instance type of the local object is as expected. 217 // One scenario where this is needed is if another package (with a 218 // different class loader) runs in the same process as the service. 219 220 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) 221 // iin; 222 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE); 223 Comparison* instOfCheck = 224 new Comparison(iin, " instanceof ", 225 new LiteralExpression(interfaceType->JavaType())); 226 IfStatement* instOfStatement = new IfStatement(); 227 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck); 228 instOfStatement->statements = new StatementBlock; 229 instOfStatement->statements->Add( 230 new ReturnStatement(new Cast(interfaceType, iin))); 231 m->statements->Add(instOfStatement); 232 233 NewExpression* ne = new NewExpression(interfaceType->GetProxy()); 234 ne->arguments.push_back(obj); 235 m->statements->Add(new ReturnStatement(ne)); 236 237 this->elements.push_back(m); 238 } 239 240 // ================================================= 241 class ProxyClass : public Class { 242 public: 243 ProxyClass(const JavaTypeNamespace* types, const Type* type, 244 const InterfaceType* interfaceType); 245 virtual ~ProxyClass(); 246 247 Variable* mRemote; 248 bool mOneWay; 249 }; 250 251 ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type, 252 const InterfaceType* interfaceType) 253 : Class() { 254 this->modifiers = PRIVATE | STATIC; 255 this->what = Class::CLASS; 256 this->type = type; 257 this->interfaces.push_back(interfaceType); 258 259 mOneWay = interfaceType->OneWay(); 260 261 // IBinder mRemote 262 mRemote = new Variable(types->IBinderType(), "mRemote"); 263 this->elements.push_back(new Field(PRIVATE, mRemote)); 264 265 // Proxy() 266 Variable* remote = new Variable(types->IBinderType(), "remote"); 267 Method* ctor = new Method; 268 ctor->name = "Proxy"; 269 ctor->statements = new StatementBlock; 270 ctor->parameters.push_back(remote); 271 ctor->statements->Add(new Assignment(mRemote, remote)); 272 this->elements.push_back(ctor); 273 274 // IBinder asBinder() 275 Method* asBinder = new Method; 276 asBinder->modifiers = PUBLIC | OVERRIDE; 277 asBinder->returnType = types->IBinderType(); 278 asBinder->name = "asBinder"; 279 asBinder->statements = new StatementBlock; 280 asBinder->statements->Add(new ReturnStatement(mRemote)); 281 this->elements.push_back(asBinder); 282 } 283 284 ProxyClass::~ProxyClass() {} 285 286 // ================================================= 287 static void generate_new_array(const Type* t, StatementBlock* addTo, 288 Variable* v, Variable* parcel, 289 JavaTypeNamespace* types) { 290 Variable* len = new Variable(types->IntType(), v->name + "_length"); 291 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt"))); 292 IfStatement* lencheck = new IfStatement(); 293 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0")); 294 lencheck->statements->Add(new Assignment(v, NULL_VALUE)); 295 lencheck->elseif = new IfStatement(); 296 lencheck->elseif->statements->Add( 297 new Assignment(v, new NewArrayExpression(t, len))); 298 addTo->Add(lencheck); 299 } 300 301 static void generate_write_to_parcel(const Type* t, StatementBlock* addTo, 302 Variable* v, Variable* parcel, int flags) { 303 t->WriteToParcel(addTo, v, parcel, flags); 304 } 305 306 static void generate_create_from_parcel(const Type* t, StatementBlock* addTo, 307 Variable* v, Variable* parcel, 308 Variable** cl) { 309 t->CreateFromParcel(addTo, v, parcel, cl); 310 } 311 312 static void generate_int_constant(const AidlIntConstant& constant, 313 Class* interface) { 314 IntConstant* decl = new IntConstant(constant.GetName(), constant.GetValue()); 315 interface->elements.push_back(decl); 316 } 317 318 static void generate_string_constant(const AidlStringConstant& constant, 319 Class* interface) { 320 StringConstant* decl = new StringConstant(constant.GetName(), 321 constant.GetValue()); 322 interface->elements.push_back(decl); 323 } 324 325 static std::unique_ptr<Method> generate_interface_method( 326 const AidlMethod& method, JavaTypeNamespace* types) { 327 std::unique_ptr<Method> decl(new Method); 328 decl->comment = method.GetComments(); 329 decl->modifiers = PUBLIC; 330 decl->returnType = method.GetType().GetLanguageType<Type>(); 331 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; 332 decl->name = method.GetName(); 333 334 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 335 decl->parameters.push_back( 336 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(), 337 arg->GetType().IsArray() ? 1 : 0)); 338 } 339 340 decl->exceptions.push_back(types->RemoteExceptionType()); 341 342 return decl; 343 } 344 345 static void generate_stub_code(const AidlInterface& iface, 346 const AidlMethod& method, 347 const std::string& transactCodeName, 348 bool oneway, 349 Variable* transact_data, 350 Variable* transact_reply, 351 JavaTypeNamespace* types, 352 StatementBlock* statements, 353 StubClass* stubClass) { 354 TryStatement* tryStatement = nullptr; 355 FinallyStatement* finallyStatement = nullptr; 356 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName()); 357 358 // interface token validation is the very first thing we do 359 statements->Add(new MethodCall(transact_data, 360 "enforceInterface", 1, 361 stubClass->get_transact_descriptor(types, 362 &method))); 363 364 // args 365 VariableFactory stubArgs("_arg"); 366 { 367 Variable* cl = NULL; 368 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 369 const Type* t = arg->GetType().GetLanguageType<Type>(); 370 Variable* v = stubArgs.Get(t); 371 v->dimension = arg->GetType().IsArray() ? 1 : 0; 372 373 statements->Add(new VariableDeclaration(v)); 374 375 if (arg->GetDirection() & AidlArgument::IN_DIR) { 376 generate_create_from_parcel(t, 377 statements, 378 v, 379 transact_data, 380 &cl); 381 } else { 382 if (!arg->GetType().IsArray()) { 383 statements->Add(new Assignment(v, new NewExpression(v->type))); 384 } else { 385 generate_new_array(v->type, 386 statements, 387 v, 388 transact_data, 389 types); 390 } 391 } 392 393 realCall->arguments.push_back(v); 394 } 395 } 396 397 if (iface.ShouldGenerateTraces()) { 398 // try and finally, but only when generating trace code 399 tryStatement = new TryStatement(); 400 finallyStatement = new FinallyStatement(); 401 402 tryStatement->statements->Add(new MethodCall( 403 new LiteralExpression("android.os.Trace"), "traceBegin", 2, 404 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"), 405 new StringLiteralExpression(iface.GetName() + "::" 406 + method.GetName() + "::server"))); 407 408 finallyStatement->statements->Add(new MethodCall( 409 new LiteralExpression("android.os.Trace"), "traceEnd", 1, 410 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"))); 411 } 412 413 // the real call 414 if (method.GetType().GetName() == "void") { 415 if (iface.ShouldGenerateTraces()) { 416 statements->Add(tryStatement); 417 tryStatement->statements->Add(realCall); 418 statements->Add(finallyStatement); 419 } else { 420 statements->Add(realCall); 421 } 422 423 if (!oneway) { 424 // report that there were no exceptions 425 MethodCall* ex = 426 new MethodCall(transact_reply, "writeNoException", 0); 427 statements->Add(ex); 428 } 429 } else { 430 Variable* _result = 431 new Variable(method.GetType().GetLanguageType<Type>(), 432 "_result", 433 method.GetType().IsArray() ? 1 : 0); 434 if (iface.ShouldGenerateTraces()) { 435 statements->Add(new VariableDeclaration(_result)); 436 statements->Add(tryStatement); 437 tryStatement->statements->Add(new Assignment(_result, realCall)); 438 statements->Add(finallyStatement); 439 } else { 440 statements->Add(new VariableDeclaration(_result, realCall)); 441 } 442 443 if (!oneway) { 444 // report that there were no exceptions 445 MethodCall* ex = 446 new MethodCall(transact_reply, "writeNoException", 0); 447 statements->Add(ex); 448 } 449 450 // marshall the return value 451 generate_write_to_parcel(method.GetType().GetLanguageType<Type>(), 452 statements, 453 _result, 454 transact_reply, 455 Type::PARCELABLE_WRITE_RETURN_VALUE); 456 } 457 458 // out parameters 459 int i = 0; 460 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 461 const Type* t = arg->GetType().GetLanguageType<Type>(); 462 Variable* v = stubArgs.Get(i++); 463 464 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 465 generate_write_to_parcel(t, 466 statements, 467 v, 468 transact_reply, 469 Type::PARCELABLE_WRITE_RETURN_VALUE); 470 } 471 } 472 473 // return true 474 statements->Add(new ReturnStatement(TRUE_VALUE)); 475 } 476 477 478 static void generate_stub_case(const AidlInterface& iface, 479 const AidlMethod& method, 480 const std::string& transactCodeName, 481 bool oneway, 482 StubClass* stubClass, 483 JavaTypeNamespace* types) { 484 Case* c = new Case(transactCodeName); 485 486 generate_stub_code(iface, 487 method, 488 transactCodeName, 489 oneway, 490 stubClass->transact_data, 491 stubClass->transact_reply, 492 types, 493 c->statements, 494 stubClass); 495 496 stubClass->transact_switch->cases.push_back(c); 497 } 498 499 static void generate_stub_case_outline(const AidlInterface& iface, 500 const AidlMethod& method, 501 const std::string& transactCodeName, 502 bool oneway, 503 StubClass* stubClass, 504 JavaTypeNamespace* types) { 505 std::string outline_name = "onTransact$" + method.GetName() + "$"; 506 // Generate an "outlined" method with the actual code. 507 { 508 Variable* transact_data = new Variable(types->ParcelType(), "data"); 509 Variable* transact_reply = new Variable(types->ParcelType(), "reply"); 510 Method* onTransact_case = new Method; 511 onTransact_case->modifiers = PRIVATE; 512 onTransact_case->returnType = types->BoolType(); 513 onTransact_case->name = outline_name; 514 onTransact_case->parameters.push_back(transact_data); 515 onTransact_case->parameters.push_back(transact_reply); 516 onTransact_case->statements = new StatementBlock; 517 onTransact_case->exceptions.push_back(types->RemoteExceptionType()); 518 stubClass->elements.push_back(onTransact_case); 519 520 generate_stub_code(iface, 521 method, 522 transactCodeName, 523 oneway, 524 transact_data, 525 transact_reply, 526 types, 527 onTransact_case->statements, 528 stubClass); 529 } 530 531 // Generate the case dispatch. 532 { 533 Case* c = new Case(transactCodeName); 534 535 MethodCall* helper_call = new MethodCall(THIS_VALUE, 536 outline_name, 537 2, 538 stubClass->transact_data, 539 stubClass->transact_reply); 540 c->statements->Add(new ReturnStatement(helper_call)); 541 542 stubClass->transact_switch->cases.push_back(c); 543 } 544 } 545 546 static std::unique_ptr<Method> generate_proxy_method( 547 const AidlInterface& iface, 548 const AidlMethod& method, 549 const std::string& transactCodeName, 550 bool oneway, 551 ProxyClass* proxyClass, 552 JavaTypeNamespace* types) { 553 std::unique_ptr<Method> proxy(new Method); 554 proxy->comment = method.GetComments(); 555 proxy->modifiers = PUBLIC | OVERRIDE; 556 proxy->returnType = method.GetType().GetLanguageType<Type>(); 557 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; 558 proxy->name = method.GetName(); 559 proxy->statements = new StatementBlock; 560 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 561 proxy->parameters.push_back( 562 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(), 563 arg->GetType().IsArray() ? 1 : 0)); 564 } 565 proxy->exceptions.push_back(types->RemoteExceptionType()); 566 567 // the parcels 568 Variable* _data = new Variable(types->ParcelType(), "_data"); 569 proxy->statements->Add(new VariableDeclaration( 570 _data, new MethodCall(types->ParcelType(), "obtain"))); 571 Variable* _reply = NULL; 572 if (!oneway) { 573 _reply = new Variable(types->ParcelType(), "_reply"); 574 proxy->statements->Add(new VariableDeclaration( 575 _reply, new MethodCall(types->ParcelType(), "obtain"))); 576 } 577 578 // the return value 579 Variable* _result = NULL; 580 if (method.GetType().GetName() != "void") { 581 _result = new Variable(proxy->returnType, "_result", 582 method.GetType().IsArray() ? 1 : 0); 583 proxy->statements->Add(new VariableDeclaration(_result)); 584 } 585 586 // try and finally 587 TryStatement* tryStatement = new TryStatement(); 588 proxy->statements->Add(tryStatement); 589 FinallyStatement* finallyStatement = new FinallyStatement(); 590 proxy->statements->Add(finallyStatement); 591 592 if (iface.ShouldGenerateTraces()) { 593 tryStatement->statements->Add(new MethodCall( 594 new LiteralExpression("android.os.Trace"), "traceBegin", 2, 595 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"), 596 new StringLiteralExpression(iface.GetName() + "::" + 597 method.GetName() + "::client"))); 598 } 599 600 // the interface identifier token: the DESCRIPTOR constant, marshalled as a 601 // string 602 tryStatement->statements->Add(new MethodCall( 603 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR"))); 604 605 // the parameters 606 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 607 const Type* t = arg->GetType().GetLanguageType<Type>(); 608 Variable* v = 609 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0); 610 AidlArgument::Direction dir = arg->GetDirection(); 611 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) { 612 IfStatement* checklen = new IfStatement(); 613 checklen->expression = new Comparison(v, "==", NULL_VALUE); 614 checklen->statements->Add( 615 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1"))); 616 checklen->elseif = new IfStatement(); 617 checklen->elseif->statements->Add( 618 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length"))); 619 tryStatement->statements->Add(checklen); 620 } else if (dir & AidlArgument::IN_DIR) { 621 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0); 622 } else { 623 delete v; 624 } 625 } 626 627 // the transact call 628 MethodCall* call = new MethodCall( 629 proxyClass->mRemote, "transact", 4, 630 new LiteralExpression("Stub." + transactCodeName), _data, 631 _reply ? _reply : NULL_VALUE, 632 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")); 633 tryStatement->statements->Add(call); 634 635 // throw back exceptions. 636 if (_reply) { 637 MethodCall* ex = new MethodCall(_reply, "readException", 0); 638 tryStatement->statements->Add(ex); 639 } 640 641 // returning and cleanup 642 if (_reply != NULL) { 643 Variable* cl = nullptr; 644 if (_result != NULL) { 645 generate_create_from_parcel(proxy->returnType, tryStatement->statements, 646 _result, _reply, &cl); 647 } 648 649 // the out/inout parameters 650 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 651 const Type* t = arg->GetType().GetLanguageType<Type>(); 652 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 653 Variable* v = 654 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0); 655 t->ReadFromParcel(tryStatement->statements, v, _reply, &cl); 656 } 657 } 658 659 finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); 660 } 661 finallyStatement->statements->Add(new MethodCall(_data, "recycle")); 662 663 if (iface.ShouldGenerateTraces()) { 664 finallyStatement->statements->Add(new MethodCall( 665 new LiteralExpression("android.os.Trace"), "traceEnd", 1, 666 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"))); 667 } 668 669 if (_result != NULL) { 670 proxy->statements->Add(new ReturnStatement(_result)); 671 } 672 673 return proxy; 674 } 675 676 static void generate_methods(const AidlInterface& iface, 677 const AidlMethod& method, 678 Class* interface, 679 StubClass* stubClass, 680 ProxyClass* proxyClass, 681 int index, 682 JavaTypeNamespace* types) { 683 const bool oneway = proxyClass->mOneWay || method.IsOneway(); 684 685 // == the TRANSACT_ constant ============================================= 686 string transactCodeName = "TRANSACTION_"; 687 transactCodeName += method.GetName(); 688 689 Field* transactCode = new Field( 690 STATIC | FINAL, new Variable(types->IntType(), transactCodeName)); 691 transactCode->value = 692 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index); 693 stubClass->elements.push_back(transactCode); 694 695 // == the declaration in the interface =================================== 696 Method* decl = generate_interface_method(method, types).release(); 697 interface->elements.push_back(decl); 698 699 // == the stub method ==================================================== 700 bool outline_stub = stubClass->transact_outline && 701 stubClass->outline_methods.count(&method) != 0; 702 if (outline_stub) { 703 generate_stub_case_outline(iface, 704 method, 705 transactCodeName, 706 oneway, 707 stubClass, 708 types); 709 } else { 710 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, types); 711 } 712 713 // == the proxy method =================================================== 714 Method* proxy = generate_proxy_method(iface, 715 method, 716 transactCodeName, 717 oneway, 718 proxyClass, 719 types).release(); 720 proxyClass->elements.push_back(proxy); 721 } 722 723 static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy, 724 const JavaTypeNamespace* types) { 725 // the interface descriptor transaction handler 726 Case* c = new Case("INTERFACE_TRANSACTION"); 727 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1, 728 stub->get_transact_descriptor(types, 729 nullptr))); 730 c->statements->Add(new ReturnStatement(TRUE_VALUE)); 731 stub->transact_switch->cases.push_back(c); 732 733 // and the proxy-side method returning the descriptor directly 734 Method* getDesc = new Method; 735 getDesc->modifiers = PUBLIC; 736 getDesc->returnType = types->StringType(); 737 getDesc->returnTypeDimension = 0; 738 getDesc->name = "getInterfaceDescriptor"; 739 getDesc->statements = new StatementBlock; 740 getDesc->statements->Add( 741 new ReturnStatement(new LiteralExpression("DESCRIPTOR"))); 742 proxy->elements.push_back(getDesc); 743 } 744 745 // Check whether (some) methods in this interface should be "outlined," that 746 // is, have specific onTransact methods for certain cases. Set up StubClass 747 // metadata accordingly. 748 // 749 // Outlining will be enabled if the interface has more than outline_threshold 750 // methods. In that case, the methods are sorted by number of arguments 751 // (so that more "complex" methods come later), and the first non_outline_count 752 // number of methods not outlined (are kept in the onTransact() method). 753 // 754 // Requirements: non_outline_count <= outline_threshold. 755 static void compute_outline_methods(const AidlInterface* iface, 756 StubClass* stub, 757 size_t outline_threshold, 758 size_t non_outline_count) { 759 CHECK_LE(non_outline_count, outline_threshold); 760 // We'll outline (create sub methods) if there are more than min_methods 761 // cases. 762 stub->transact_outline = iface->GetMethods().size() > outline_threshold; 763 if (stub->transact_outline) { 764 stub->all_method_count = iface->GetMethods().size(); 765 std::vector<const AidlMethod*> methods; 766 methods.reserve(iface->GetMethods().size()); 767 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) { 768 methods.push_back(ptr.get()); 769 } 770 771 std::stable_sort( 772 methods.begin(), 773 methods.end(), 774 [](const AidlMethod* m1, const AidlMethod* m2) { 775 return m1->GetArguments().size() < m2->GetArguments().size(); 776 }); 777 778 stub->outline_methods.insert(methods.begin() + non_outline_count, 779 methods.end()); 780 } 781 } 782 783 Class* generate_binder_interface_class(const AidlInterface* iface, 784 JavaTypeNamespace* types, 785 const JavaOptions& options) { 786 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>(); 787 788 // the interface class 789 Class* interface = new Class; 790 interface->comment = iface->GetComments(); 791 interface->modifiers = PUBLIC; 792 interface->what = Class::INTERFACE; 793 interface->type = interfaceType; 794 interface->interfaces.push_back(types->IInterfaceType()); 795 796 // the stub inner class 797 StubClass* stub = 798 new StubClass(interfaceType->GetStub(), interfaceType, types); 799 interface->elements.push_back(stub); 800 801 compute_outline_methods(iface, 802 stub, 803 options.onTransact_outline_threshold_, 804 options.onTransact_non_outline_count_); 805 806 // the proxy inner class 807 ProxyClass* proxy = 808 new ProxyClass(types, interfaceType->GetProxy(), interfaceType); 809 stub->elements.push_back(proxy); 810 811 // stub and proxy support for getInterfaceDescriptor() 812 generate_interface_descriptors(stub, proxy, types); 813 814 // all the declared constants of the interface 815 for (const auto& item : iface->GetIntConstants()) { 816 generate_int_constant(*item, interface); 817 } 818 for (const auto& item : iface->GetStringConstants()) { 819 generate_string_constant(*item, interface); 820 } 821 822 // all the declared methods of the interface 823 824 for (const auto& item : iface->GetMethods()) { 825 generate_methods(*iface, 826 *item, 827 interface, 828 stub, 829 proxy, 830 item->GetId(), 831 types); 832 } 833 stub->finish(); 834 835 return interface; 836 } 837 838 } // namespace java 839 } // namespace android 840 } // namespace aidl 841