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_read_from_parcel(const Type* t, StatementBlock* addTo, 249 Variable* v, Variable* parcel, 250 Variable** cl) { 251 t->ReadFromParcel(addTo, v, parcel, cl); 252 } 253 254 static void generate_constant(const AidlConstant& constant, Class* interface) { 255 Constant* decl = new Constant; 256 decl->name = constant.GetName(); 257 decl->value = constant.GetValue(); 258 259 interface->elements.push_back(decl); 260 } 261 262 static void generate_method(const AidlMethod& method, Class* interface, 263 StubClass* stubClass, ProxyClass* proxyClass, 264 int index, JavaTypeNamespace* types) { 265 int i; 266 bool hasOutParams = false; 267 268 const bool oneway = proxyClass->mOneWay || method.IsOneway(); 269 270 // == the TRANSACT_ constant ============================================= 271 string transactCodeName = "TRANSACTION_"; 272 transactCodeName += method.GetName(); 273 274 char transactCodeValue[60]; 275 sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", 276 index); 277 278 Field* transactCode = new Field( 279 STATIC | FINAL, new Variable(types->IntType(), transactCodeName)); 280 transactCode->value = transactCodeValue; 281 stubClass->elements.push_back(transactCode); 282 283 // == the declaration in the interface =================================== 284 Method* decl = new Method; 285 decl->comment = method.GetComments(); 286 decl->modifiers = PUBLIC; 287 decl->returnType = method.GetType().GetLanguageType<Type>(); 288 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; 289 decl->name = method.GetName(); 290 291 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 292 decl->parameters.push_back( 293 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(), 294 arg->GetType().IsArray() ? 1 : 0)); 295 } 296 297 decl->exceptions.push_back(types->RemoteExceptionType()); 298 299 interface->elements.push_back(decl); 300 301 // == the stub method ==================================================== 302 303 Case* c = new Case(transactCodeName); 304 305 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName()); 306 307 // interface token validation is the very first thing we do 308 c->statements->Add(new MethodCall(stubClass->transact_data, 309 "enforceInterface", 1, 310 new LiteralExpression("DESCRIPTOR"))); 311 312 // args 313 Variable* cl = NULL; 314 VariableFactory stubArgs("_arg"); 315 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 316 const Type* t = arg->GetType().GetLanguageType<Type>(); 317 Variable* v = stubArgs.Get(t); 318 v->dimension = arg->GetType().IsArray() ? 1 : 0; 319 320 c->statements->Add(new VariableDeclaration(v)); 321 322 if (arg->GetDirection() & AidlArgument::IN_DIR) { 323 generate_create_from_parcel(t, c->statements, v, stubClass->transact_data, 324 &cl); 325 } else { 326 if (!arg->GetType().IsArray()) { 327 c->statements->Add(new Assignment(v, new NewExpression(v->type))); 328 } else { 329 generate_new_array(v->type, c->statements, v, stubClass->transact_data, 330 types); 331 } 332 } 333 334 realCall->arguments.push_back(v); 335 } 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 hasOutParams = true; 376 } 377 } 378 379 // return true 380 c->statements->Add(new ReturnStatement(TRUE_VALUE)); 381 stubClass->transact_switch->cases.push_back(c); 382 383 // == the proxy method =================================================== 384 Method* proxy = new Method; 385 proxy->comment = method.GetComments(); 386 proxy->modifiers = PUBLIC | OVERRIDE; 387 proxy->returnType = method.GetType().GetLanguageType<Type>(); 388 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0; 389 proxy->name = method.GetName(); 390 proxy->statements = new StatementBlock; 391 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 392 proxy->parameters.push_back( 393 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(), 394 arg->GetType().IsArray() ? 1 : 0)); 395 } 396 proxy->exceptions.push_back(types->RemoteExceptionType()); 397 proxyClass->elements.push_back(proxy); 398 399 // the parcels 400 Variable* _data = new Variable(types->ParcelType(), "_data"); 401 proxy->statements->Add(new VariableDeclaration( 402 _data, new MethodCall(types->ParcelType(), "obtain"))); 403 Variable* _reply = NULL; 404 if (!oneway) { 405 _reply = new Variable(types->ParcelType(), "_reply"); 406 proxy->statements->Add(new VariableDeclaration( 407 _reply, new MethodCall(types->ParcelType(), "obtain"))); 408 } 409 410 // the return value 411 _result = NULL; 412 if (method.GetType().GetName() != "void") { 413 _result = new Variable(proxy->returnType, "_result", 414 method.GetType().IsArray() ? 1 : 0); 415 proxy->statements->Add(new VariableDeclaration(_result)); 416 } 417 418 // try and finally 419 TryStatement* tryStatement = new TryStatement(); 420 proxy->statements->Add(tryStatement); 421 FinallyStatement* finallyStatement = new FinallyStatement(); 422 proxy->statements->Add(finallyStatement); 423 424 // the interface identifier token: the DESCRIPTOR constant, marshalled as a 425 // string 426 tryStatement->statements->Add(new MethodCall( 427 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR"))); 428 429 // the parameters 430 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 431 const Type* t = arg->GetType().GetLanguageType<Type>(); 432 Variable* v = 433 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0); 434 AidlArgument::Direction dir = arg->GetDirection(); 435 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) { 436 IfStatement* checklen = new IfStatement(); 437 checklen->expression = new Comparison(v, "==", NULL_VALUE); 438 checklen->statements->Add( 439 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1"))); 440 checklen->elseif = new IfStatement(); 441 checklen->elseif->statements->Add( 442 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length"))); 443 tryStatement->statements->Add(checklen); 444 } else if (dir & AidlArgument::IN_DIR) { 445 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0); 446 } 447 } 448 449 // the transact call 450 MethodCall* call = new MethodCall( 451 proxyClass->mRemote, "transact", 4, 452 new LiteralExpression("Stub." + transactCodeName), _data, 453 _reply ? _reply : NULL_VALUE, 454 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")); 455 tryStatement->statements->Add(call); 456 457 // throw back exceptions. 458 if (_reply) { 459 MethodCall* ex = new MethodCall(_reply, "readException", 0); 460 tryStatement->statements->Add(ex); 461 } 462 463 // returning and cleanup 464 if (_reply != NULL) { 465 if (_result != NULL) { 466 generate_create_from_parcel(proxy->returnType, tryStatement->statements, 467 _result, _reply, &cl); 468 } 469 470 // the out/inout parameters 471 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) { 472 const Type* t = arg->GetType().GetLanguageType<Type>(); 473 Variable* v = 474 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0); 475 if (arg->GetDirection() & AidlArgument::OUT_DIR) { 476 generate_read_from_parcel(t, tryStatement->statements, v, _reply, &cl); 477 } 478 } 479 480 finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); 481 } 482 finallyStatement->statements->Add(new MethodCall(_data, "recycle")); 483 484 if (_result != NULL) { 485 proxy->statements->Add(new ReturnStatement(_result)); 486 } 487 } 488 489 static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy, 490 const JavaTypeNamespace* types) { 491 // the interface descriptor transaction handler 492 Case* c = new Case("INTERFACE_TRANSACTION"); 493 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1, 494 new LiteralExpression("DESCRIPTOR"))); 495 c->statements->Add(new ReturnStatement(TRUE_VALUE)); 496 stub->transact_switch->cases.push_back(c); 497 498 // and the proxy-side method returning the descriptor directly 499 Method* getDesc = new Method; 500 getDesc->modifiers = PUBLIC; 501 getDesc->returnType = types->StringType(); 502 getDesc->returnTypeDimension = 0; 503 getDesc->name = "getInterfaceDescriptor"; 504 getDesc->statements = new StatementBlock; 505 getDesc->statements->Add( 506 new ReturnStatement(new LiteralExpression("DESCRIPTOR"))); 507 proxy->elements.push_back(getDesc); 508 } 509 510 Class* generate_binder_interface_class(const AidlInterface* iface, 511 JavaTypeNamespace* types) { 512 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>(); 513 514 // the interface class 515 Class* interface = new Class; 516 interface->comment = iface->GetComments(); 517 interface->modifiers = PUBLIC; 518 interface->what = Class::INTERFACE; 519 interface->type = interfaceType; 520 interface->interfaces.push_back(types->IInterfaceType()); 521 522 // the stub inner class 523 StubClass* stub = 524 new StubClass(interfaceType->GetStub(), interfaceType, types); 525 interface->elements.push_back(stub); 526 527 // the proxy inner class 528 ProxyClass* proxy = 529 new ProxyClass(types, interfaceType->GetProxy(), interfaceType); 530 stub->elements.push_back(proxy); 531 532 // stub and proxy support for getInterfaceDescriptor() 533 generate_interface_descriptors(stub, proxy, types); 534 535 // all the declared constants of the interface 536 for (const auto& item : iface->GetConstants()) { 537 generate_constant(*item, interface); 538 } 539 540 // all the declared methods of the interface 541 for (const auto& item : iface->GetMethods()) { 542 generate_method(*item, interface, stub, proxy, item->GetId(), types); 543 } 544 545 return interface; 546 } 547 548 } // namespace java 549 } // namespace android 550 } // namespace aidl 551