blob: b8fded043cb79b86499646eee93b1496597d810a [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 {
Christopher Wileydb154a52015-09-28 16:32:25 -070015namespace java {
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070016
Adam Lesinskiffa16862014-01-23 18:17:42 -080017// =================================================
18class StubClass : public Class
19{
20public:
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070021 StubClass(const Type* type, const Type* interfaceType,
22 JavaTypeNamespace* types);
Adam Lesinskiffa16862014-01-23 18:17:42 -080023 virtual ~StubClass();
24
25 Variable* transact_code;
26 Variable* transact_data;
27 Variable* transact_reply;
28 Variable* transact_flags;
29 SwitchStatement* transact_switch;
30private:
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070031 void make_as_interface(const Type* interfaceType, JavaTypeNamespace* types);
32
33 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -080034};
35
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070036StubClass::StubClass(const Type* type, const Type* interfaceType,
37 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -080038 :Class()
39{
40 this->comment = "/** Local-side IPC implementation stub class. */";
41 this->modifiers = PUBLIC | ABSTRACT | STATIC;
42 this->what = Class::CLASS;
43 this->type = type;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070044 this->extends = types->BinderNativeType();
Adam Lesinskiffa16862014-01-23 18:17:42 -080045 this->interfaces.push_back(interfaceType);
46
47 // descriptor
48 Field* descriptor = new Field(STATIC | FINAL | PRIVATE,
Christopher Wiley60b02ae2015-09-23 16:35:18 -070049 new Variable(types->StringType(), "DESCRIPTOR"));
Adam Lesinskiffa16862014-01-23 18:17:42 -080050 descriptor->value = "\"" + interfaceType->QualifiedName() + "\"";
51 this->elements.push_back(descriptor);
52
53 // ctor
54 Method* ctor = new Method;
55 ctor->modifiers = PUBLIC;
56 ctor->comment = "/** Construct the stub at attach it to the "
57 "interface. */";
58 ctor->name = "Stub";
59 ctor->statements = new StatementBlock;
60 MethodCall* attach = new MethodCall(THIS_VALUE, "attachInterface",
61 2, THIS_VALUE, new LiteralExpression("DESCRIPTOR"));
62 ctor->statements->Add(attach);
63 this->elements.push_back(ctor);
64
65 // asInterface
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070066 make_as_interface(interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -080067
68 // asBinder
69 Method* asBinder = new Method;
70 asBinder->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070071 asBinder->returnType = types->IBinderType();
Adam Lesinskiffa16862014-01-23 18:17:42 -080072 asBinder->name = "asBinder";
73 asBinder->statements = new StatementBlock;
74 asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
75 this->elements.push_back(asBinder);
76
77 // onTransact
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070078 this->transact_code = new Variable(types->IntType(), "code");
Christopher Wiley60b02ae2015-09-23 16:35:18 -070079 this->transact_data = new Variable(types->ParcelType(), "data");
80 this->transact_reply = new Variable(types->ParcelType(), "reply");
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070081 this->transact_flags = new Variable(types->IntType(), "flags");
Adam Lesinskiffa16862014-01-23 18:17:42 -080082 Method* onTransact = new Method;
83 onTransact->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070084 onTransact->returnType = types->BoolType();
Adam Lesinskiffa16862014-01-23 18:17:42 -080085 onTransact->name = "onTransact";
86 onTransact->parameters.push_back(this->transact_code);
87 onTransact->parameters.push_back(this->transact_data);
88 onTransact->parameters.push_back(this->transact_reply);
89 onTransact->parameters.push_back(this->transact_flags);
90 onTransact->statements = new StatementBlock;
Christopher Wiley60b02ae2015-09-23 16:35:18 -070091 onTransact->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -080092 this->elements.push_back(onTransact);
93 this->transact_switch = new SwitchStatement(this->transact_code);
94
95 onTransact->statements->Add(this->transact_switch);
96 MethodCall* superCall = new MethodCall(SUPER_VALUE, "onTransact", 4,
97 this->transact_code, this->transact_data,
98 this->transact_reply, this->transact_flags);
99 onTransact->statements->Add(new ReturnStatement(superCall));
100}
101
102StubClass::~StubClass()
103{
104}
105
106void
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700107StubClass::make_as_interface(const Type *interfaceType,
108 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800109{
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700110 Variable* obj = new Variable(types->IBinderType(), "obj");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800111
112 Method* m = new Method;
113 m->comment = "/**\n * Cast an IBinder object into an ";
114 m->comment += interfaceType->QualifiedName();
115 m->comment += " interface,\n";
116 m->comment += " * generating a proxy if needed.\n */";
117 m->modifiers = PUBLIC | STATIC;
118 m->returnType = interfaceType;
119 m->name = "asInterface";
120 m->parameters.push_back(obj);
121 m->statements = new StatementBlock;
122
123 IfStatement* ifstatement = new IfStatement();
124 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
125 ifstatement->statements = new StatementBlock;
126 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
127 m->statements->Add(ifstatement);
128
129 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
130 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
131 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700132 IInterfaceType* iinType = new IInterfaceType(types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800133 Variable *iin = new Variable(iinType, "iin");
134 VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface, NULL);
135 m->statements->Add(iinVd);
136
137 // Ensure the instance type of the local object is as expected.
138 // One scenario where this is needed is if another package (with a
139 // different class loader) runs in the same process as the service.
140
141 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>) iin;
142 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
143 Comparison* instOfCheck = new Comparison(iin, " instanceof ",
144 new LiteralExpression(interfaceType->QualifiedName()));
145 IfStatement* instOfStatement = new IfStatement();
146 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
147 instOfStatement->statements = new StatementBlock;
148 instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType, iin)));
149 m->statements->Add(instOfStatement);
150
151 string proxyType = interfaceType->QualifiedName();
152 proxyType += ".Stub.Proxy";
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700153 NewExpression* ne = new NewExpression(types->Find(proxyType));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800154 ne->arguments.push_back(obj);
155 m->statements->Add(new ReturnStatement(ne));
156
157 this->elements.push_back(m);
158}
159
160
161
162// =================================================
163class ProxyClass : public Class
164{
165public:
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700166 ProxyClass(const JavaTypeNamespace* types, const Type* type,
167 const InterfaceType* interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800168 virtual ~ProxyClass();
169
170 Variable* mRemote;
171 bool mOneWay;
172};
173
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700174ProxyClass::ProxyClass(const JavaTypeNamespace* types,
175 const Type* type, const InterfaceType* interfaceType)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800176 :Class()
177{
178 this->modifiers = PRIVATE | STATIC;
179 this->what = Class::CLASS;
180 this->type = type;
181 this->interfaces.push_back(interfaceType);
182
183 mOneWay = interfaceType->OneWay();
184
185 // IBinder mRemote
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700186 mRemote = new Variable(types->IBinderType(), "mRemote");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800187 this->elements.push_back(new Field(PRIVATE, mRemote));
188
189 // Proxy()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700190 Variable* remote = new Variable(types->IBinderType(), "remote");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800191 Method* ctor = new Method;
192 ctor->name = "Proxy";
193 ctor->statements = new StatementBlock;
194 ctor->parameters.push_back(remote);
195 ctor->statements->Add(new Assignment(mRemote, remote));
196 this->elements.push_back(ctor);
197
198 // IBinder asBinder()
199 Method* asBinder = new Method;
200 asBinder->modifiers = PUBLIC | OVERRIDE;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700201 asBinder->returnType = types->IBinderType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800202 asBinder->name = "asBinder";
203 asBinder->statements = new StatementBlock;
204 asBinder->statements->Add(new ReturnStatement(mRemote));
205 this->elements.push_back(asBinder);
206}
207
208ProxyClass::~ProxyClass()
209{
210}
211
212// =================================================
213static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700214generate_new_array(const Type* t, StatementBlock* addTo, Variable* v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700215 Variable* parcel, JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800216{
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700217 Variable* len = new Variable(types->IntType(), v->name + "_length");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800218 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
219 IfStatement* lencheck = new IfStatement();
220 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
221 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
222 lencheck->elseif = new IfStatement();
223 lencheck->elseif->statements->Add(new Assignment(v,
224 new NewArrayExpression(t, len)));
225 addTo->Add(lencheck);
226}
227
228static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700229generate_write_to_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800230 Variable* parcel, int flags)
231{
232 if (v->dimension == 0) {
233 t->WriteToParcel(addTo, v, parcel, flags);
234 }
235 if (v->dimension == 1) {
236 t->WriteArrayToParcel(addTo, v, parcel, flags);
237 }
238}
239
240static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700241generate_create_from_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800242 Variable* parcel, Variable** cl)
243{
244 if (v->dimension == 0) {
245 t->CreateFromParcel(addTo, v, parcel, cl);
246 }
247 if (v->dimension == 1) {
248 t->CreateArrayFromParcel(addTo, v, parcel, cl);
249 }
250}
251
252static void
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700253generate_read_from_parcel(const Type* t, StatementBlock* addTo, Variable* v,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800254 Variable* parcel, Variable** cl)
255{
256 if (v->dimension == 0) {
257 t->ReadFromParcel(addTo, v, parcel, cl);
258 }
259 if (v->dimension == 1) {
260 t->ReadArrayFromParcel(addTo, v, parcel, cl);
261 }
262}
263
264
265static void
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700266generate_method(const AidlMethod& method, Class* interface,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700267 StubClass* stubClass, ProxyClass* proxyClass, int index,
268 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800269{
Adam Lesinskiffa16862014-01-23 18:17:42 -0800270 int i;
271 bool hasOutParams = false;
272
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700273 const bool oneway = proxyClass->mOneWay || method.oneway;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800274
275 // == the TRANSACT_ constant =============================================
276 string transactCodeName = "TRANSACTION_";
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700277 transactCodeName += method.name.data;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800278
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;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700289 decl->comment = gather_comments(method.comments_token->extra);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800290 decl->modifiers = PUBLIC;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700291 decl->returnType = types->Find(method.type->type.data);
292 decl->returnTypeDimension = method.type->dimension;
293 decl->name = method.name.data;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800294
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700295 for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800296 decl->parameters.push_back(new Variable(
Casey Dahlin0ee37582015-09-30 16:31:55 -0700297 types->Find(arg->GetType().type.data), arg->GetName(),
298 arg->GetType().dimension));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800299 }
300
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700301 decl->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800302
303 interface->elements.push_back(decl);
304
305 // == the stub method ====================================================
306
307 Case* c = new Case(transactCodeName);
308
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700309 MethodCall* realCall = new MethodCall(THIS_VALUE, method.name.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800310
311 // interface token validation is the very first thing we do
312 c->statements->Add(new MethodCall(stubClass->transact_data,
313 "enforceInterface", 1, new LiteralExpression("DESCRIPTOR")));
314
315 // args
316 Variable* cl = NULL;
317 VariableFactory stubArgs("_arg");
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700318 for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
Casey Dahlin0ee37582015-09-30 16:31:55 -0700319 const Type* t = types->Find(arg->GetType().type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800320 Variable* v = stubArgs.Get(t);
Casey Dahlin0ee37582015-09-30 16:31:55 -0700321 v->dimension = arg->GetType().dimension;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800322
323 c->statements->Add(new VariableDeclaration(v));
324
Casey Dahlinc378c992015-09-29 16:50:40 -0700325 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800326 generate_create_from_parcel(t, c->statements, v,
327 stubClass->transact_data, &cl);
328 } else {
Casey Dahlin0ee37582015-09-30 16:31:55 -0700329 if (arg->GetType().dimension == 0) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800330 c->statements->Add(new Assignment(v, new NewExpression(v->type)));
331 }
Casey Dahlin0ee37582015-09-30 16:31:55 -0700332 else if (arg->GetType().dimension == 1) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800333 generate_new_array(v->type, c->statements, v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700334 stubClass->transact_data, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800335 }
336 else {
337 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__,
338 __LINE__);
339 }
340 }
341
342 realCall->arguments.push_back(v);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800343 }
344
345 // the real call
346 Variable* _result = NULL;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700347 if (0 == strcmp(method.type->type.data, "void")) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800348 c->statements->Add(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 } else {
357 _result = new Variable(decl->returnType, "_result",
358 decl->returnTypeDimension);
359 c->statements->Add(new VariableDeclaration(_result, realCall));
360
361 if (!oneway) {
362 // report that there were no exceptions
363 MethodCall* ex = new MethodCall(stubClass->transact_reply,
364 "writeNoException", 0);
365 c->statements->Add(ex);
366 }
367
368 // marshall the return value
369 generate_write_to_parcel(decl->returnType, c->statements, _result,
370 stubClass->transact_reply,
371 Type::PARCELABLE_WRITE_RETURN_VALUE);
372 }
373
374 // out parameters
375 i = 0;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700376 for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
Casey Dahlin0ee37582015-09-30 16:31:55 -0700377 const Type* t = types->Find(arg->GetType().type.data);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800378 Variable* v = stubArgs.Get(i++);
379
Casey Dahlinc378c992015-09-29 16:50:40 -0700380 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800381 generate_write_to_parcel(t, c->statements, v,
382 stubClass->transact_reply,
383 Type::PARCELABLE_WRITE_RETURN_VALUE);
384 hasOutParams = true;
385 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800386 }
387
388 // return true
389 c->statements->Add(new ReturnStatement(TRUE_VALUE));
390 stubClass->transact_switch->cases.push_back(c);
391
392 // == the proxy method ===================================================
393 Method* proxy = new Method;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700394 proxy->comment = gather_comments(method.comments_token->extra);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800395 proxy->modifiers = PUBLIC | OVERRIDE;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700396 proxy->returnType = types->Find(method.type->type.data);
397 proxy->returnTypeDimension = method.type->dimension;
398 proxy->name = method.name.data;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800399 proxy->statements = new StatementBlock;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700400 for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800401 proxy->parameters.push_back(new Variable(
Casey Dahlin0ee37582015-09-30 16:31:55 -0700402 types->Find(arg->GetType().type.data), arg->GetName(),
403 arg->GetType().dimension));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800404 }
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700405 proxy->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800406 proxyClass->elements.push_back(proxy);
407
408 // the parcels
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700409 Variable* _data = new Variable(types->ParcelType(), "_data");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800410 proxy->statements->Add(new VariableDeclaration(_data,
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700411 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800412 Variable* _reply = NULL;
413 if (!oneway) {
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700414 _reply = new Variable(types->ParcelType(), "_reply");
415 proxy->statements->Add(
416 new VariableDeclaration(
417 _reply,
418 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800419 }
420
421 // the return value
422 _result = NULL;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700423 if (0 != strcmp(method.type->type.data, "void")) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800424 _result = new Variable(proxy->returnType, "_result",
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700425 method.type->dimension);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800426 proxy->statements->Add(new VariableDeclaration(_result));
427 }
428
429 // try and finally
430 TryStatement* tryStatement = new TryStatement();
431 proxy->statements->Add(tryStatement);
432 FinallyStatement* finallyStatement = new FinallyStatement();
433 proxy->statements->Add(finallyStatement);
434
435 // the interface identifier token: the DESCRIPTOR constant, marshalled as a string
436 tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken",
437 1, new LiteralExpression("DESCRIPTOR")));
438
439 // the parameters
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700440 for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
Casey Dahlin0ee37582015-09-30 16:31:55 -0700441 const Type* t = types->Find(arg->GetType().type.data);
442 Variable* v = new Variable(t, arg->GetName(), arg->GetType().dimension);
Casey Dahlinc378c992015-09-29 16:50:40 -0700443 AidlArgument::Direction dir = arg->GetDirection();
Casey Dahlin0ee37582015-09-30 16:31:55 -0700444 if (dir == AidlArgument::OUT_DIR && arg->GetType().dimension != 0) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800445 IfStatement* checklen = new IfStatement();
446 checklen->expression = new Comparison(v, "==", NULL_VALUE);
447 checklen->statements->Add(new MethodCall(_data, "writeInt", 1,
448 new LiteralExpression("-1")));
449 checklen->elseif = new IfStatement();
450 checklen->elseif->statements->Add(new MethodCall(_data, "writeInt",
451 1, new FieldVariable(v, "length")));
452 tryStatement->statements->Add(checklen);
453 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700454 else if (dir & AidlArgument::IN_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800455 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0);
456 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800457 }
458
459 // the transact call
460 MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4,
461 new LiteralExpression("Stub." + transactCodeName),
462 _data, _reply ? _reply : NULL_VALUE,
463 new LiteralExpression(
464 oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0"));
465 tryStatement->statements->Add(call);
466
467 // throw back exceptions.
468 if (_reply) {
469 MethodCall* ex = new MethodCall(_reply, "readException", 0);
470 tryStatement->statements->Add(ex);
471 }
472
473 // returning and cleanup
474 if (_reply != NULL) {
475 if (_result != NULL) {
476 generate_create_from_parcel(proxy->returnType,
477 tryStatement->statements, _result, _reply, &cl);
478 }
479
480 // the out/inout parameters
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700481 for (const std::unique_ptr<AidlArgument>& arg : *method.args) {
Casey Dahlin0ee37582015-09-30 16:31:55 -0700482 const Type* t = types->Find(arg->GetType().type.data);
483 Variable* v = new Variable(t, arg->GetName(), arg->GetType().dimension);
Casey Dahlinc378c992015-09-29 16:50:40 -0700484 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800485 generate_read_from_parcel(t, tryStatement->statements,
486 v, _reply, &cl);
487 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800488 }
489
490 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
491 }
492 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
493
494 if (_result != NULL) {
495 proxy->statements->Add(new ReturnStatement(_result));
496 }
497}
498
499static void
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700500generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
501 const JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800502{
503 // the interface descriptor transaction handler
504 Case* c = new Case("INTERFACE_TRANSACTION");
505 c->statements->Add(new MethodCall(stub->transact_reply, "writeString",
506 1, new LiteralExpression("DESCRIPTOR")));
507 c->statements->Add(new ReturnStatement(TRUE_VALUE));
508 stub->transact_switch->cases.push_back(c);
509
510 // and the proxy-side method returning the descriptor directly
511 Method* getDesc = new Method;
512 getDesc->modifiers = PUBLIC;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700513 getDesc->returnType = types->StringType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800514 getDesc->returnTypeDimension = 0;
515 getDesc->name = "getInterfaceDescriptor";
516 getDesc->statements = new StatementBlock;
517 getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
518 proxy->elements.push_back(getDesc);
519}
520
521Class*
Christopher Wiley84c1eac2015-09-23 13:29:28 -0700522generate_binder_interface_class(const interface_type* iface,
523 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800524{
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700525 const InterfaceType* interfaceType = static_cast<const InterfaceType*>(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700526 types->Find(iface->package, iface->name.data));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800527
528 // the interface class
529 Class* interface = new Class;
530 interface->comment = gather_comments(iface->comments_token->extra);
531 interface->modifiers = PUBLIC;
532 interface->what = Class::INTERFACE;
533 interface->type = interfaceType;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700534 interface->interfaces.push_back(types->IInterfaceType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800535
536 // the stub inner class
537 StubClass* stub = new StubClass(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700538 types->Find(iface->package, append(iface->name.data, ".Stub").c_str()),
539 interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800540 interface->elements.push_back(stub);
541
542 // the proxy inner class
543 ProxyClass* proxy = new ProxyClass(
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700544 types,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700545 types->Find(iface->package,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800546 append(iface->name.data, ".Stub.Proxy").c_str()),
547 interfaceType);
548 stub->elements.push_back(proxy);
549
550 // stub and proxy support for getInterfaceDescriptor()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700551 generate_interface_descriptors(stub, proxy, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800552
553 // all the declared methods of the interface
554 int index = 0;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700555 for (const auto& item : *iface->methods) {
556 generate_method(*item, interface, stub, proxy,
Casey Dahlindff80e52015-09-29 13:57:06 -0700557 item->assigned_id, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800558 index++;
559 }
560
561 return interface;
562}
563
Christopher Wileydb154a52015-09-28 16:32:25 -0700564} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700565} // namespace android
566} // namespace aidl