static void generate_method(const method_type* method, Class* interface, StubClass* stubClass, ProxyClass* proxyClass, int index) { arg_type* arg; int i; bool hasOutParams = false; const bool oneway = proxyClass->mOneWay || method->oneway; // == the TRANSACT_ constant ============================================= string transactCodeName = "TRANSACTION_"; transactCodeName += method->name.data; //char transactCodeValue[60]; //sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index); //Field* transactCode = new Field(STATIC | FINAL, // new Variable(INT_TYPE, transactCodeName)); //transactCode->value = transactCodeValue; //interface->elements.push_back(transactCode); if (interface->methodEnum == 0) interface->methodEnum = new Enum(); EnumItem* item = new EnumItem(); item->name = transactCodeName; if (interface->methodEnum->items.size() == 0) item->value = "IBinder::FIRST_CALL_TRANSACTION"; else item->value = ""; interface->methodEnum->items.push_back(item); interface->declareMetaInterfaceName = string(interface->type->Name().c_str() + 1); interface->implementMetaInterfaceName = string(interface->type->Name().c_str() + 1); // +JDN //interface->implementMetaInterfaceDesc = interface->type->CPPQualifiedName(); interface->implementMetaInterfaceDesc = interface->type->QualifiedName(); // -JDN // == the declaration in the interface =================================== Method* decl = new Method; decl->comment = gather_comments(method->comments_token->extra); decl->modifiers = VIRTUAL; decl->returnType = NAMES.Search(method->type.type.data); decl->returnTypeDimension = method->type.dimension; decl->name = method->name.data; arg = method->args; while (arg != NULL) { Type* vType = NAMES.Search(arg->type.type.data); Variable* v = new Variable( vType, arg->name.data, arg->type.dimension); UserDataType* userDataType = dynamic_cast<UserDataType*>(vType); if (userDataType != NULL) { v->modifiers = POINTER; } decl->parameters.push_back(v); arg = arg->next; } // No exception in C++ //decl->exceptions.push_back(REMOTE_EXCEPTION_TYPE); interface->elements.push_back(decl); // == the stub method ==================================================== Case* c = new Case(transactCodeName); Variable* thisVar = new Variable(interface->type, "this"); thisVar->modifiers = POINTER; MethodCall* realCall = new MethodCall(thisVar/*THIS_VALUE*/, method->name.data); // interface token validation is the very first thing we do string getDescriptor = interface->type->Name() + string("::getInterfaceDescriptor()"); // +JDN Don t do checkInterface + enforceInterface it broke serialization // c->statements->Add(new MethodCall(stubClass->transact_data, // "enforceInterface", 1, new LiteralExpression(getDescriptor/*"DESCRIPTOR"*/))); // -JDN // args Variable* cl = NULL; VariableFactory stubArgs("_arg"); arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = stubArgs.Get(t); UserDataType* userDataType = dynamic_cast<UserDataType*>(t); InterfaceType* interfaceType = dynamic_cast<InterfaceType*>(t); if (userDataType != NULL) v->modifiers |= POINTER; else if (interfaceType != NULL) v->modifiers |= STRONG_POINTER; //if (userDataType != NULL) v->modifiers |= CALL_POINTER; v->dimension = arg->type.dimension; c->statements->Add(new VariableDeclaration(v)); if (convert_direction(arg->direction.data) & IN_PARAMETER) { generate_create_from_parcel(t, c->statements, v, stubClass->transact_data, &cl); } else { if (arg->type.dimension == 0) { c->statements->Add(new Assignment(v, new NewExpression(v->type))); } else if (arg->type.dimension == 1) { generate_new_array(v->type, c->statements, v, stubClass->transact_data); } else { fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); } } realCall->arguments.push_back(v); arg = arg->next; } // the real call Variable* _result = NULL; if (0 == strcmp(method->type.type.data, "void")) { c->statements->Add(realCall); if (!oneway) { // report that there were no exceptions MethodCall* ex = new MethodCall(stubClass->transact_reply, "writeNoException", 0); c->statements->Add(ex); } } else { _result = new Variable(decl->returnType, "_result", decl->returnTypeDimension); UserDataType* userDataType = dynamic_cast<UserDataType*>(decl->returnType); InterfaceType* interfaceType = dynamic_cast<InterfaceType*>(decl->returnType); if (userDataType != NULL) _result->modifiers = POINTER; else if (interfaceType != NULL) _result->modifiers = STRONG_POINTER; c->statements->Add(new VariableDeclaration(_result, realCall)); if (!oneway) { // report that there were no exceptions MethodCall* ex = new MethodCall(stubClass->transact_reply, "writeNoException", 0); c->statements->Add(ex); } // marshall the return value generate_write_to_parcel(decl->returnType, c->statements, _result, stubClass->transact_reply, Type::PARCELABLE_WRITE_RETURN_VALUE); } // out parameters i = 0; arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = stubArgs.Get(i++); if (convert_direction(arg->direction.data) & OUT_PARAMETER) { generate_write_to_parcel(t, c->statements, v, stubClass->transact_reply, Type::PARCELABLE_WRITE_RETURN_VALUE); hasOutParams = true; } arg = arg->next; } // return true c->statements->Add(new ReturnStatement(new LiteralExpression("NO_ERROR"))); stubClass->transact_switch->cases.push_back(c); // == the proxy method =================================================== Method* proxy = new Method; proxy->comment = gather_comments(method->comments_token->extra); proxy->modifiers = PUBLIC | OVERRIDE; proxy->returnType = NAMES.Search(method->type.type.data); proxy->returnTypeDimension = method->type.dimension; proxy->name = method->name.data; proxy->statements = new StatementBlock; proxy->classType = proxyClass->type; arg = method->args; while (arg != NULL) { Type* vType = NAMES.Search(arg->type.type.data); Variable* v = new Variable( vType, arg->name.data, arg->type.dimension); UserDataType* userDataType = dynamic_cast<UserDataType*>(vType); InterfaceType* interfaceType = dynamic_cast<InterfaceType*>(vType); if (userDataType != NULL) { v->modifiers |= POINTER; } else if (interfaceType != NULL) { v->modifiers |= STRONG_POINTER; } proxy->parameters.push_back(v/*new Variable( NAMES.Search(arg->type.type.data), arg->name.data, arg->type.dimension)*/); arg = arg->next; } //proxy->exceptions.push_back(REMOTE_EXCEPTION_TYPE); proxyClass->elements.push_back(proxy); // the parcels Variable* _data = new Variable(PARCEL_TYPE, "_data"); //proxy->statements->Add(new VariableDeclaration(_data, // new MethodCall(PARCEL_TYPE, "obtain"))); proxy->statements->Add(new VariableDeclaration(_data)); Variable* _reply = NULL; if (!oneway) { _reply = new Variable(PARCEL_TYPE, "_reply"); //proxy->statements->Add(new VariableDeclaration(_reply, // new MethodCall(PARCEL_TYPE, "obtain"))); proxy->statements->Add(new VariableDeclaration(_reply)); } // the return value _result = NULL; if (0 != strcmp(method->type.type.data, "void")) { _result = new Variable(proxy->returnType, "_result", method->type.dimension); UserDataType* userDataType = dynamic_cast<UserDataType*>(proxy->returnType); InterfaceType* interfaceType = dynamic_cast<InterfaceType*>(proxy->returnType); if (userDataType != NULL) { _result->modifiers = POINTER; } else if (interfaceType != NULL) { _result->modifiers = STRONG_POINTER; } proxy->statements->Add(new VariableDeclaration(_result)); } // try and finally //TryStatement* tryStatement = new TryStatement(); //proxy->statements->Add(tryStatement); //FinallyStatement* finallyStatement = new FinallyStatement(); //proxy->statements->Add(finallyStatement); // the interface identifier token: the DESCRIPTOR constant, marshalled as a string /*tryStatement*/proxy->statements->Add(new MethodCall(_data, "writeInterfaceToken", 1, new LiteralExpression(getDescriptor/*"DESCRIPTOR"*/))); // the parameters arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = new Variable(t, arg->name.data, arg->type.dimension); int dir = convert_direction(arg->direction.data); v->modifiers |= POINTER; if (dir == OUT_PARAMETER && arg->type.dimension != 0) { IfStatement* checklen = new IfStatement(); checklen->expression = new Comparison(v, "==", NULL_VALUE); checklen->statements->Add(new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1"))); checklen->elseif = new IfStatement(); checklen->elseif->statements->Add(new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length"))); /*tryStatement*/proxy->statements->Add(checklen); } else if (dir & IN_PARAMETER) { // +JDN // ALERT LEAK !!!! Variable* localParcel = new Variable(); localParcel->type = _data->type; localParcel->name = _data->name; localParcel->dimension = _data->dimension; localParcel->modifiers = _data->modifiers; localParcel->modifiers |= CALL_REFERENCE; // printf("generating parcel for %s (%s)\n", v->name.c_str(), v->type->Name().c_str()); //generate_write_to_parcel(t, /*tryStatement*/proxy->statements, v, _data, 0); generate_write_to_parcel(t, /*tryStatement*/proxy->statements, v, localParcel, 0); // -JDN } else { // printf("else\n", ""); // Do nothing } arg = arg->next; } // the transact call Variable* callReply = NULL; if (_reply != NULL) { callReply = new Variable(_reply->type, _reply->name); callReply->modifiers = CALL_REFERENCE; } MethodCall* call = new MethodCall(/*proxyClass->mRemote*/ new LiteralExpression("(*(remote()))"), "transact", 4, new LiteralExpression(/*"Stub." +*/ transactCodeName), _data, callReply ? callReply : NULL_VALUE, new LiteralExpression( oneway ? /*"android.os.IBinder.FLAG_ONEWAY"*/ "IBinder::FLAG_ONEWAY" : "0")); /*tryStatement*/proxy->statements->Add(call); // throw back exceptions. if (_reply) { MethodCall* ex = new MethodCall(_reply, "readExceptionCode", 0); /*tryStatement*/proxy->statements->Add(ex); } // returning and cleanup if (_reply != NULL) { if (_result != NULL) { generate_create_from_parcel(proxy->returnType, /*tryStatement*/proxy->statements, _result, _reply, &cl); } // the out/inout parameters arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = new Variable(t, arg->name.data, arg->type.dimension); UserDataType* userDataType = dynamic_cast<UserDataType*>(t); if (userDataType != NULL) v->modifiers = POINTER; if (convert_direction(arg->direction.data) & OUT_PARAMETER) { generate_read_from_parcel(t, /*tryStatement*/proxy->statements, v, _reply, &cl); } arg = arg->next; } //finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); } //finallyStatement->statements->Add(new MethodCall(_data, "recycle")); if (_result != NULL) { proxy->statements->Add(new ReturnStatement(_result)); } }
static void generate_method(const method_type* method, Class* interface, StubClass* stubClass, ProxyClass* proxyClass, int index) { arg_type* arg; int i; bool hasOutParams = false; const bool oneway = proxyClass->mOneWay || method->oneway; // == the TRANSACT_ constant ============================================= string transactCodeName = "TRANSACTION_"; transactCodeName += method->name.data; char transactCodeValue[50]; sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index); Field* transactCode = new Field(STATIC | FINAL, new Variable(INT_TYPE, transactCodeName)); transactCode->value = transactCodeValue; stubClass->elements.push_back(transactCode); // == the declaration in the interface =================================== Method* decl = new Method; decl->comment = gather_comments(method->comments_token->extra); decl->modifiers = PUBLIC; decl->returnType = NAMES.Search(method->type.type.data); decl->returnTypeDimension = method->type.dimension; decl->name = method->name.data; arg = method->args; while (arg != NULL) { decl->parameters.push_back(new Variable( NAMES.Search(arg->type.type.data), arg->name.data, arg->type.dimension)); arg = arg->next; } decl->exceptions.push_back(REMOTE_EXCEPTION_TYPE); interface->elements.push_back(decl); // == the stub method ==================================================== Case* c = new Case(transactCodeName); MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data); // interface token validation is the very first thing we do c->statements->Add(new MethodCall(stubClass->transact_data, "enforceInterface", 1, new LiteralExpression("DESCRIPTOR"))); // args Variable* cl = NULL; VariableFactory stubArgs("_arg"); arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = stubArgs.Get(t); v->dimension = arg->type.dimension; c->statements->Add(new VariableDeclaration(v)); if (convert_direction(arg->direction.data) & IN_PARAMETER) { generate_create_from_parcel(t, c->statements, v, stubClass->transact_data, &cl); } else { if (arg->type.dimension == 0) { c->statements->Add(new Assignment( v, new NewExpression(v->type))); } else if (arg->type.dimension == 1) { generate_new_array(v->type, c->statements, v, stubClass->transact_data); } else { fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__); } } realCall->arguments.push_back(v); arg = arg->next; } // the real call Variable* _result = NULL; if (0 == strcmp(method->type.type.data, "void")) { c->statements->Add(realCall); if (!oneway) { // report that there were no exceptions MethodCall* ex = new MethodCall(stubClass->transact_reply, "writeNoException", 0); c->statements->Add(ex); } } else { _result = new Variable(decl->returnType, "_result", decl->returnTypeDimension); c->statements->Add(new VariableDeclaration(_result, realCall)); if (!oneway) { // report that there were no exceptions MethodCall* ex = new MethodCall(stubClass->transact_reply, "writeNoException", 0); c->statements->Add(ex); } // marshall the return value generate_write_to_parcel(decl->returnType, c->statements, _result, stubClass->transact_reply, Type::PARCELABLE_WRITE_RETURN_VALUE); } // out parameters i = 0; arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = stubArgs.Get(i++); if (convert_direction(arg->direction.data) & OUT_PARAMETER) { generate_write_to_parcel(t, c->statements, v, stubClass->transact_reply, Type::PARCELABLE_WRITE_RETURN_VALUE); hasOutParams = true; } arg = arg->next; } // return true c->statements->Add(new ReturnStatement(TRUE_VALUE)); stubClass->transact_switch->cases.push_back(c); // == the proxy method =================================================== Method* proxy = new Method; proxy->comment = gather_comments(method->comments_token->extra); proxy->modifiers = PUBLIC; proxy->returnType = NAMES.Search(method->type.type.data); proxy->returnTypeDimension = method->type.dimension; proxy->name = method->name.data; proxy->statements = new StatementBlock; arg = method->args; while (arg != NULL) { proxy->parameters.push_back(new Variable( NAMES.Search(arg->type.type.data), arg->name.data, arg->type.dimension)); arg = arg->next; } proxy->exceptions.push_back(REMOTE_EXCEPTION_TYPE); proxyClass->elements.push_back(proxy); // the parcels Variable* _data = new Variable(PARCEL_TYPE, "_data"); proxy->statements->Add(new VariableDeclaration(_data, new MethodCall(PARCEL_TYPE, "obtain"))); Variable* _reply = NULL; if (!oneway) { _reply = new Variable(PARCEL_TYPE, "_reply"); proxy->statements->Add(new VariableDeclaration(_reply, new MethodCall(PARCEL_TYPE, "obtain"))); } // the return value _result = NULL; if (0 != strcmp(method->type.type.data, "void")) { _result = new Variable(proxy->returnType, "_result", method->type.dimension); proxy->statements->Add(new VariableDeclaration(_result)); } // try and finally TryStatement* tryStatement = new TryStatement(); proxy->statements->Add(tryStatement); FinallyStatement* finallyStatement = new FinallyStatement(); proxy->statements->Add(finallyStatement); // the interface identifier token: the DESCRIPTOR constant, marshalled as a string tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR"))); // the parameters arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = new Variable(t, arg->name.data, arg->type.dimension); int dir = convert_direction(arg->direction.data); if (dir == OUT_PARAMETER && arg->type.dimension != 0) { IfStatement* checklen = new IfStatement(); checklen->expression = new Comparison(v, "==", NULL_VALUE); checklen->statements->Add(new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1"))); checklen->elseif = new IfStatement(); checklen->elseif->statements->Add(new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length"))); tryStatement->statements->Add(checklen); } else if (dir & IN_PARAMETER) { generate_write_to_parcel(t, tryStatement->statements, v, _data, 0); } arg = arg->next; } // the transact call MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4, new LiteralExpression("Stub." + transactCodeName), _data, _reply ? _reply : NULL_VALUE, new LiteralExpression( oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")); tryStatement->statements->Add(call); // throw back exceptions. if (_reply) { MethodCall* ex = new MethodCall(_reply, "readException", 0); tryStatement->statements->Add(ex); } // returning and cleanup if (_reply != NULL) { if (_result != NULL) { generate_create_from_parcel(proxy->returnType, tryStatement->statements, _result, _reply, &cl); } // the out/inout parameters arg = method->args; while (arg != NULL) { Type* t = NAMES.Search(arg->type.type.data); Variable* v = new Variable(t, arg->name.data, arg->type.dimension); if (convert_direction(arg->direction.data) & OUT_PARAMETER) { generate_read_from_parcel(t, tryStatement->statements, v, _reply, &cl); } arg = arg->next; } finallyStatement->statements->Add(new MethodCall(_reply, "recycle")); } finallyStatement->statements->Add(new MethodCall(_data, "recycle")); if (_result != NULL) { proxy->statements->Add(new ReturnStatement(_result)); } }