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 "aidl.h" 18 #include "aidl_to_java.h" 19 #include "generate_java.h" 20 #include "logging.h" 21 #include "options.h" 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include <algorithm> 28 #include <unordered_set> 29 #include <utility> 30 #include <vector> 31 32 #include <android-base/macros.h> 33 #include <android-base/stringprintf.h> 34 35 using android::base::Join; 36 using android::base::StringPrintf; 37 38 using std::string; 39 using std::unique_ptr; 40 using std::vector; 41 42 namespace android { 43 namespace aidl { 44 namespace java { 45 46 // ================================================= 47 class VariableFactory { 48 public: 49 using Variable = ::android::aidl::java::Variable; 50 VariableFactory(const std::string & base)51 explicit VariableFactory(const std::string& base) : base_(base), index_(0) {} Get(const AidlTypeSpecifier & type,const AidlTypenames & typenames)52 std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) { 53 auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames), 54 StringPrintf("%s%d", base_.c_str(), index_)); 55 vars_.push_back(v); 56 index_++; 57 return v; 58 } 59 Get(int index)60 std::shared_ptr<Variable> Get(int index) { return vars_[index]; } 61 62 private: 63 std::vector<std::shared_ptr<Variable>> vars_; 64 std::string base_; 65 int index_; 66 67 DISALLOW_COPY_AND_ASSIGN(VariableFactory); 68 }; 69 70 // ================================================= 71 class StubClass : public Class { 72 public: 73 StubClass(const AidlInterface* interfaceType, const Options& options); 74 ~StubClass() override = default; 75 76 std::shared_ptr<Variable> transact_code; 77 std::shared_ptr<Variable> transact_data; 78 std::shared_ptr<Variable> transact_reply; 79 std::shared_ptr<Variable> transact_flags; 80 std::shared_ptr<SwitchStatement> transact_switch; 81 std::shared_ptr<StatementBlock> transact_statements; 82 std::shared_ptr<SwitchStatement> code_to_method_name_switch; 83 84 // Where onTransact cases should be generated as separate methods. 85 bool transact_outline; 86 // Specific methods that should be outlined when transact_outline is true. 87 std::unordered_set<const AidlMethod*> outline_methods; 88 // Number of all methods. 89 size_t all_method_count; 90 91 // Finish generation. This will add a default case to the switch. 92 void finish(); 93 94 std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method); 95 96 private: 97 void make_as_interface(const AidlInterface* interfaceType); 98 99 std::shared_ptr<Variable> transact_descriptor; 100 const Options& options_; 101 102 DISALLOW_COPY_AND_ASSIGN(StubClass); 103 }; 104 StubClass(const AidlInterface * interfaceType,const Options & options)105 StubClass::StubClass(const AidlInterface* interfaceType, const Options& options) 106 : Class(), options_(options) { 107 transact_descriptor = nullptr; 108 transact_outline = false; 109 all_method_count = 0; // Will be set when outlining may be enabled. 110 111 this->comment = "/** Local-side IPC implementation stub class. */"; 112 this->modifiers = PUBLIC | ABSTRACT | STATIC; 113 this->what = Class::CLASS; 114 this->type = interfaceType->GetCanonicalName() + ".Stub"; 115 this->extends = "android.os.Binder"; 116 this->interfaces.push_back(interfaceType->GetCanonicalName()); 117 118 // descriptor 119 auto descriptor = std::make_shared<Field>( 120 STATIC | FINAL | PRIVATE, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR")); 121 if (options.IsStructured()) { 122 // mangle the interface name at build time and demangle it at runtime, to avoid 123 // being renamed by jarjar. See b/153843174 124 std::string name = interfaceType->GetCanonicalName(); 125 std::replace(name.begin(), name.end(), '.', '$'); 126 descriptor->value = "\"" + name + "\".replace('$', '.')"; 127 } else { 128 descriptor->value = "\"" + interfaceType->GetCanonicalName() + "\""; 129 } 130 this->elements.push_back(descriptor); 131 132 // ctor 133 auto ctor = std::make_shared<Method>(); 134 ctor->modifiers = PUBLIC; 135 ctor->comment = 136 "/** Construct the stub at attach it to the " 137 "interface. */"; 138 ctor->name = "Stub"; 139 ctor->statements = std::make_shared<StatementBlock>(); 140 if (interfaceType->IsVintfStability()) { 141 auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n"); 142 ctor->statements->Add(stability); 143 } 144 auto attach = std::make_shared<MethodCall>( 145 THIS_VALUE, "attachInterface", 146 std::vector<std::shared_ptr<Expression>>{THIS_VALUE, 147 std::make_shared<LiteralExpression>("DESCRIPTOR")}); 148 ctor->statements->Add(attach); 149 this->elements.push_back(ctor); 150 151 // asInterface 152 make_as_interface(interfaceType); 153 154 // asBinder 155 auto asBinder = std::make_shared<Method>(); 156 asBinder->modifiers = PUBLIC | OVERRIDE; 157 asBinder->returnType = "android.os.IBinder"; 158 asBinder->name = "asBinder"; 159 asBinder->statements = std::make_shared<StatementBlock>(); 160 asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE)); 161 this->elements.push_back(asBinder); 162 163 if (options_.GenTransactionNames()) { 164 // getDefaultTransactionName 165 auto getDefaultTransactionName = std::make_shared<Method>(); 166 getDefaultTransactionName->comment = "/** @hide */"; 167 getDefaultTransactionName->modifiers = PUBLIC | STATIC; 168 getDefaultTransactionName->returnType = "java.lang.String"; 169 getDefaultTransactionName->name = "getDefaultTransactionName"; 170 auto code = std::make_shared<Variable>("int", "transactionCode"); 171 getDefaultTransactionName->parameters.push_back(code); 172 getDefaultTransactionName->statements = std::make_shared<StatementBlock>(); 173 this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code); 174 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch); 175 this->elements.push_back(getDefaultTransactionName); 176 177 // getTransactionName 178 auto getTransactionName = std::make_shared<Method>(); 179 getTransactionName->comment = "/** @hide */"; 180 getTransactionName->modifiers = PUBLIC; 181 getTransactionName->returnType = "java.lang.String"; 182 getTransactionName->name = "getTransactionName"; 183 auto code2 = std::make_shared<Variable>("int", "transactionCode"); 184 getTransactionName->parameters.push_back(code2); 185 getTransactionName->statements = std::make_shared<StatementBlock>(); 186 getTransactionName->statements->Add(std::make_shared<ReturnStatement>( 187 std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName", 188 std::vector<std::shared_ptr<Expression>>{code2}))); 189 this->elements.push_back(getTransactionName); 190 } 191 192 // onTransact 193 this->transact_code = std::make_shared<Variable>("int", "code"); 194 this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data"); 195 this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply"); 196 this->transact_flags = std::make_shared<Variable>("int", "flags"); 197 auto onTransact = std::make_shared<Method>(); 198 onTransact->modifiers = PUBLIC | OVERRIDE; 199 onTransact->returnType = "boolean"; 200 onTransact->name = "onTransact"; 201 onTransact->parameters.push_back(this->transact_code); 202 onTransact->parameters.push_back(this->transact_data); 203 onTransact->parameters.push_back(this->transact_reply); 204 onTransact->parameters.push_back(this->transact_flags); 205 onTransact->statements = std::make_shared<StatementBlock>(); 206 transact_statements = onTransact->statements; 207 onTransact->exceptions.push_back("android.os.RemoteException"); 208 this->elements.push_back(onTransact); 209 this->transact_switch = std::make_shared<SwitchStatement>(this->transact_code); 210 } 211 finish()212 void StubClass::finish() { 213 auto default_case = std::make_shared<Case>(); 214 215 auto superCall = std::make_shared<MethodCall>( 216 SUPER_VALUE, "onTransact", 217 std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data, 218 this->transact_reply, this->transact_flags}); 219 default_case->statements->Add(std::make_shared<ReturnStatement>(superCall)); 220 transact_switch->cases.push_back(default_case); 221 222 transact_statements->Add(this->transact_switch); 223 224 // getTransactionName 225 if (options_.GenTransactionNames()) { 226 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION. 227 // Common transaction codes will not be resolved to a string by getTransactionName. The method 228 // will return NULL in this case. 229 auto code_switch_default_case = std::make_shared<Case>(); 230 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE)); 231 this->code_to_method_name_switch->cases.push_back(code_switch_default_case); 232 } 233 } 234 235 // The the expression for the interface's descriptor to be used when 236 // generating code for the given method. Null is acceptable for method 237 // and stands for synthetic cases. get_transact_descriptor(const AidlMethod * method)238 std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) { 239 if (transact_outline) { 240 if (method != nullptr) { 241 // When outlining, each outlined method needs its own literal. 242 if (outline_methods.count(method) != 0) { 243 return std::make_shared<LiteralExpression>("DESCRIPTOR"); 244 } 245 } else { 246 // Synthetic case. A small number is assumed. Use its own descriptor 247 // if there are only synthetic cases. 248 if (outline_methods.size() == all_method_count) { 249 return std::make_shared<LiteralExpression>("DESCRIPTOR"); 250 } 251 } 252 } 253 254 // When not outlining, store the descriptor literal into a local variable, in 255 // an effort to save const-string instructions in each switch case. 256 if (transact_descriptor == nullptr) { 257 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor"); 258 transact_statements->Add(std::make_shared<VariableDeclaration>( 259 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR"))); 260 } 261 return transact_descriptor; 262 } 263 make_as_interface(const AidlInterface * interfaceType)264 void StubClass::make_as_interface(const AidlInterface* interfaceType) { 265 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj"); 266 267 auto m = std::make_shared<Method>(); 268 m->comment = "/**\n * Cast an IBinder object into an "; 269 m->comment += interfaceType->GetCanonicalName(); 270 m->comment += " interface,\n"; 271 m->comment += " * generating a proxy if needed.\n */"; 272 m->modifiers = PUBLIC | STATIC; 273 m->returnType = interfaceType->GetCanonicalName(); 274 m->name = "asInterface"; 275 m->parameters.push_back(obj); 276 m->statements = std::make_shared<StatementBlock>(); 277 278 auto ifstatement = std::make_shared<IfStatement>(); 279 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE); 280 ifstatement->statements = std::make_shared<StatementBlock>(); 281 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE)); 282 m->statements->Add(ifstatement); 283 284 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR) 285 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface"); 286 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR")); 287 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin"); 288 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface); 289 m->statements->Add(iinVd); 290 291 // Ensure the instance type of the local object is as expected. 292 // One scenario where this is needed is if another package (with a 293 // different class loader) runs in the same process as the service. 294 295 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) 296 // iin; 297 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE); 298 auto instOfCheck = std::make_shared<Comparison>( 299 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName())); 300 auto instOfStatement = std::make_shared<IfStatement>(); 301 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck); 302 instOfStatement->statements = std::make_shared<StatementBlock>(); 303 instOfStatement->statements->Add(std::make_shared<ReturnStatement>( 304 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin))); 305 m->statements->Add(instOfStatement); 306 307 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy"); 308 ne->arguments.push_back(obj); 309 m->statements->Add(std::make_shared<ReturnStatement>(ne)); 310 311 this->elements.push_back(m); 312 } 313 314 // ================================================= 315 class ProxyClass : public Class { 316 public: 317 ProxyClass(const AidlInterface* interfaceType, const Options& options); 318 ~ProxyClass() override; 319 320 std::shared_ptr<Variable> mRemote; 321 }; 322 ProxyClass(const AidlInterface * interfaceType,const Options & options)323 ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() { 324 this->modifiers = PRIVATE | STATIC; 325 this->what = Class::CLASS; 326 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy"; 327 this->interfaces.push_back(interfaceType->GetCanonicalName()); 328 329 // IBinder mRemote 330 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote"); 331 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote)); 332 333 // Proxy() 334 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote"); 335 auto ctor = std::make_shared<Method>(); 336 ctor->name = "Proxy"; 337 ctor->statements = std::make_shared<StatementBlock>(); 338 ctor->parameters.push_back(remote); 339 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote)); 340 this->elements.push_back(ctor); 341 342 if (options.Version() > 0) { 343 std::ostringstream code; 344 code << "private int mCachedVersion = -1;\n"; 345 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str())); 346 } 347 if (!options.Hash().empty()) { 348 std::ostringstream code; 349 code << "private String mCachedHash = \"-1\";\n"; 350 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str())); 351 } 352 353 // IBinder asBinder() 354 auto asBinder = std::make_shared<Method>(); 355 asBinder->modifiers = PUBLIC | OVERRIDE; 356 asBinder->returnType = "android.os.IBinder"; 357 asBinder->name = "asBinder"; 358 asBinder->statements = std::make_shared<StatementBlock>(); 359 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote)); 360 this->elements.push_back(asBinder); 361 } 362 ~ProxyClass()363 ProxyClass::~ProxyClass() {} 364 365 // ================================================= generate_new_array(const AidlTypeSpecifier & type,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel)366 static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames, 367 std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v, 368 std::shared_ptr<Variable> parcel) { 369 auto len = std::make_shared<Variable>("int", v->name + "_length"); 370 addTo->Add( 371 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt"))); 372 auto lencheck = std::make_shared<IfStatement>(); 373 lencheck->expression = 374 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0")); 375 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE)); 376 lencheck->elseif = std::make_shared<IfStatement>(); 377 lencheck->elseif->statements->Add(std::make_shared<Assignment>( 378 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len))); 379 addTo->Add(lencheck); 380 } 381 generate_write_to_parcel(const AidlTypeSpecifier & type,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel,bool is_return_value,const AidlTypenames & typenames)382 static void generate_write_to_parcel(const AidlTypeSpecifier& type, 383 std::shared_ptr<StatementBlock> addTo, 384 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel, 385 bool is_return_value, const AidlTypenames& typenames) { 386 string code; 387 CodeWriterPtr writer = CodeWriter::ForString(&code); 388 CodeGeneratorContext context{ 389 .writer = *(writer.get()), 390 .typenames = typenames, 391 .type = type, 392 .parcel = parcel->name, 393 .var = v->name, 394 .is_return_value = is_return_value, 395 }; 396 WriteToParcelFor(context); 397 writer->Close(); 398 addTo->Add(std::make_shared<LiteralStatement>(code)); 399 } 400 generate_int_constant(Class * interface,const std::string & name,const std::string & value)401 static void generate_int_constant(Class* interface, const std::string& name, 402 const std::string& value) { 403 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str()); 404 interface->elements.push_back(std::make_shared<LiteralClassElement>(code)); 405 } 406 generate_string_constant(Class * interface,const std::string & name,const std::string & value)407 static void generate_string_constant(Class* interface, const std::string& name, 408 const std::string& value) { 409 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str()); 410 interface->elements.push_back(std::make_shared<LiteralClassElement>(code)); 411 } 412 generate_interface_method(const AidlMethod & method,const AidlTypenames & typenames)413 static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method, 414 const AidlTypenames& typenames) { 415 auto decl = std::make_shared<Method>(); 416 decl->comment = method.GetComments(); 417 decl->modifiers = PUBLIC; 418 decl->returnType = JavaSignatureOf(method.GetType(), typenames); 419 decl->name = method.GetName(); 420 decl->annotations = generate_java_annotations(method.GetType()); 421 422 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 423 decl->parameters.push_back( 424 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName())); 425 } 426 427 decl->exceptions.push_back("android.os.RemoteException"); 428 429 return decl; 430 } 431 generate_stub_code(const AidlInterface & iface,const AidlMethod & method,bool oneway,std::shared_ptr<Variable> transact_data,std::shared_ptr<Variable> transact_reply,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> statements,std::shared_ptr<StubClass> stubClass,const Options & options)432 static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway, 433 std::shared_ptr<Variable> transact_data, 434 std::shared_ptr<Variable> transact_reply, 435 const AidlTypenames& typenames, 436 std::shared_ptr<StatementBlock> statements, 437 std::shared_ptr<StubClass> stubClass, const Options& options) { 438 std::shared_ptr<TryStatement> tryStatement; 439 std::shared_ptr<FinallyStatement> finallyStatement; 440 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName()); 441 442 // interface token validation is the very first thing we do 443 statements->Add(std::make_shared<MethodCall>( 444 transact_data, "enforceInterface", 445 std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)})); 446 447 // args 448 VariableFactory stubArgs("_arg"); 449 { 450 // keep this across different args in order to create the classloader 451 // at most once. 452 bool is_classloader_created = false; 453 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 454 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames); 455 456 statements->Add(std::make_shared<VariableDeclaration>(v)); 457 458 if (arg->GetDirection() & AidlArgument::IN_DIR) { 459 string code; 460 CodeWriterPtr writer = CodeWriter::ForString(&code); 461 CodeGeneratorContext context{.writer = *(writer.get()), 462 .typenames = typenames, 463 .type = arg->GetType(), 464 .parcel = transact_data->name, 465 .var = v->name, 466 .is_classloader_created = &is_classloader_created}; 467 CreateFromParcelFor(context); 468 writer->Close(); 469 statements->Add(std::make_shared<LiteralStatement>(code)); 470 } else { 471 if (!arg->GetType().IsArray()) { 472 statements->Add(std::make_shared<Assignment>( 473 v, std::make_shared<NewExpression>( 474 InstantiableJavaSignatureOf(arg->GetType(), typenames)))); 475 } else { 476 generate_new_array(arg->GetType(), typenames, statements, v, transact_data); 477 } 478 } 479 480 realCall->arguments.push_back(v); 481 } 482 } 483 484 if (options.GenTraces()) { 485 // try and finally, but only when generating trace code 486 tryStatement = std::make_shared<TryStatement>(); 487 finallyStatement = std::make_shared<FinallyStatement>(); 488 489 tryStatement->statements->Add(std::make_shared<MethodCall>( 490 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin", 491 std::vector<std::shared_ptr<Expression>>{ 492 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"), 493 std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() + 494 "::server")})); 495 496 finallyStatement->statements->Add(std::make_shared<MethodCall>( 497 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd", 498 std::vector<std::shared_ptr<Expression>>{ 499 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")})); 500 } 501 502 // the real call 503 if (method.GetType().GetName() == "void") { 504 if (options.GenTraces()) { 505 statements->Add(tryStatement); 506 tryStatement->statements->Add(realCall); 507 statements->Add(finallyStatement); 508 } else { 509 statements->Add(realCall); 510 } 511 512 if (!oneway) { 513 // report that there were no exceptions 514 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException"); 515 statements->Add(ex); 516 } 517 } else { 518 auto _result = 519 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result"); 520 if (options.GenTraces()) { 521 statements->Add(std::make_shared<VariableDeclaration>(_result)); 522 statements->Add(tryStatement); 523 tryStatement->statements->Add(std::make_shared<Assignment>(_result, realCall)); 524 statements->Add(finallyStatement); 525 } else { 526 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall)); 527 } 528 529 if (!oneway) { 530 // report that there were no exceptions 531 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException"); 532 statements->Add(ex); 533 } 534 535 // marshall the return value 536 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true, 537 typenames); 538 } 539 540 // out parameters 541 int i = 0; 542 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 543 std::shared_ptr<Variable> v = stubArgs.Get(i++); 544 545 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 546 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames); 547 } 548 } 549 550 // return true 551 statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE)); 552 } 553 generate_stub_case(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<StubClass> stubClass,const AidlTypenames & typenames,const Options & options)554 static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method, 555 const std::string& transactCodeName, bool oneway, 556 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames, 557 const Options& options) { 558 auto c = std::make_shared<Case>(transactCodeName); 559 560 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply, 561 typenames, c->statements, stubClass, options); 562 563 stubClass->transact_switch->cases.push_back(c); 564 } 565 generate_stub_case_outline(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<StubClass> stubClass,const AidlTypenames & typenames,const Options & options)566 static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method, 567 const std::string& transactCodeName, bool oneway, 568 std::shared_ptr<StubClass> stubClass, 569 const AidlTypenames& typenames, const Options& options) { 570 std::string outline_name = "onTransact$" + method.GetName() + "$"; 571 // Generate an "outlined" method with the actual code. 572 { 573 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data"); 574 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply"); 575 auto onTransact_case = std::make_shared<Method>(); 576 onTransact_case->modifiers = PRIVATE; 577 onTransact_case->returnType = "boolean"; 578 onTransact_case->name = outline_name; 579 onTransact_case->parameters.push_back(transact_data); 580 onTransact_case->parameters.push_back(transact_reply); 581 onTransact_case->statements = std::make_shared<StatementBlock>(); 582 onTransact_case->exceptions.push_back("android.os.RemoteException"); 583 stubClass->elements.push_back(onTransact_case); 584 585 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames, 586 onTransact_case->statements, stubClass, options); 587 } 588 589 // Generate the case dispatch. 590 { 591 auto c = std::make_shared<Case>(transactCodeName); 592 593 auto helper_call = 594 std::make_shared<MethodCall>(THIS_VALUE, outline_name, 595 std::vector<std::shared_ptr<Expression>>{ 596 stubClass->transact_data, stubClass->transact_reply}); 597 c->statements->Add(std::make_shared<ReturnStatement>(helper_call)); 598 599 stubClass->transact_switch->cases.push_back(c); 600 } 601 } 602 generate_proxy_method(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<ProxyClass> proxyClass,const AidlTypenames & typenames,const Options & options)603 static std::shared_ptr<Method> generate_proxy_method( 604 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName, 605 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames, 606 const Options& options) { 607 auto proxy = std::make_shared<Method>(); 608 proxy->comment = method.GetComments(); 609 proxy->modifiers = PUBLIC | OVERRIDE; 610 proxy->returnType = JavaSignatureOf(method.GetType(), typenames); 611 proxy->name = method.GetName(); 612 proxy->statements = std::make_shared<StatementBlock>(); 613 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 614 proxy->parameters.push_back( 615 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName())); 616 } 617 proxy->exceptions.push_back("android.os.RemoteException"); 618 619 // the parcels 620 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data"); 621 proxy->statements->Add(std::make_shared<VariableDeclaration>( 622 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain"))); 623 std::shared_ptr<Variable> _reply = nullptr; 624 if (!oneway) { 625 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply"); 626 proxy->statements->Add(std::make_shared<VariableDeclaration>( 627 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain"))); 628 } 629 630 // the return value 631 std::shared_ptr<Variable> _result = nullptr; 632 if (method.GetType().GetName() != "void") { 633 _result = std::make_shared<Variable>(*proxy->returnType, "_result"); 634 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result)); 635 } 636 637 // try and finally 638 auto tryStatement = std::make_shared<TryStatement>(); 639 proxy->statements->Add(tryStatement); 640 auto finallyStatement = std::make_shared<FinallyStatement>(); 641 proxy->statements->Add(finallyStatement); 642 643 if (options.GenTraces()) { 644 tryStatement->statements->Add(std::make_shared<MethodCall>( 645 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin", 646 std::vector<std::shared_ptr<Expression>>{ 647 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"), 648 std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() + 649 "::client")})); 650 } 651 652 // the interface identifier token: the DESCRIPTOR constant, marshalled as a 653 // string 654 tryStatement->statements->Add(std::make_shared<MethodCall>( 655 _data, "writeInterfaceToken", 656 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")})); 657 658 // the parameters 659 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 660 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()); 661 AidlArgument::Direction dir = arg->GetDirection(); 662 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) { 663 auto checklen = std::make_shared<IfStatement>(); 664 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE); 665 checklen->statements->Add(std::make_shared<MethodCall>( 666 _data, "writeInt", 667 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")})); 668 checklen->elseif = std::make_shared<IfStatement>(); 669 checklen->elseif->statements->Add(std::make_shared<MethodCall>( 670 _data, "writeInt", 671 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")})); 672 tryStatement->statements->Add(checklen); 673 } else if (dir & AidlArgument::IN_DIR) { 674 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false, 675 typenames); 676 } 677 } 678 679 // the transact call 680 auto call = std::make_shared<MethodCall>( 681 proxyClass->mRemote, "transact", 682 std::vector<std::shared_ptr<Expression>>{ 683 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data, 684 _reply ? _reply : NULL_VALUE, 685 std::make_shared<LiteralExpression>(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")}); 686 auto _status = std::make_shared<Variable>("boolean", "_status"); 687 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call)); 688 689 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall 690 // back to the local method in the default impl, if set before. 691 vector<string> arg_names; 692 for (const auto& arg : method.GetArguments()) { 693 arg_names.emplace_back(arg->GetName()); 694 } 695 bool has_return_type = method.GetType().GetName() != "void"; 696 tryStatement->statements->Add(std::make_shared<LiteralStatement>( 697 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n" 698 " return getDefaultImpl().%s(%s);\n" 699 "}\n" 700 : "if (!_status && getDefaultImpl() != null) {\n" 701 " getDefaultImpl().%s(%s);\n" 702 " return;\n" 703 "}\n", 704 method.GetName().c_str(), Join(arg_names, ", ").c_str()))); 705 706 // throw back exceptions. 707 if (_reply) { 708 auto ex = std::make_shared<MethodCall>(_reply, "readException"); 709 tryStatement->statements->Add(ex); 710 } 711 712 // returning and cleanup 713 if (_reply != nullptr) { 714 // keep this across return value and arguments in order to create the 715 // classloader at most once. 716 bool is_classloader_created = false; 717 if (_result != nullptr) { 718 string code; 719 CodeWriterPtr writer = CodeWriter::ForString(&code); 720 CodeGeneratorContext context{.writer = *(writer.get()), 721 .typenames = typenames, 722 .type = method.GetType(), 723 .parcel = _reply->name, 724 .var = _result->name, 725 .is_classloader_created = &is_classloader_created}; 726 CreateFromParcelFor(context); 727 writer->Close(); 728 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code)); 729 } 730 731 // the out/inout parameters 732 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 733 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 734 string code; 735 CodeWriterPtr writer = CodeWriter::ForString(&code); 736 CodeGeneratorContext context{.writer = *(writer.get()), 737 .typenames = typenames, 738 .type = arg->GetType(), 739 .parcel = _reply->name, 740 .var = arg->GetName(), 741 .is_classloader_created = &is_classloader_created}; 742 ReadFromParcelFor(context); 743 writer->Close(); 744 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code)); 745 } 746 } 747 748 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle")); 749 } 750 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle")); 751 752 if (options.GenTraces()) { 753 finallyStatement->statements->Add(std::make_shared<MethodCall>( 754 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd", 755 std::vector<std::shared_ptr<Expression>>{ 756 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")})); 757 } 758 759 if (_result != nullptr) { 760 proxy->statements->Add(std::make_shared<ReturnStatement>(_result)); 761 } 762 763 return proxy; 764 } 765 generate_methods(const AidlInterface & iface,const AidlMethod & method,Class * interface,std::shared_ptr<StubClass> stubClass,std::shared_ptr<ProxyClass> proxyClass,int index,const AidlTypenames & typenames,const Options & options)766 static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface, 767 std::shared_ptr<StubClass> stubClass, 768 std::shared_ptr<ProxyClass> proxyClass, int index, 769 const AidlTypenames& typenames, const Options& options) { 770 const bool oneway = method.IsOneway(); 771 772 // == the TRANSACT_ constant ============================================= 773 string transactCodeName = "TRANSACTION_"; 774 transactCodeName += method.GetName(); 775 776 auto transactCode = 777 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName)); 778 transactCode->value = 779 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index); 780 stubClass->elements.push_back(transactCode); 781 782 // getTransactionName 783 if (options.GenTransactionNames()) { 784 auto c = std::make_shared<Case>(transactCodeName); 785 c->statements->Add(std::make_shared<ReturnStatement>( 786 std::make_shared<StringLiteralExpression>(method.GetName()))); 787 stubClass->code_to_method_name_switch->cases.push_back(c); 788 } 789 790 // == the declaration in the interface =================================== 791 std::shared_ptr<ClassElement> decl; 792 if (method.IsUserDefined()) { 793 decl = generate_interface_method(method, typenames); 794 } else { 795 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) { 796 std::ostringstream code; 797 code << "public int " << kGetInterfaceVersion << "() " 798 << "throws android.os.RemoteException;\n"; 799 decl = std::make_shared<LiteralClassElement>(code.str()); 800 } 801 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) { 802 std::ostringstream code; 803 code << "public String " << kGetInterfaceHash << "() " 804 << "throws android.os.RemoteException;\n"; 805 decl = std::make_shared<LiteralClassElement>(code.str()); 806 } 807 } 808 interface->elements.push_back(decl); 809 810 // == the stub method ==================================================== 811 if (method.IsUserDefined()) { 812 bool outline_stub = 813 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0; 814 if (outline_stub) { 815 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames, 816 options); 817 } else { 818 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options); 819 } 820 } else { 821 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) { 822 auto c = std::make_shared<Case>(transactCodeName); 823 std::ostringstream code; 824 code << "data.enforceInterface(descriptor);\n" 825 << "reply.writeNoException();\n" 826 << "reply.writeInt(" << kGetInterfaceVersion << "());\n" 827 << "return true;\n"; 828 c->statements->Add(std::make_shared<LiteralStatement>(code.str())); 829 stubClass->transact_switch->cases.push_back(c); 830 } 831 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) { 832 auto c = std::make_shared<Case>(transactCodeName); 833 std::ostringstream code; 834 code << "data.enforceInterface(descriptor);\n" 835 << "reply.writeNoException();\n" 836 << "reply.writeString(" << kGetInterfaceHash << "());\n" 837 << "return true;\n"; 838 c->statements->Add(std::make_shared<LiteralStatement>(code.str())); 839 stubClass->transact_switch->cases.push_back(c); 840 } 841 } 842 843 // == the proxy method =================================================== 844 std::shared_ptr<ClassElement> proxy = nullptr; 845 if (method.IsUserDefined()) { 846 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames, 847 options); 848 849 } else { 850 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) { 851 std::ostringstream code; 852 code << "@Override\n" 853 << "public int " << kGetInterfaceVersion << "()" 854 << " throws " 855 << "android.os.RemoteException {\n" 856 << " if (mCachedVersion == -1) {\n" 857 << " android.os.Parcel data = android.os.Parcel.obtain();\n" 858 << " android.os.Parcel reply = android.os.Parcel.obtain();\n" 859 << " try {\n" 860 << " data.writeInterfaceToken(DESCRIPTOR);\n" 861 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", " 862 << "data, reply, 0);\n" 863 << " if (!_status) {\n" 864 << " if (getDefaultImpl() != null) {\n" 865 << " return getDefaultImpl().getInterfaceVersion();\n" 866 << " }\n" 867 << " }\n" 868 << " reply.readException();\n" 869 << " mCachedVersion = reply.readInt();\n" 870 << " } finally {\n" 871 << " reply.recycle();\n" 872 << " data.recycle();\n" 873 << " }\n" 874 << " }\n" 875 << " return mCachedVersion;\n" 876 << "}\n"; 877 proxy = std::make_shared<LiteralClassElement>(code.str()); 878 } 879 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) { 880 std::ostringstream code; 881 code << "@Override\n" 882 << "public synchronized String " << kGetInterfaceHash << "()" 883 << " throws " 884 << "android.os.RemoteException {\n" 885 << " if (\"-1\".equals(mCachedHash)) {\n" 886 << " android.os.Parcel data = android.os.Parcel.obtain();\n" 887 << " android.os.Parcel reply = android.os.Parcel.obtain();\n" 888 << " try {\n" 889 << " data.writeInterfaceToken(DESCRIPTOR);\n" 890 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", " 891 << "data, reply, 0);\n" 892 << " if (!_status) {\n" 893 << " if (getDefaultImpl() != null) {\n" 894 << " return getDefaultImpl().getInterfaceHash();\n" 895 << " }\n" 896 << " }\n" 897 << " reply.readException();\n" 898 << " mCachedHash = reply.readString();\n" 899 << " } finally {\n" 900 << " reply.recycle();\n" 901 << " data.recycle();\n" 902 << " }\n" 903 << " }\n" 904 << " return mCachedHash;\n" 905 << "}\n"; 906 proxy = std::make_shared<LiteralClassElement>(code.str()); 907 } 908 } 909 if (proxy != nullptr) { 910 proxyClass->elements.push_back(proxy); 911 } 912 } 913 generate_interface_descriptors(std::shared_ptr<StubClass> stub,std::shared_ptr<ProxyClass> proxy)914 static void generate_interface_descriptors(std::shared_ptr<StubClass> stub, 915 std::shared_ptr<ProxyClass> proxy) { 916 // the interface descriptor transaction handler 917 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION"); 918 c->statements->Add(std::make_shared<MethodCall>( 919 stub->transact_reply, "writeString", 920 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)})); 921 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE)); 922 stub->transact_switch->cases.push_back(c); 923 924 // and the proxy-side method returning the descriptor directly 925 auto getDesc = std::make_shared<Method>(); 926 getDesc->modifiers = PUBLIC; 927 getDesc->returnType = "java.lang.String"; 928 getDesc->name = "getInterfaceDescriptor"; 929 getDesc->statements = std::make_shared<StatementBlock>(); 930 getDesc->statements->Add( 931 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR"))); 932 proxy->elements.push_back(getDesc); 933 } 934 935 // Check whether (some) methods in this interface should be "outlined," that 936 // is, have specific onTransact methods for certain cases. Set up StubClass 937 // metadata accordingly. 938 // 939 // Outlining will be enabled if the interface has more than outline_threshold 940 // methods. In that case, the methods are sorted by number of arguments 941 // (so that more "complex" methods come later), and the first non_outline_count 942 // number of methods not outlined (are kept in the onTransact() method). 943 // 944 // Requirements: non_outline_count <= outline_threshold. compute_outline_methods(const AidlInterface * iface,const std::shared_ptr<StubClass> stub,size_t outline_threshold,size_t non_outline_count)945 static void compute_outline_methods(const AidlInterface* iface, 946 const std::shared_ptr<StubClass> stub, size_t outline_threshold, 947 size_t non_outline_count) { 948 CHECK_LE(non_outline_count, outline_threshold); 949 // We'll outline (create sub methods) if there are more than min_methods 950 // cases. 951 stub->transact_outline = iface->GetMethods().size() > outline_threshold; 952 if (stub->transact_outline) { 953 stub->all_method_count = iface->GetMethods().size(); 954 std::vector<const AidlMethod*> methods; 955 methods.reserve(iface->GetMethods().size()); 956 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) { 957 methods.push_back(ptr.get()); 958 } 959 960 std::stable_sort( 961 methods.begin(), 962 methods.end(), 963 [](const AidlMethod* m1, const AidlMethod* m2) { 964 return m1->GetArguments().size() < m2->GetArguments().size(); 965 }); 966 967 stub->outline_methods.insert(methods.begin() + non_outline_count, 968 methods.end()); 969 } 970 } 971 generate_default_impl_method(const AidlMethod & method,const AidlTypenames & typenames)972 static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method, 973 const AidlTypenames& typenames) { 974 auto default_method = std::make_shared<Method>(); 975 default_method->comment = method.GetComments(); 976 default_method->modifiers = PUBLIC | OVERRIDE; 977 default_method->returnType = JavaSignatureOf(method.GetType(), typenames); 978 default_method->name = method.GetName(); 979 default_method->statements = std::make_shared<StatementBlock>(); 980 for (const auto& arg : method.GetArguments()) { 981 default_method->parameters.push_back( 982 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName())); 983 } 984 default_method->exceptions.push_back("android.os.RemoteException"); 985 986 if (method.GetType().GetName() != "void") { 987 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames); 988 default_method->statements->Add( 989 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str()))); 990 } 991 return default_method; 992 } 993 generate_default_impl_class(const AidlInterface & iface,const AidlTypenames & typenames,const Options & options)994 static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface, 995 const AidlTypenames& typenames, 996 const Options& options) { 997 auto default_class = std::make_shared<Class>(); 998 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */"; 999 default_class->modifiers = PUBLIC | STATIC; 1000 default_class->what = Class::CLASS; 1001 default_class->type = iface.GetCanonicalName() + ".Default"; 1002 default_class->interfaces.emplace_back(iface.GetCanonicalName()); 1003 1004 for (const auto& m : iface.GetMethods()) { 1005 if (m->IsUserDefined()) { 1006 default_class->elements.emplace_back(generate_default_impl_method(*m.get(), typenames)); 1007 } else { 1008 // These are called only when the remote side does not implement these 1009 // methods, which is normally impossible, because these methods are 1010 // automatically declared in the interface class and not implementing 1011 // them on the remote side causes a compilation error. But if the remote 1012 // side somehow managed to not implement it, that's an error and we 1013 // report the case by returning an invalid value here. 1014 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) { 1015 std::ostringstream code; 1016 code << "@Override\n" 1017 << "public int " << kGetInterfaceVersion << "() {\n" 1018 << " return 0;\n" 1019 << "}\n"; 1020 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str())); 1021 } 1022 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) { 1023 std::ostringstream code; 1024 code << "@Override\n" 1025 << "public String " << kGetInterfaceHash << "() {\n" 1026 << " return \"\";\n" 1027 << "}\n"; 1028 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str())); 1029 } 1030 } 1031 } 1032 1033 default_class->elements.emplace_back( 1034 std::make_shared<LiteralClassElement>("@Override\n" 1035 "public android.os.IBinder asBinder() {\n" 1036 " return null;\n" 1037 "}\n")); 1038 1039 return default_class; 1040 } 1041 generate_binder_interface_class(const AidlInterface * iface,const AidlTypenames & typenames,const Options & options)1042 std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface, 1043 const AidlTypenames& typenames, 1044 const Options& options) { 1045 // the interface class 1046 auto interface = std::make_unique<Class>(); 1047 interface->comment = iface->GetComments(); 1048 interface->modifiers = PUBLIC; 1049 interface->what = Class::INTERFACE; 1050 interface->type = iface->GetCanonicalName(); 1051 interface->interfaces.push_back("android.os.IInterface"); 1052 interface->annotations = generate_java_annotations(*iface); 1053 1054 if (options.Version()) { 1055 std::ostringstream code; 1056 code << "/**\n" 1057 << " * The version of this interface that the caller is built against.\n" 1058 << " * This might be different from what {@link #getInterfaceVersion()\n" 1059 << " * getInterfaceVersion} returns as that is the version of the interface\n" 1060 << " * that the remote object is implementing.\n" 1061 << " */\n" 1062 << "public static final int VERSION = " << options.Version() << ";\n"; 1063 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str())); 1064 } 1065 if (!options.Hash().empty()) { 1066 std::ostringstream code; 1067 code << "public static final String HASH = \"" << options.Hash() << "\";\n"; 1068 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str())); 1069 } 1070 1071 // the default impl class 1072 auto default_impl = generate_default_impl_class(*iface, typenames, options); 1073 interface->elements.emplace_back(default_impl); 1074 1075 // the stub inner class 1076 auto stub = std::make_shared<StubClass>(iface, options); 1077 interface->elements.push_back(stub); 1078 1079 compute_outline_methods(iface, 1080 stub, 1081 options.onTransact_outline_threshold_, 1082 options.onTransact_non_outline_count_); 1083 1084 // the proxy inner class 1085 auto proxy = std::make_shared<ProxyClass>(iface, options); 1086 stub->elements.push_back(proxy); 1087 1088 // stub and proxy support for getInterfaceDescriptor() 1089 generate_interface_descriptors(stub, proxy); 1090 1091 // all the declared constants of the interface 1092 for (const auto& constant : iface->GetConstantDeclarations()) { 1093 const AidlConstantValue& value = constant->GetValue(); 1094 auto comment = constant->GetType().GetComments(); 1095 if (comment.length() != 0) { 1096 auto code = StringPrintf("%s\n", comment.c_str()); 1097 interface->elements.push_back(std::make_shared<LiteralClassElement>(code)); 1098 } 1099 switch (value.GetType()) { 1100 case AidlConstantValue::Type::STRING: { 1101 generate_string_constant(interface.get(), constant->GetName(), 1102 constant->ValueString(ConstantValueDecorator)); 1103 break; 1104 } 1105 case AidlConstantValue::Type::BOOLEAN: // fall-through 1106 case AidlConstantValue::Type::INT8: // fall-through 1107 case AidlConstantValue::Type::INT32: { 1108 generate_int_constant(interface.get(), constant->GetName(), 1109 constant->ValueString(ConstantValueDecorator)); 1110 break; 1111 } 1112 default: { 1113 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType()); 1114 } 1115 } 1116 } 1117 1118 // all the declared methods of the interface 1119 1120 for (const auto& item : iface->GetMethods()) { 1121 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames, 1122 options); 1123 } 1124 1125 // additional static methods for the default impl set/get to the 1126 // stub class. Can't add them to the interface as the generated java files 1127 // may be compiled with Java < 1.7 where static interface method isn't 1128 // supported. 1129 // TODO(b/111417145) make this conditional depending on the Java language 1130 // version requested 1131 const string i_name = iface->GetCanonicalName(); 1132 stub->elements.emplace_back(std::make_shared<LiteralClassElement>( 1133 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n" 1134 " // Only one user of this interface can use this function\n" 1135 " // at a time. This is a heuristic to detect if two different\n" 1136 " // users in the same process use this function.\n" 1137 " if (Stub.Proxy.sDefaultImpl != null) {\n" 1138 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n" 1139 " }\n" 1140 " if (impl != null) {\n" 1141 " Stub.Proxy.sDefaultImpl = impl;\n" 1142 " return true;\n" 1143 " }\n" 1144 " return false;\n" 1145 "}\n", 1146 i_name.c_str()))); 1147 stub->elements.emplace_back( 1148 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n" 1149 " return Stub.Proxy.sDefaultImpl;\n" 1150 "}\n", 1151 i_name.c_str()))); 1152 1153 // the static field is defined in the proxy class, not in the interface class 1154 // because all fields in an interface class are by default final. 1155 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>( 1156 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str()))); 1157 1158 stub->finish(); 1159 1160 return interface; 1161 } 1162 1163 } // namespace java 1164 } // namespace aidl 1165 } // namespace android 1166