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