blob: b7ae4703b23886a387b02cf9ab0e229fdba14b62 [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 Dahlinf4a93112015-10-05 16:58:09 -0700273 const bool oneway = proxyClass->mOneWay || method.IsOneway();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800274
275 // == the TRANSACT_ constant =============================================
276 string transactCodeName = "TRANSACTION_";
Casey Dahlinf4a93112015-10-05 16:58:09 -0700277 transactCodeName += method.GetName();
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 Dahlinf2d23f72015-10-02 16:19:19 -0700289 decl->comment = method.GetComments();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800290 decl->modifiers = PUBLIC;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700291 decl->returnType = types->Find(method.GetType().GetName());
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700292 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700293 decl->name = method.GetName();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800294
Casey Dahlinf4a93112015-10-05 16:58:09 -0700295 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800296 decl->parameters.push_back(new Variable(
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700297 types->Find(arg->GetType().GetName()), arg->GetName(),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700298 arg->GetType().IsArray() ? 1 : 0));
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 Dahlinf4a93112015-10-05 16:58:09 -0700309 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
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 Dahlinf4a93112015-10-05 16:58:09 -0700318 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700319 const Type* t = types->Find(arg->GetType().GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800320 Variable* v = stubArgs.Get(t);
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700321 v->dimension = arg->GetType().IsArray() ? 1 : 0;
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 Dahlinf7a421c2015-10-05 17:24:28 -0700329 if (!arg->GetType().IsArray()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800330 c->statements->Add(new Assignment(v, new NewExpression(v->type)));
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700331 } else {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800332 generate_new_array(v->type, c->statements, v,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700333 stubClass->transact_data, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800334 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800335 }
336
337 realCall->arguments.push_back(v);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800338 }
339
340 // the real call
341 Variable* _result = NULL;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700342 if (method.GetType().GetName() == "void") {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800343 c->statements->Add(realCall);
344
345 if (!oneway) {
346 // report that there were no exceptions
347 MethodCall* ex = new MethodCall(stubClass->transact_reply,
348 "writeNoException", 0);
349 c->statements->Add(ex);
350 }
351 } else {
352 _result = new Variable(decl->returnType, "_result",
353 decl->returnTypeDimension);
354 c->statements->Add(new VariableDeclaration(_result, realCall));
355
356 if (!oneway) {
357 // report that there were no exceptions
358 MethodCall* ex = new MethodCall(stubClass->transact_reply,
359 "writeNoException", 0);
360 c->statements->Add(ex);
361 }
362
363 // marshall the return value
364 generate_write_to_parcel(decl->returnType, c->statements, _result,
365 stubClass->transact_reply,
366 Type::PARCELABLE_WRITE_RETURN_VALUE);
367 }
368
369 // out parameters
370 i = 0;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700371 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700372 const Type* t = types->Find(arg->GetType().GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800373 Variable* v = stubArgs.Get(i++);
374
Casey Dahlinc378c992015-09-29 16:50:40 -0700375 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800376 generate_write_to_parcel(t, c->statements, v,
377 stubClass->transact_reply,
378 Type::PARCELABLE_WRITE_RETURN_VALUE);
379 hasOutParams = true;
380 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800381 }
382
383 // return true
384 c->statements->Add(new ReturnStatement(TRUE_VALUE));
385 stubClass->transact_switch->cases.push_back(c);
386
387 // == the proxy method ===================================================
388 Method* proxy = new Method;
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700389 proxy->comment = method.GetComments();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800390 proxy->modifiers = PUBLIC | OVERRIDE;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700391 proxy->returnType = types->Find(method.GetType().GetName());
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700392 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700393 proxy->name = method.GetName();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800394 proxy->statements = new StatementBlock;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700395 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800396 proxy->parameters.push_back(new Variable(
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700397 types->Find(arg->GetType().GetName()), arg->GetName(),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700398 arg->GetType().IsArray() ? 1 : 0));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800399 }
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700400 proxy->exceptions.push_back(types->RemoteExceptionType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800401 proxyClass->elements.push_back(proxy);
402
403 // the parcels
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700404 Variable* _data = new Variable(types->ParcelType(), "_data");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800405 proxy->statements->Add(new VariableDeclaration(_data,
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700406 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800407 Variable* _reply = NULL;
408 if (!oneway) {
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700409 _reply = new Variable(types->ParcelType(), "_reply");
410 proxy->statements->Add(
411 new VariableDeclaration(
412 _reply,
413 new MethodCall(types->ParcelType(), "obtain")));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800414 }
415
416 // the return value
417 _result = NULL;
Casey Dahlinf4a93112015-10-05 16:58:09 -0700418 if (method.GetType().GetName() != "void") {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800419 _result = new Variable(proxy->returnType, "_result",
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700420 method.GetType().IsArray() ? 1 : 0);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800421 proxy->statements->Add(new VariableDeclaration(_result));
422 }
423
424 // try and finally
425 TryStatement* tryStatement = new TryStatement();
426 proxy->statements->Add(tryStatement);
427 FinallyStatement* finallyStatement = new FinallyStatement();
428 proxy->statements->Add(finallyStatement);
429
430 // the interface identifier token: the DESCRIPTOR constant, marshalled as a string
431 tryStatement->statements->Add(new MethodCall(_data, "writeInterfaceToken",
432 1, new LiteralExpression("DESCRIPTOR")));
433
434 // the parameters
Casey Dahlinf4a93112015-10-05 16:58:09 -0700435 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700436 const Type* t = types->Find(arg->GetType().GetName());
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700437 Variable* v = new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
Casey Dahlinc378c992015-09-29 16:50:40 -0700438 AidlArgument::Direction dir = arg->GetDirection();
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700439 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800440 IfStatement* checklen = new IfStatement();
441 checklen->expression = new Comparison(v, "==", NULL_VALUE);
442 checklen->statements->Add(new MethodCall(_data, "writeInt", 1,
443 new LiteralExpression("-1")));
444 checklen->elseif = new IfStatement();
445 checklen->elseif->statements->Add(new MethodCall(_data, "writeInt",
446 1, new FieldVariable(v, "length")));
447 tryStatement->statements->Add(checklen);
448 }
Casey Dahlinc378c992015-09-29 16:50:40 -0700449 else if (dir & AidlArgument::IN_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800450 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0);
451 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800452 }
453
454 // the transact call
455 MethodCall* call = new MethodCall(proxyClass->mRemote, "transact", 4,
456 new LiteralExpression("Stub." + transactCodeName),
457 _data, _reply ? _reply : NULL_VALUE,
458 new LiteralExpression(
459 oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0"));
460 tryStatement->statements->Add(call);
461
462 // throw back exceptions.
463 if (_reply) {
464 MethodCall* ex = new MethodCall(_reply, "readException", 0);
465 tryStatement->statements->Add(ex);
466 }
467
468 // returning and cleanup
469 if (_reply != NULL) {
470 if (_result != NULL) {
471 generate_create_from_parcel(proxy->returnType,
472 tryStatement->statements, _result, _reply, &cl);
473 }
474
475 // the out/inout parameters
Casey Dahlinf4a93112015-10-05 16:58:09 -0700476 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700477 const Type* t = types->Find(arg->GetType().GetName());
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700478 Variable* v = new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
Casey Dahlinc378c992015-09-29 16:50:40 -0700479 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Adam Lesinskiffa16862014-01-23 18:17:42 -0800480 generate_read_from_parcel(t, tryStatement->statements,
481 v, _reply, &cl);
482 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800483 }
484
485 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
486 }
487 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
488
489 if (_result != NULL) {
490 proxy->statements->Add(new ReturnStatement(_result));
491 }
492}
493
494static void
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700495generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
496 const JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800497{
498 // the interface descriptor transaction handler
499 Case* c = new Case("INTERFACE_TRANSACTION");
500 c->statements->Add(new MethodCall(stub->transact_reply, "writeString",
501 1, new LiteralExpression("DESCRIPTOR")));
502 c->statements->Add(new ReturnStatement(TRUE_VALUE));
503 stub->transact_switch->cases.push_back(c);
504
505 // and the proxy-side method returning the descriptor directly
506 Method* getDesc = new Method;
507 getDesc->modifiers = PUBLIC;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700508 getDesc->returnType = types->StringType();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800509 getDesc->returnTypeDimension = 0;
510 getDesc->name = "getInterfaceDescriptor";
511 getDesc->statements = new StatementBlock;
512 getDesc->statements->Add(new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
513 proxy->elements.push_back(getDesc);
514}
515
516Class*
Christopher Wiley84c1eac2015-09-23 13:29:28 -0700517generate_binder_interface_class(const interface_type* iface,
518 JavaTypeNamespace* types)
Adam Lesinskiffa16862014-01-23 18:17:42 -0800519{
Christopher Wiley8f6816e2015-09-22 17:03:47 -0700520 const InterfaceType* interfaceType = static_cast<const InterfaceType*>(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700521 types->Find(iface->package, iface->name.data));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800522
523 // the interface class
524 Class* interface = new Class;
525 interface->comment = gather_comments(iface->comments_token->extra);
526 interface->modifiers = PUBLIC;
527 interface->what = Class::INTERFACE;
528 interface->type = interfaceType;
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700529 interface->interfaces.push_back(types->IInterfaceType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800530
531 // the stub inner class
532 StubClass* stub = new StubClass(
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700533 types->Find(iface->package, append(iface->name.data, ".Stub").c_str()),
534 interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800535 interface->elements.push_back(stub);
536
537 // the proxy inner class
538 ProxyClass* proxy = new ProxyClass(
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700539 types,
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -0700540 types->Find(iface->package,
Adam Lesinskiffa16862014-01-23 18:17:42 -0800541 append(iface->name.data, ".Stub.Proxy").c_str()),
542 interfaceType);
543 stub->elements.push_back(proxy);
544
545 // stub and proxy support for getInterfaceDescriptor()
Christopher Wiley60b02ae2015-09-23 16:35:18 -0700546 generate_interface_descriptors(stub, proxy, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800547
548 // all the declared methods of the interface
549 int index = 0;
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700550 for (const auto& item : *iface->methods) {
551 generate_method(*item, interface, stub, proxy,
Casey Dahlinf4a93112015-10-05 16:58:09 -0700552 item->GetId(), types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800553 index++;
554 }
555
556 return interface;
557}
558
Christopher Wileydb154a52015-09-28 16:32:25 -0700559} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700560} // namespace android
561} // namespace aidl