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 #include <string.h> 23 24 #include <android-base/macros.h> 25 26 #include "type_java.h" 27 28 using std::string; 29 30 namespace android { 31 namespace aidl { 32 namespace java { 33 34 // ================================================= 35 class StubClass : public Class { 36 public: 37 StubClass(const Type* type, const InterfaceType* interfaceType, 38 JavaTypeNamespace* types); 39 virtual ~StubClass() = default; 40 41 Variable* transact_code; 42 Variable* transact_data; 43 Variable* transact_reply; 44 Variable* transact_flags; 45 SwitchStatement* transact_switch; 46 47 private: 48 void make_as_interface(const InterfaceType* interfaceType, 49 JavaTypeNamespace* types); 50 51 DISALLOW_COPY_AND_ASSIGN(StubClass); 52 }; 53 54 StubClass::StubClass(const Type* type, const InterfaceType* interfaceType, 55 JavaTypeNamespace* types) 56 : Class() { 57 this->comment = "/** Local-side IPC implementation stub class. */"; 58 this->modifiers = PUBLIC | ABSTRACT | STATIC; 59 this->what = Class::CLASS; 60 this->type = type; 61 this->extends = types->BinderNativeType(); 62 this->interfaces.push_back(interfaceType); 63 64 // descriptor 65 Field* descriptor = 66 new Field(STATIC | FINAL | PRIVATE, 67 new Variable(types->StringType(), "DESCRIPTOR")); 68 descriptor->value = "\"" + interfaceType->JavaType() + "\""; 69 this->elements.push_back(descriptor); 70 71 // ctor 72 Method* ctor = new Method; 73 ctor->modifiers = PUBLIC; 74 ctor->comment = 75 "/** Construct the stub at attach it to the " 76 "interface. */"; 77 ctor->name = "Stub"; 78 ctor->statements = new StatementBlock; 79 MethodCall* attach = 80 new MethodCall(THIS_VALUE, "attachInterface", 2, THIS_VALUE, 81 new LiteralExpression("DESCRIPTOR")); 82 ctor->statements->Add(attach); 83 this->elements.push_back(ctor); 84 85 // asInterface 86 make_as_interface(interfaceType, types); 87 88 // asBinder 89 Method* asBinder = new Method; 90 asBinder->modifiers = PUBLIC | OVERRIDE; 91 asBinder->returnType = types->IBinderType(); 92 asBinder->name = "asBinder"; 93 asBinder->statements = new StatementBlock; 94 asBinder->statements->Add(new ReturnStatement(THIS_VALUE)); 95 this->elements.push_back(asBinder); 96 97 // onTransact 98 this->transact_code = new Variable(types->IntType(), "code"); 99 this->transact_data = new Variable(types->ParcelType(), "data"); 100 this->transact_reply = new Variable(types->ParcelType(), "reply"); 101 this->transact_flags = new Variable(types->IntType(), "flags"); 102 Method* onTransact = new Method; 103 onTransact->modifiers = PUBLIC | OVERRIDE; 104 onTransact->returnType = types->BoolType(); 105 onTransact->name = "onTransact"; 106 onTransact->parameters.push_back(this->transact_code); 107 onTransact->parameters.push_back(this->transact_data); 108 onTransact->parameters.push_back(this->transact_reply); 109 onTransact->parameters.push_back(this->transact_flags); 110 onTransact->statements = new StatementBlock; 111 onTransact->exceptions.push_back(types->RemoteExceptionType()); 112 this->elements.push_back(onTransact); 113 this->transact_switch = new SwitchStatement(this->transact_code); 114 115 onTransact->statements->Add(this->transact_switch); 116 MethodCall* superCall = new MethodCall( 117 SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data, 118 this->transact_reply, this->transact_flags); 119 onTransact->statements->Add(new ReturnStatement(superCall)); 120 } 121 122 void StubClass::make_as_interface(const InterfaceType* interfaceType, 123 JavaTypeNamespace* types) { 124 Variable* obj = new Variable(types->IBinderType(), "obj"); 125 126 Method* m = new Method; 127 m->comment = "/**\n * Cast an IBinder object into an "; 128 m->comment += interfaceType->JavaType(); 129 m->comment += " interface,\n"; 130 m->comment += " * generating a proxy if needed.\n */"; 131 m->modifiers = PUBLIC | STATIC; 132 m->returnType = interfaceType; 133 m->name = "asInterface"; 134 m->parameters.push_back(obj); 135 m->statements = new StatementBlock; 136 137 IfStatement* ifstatement = new IfStatement(); 138 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE); 139 ifstatement->statements = new StatementBlock; 140 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE)); 141 m->statements->Add(ifstatement); 142 143 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR) 144 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface"); 145 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR")); 146 IInterfaceType* iinType = new IInterfaceType(types); 147 Variable* iin = new Variable(iinType, "iin"); 148 VariableDeclaration* iinVd = 149 new VariableDeclaration(iin, queryLocalInterface, NULL); 150 m->statements->Add(iinVd); 151 152 // Ensure the instance type of the local object is as expected. 153 // One scenario where this is needed is if another package (with a 154 // different class loader) runs in the same process as the service. 155 156 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) 157 // iin; 158 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE); 159 Comparison* instOfCheck = 160 new Comparison(iin, " instanceof ", 161 new LiteralExpression(interfaceType->JavaType())); 162 IfStatement* instOfStatement = new IfStatement(); 163 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck); 164 instOfStatement->statements = new StatementBlock; 165 instOfStatement->statements->Add( 166 new ReturnStatement(new Cast(interfaceType, iin))); 167 m->statements->Add(instOfStatement); 168 169 NewExpression* ne = new NewExpression(interfaceType->GetProxy()); 170 ne->arguments.push_back(obj); 171 m->statements->Add(new ReturnStatement(ne)); 172 173 this->elements.push_back(m); 174 } 175 176 // ================================================= 177 class ProxyClass : public Class { 178 public: 179 ProxyClass(const JavaTypeNamespace* types, const Type* type, 180 const InterfaceType* interfaceType); 181 virtual ~ProxyClass(); 182 183 Variable* mRemote; 184 bool mOneWay; 185 }; 186 187 ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type, 188 const InterfaceType* interfaceType) 189 : Class() { 190 this->modifiers = PRIVATE | STATIC; 191 this->what = Class::CLASS; 192 this->type = type; 193 this->interfaces.push_back(interfaceType); 194 195 mOneWay = interfaceType->OneWay(); 196 197 // IBinder mRemote 198 mRemote = new Variable(types->IBinderType(), "mRemote"); 199 this->elements.push_back(new Field(PRIVATE, mRemote)); 200 201 // Proxy() 202 Variable* remote = new Variable(types->IBinderType(), "remote"); 203 Method* ctor = new Method; 204 ctor->name = "Proxy"; 205 ctor->statements = new StatementBlock; 206 ctor->parameters.push_back(remote); 207 ctor->statements->Add(new Assignment(mRemote, remote)); 208 this->elements.push_back(ctor); 209 210 // IBinder asBinder() 211 Method* asBinder = new Method; 212 asBinder->modifiers = PUBLIC | OVERRIDE; 213 asBinder->returnType = types->IBinderType(); 214 asBinder->name = "asBinder"; 215 asBinder->statements = new StatementBlock; 216 asBinder->statements->Add(new ReturnStatement(mRemote)); 217 this->elements.push_back(asBinder); 218 } 219 220 ProxyClass::~ProxyClass() {} 221 222 // ================================================= 223 static void generate_new_array(const Type* t, StatementBlock* addTo, 224 Variable* v, Variable* parcel, 225 JavaTypeNamespace* types) { 226 Variable* len = new Variable(types->IntType(), v->name + "_length"); 227 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt"))); 228 IfStatement* lencheck = new IfStatement(); 229 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0")); 230 lencheck->statements->Add(new Assignment(v, NULL_VALUE)); 231 lencheck->elseif = new IfStatement(); 232 lencheck->elseif->statements->Add( 233 new Assignment(v, new NewArrayExpression(t, len))); 234 addTo->Add(lencheck); 235 } 236 237 static void generate_write_to_parcel(const Type* t, StatementBlock* addTo, 238 Variable* v, Variable* parcel, int flags) { 239 t->WriteToParcel(addTo, v, parcel, flags); 240 } 241 242 static void generate_create_from_parcel(const Type* t, StatementBlock* addTo, 243 Variable* v, Variable* parcel, 244 Variable** cl) { 245 t->CreateFromParcel(addTo, v, parcel, cl); 246 } 247 248 static void generate_int_constant(const AidlIntConstant& constant, 249 Class* interface) { 250 IntConstant* decl = new IntConstant(constant.GetName(), constant.GetValue()); 251 interface->elements.push_back(decl); 252 } 253 254 static void generate_string_constant(const AidlStringConstant& constant, 255 Class* interface) { 256 StringConstant* decl = new StringConstant(constant.GetName(), 257 constant.GetValue()); 258 interface->elements.push_back(decl); 259 } 260 261 static void generate_method(const AidlMethod& method, Class* interface, 262 StubClass* stubClass, ProxyClass* proxyClass, 263 int index, JavaTypeNamespace* types) { 264 int i; 265 266 const bool oneway = proxyClass->mOneWay || method.IsOneway(); 267 268 // == the TRANSACT_ constant ============================================= 269 string transactCodeName = "TRANSACTION_"; 270 transactCodeName += method.GetName(); 271 272 char transactCodeValue[60]; 273 sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", 274 index); 275 276 Field* transactCode = new Field( 277 STATIC | FINAL, new Variable(types->IntType(), transactCodeName)); 278 transactCode->value = transactCodeValue; 279 stubClass->elements.push_back(transactCode); 280 281 // == the declaration in the interface =================================== 282 Method* decl = new Method; 283 decl->comment = method.GetComments(); 284 decl->modifiers = PUBLIC; 285 decl->returnType = method.GetType().GetLanguageType<Type>(); 286 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; 287 decl->name = method.GetName(); 288 289 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 290 decl->parameters.push_back( 291 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(), 292 arg->GetType().IsArray() ? 1 : 0)); 293 } 294 295 decl->exceptions.push_back(types->RemoteExceptionType()); 296 297 interface->elements.push_back(decl); 298 299 // == the stub method ==================================================== 300 301 Case* c = new Case(transactCodeName); 302 303 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName()); 304 305 // interface token validation is the very first thing we do 306 c->statements->Add(new MethodCall(stubClass->transact_data, 307 "enforceInterface", 1, 308 new LiteralExpression("DESCRIPTOR"))); 309 310 // args 311 Variable* cl = NULL; 312 VariableFactory stubArgs("_arg"); 313 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 314 const Type* t = arg->GetType().GetLanguageType<Type>(); 315 Variable* v = stubArgs.Get(t); 316 v->dimension = arg->GetType().IsArray() ? 1 : 0; 317 318 c->statements->Add(new VariableDeclaration(v)); 319 320 if (arg->GetDirection() & AidlArgument::IN_DIR) { 321 generate_create_from_parcel(t, c->statements, v, stubClass->transact_data, 322 &cl); 323 } else { 324 if (!arg->GetType().IsArray()) { 325 c->statements->Add(new Assignment(v, new NewExpression(v->type))); 326 } else { 327 generate_new_array(v->type, c->statements, v, stubClass->transact_data, 328 types); 329 } 330 } 331 332 realCall->arguments.push_back(v); 333 } 334 335 cl = NULL; 336 337 // the real call 338 Variable* _result = NULL; 339 if (method.GetType().GetName() == "void") { 340 c->statements->Add(realCall); 341 342 if (!oneway) { 343 // report that there were no exceptions 344 MethodCall* ex = 345 new MethodCall(stubClass->transact_reply, "writeNoException", 0); 346 c->statements->Add(ex); 347 } 348 } else { 349 _result = 350 new Variable(decl->returnType, "_result", decl->returnTypeDimension); 351 c->statements->Add(new VariableDeclaration(_result, realCall)); 352 353 if (!oneway) { 354 // report that there were no exceptions 355 MethodCall* ex = 356 new MethodCall(stubClass->transact_reply, "writeNoException", 0); 357 c->statements->Add(ex); 358 } 359 360 // marshall the return value 361 generate_write_to_parcel(decl->returnType, c->statements, _result, 362 stubClass->transact_reply, 363 Type::PARCELABLE_WRITE_RETURN_VALUE); 364 } 365 366 // out parameters 367 i = 0; 368 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 369 const Type* t = arg->GetType().GetLanguageType<Type>(); 370 Variable* v = stubArgs.Get(i++); 371 372 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 373 generate_write_to_parcel(t, c->statements, v, stubClass->transact_reply, 374 Type::PARCELABLE_WRITE_RETURN_VALUE); 375 } 376 } 377 378 // return true 379 c->statements->Add(new ReturnStatement(TRUE_VALUE)); 380 stubClass->transact_switch->cases.push_back(c); 381 382 // == the proxy method =================================================== 383 Method* proxy = new Method; 384 proxy->comment = method.GetComments(); 385 proxy->modifiers = PUBLIC | OVERRIDE; 386 proxy->returnType = method.GetType().GetLanguageType<Type>(); 387 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; 388 proxy->name = method.GetName(); 389 proxy->statements = new StatementBlock; 390 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 391 proxy->parameters.push_back( 392 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(), 393 arg->GetType().IsArray() ? 1 : 0)); 394 } 395 proxy->exceptions.push_back(types->RemoteExceptionType()); 396 proxyClass->elements.push_back(proxy); 397 398 // the parcels 399 Variable* _data = new Variable(types->ParcelType(), "_data"); 400 proxy->statements->Add(new VariableDeclaration( 401 _data, new MethodCall(types->ParcelType(), "obtain"))); 402 Variable* _reply = NULL; 403 if (!oneway) { 404 _reply = new Variable(types->ParcelType(), "_reply"); 405 proxy->statements->Add(new VariableDeclaration( 406 _reply, new MethodCall(types->ParcelType(), "obtain"))); 407 } 408 409 // the return value 410 _result = NULL; 411 if (method.GetType().GetName() != "void") { 412 _result = new Variable(proxy->returnType, "_result", 413 method.GetType().IsArray() ? 1 : 0); 414 proxy->statements->Add(new VariableDeclaration(_result)); 415 } 416 417 // try and finally 418 TryStatement* tryStatement = new TryStatement(); 419 proxy->statements->Add(tryStatement); 420 FinallyStatement* finallyStatement = new FinallyStatement(); 421 proxy->statements->Add(finallyStatement); 422 423 // the interface identifier token: the DESCRIPTOR constant, marshalled as a 424 // string 425 tryStatement->statements->Add(new MethodCall( 426 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR"))); 427 428 // the parameters 429 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 430 const Type* t = arg->GetType().GetLanguageType<Type>(); 431 Variable* v = 432 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0); 433 AidlArgument::Direction dir = arg->GetDirection(); 434 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) { 435 IfStatement* checklen = new IfStatement(); 436 checklen->expression = new Comparison(v, "==", NULL_VALUE); 437 checklen->statements->Add( 438 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1"))); 439 checklen->elseif = new IfStatement(); 440 checklen->elseif->statements->Add( 441 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length"))); 442 tryStatement->statements->Add(checklen); 443 } else if (dir & AidlArgument::IN_DIR) { 444 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0); 445 } else { 446 delete v; 447 } 448 } 449 450 // the transact call 451 MethodCall* call = new MethodCall( 452 proxyClass->mRemote, "transact", 4, 453 new LiteralExpression("Stub." + transactCodeName), _data, 454 _reply ? _reply : NULL_VALUE, 455 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")); 456 tryStatement->statements->Add(call); 457 458 // throw back exceptions. 459 if (_reply) { 460 MethodCall* ex = new MethodCall(_reply, "readException", 0); 461 tryStatement->statements->Add(ex); 462 } 463 464 // returning and cleanup 465 if (_reply != NULL) { 466 if (_result != NULL) { 467 generate_create_from_parcel(proxy->returnType, tryStatement->statements, 468 _result, _reply, &cl); 469 } 470 471 // the out/inout parameters 472 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 473 const Type* t = arg->GetType().GetLanguageType<Type>(); 474 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 475 Variable* v = 476 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0); 477 t->ReadFromParcel(tryStatement->statements, v, _reply, &cl); 478 } 479 } 480 481 finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); 482 } 483 finallyStatement->statements->Add(new MethodCall(_data, "recycle")); 484 485 if (_result != NULL) { 486 proxy->statements->Add(new ReturnStatement(_result)); 487 } 488 } 489 490 static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy, 491 const JavaTypeNamespace* types) { 492 // the interface descriptor transaction handler 493 Case* c = new Case("INTERFACE_TRANSACTION"); 494 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1, 495 new LiteralExpression("DESCRIPTOR"))); 496 c->statements->Add(new ReturnStatement(TRUE_VALUE)); 497 stub->transact_switch->cases.push_back(c); 498 499 // and the proxy-side method returning the descriptor directly 500 Method* getDesc = new Method; 501 getDesc->modifiers = PUBLIC; 502 getDesc->returnType = types->StringType(); 503 getDesc->returnTypeDimension = 0; 504 getDesc->name = "getInterfaceDescriptor"; 505 getDesc->statements = new StatementBlock; 506 getDesc->statements->Add( 507 new ReturnStatement(new LiteralExpression("DESCRIPTOR"))); 508 proxy->elements.push_back(getDesc); 509 } 510 511 Class* generate_binder_interface_class(const AidlInterface* iface, 512 JavaTypeNamespace* types) { 513 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>(); 514 515 // the interface class 516 Class* interface = new Class; 517 interface->comment = iface->GetComments(); 518 interface->modifiers = PUBLIC; 519 interface->what = Class::INTERFACE; 520 interface->type = interfaceType; 521 interface->interfaces.push_back(types->IInterfaceType()); 522 523 // the stub inner class 524 StubClass* stub = 525 new StubClass(interfaceType->GetStub(), interfaceType, types); 526 interface->elements.push_back(stub); 527 528 // the proxy inner class 529 ProxyClass* proxy = 530 new ProxyClass(types, interfaceType->GetProxy(), interfaceType); 531 stub->elements.push_back(proxy); 532 533 // stub and proxy support for getInterfaceDescriptor() 534 generate_interface_descriptors(stub, proxy, types); 535 536 // all the declared constants of the interface 537 for (const auto& item : iface->GetIntConstants()) { 538 generate_int_constant(*item, interface); 539 } 540 for (const auto& item : iface->GetStringConstants()) { 541 generate_string_constant(*item, interface); 542 } 543 544 // all the declared methods of the interface 545 for (const auto& item : iface->GetMethods()) { 546 generate_method(*item, interface, stub, proxy, item->GetId(), types); 547 } 548 549 return interface; 550 } 551 552 } // namespace java 553 } // namespace android 554 } // namespace aidl 555