blob: a0ff744d9fde81768c064cd2acb06662f14c6c1a [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
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -07008#include <base/macros.h>
9
Christopher Wileyf690be52015-09-14 15:19:10 -070010#include "parse_helpers.h"
Christopher Wiley775fa1f2015-09-22 15:00:12 -070011#include "type_java.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070012
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070013namespace android {
14namespace aidl {
15
Adam Lesinskiffa16862014-01-23 18:17:42 -080016// =================================================
17class StubClass : public Class
18{
19public:
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070020 StubClass(const Type* type, const Type* interfaceType,
21 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:
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070030 void make_as_interface(const Type* interfaceType, JavaTypeNamespace* types);
31
32 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -080033};
34
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070035StubClass::StubClass(const Type* type, const Type* interfaceType,
36 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
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700106StubClass::make_as_interface(const Type *interfaceType,
107 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
150 string proxyType = interfaceType->QualifiedName();
151 proxyType += ".Stub.Proxy";
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700152 NewExpression* ne = new NewExpression(types->Find(proxyType));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800153 ne->arguments.push_back(obj);
154 m->statements->Add(new ReturnStatement(ne));
155
156 this->elements.push_back(m);
157}
158
159
160
161// =================================================
162class ProxyClass : public Class
163{
164public:
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700165 ProxyClass(const JavaTypeNamespace* types, const Type* type,
166 const InterfaceType* interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800167 virtual ~ProxyClass();
168
169 Variable* mRemote;
170 bool mOneWay;
171};
172
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700173ProxyClass::ProxyClass(const JavaTypeNamespace* types,
174 const Type* type, const InterfaceType* interfaceType)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800175 :Class()
176{
177 this->modifiers = PRIVATE | STATIC;
178 this->what = Class::CLASS;
179 this->type = type;
180 this->interfaces.push_back(interfaceType);
181
182 mOneWay = interfaceType->OneWay();
183
184 // IBinder mRemote
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700185 mRemote = new Variable(types->IBinderType(), "mRemote");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800186 this->elements.push_back(new Field(PRIVATE, mRemote));
187
188 // Proxy()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700189 Variable* remote = new Variable(types->IBinderType(), "remote");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800190 Method* ctor = new Method;
191 ctor->name = "Proxy";
192 ctor->statements = new StatementBlock;
193 ctor->parameters.push_back(remote);
194 ctor->statements->Add(new Assignment(mRemote, remote));
195 this->elements.push_back(ctor);
196
197 // IBinder asBinder()
198 Method* asBinder = new Method;
199 asBinder->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700200 asBinder->returnType = types->IBinderType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800201 asBinder->name = "asBinder";
202 asBinder->statements = new StatementBlock;
203 asBinder->statements->Add(new ReturnStatement(mRemote));
204 this->elements.push_back(asBinder);
205}
206
207ProxyClass::~ProxyClass()
208{
209}
210
211// =================================================
212static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700213generate_new_array(const Type* t, StatementBlock* addTo, Variable* v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700214 Variable* parcel, JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800215{
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700216 Variable* len = new Variable(types->IntType(), v->name + "_length");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800217 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
218 IfStatement* lencheck = new IfStatement();
219 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
220 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
221 lencheck->elseif = new IfStatement();
222 lencheck->elseif->statements->Add(new Assignment(v,
223 new NewArrayExpression(t, len)));
224 addTo->Add(lencheck);
225}
226
227static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700228generate_write_to_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800229 Variable* parcel, int flags)
230{
231 if (v->dimension == 0) {
232 t->WriteToParcel(addTo, v, parcel, flags);
233 }
234 if (v->dimension == 1) {
235 t->WriteArrayToParcel(addTo, v, parcel, flags);
236 }
237}
238
239static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700240generate_create_from_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800241 Variable* parcel, Variable** cl)
242{
243 if (v->dimension == 0) {
244 t->CreateFromParcel(addTo, v, parcel, cl);
245 }
246 if (v->dimension == 1) {
247 t->CreateArrayFromParcel(addTo, v, parcel, cl);
248 }
249}
250
251static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700252generate_read_from_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800253 Variable* parcel, Variable** cl)
254{
255 if (v->dimension == 0) {
256 t->ReadFromParcel(addTo, v, parcel, cl);
257 }
258 if (v->dimension == 1) {
259 t->ReadArrayFromParcel(addTo, v, parcel, cl);
260 }
261}
262
263
264static void
265generate_method(const method_type* method, Class* interface,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700266 StubClass* stubClass, ProxyClass* proxyClass, int index,
267 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800268{
269 arg_type* arg;
270 int i;
271 bool hasOutParams = false;
272
273 const bool oneway = proxyClass->mOneWay || method->oneway;
274
275 // == the TRANSACT_ constant =============================================
276 string transactCodeName = "TRANSACTION_";
277 transactCodeName += method->name.data;
278
279 char transactCodeValue[60];
280 sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
281
282 Field* transactCode = new Field(STATIC | FINAL,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700283 new Variable(types->IntType(), transactCodeName));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800284 transactCode->value = transactCodeValue;
285 stubClass->elements.push_back(transactCode);
286
287 // == the declaration in the interface ===================================
288 Method* decl = new Method;
289 decl->comment = gather_comments(method->comments_token->extra);
290 decl->modifiers = PUBLIC;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700291 decl->returnType = types->Search(method->type.type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800292 decl->returnTypeDimension = method->type.dimension;
293 decl->name = method->name.data;
294
295 arg = method->args;
296 while (arg != NULL) {
297 decl->parameters.push_back(new Variable(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700298 types->Search(arg->type.type.data), arg->name.data,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800299 arg->type.dimension));
300 arg = arg->next;
301 }
302
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700303 decl->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800304
305 interface->elements.push_back(decl);
306
307 // == the stub method ====================================================
308
309 Case* c = new Case(transactCodeName);
310
311 MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data);
312
313 // interface token validation is the very first thing we do
314 c->statements->Add(new MethodCall(stubClass->transact_data,
315 "enforceInterface", 1, new LiteralExpression("DESCRIPTOR")));
316
317 // args
318 Variable* cl = NULL;
319 VariableFactory stubArgs("_arg");
320 arg = method->args;
321 while (arg != NULL) {
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700322 const Type* t = types->Search(arg->type.type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800323 Variable* v = stubArgs.Get(t);
324 v->dimension = arg->type.dimension;
325
326 c->statements->Add(new VariableDeclaration(v));
327
328 if (convert_direction(arg->direction.data) & IN_PARAMETER) {
329 generate_create_from_parcel(t, c->statements, v,
330 stubClass->transact_data, &cl);
331 } else {
332 if (arg->type.dimension == 0) {
333 c->statements->Add(new Assignment(v, new NewExpression(v->type)));
334 }
335 else if (arg->type.dimension == 1) {
336 generate_new_array(v->type, c->statements, v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700337 stubClass->transact_data, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800338 }
339 else {
340 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
341 __LINE__);
342 }
343 }
344
345 realCall->arguments.push_back(v);
346
347 arg = arg->next;
348 }
349
350 // the real call
351 Variable* _result = NULL;
352 if (0 == strcmp(method->type.type.data, "void")) {
353 c->statements->Add(realCall);
354
355 if (!oneway) {
356 // report that there were no exceptions
357 MethodCall* ex = new MethodCall(stubClass->transact_reply,
358 "writeNoException", 0);
359 c->statements->Add(ex);
360 }
361 } else {
362 _result = new Variable(decl->returnType, "_result",
363 decl->returnTypeDimension);
364 c->statements->Add(new VariableDeclaration(_result, realCall));
365
366 if (!oneway) {
367 // report that there were no exceptions
368 MethodCall* ex = new MethodCall(stubClass->transact_reply,
369 "writeNoException", 0);
370 c->statements->Add(ex);
371 }
372
373 // marshall the return value
374 generate_write_to_parcel(decl->returnType, c->statements, _result,
375 stubClass->transact_reply,
376 Type::PARCELABLE_WRITE_RETURN_VALUE);
377 }
378
379 // out parameters
380 i = 0;
381 arg = method->args;
382 while (arg != NULL) {
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700383 const Type* t = types->Search(arg->type.type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800384 Variable* v = stubArgs.Get(i++);
385
386 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
387 generate_write_to_parcel(t, c->statements, v,
388 stubClass->transact_reply,
389 Type::PARCELABLE_WRITE_RETURN_VALUE);
390 hasOutParams = true;
391 }
392
393 arg = arg->next;
394 }
395
396 // return true
397 c->statements->Add(new ReturnStatement(TRUE_VALUE));
398 stubClass->transact_switch->cases.push_back(c);
399
400 // == the proxy method ===================================================
401 Method* proxy = new Method;
402 proxy->comment = gather_comments(method->comments_token->extra);
403 proxy->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700404 proxy->returnType = types->Search(method->type.type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800405 proxy->returnTypeDimension = method->type.dimension;
406 proxy->name = method->name.data;
407 proxy->statements = new StatementBlock;
408 arg = method->args;
409 while (arg != NULL) {
410 proxy->parameters.push_back(new Variable(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700411 types->Search(arg->type.type.data), arg->name.data,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800412 arg->type.dimension));
413 arg = arg->next;
414 }
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700415 proxy->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800416 proxyClass->elements.push_back(proxy);
417
418 // the parcels
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700419 Variable* _data = new Variable(types->ParcelType(), "_data");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800420 proxy->statements->Add(new VariableDeclaration(_data,
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700421 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800422 Variable* _reply = NULL;
423 if (!oneway) {
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700424 _reply = new Variable(types->ParcelType(), "_reply");
425 proxy->statements->Add(
426 new VariableDeclaration(
427 _reply,
428 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800429 }
430
431 // the return value
432 _result = NULL;
433 if (0 != strcmp(method->type.type.data, "void")) {
434 _result = new Variable(proxy->returnType, "_result",
435 method->type.dimension);
436 proxy->statements->Add(new VariableDeclaration(_result));
437 }
438
439 // try and finally
440 TryStatement* tryStatement = new TryStatement();
441 proxy->statements->Add(tryStatement);
442 FinallyStatement* finallyStatement = new FinallyStatement();
443 proxy->statements->Add(finallyStatement);
444
445 // the interface identifier token: the DESCRIPTOR constant, marshalled as a string
446 tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken",
447 1, new LiteralExpression("DESCRIPTOR")));
448
449 // the parameters
450 arg = method->args;
451 while (arg != NULL) {
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700452 const Type* t = types->Search(arg->type.type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800453 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
454 int dir = convert_direction(arg->direction.data);
455 if (dir == OUT_PARAMETER && arg->type.dimension != 0) {
456 IfStatement* checklen = new IfStatement();
457 checklen->expression = new Comparison(v, "==", NULL_VALUE);
458 checklen->statements->Add(new MethodCall(_data, "writeInt", 1,
459 new LiteralExpression("-1")));
460 checklen->elseif = new IfStatement();
461 checklen->elseif->statements->Add(new MethodCall(_data, "writeInt",
462 1, new FieldVariable(v, "length")));
463 tryStatement->statements->Add(checklen);
464 }
465 else if (dir & IN_PARAMETER) {
466 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0);
467 }
468 arg = arg->next;
469 }
470
471 // the transact call
472 MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4,
473 new LiteralExpression("Stub." + transactCodeName),
474 _data, _reply ? _reply : NULL_VALUE,
475 new LiteralExpression(
476 oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0"));
477 tryStatement->statements->Add(call);
478
479 // throw back exceptions.
480 if (_reply) {
481 MethodCall* ex = new MethodCall(_reply, "readException", 0);
482 tryStatement->statements->Add(ex);
483 }
484
485 // returning and cleanup
486 if (_reply != NULL) {
487 if (_result != NULL) {
488 generate_create_from_parcel(proxy->returnType,
489 tryStatement->statements, _result, _reply, &cl);
490 }
491
492 // the out/inout parameters
493 arg = method->args;
494 while (arg != NULL) {
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700495 const Type* t = types->Search(arg->type.type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800496 Variable* v = new Variable(t, arg->name.data, arg->type.dimension);
497 if (convert_direction(arg->direction.data) & OUT_PARAMETER) {
498 generate_read_from_parcel(t, tryStatement->statements,
499 v, _reply, &cl);
500 }
501 arg = arg->next;
502 }
503
504 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
505 }
506 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
507
508 if (_result != NULL) {
509 proxy->statements->Add(new ReturnStatement(_result));
510 }
511}
512
513static void
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700514generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
515 const JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800516{
517 // the interface descriptor transaction handler
518 Case* c = new Case("INTERFACE_TRANSACTION");
519 c->statements->Add(new MethodCall(stub->transact_reply, "writeString",
520 1, new LiteralExpression("DESCRIPTOR")));
521 c->statements->Add(new ReturnStatement(TRUE_VALUE));
522 stub->transact_switch->cases.push_back(c);
523
524 // and the proxy-side method returning the descriptor directly
525 Method* getDesc = new Method;
526 getDesc->modifiers = PUBLIC;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700527 getDesc->returnType = types->StringType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800528 getDesc->returnTypeDimension = 0;
529 getDesc->name = "getInterfaceDescriptor";
530 getDesc->statements = new StatementBlock;
531 getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
532 proxy->elements.push_back(getDesc);
533}
534
535Class*
Christopher Wiley84c1eac2015-09-23 13:29:28 -0700536generate_binder_interface_class(const interface_type* iface,
537 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800538{
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700539 const InterfaceType* interfaceType = static_cast<const InterfaceType*>(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700540 types->Find(iface->package, iface->name.data));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800541
542 // the interface class
543 Class* interface = new Class;
544 interface->comment = gather_comments(iface->comments_token->extra);
545 interface->modifiers = PUBLIC;
546 interface->what = Class::INTERFACE;
547 interface->type = interfaceType;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700548 interface->interfaces.push_back(types->IInterfaceType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800549
550 // the stub inner class
551 StubClass* stub = new StubClass(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700552 types->Find(iface->package, append(iface->name.data, ".Stub").c_str()),
553 interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800554 interface->elements.push_back(stub);
555
556 // the proxy inner class
557 ProxyClass* proxy = new ProxyClass(
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700558 types,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700559 types->Find(iface->package,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800560 append(iface->name.data, ".Stub.Proxy").c_str()),
561 interfaceType);
562 stub->elements.push_back(proxy);
563
564 // stub and proxy support for getInterfaceDescriptor()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700565 generate_interface_descriptors(stub, proxy, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800566
567 // all the declared methods of the interface
568 int index = 0;
569 interface_item_type* item = iface->interface_items;
570 while (item != NULL) {
571 if (item->item_type == METHOD_TYPE) {
572 method_type * method_item = (method_type*) item;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700573 generate_method(method_item, interface, stub, proxy,
574 method_item->assigned_id, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800575 }
576 item = item->next;
577 index++;
578 }
579
580 return interface;
581}
582
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700583} // namespace android
584} // namespace aidl