blob: f595a2c97eb764575d0fcbd5aac4326442eda9d6 [file] [log] [blame]
Adam Lesinskiffa16862014-01-23 18:17:42 -08001#include "generate_java.h"
Christopher Wileyf690be52015-09-14 15:19:10 -07002
Adam Lesinskiffa16862014-01-23 18:17:42 -08003#include <string.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
Elliott Hughes0a620672015-12-04 13:53:18 -08008#include <android-base/macros.h>
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -07009
Christopher Wiley775fa1f2015-09-22 15:00:12 -070010#include "type_java.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070011
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070012namespace android {
13namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070014namespace java {
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070015
Adam Lesinskiffa16862014-01-23 18:17:42 -080016// =================================================
17class StubClass : public Class
18{
19public:
Casey Dahlina2f77c42015-12-01 18:26:02 -080020 StubClass(const Type* type, const InterfaceType* interfaceType,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070021 JavaTypeNamespace* types);
Adam Lesinskiffa16862014-01-23 18:17:42 -080022 virtual ~StubClass();
23
24 Variable* transact_code;
25 Variable* transact_data;
26 Variable* transact_reply;
27 Variable* transact_flags;
28 SwitchStatement* transact_switch;
29private:
Casey Dahlina2f77c42015-12-01 18:26:02 -080030 void make_as_interface(const InterfaceType* interfaceType, JavaTypeNamespace* types);
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070031
32 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -080033};
34
Casey Dahlina2f77c42015-12-01 18:26:02 -080035StubClass::StubClass(const Type* type, const InterfaceType* interfaceType,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070036 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -080037 :Class()
38{
39 this->comment = "/** Local-side IPC implementation stub class. */";
40 this->modifiers = PUBLIC | ABSTRACT | STATIC;
41 this->what = Class::CLASS;
42 this->type = type;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070043 this->extends = types->BinderNativeType();
Adam Lesinskiffa16862014-01-23 18:17:42 -080044 this->interfaces.push_back(interfaceType);
45
46 // descriptor
47 Field* descriptor = new Field(STATIC | FINAL | PRIVATE,
Christopher Wiley60b02ae2015-09-23 16:35:18 -070048 new Variable(types->StringType(), "DESCRIPTOR"));
Adam Lesinskiffa16862014-01-23 18:17:42 -080049 descriptor->value = "\"" + interfaceType->QualifiedName() + "\"";
50 this->elements.push_back(descriptor);
51
52 // ctor
53 Method* ctor = new Method;
54 ctor->modifiers = PUBLIC;
55 ctor->comment = "/** Construct the stub at attach it to the "
56 "interface. */";
57 ctor->name = "Stub";
58 ctor->statements = new StatementBlock;
59 MethodCall* attach = new MethodCall(THIS_VALUE, "attachInterface",
60 2, THIS_VALUE, new LiteralExpression("DESCRIPTOR"));
61 ctor->statements->Add(attach);
62 this->elements.push_back(ctor);
63
64 // asInterface
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070065 make_as_interface(interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -080066
67 // asBinder
68 Method* asBinder = new Method;
69 asBinder->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070070 asBinder->returnType = types->IBinderType();
Adam Lesinskiffa16862014-01-23 18:17:42 -080071 asBinder->name = "asBinder";
72 asBinder->statements = new StatementBlock;
73 asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
74 this->elements.push_back(asBinder);
75
76 // onTransact
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070077 this->transact_code = new Variable(types->IntType(), "code");
Christopher Wiley60b02ae2015-09-23 16:35:18 -070078 this->transact_data = new Variable(types->ParcelType(), "data");
79 this->transact_reply = new Variable(types->ParcelType(), "reply");
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070080 this->transact_flags = new Variable(types->IntType(), "flags");
Adam Lesinskiffa16862014-01-23 18:17:42 -080081 Method* onTransact = new Method;
82 onTransact->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070083 onTransact->returnType = types->BoolType();
Adam Lesinskiffa16862014-01-23 18:17:42 -080084 onTransact->name = "onTransact";
85 onTransact->parameters.push_back(this->transact_code);
86 onTransact->parameters.push_back(this->transact_data);
87 onTransact->parameters.push_back(this->transact_reply);
88 onTransact->parameters.push_back(this->transact_flags);
89 onTransact->statements = new StatementBlock;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070090 onTransact->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -080091 this->elements.push_back(onTransact);
92 this->transact_switch = new SwitchStatement(this->transact_code);
93
94 onTransact->statements->Add(this->transact_switch);
95 MethodCall* superCall = new MethodCall(SUPER_VALUE, "onTransact", 4,
96 this->transact_code, this->transact_data,
97 this->transact_reply, this->transact_flags);
98 onTransact->statements->Add(new ReturnStatement(superCall));
99}
100
101StubClass::~StubClass()
102{
103}
104
105void
Casey Dahlina2f77c42015-12-01 18:26:02 -0800106StubClass::make_as_interface(const InterfaceType *interfaceType,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700107 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800108{
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700109 Variable* obj = new Variable(types->IBinderType(), "obj");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800110
111 Method* m = new Method;
112 m->comment = "/**\n * Cast an IBinder object into an ";
113 m->comment += interfaceType->QualifiedName();
114 m->comment += " interface,\n";
115 m->comment += " * generating a proxy if needed.\n */";
116 m->modifiers = PUBLIC | STATIC;
117 m->returnType = interfaceType;
118 m->name = "asInterface";
119 m->parameters.push_back(obj);
120 m->statements = new StatementBlock;
121
122 IfStatement* ifstatement = new IfStatement();
123 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
124 ifstatement->statements = new StatementBlock;
125 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
126 m->statements->Add(ifstatement);
127
128 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
129 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
130 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700131 IInterfaceType* iinType = new IInterfaceType(types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800132 Variable *iin = new Variable(iinType, "iin");
133 VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface, NULL);
134 m->statements->Add(iinVd);
135
136 // Ensure the instance type of the local object is as expected.
137 // One scenario where this is needed is if another package (with a
138 // different class loader) runs in the same process as the service.
139
140 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) iin;
141 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
142 Comparison* instOfCheck = new Comparison(iin, " instanceof ",
143 new LiteralExpression(interfaceType->QualifiedName()));
144 IfStatement* instOfStatement = new IfStatement();
145 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
146 instOfStatement->statements = new StatementBlock;
147 instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType, iin)));
148 m->statements->Add(instOfStatement);
149
Casey Dahlina2f77c42015-12-01 18:26:02 -0800150 NewExpression* ne = new NewExpression(interfaceType->GetProxy());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800151 ne->arguments.push_back(obj);
152 m->statements->Add(new ReturnStatement(ne));
153
154 this->elements.push_back(m);
155}
156
157
158
159// =================================================
160class ProxyClass : public Class
161{
162public:
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700163 ProxyClass(const JavaTypeNamespace* types, const Type* type,
164 const InterfaceType* interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800165 virtual ~ProxyClass();
166
167 Variable* mRemote;
168 bool mOneWay;
169};
170
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700171ProxyClass::ProxyClass(const JavaTypeNamespace* types,
172 const Type* type, const InterfaceType* interfaceType)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800173 :Class()
174{
175 this->modifiers = PRIVATE | STATIC;
176 this->what = Class::CLASS;
177 this->type = type;
178 this->interfaces.push_back(interfaceType);
179
180 mOneWay = interfaceType->OneWay();
181
182 // IBinder mRemote
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700183 mRemote = new Variable(types->IBinderType(), "mRemote");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800184 this->elements.push_back(new Field(PRIVATE, mRemote));
185
186 // Proxy()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700187 Variable* remote = new Variable(types->IBinderType(), "remote");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800188 Method* ctor = new Method;
189 ctor->name = "Proxy";
190 ctor->statements = new StatementBlock;
191 ctor->parameters.push_back(remote);
192 ctor->statements->Add(new Assignment(mRemote, remote));
193 this->elements.push_back(ctor);
194
195 // IBinder asBinder()
196 Method* asBinder = new Method;
197 asBinder->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700198 asBinder->returnType = types->IBinderType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800199 asBinder->name = "asBinder";
200 asBinder->statements = new StatementBlock;
201 asBinder->statements->Add(new ReturnStatement(mRemote));
202 this->elements.push_back(asBinder);
203}
204
205ProxyClass::~ProxyClass()
206{
207}
208
209// =================================================
210static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700211generate_new_array(const Type* t, StatementBlock* addTo, Variable* v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700212 Variable* parcel, JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800213{
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700214 Variable* len = new Variable(types->IntType(), v->name + "_length");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800215 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
216 IfStatement* lencheck = new IfStatement();
217 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
218 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
219 lencheck->elseif = new IfStatement();
220 lencheck->elseif->statements->Add(new Assignment(v,
221 new NewArrayExpression(t, len)));
222 addTo->Add(lencheck);
223}
224
225static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700226generate_write_to_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800227 Variable* parcel, int flags)
228{
Casey Dahlina2f77c42015-12-01 18:26:02 -0800229 t->WriteToParcel(addTo, v, parcel, flags);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800230}
231
232static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700233generate_create_from_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800234 Variable* parcel, Variable** cl)
235{
Casey Dahlina2f77c42015-12-01 18:26:02 -0800236 t->CreateFromParcel(addTo, v, parcel, cl);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800237}
238
239static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700240generate_read_from_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800241 Variable* parcel, Variable** cl)
242{
Casey Dahlina2f77c42015-12-01 18:26:02 -0800243 t->ReadFromParcel(addTo, v, parcel, cl);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800244}
245
246
247static void
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800248generate_constant(const AidlConstant& constant, Class* interface)
249{
250 Constant* decl = new Constant;
251 decl->name = constant.GetName();
252 decl->value = constant.GetValue();
253
254 interface->elements.push_back(decl);
255}
256
257static void
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700258generate_method(const AidlMethod& method, Class* interface,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700259 StubClass* stubClass, ProxyClass* proxyClass, int index,
260 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800261{
Adam Lesinskiffa16862014-01-23 18:17:42 -0800262 int i;
263 bool hasOutParams = false;
264
Casey Dahlinf4a93112015-10-05 16:58:09 -0700265 const bool oneway = proxyClass->mOneWay || method.IsOneway();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800266
267 // == the TRANSACT_ constant =============================================
268 string transactCodeName = "TRANSACTION_";
Casey Dahlinf4a93112015-10-05 16:58:09 -0700269 transactCodeName += method.GetName();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800270
271 char transactCodeValue[60];
272 sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
273
274 Field* transactCode = new Field(STATIC | FINAL,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700275 new Variable(types->IntType(), transactCodeName));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800276 transactCode->value = transactCodeValue;
277 stubClass->elements.push_back(transactCode);
278
279 // == the declaration in the interface ===================================
280 Method* decl = new Method;
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700281 decl->comment = method.GetComments();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800282 decl->modifiers = PUBLIC;
Casey Dahlina2f77c42015-12-01 18:26:02 -0800283 decl->returnType = method.GetType().GetLanguageType<Type>();
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700284 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700285 decl->name = method.GetName();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800286
Casey Dahlinf4a93112015-10-05 16:58:09 -0700287 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800288 decl->parameters.push_back(new Variable(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800289 arg->GetType().GetLanguageType<Type>(), arg->GetName(),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700290 arg->GetType().IsArray() ? 1 : 0));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800291 }
292
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700293 decl->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800294
295 interface->elements.push_back(decl);
296
297 // == the stub method ====================================================
298
299 Case* c = new Case(transactCodeName);
300
Casey Dahlinf4a93112015-10-05 16:58:09 -0700301 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800302
303 // interface token validation is the very first thing we do
304 c->statements->Add(new MethodCall(stubClass->transact_data,
305 "enforceInterface", 1, new LiteralExpression("DESCRIPTOR")));
306
307 // args
308 Variable* cl = NULL;
309 VariableFactory stubArgs("_arg");
Casey Dahlinf4a93112015-10-05 16:58:09 -0700310 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800311 const Type* t = arg->GetType().GetLanguageType<Type>();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800312 Variable* v = stubArgs.Get(t);
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700313 v->dimension = arg->GetType().IsArray() ? 1 : 0;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800314
315 c->statements->Add(new VariableDeclaration(v));
316
Casey Dahlinc378c992015-09-29 16:50:40 -0700317 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800318 generate_create_from_parcel(t, c->statements, v,
319 stubClass->transact_data, &cl);
320 } else {
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700321 if (!arg->GetType().IsArray()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800322 c->statements->Add(new Assignment(v, new NewExpression(v->type)));
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700323 } else {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800324 generate_new_array(v->type, c->statements, v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700325 stubClass->transact_data, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800326 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800327 }
328
329 realCall->arguments.push_back(v);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800330 }
331
332 // the real call
333 Variable* _result = NULL;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700334 if (method.GetType().GetName() == "void") {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800335 c->statements->Add(realCall);
336
337 if (!oneway) {
338 // report that there were no exceptions
339 MethodCall* ex = new MethodCall(stubClass->transact_reply,
340 "writeNoException", 0);
341 c->statements->Add(ex);
342 }
343 } else {
344 _result = new Variable(decl->returnType, "_result",
345 decl->returnTypeDimension);
346 c->statements->Add(new VariableDeclaration(_result, realCall));
347
348 if (!oneway) {
349 // report that there were no exceptions
350 MethodCall* ex = new MethodCall(stubClass->transact_reply,
351 "writeNoException", 0);
352 c->statements->Add(ex);
353 }
354
355 // marshall the return value
356 generate_write_to_parcel(decl->returnType, c->statements, _result,
357 stubClass->transact_reply,
358 Type::PARCELABLE_WRITE_RETURN_VALUE);
359 }
360
361 // out parameters
362 i = 0;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700363 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800364 const Type* t = arg->GetType().GetLanguageType<Type>();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800365 Variable* v = stubArgs.Get(i++);
366
Casey Dahlinc378c992015-09-29 16:50:40 -0700367 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800368 generate_write_to_parcel(t, c->statements, v,
369 stubClass->transact_reply,
370 Type::PARCELABLE_WRITE_RETURN_VALUE);
371 hasOutParams = true;
372 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800373 }
374
375 // return true
376 c->statements->Add(new ReturnStatement(TRUE_VALUE));
377 stubClass->transact_switch->cases.push_back(c);
378
379 // == the proxy method ===================================================
380 Method* proxy = new Method;
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700381 proxy->comment = method.GetComments();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800382 proxy->modifiers = PUBLIC | OVERRIDE;
Casey Dahlina2f77c42015-12-01 18:26:02 -0800383 proxy->returnType = method.GetType().GetLanguageType<Type>();
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700384 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700385 proxy->name = method.GetName();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800386 proxy->statements = new StatementBlock;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700387 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800388 proxy->parameters.push_back(new Variable(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800389 arg->GetType().GetLanguageType<Type>(), arg->GetName(),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700390 arg->GetType().IsArray() ? 1 : 0));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800391 }
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700392 proxy->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800393 proxyClass->elements.push_back(proxy);
394
395 // the parcels
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700396 Variable* _data = new Variable(types->ParcelType(), "_data");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800397 proxy->statements->Add(new VariableDeclaration(_data,
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700398 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800399 Variable* _reply = NULL;
400 if (!oneway) {
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700401 _reply = new Variable(types->ParcelType(), "_reply");
402 proxy->statements->Add(
403 new VariableDeclaration(
404 _reply,
405 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800406 }
407
408 // the return value
409 _result = NULL;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700410 if (method.GetType().GetName() != "void") {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800411 _result = new Variable(proxy->returnType, "_result",
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700412 method.GetType().IsArray() ? 1 : 0);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800413 proxy->statements->Add(new VariableDeclaration(_result));
414 }
415
416 // try and finally
417 TryStatement* tryStatement = new TryStatement();
418 proxy->statements->Add(tryStatement);
419 FinallyStatement* finallyStatement = new FinallyStatement();
420 proxy->statements->Add(finallyStatement);
421
422 // the interface identifier token: the DESCRIPTOR constant, marshalled as a string
423 tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken",
424 1, new LiteralExpression("DESCRIPTOR")));
425
426 // the parameters
Casey Dahlinf4a93112015-10-05 16:58:09 -0700427 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800428 const Type* t = arg->GetType().GetLanguageType<Type>();
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700429 Variable* v = new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
Casey Dahlinc378c992015-09-29 16:50:40 -0700430 AidlArgument::Direction dir = arg->GetDirection();
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700431 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800432 IfStatement* checklen = new IfStatement();
433 checklen->expression = new Comparison(v, "==", NULL_VALUE);
434 checklen->statements->Add(new MethodCall(_data, "writeInt", 1,
435 new LiteralExpression("-1")));
436 checklen->elseif = new IfStatement();
437 checklen->elseif->statements->Add(new MethodCall(_data, "writeInt",
438 1, new FieldVariable(v, "length")));
439 tryStatement->statements->Add(checklen);
440 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700441 else if (dir & AidlArgument::IN_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800442 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0);
443 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800444 }
445
446 // the transact call
447 MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4,
448 new LiteralExpression("Stub." + transactCodeName),
449 _data, _reply ? _reply : NULL_VALUE,
450 new LiteralExpression(
451 oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0"));
452 tryStatement->statements->Add(call);
453
454 // throw back exceptions.
455 if (_reply) {
456 MethodCall* ex = new MethodCall(_reply, "readException", 0);
457 tryStatement->statements->Add(ex);
458 }
459
460 // returning and cleanup
461 if (_reply != NULL) {
462 if (_result != NULL) {
463 generate_create_from_parcel(proxy->returnType,
464 tryStatement->statements, _result, _reply, &cl);
465 }
466
467 // the out/inout parameters
Casey Dahlinf4a93112015-10-05 16:58:09 -0700468 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800469 const Type* t = arg->GetType().GetLanguageType<Type>();
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700470 Variable* v = new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
Casey Dahlinc378c992015-09-29 16:50:40 -0700471 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800472 generate_read_from_parcel(t, tryStatement->statements,
473 v, _reply, &cl);
474 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800475 }
476
477 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
478 }
479 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
480
481 if (_result != NULL) {
482 proxy->statements->Add(new ReturnStatement(_result));
483 }
484}
485
486static void
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700487generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
488 const JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800489{
490 // the interface descriptor transaction handler
491 Case* c = new Case("INTERFACE_TRANSACTION");
492 c->statements->Add(new MethodCall(stub->transact_reply, "writeString",
493 1, new LiteralExpression("DESCRIPTOR")));
494 c->statements->Add(new ReturnStatement(TRUE_VALUE));
495 stub->transact_switch->cases.push_back(c);
496
497 // and the proxy-side method returning the descriptor directly
498 Method* getDesc = new Method;
499 getDesc->modifiers = PUBLIC;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700500 getDesc->returnType = types->StringType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800501 getDesc->returnTypeDimension = 0;
502 getDesc->name = "getInterfaceDescriptor";
503 getDesc->statements = new StatementBlock;
504 getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
505 proxy->elements.push_back(getDesc);
506}
507
508Class*
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700509generate_binder_interface_class(const AidlInterface* iface,
Christopher Wiley84c1eac2015-09-23 13:29:28 -0700510 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800511{
Casey Dahlina2f77c42015-12-01 18:26:02 -0800512 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800513
514 // the interface class
515 Class* interface = new Class;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700516 interface->comment = iface->GetComments();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800517 interface->modifiers = PUBLIC;
518 interface->what = Class::INTERFACE;
519 interface->type = interfaceType;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700520 interface->interfaces.push_back(types->IInterfaceType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800521
522 // the stub inner class
523 StubClass* stub = new StubClass(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800524 interfaceType->GetStub(),
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700525 interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800526 interface->elements.push_back(stub);
527
528 // the proxy inner class
529 ProxyClass* proxy = new ProxyClass(
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700530 types,
Casey Dahlina2f77c42015-12-01 18:26:02 -0800531 interfaceType->GetProxy(),
Adam Lesinskiffa16862014-01-23 18:17:42 -0800532 interfaceType);
533 stub->elements.push_back(proxy);
534
535 // stub and proxy support for getInterfaceDescriptor()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700536 generate_interface_descriptors(stub, proxy, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800537
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800538 // all the declared constants of the interface
539 for (const auto& item : iface->GetConstants()) {
540 generate_constant(*item, interface);
541 }
542
Adam Lesinskiffa16862014-01-23 18:17:42 -0800543 // all the declared methods of the interface
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700544 for (const auto& item : iface->GetMethods()) {
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700545 generate_method(*item, interface, stub, proxy,
Casey Dahlinf4a93112015-10-05 16:58:09 -0700546 item->GetId(), types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800547 }
548
549 return interface;
550}
551
Christopher Wileydb154a52015-09-28 16:32:25 -0700552} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700553} // namespace android
554} // namespace aidl