1 /*
2 * Copyright (C) 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "generate_java.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <string.h>
23
24 #include <android-base/macros.h>
25
26 #include "type_java.h"
27
28 using std::string;
29
30 namespace android {
31 namespace aidl {
32 namespace java {
33
34 // =================================================
35 class StubClass : public Class {
36 public:
37 StubClass(const Type* type, const InterfaceType* interfaceType,
38 JavaTypeNamespace* types);
39 virtual ~StubClass() = default;
40
41 Variable* transact_code;
42 Variable* transact_data;
43 Variable* transact_reply;
44 Variable* transact_flags;
45 SwitchStatement* transact_switch;
46
47 private:
48 void make_as_interface(const InterfaceType* interfaceType,
49 JavaTypeNamespace* types);
50
51 DISALLOW_COPY_AND_ASSIGN(StubClass);
52 };
53
StubClass(const Type * type,const InterfaceType * interfaceType,JavaTypeNamespace * types)54 StubClass::StubClass(const Type* type, const InterfaceType* interfaceType,
55 JavaTypeNamespace* types)
56 : Class() {
57 this->comment = "/** Local-side IPC implementation stub class. */";
58 this->modifiers = PUBLIC | ABSTRACT | STATIC;
59 this->what = Class::CLASS;
60 this->type = type;
61 this->extends = types->BinderNativeType();
62 this->interfaces.push_back(interfaceType);
63
64 // descriptor
65 Field* descriptor =
66 new Field(STATIC | FINAL | PRIVATE,
67 new Variable(types->StringType(), "DESCRIPTOR"));
68 descriptor->value = "\"" + interfaceType->JavaType() + "\"";
69 this->elements.push_back(descriptor);
70
71 // ctor
72 Method* ctor = new Method;
73 ctor->modifiers = PUBLIC;
74 ctor->comment =
75 "/** Construct the stub at attach it to the "
76 "interface. */";
77 ctor->name = "Stub";
78 ctor->statements = new StatementBlock;
79 MethodCall* attach =
80 new MethodCall(THIS_VALUE, "attachInterface", 2, THIS_VALUE,
81 new LiteralExpression("DESCRIPTOR"));
82 ctor->statements->Add(attach);
83 this->elements.push_back(ctor);
84
85 // asInterface
86 make_as_interface(interfaceType, types);
87
88 // asBinder
89 Method* asBinder = new Method;
90 asBinder->modifiers = PUBLIC | OVERRIDE;
91 asBinder->returnType = types->IBinderType();
92 asBinder->name = "asBinder";
93 asBinder->statements = new StatementBlock;
94 asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
95 this->elements.push_back(asBinder);
96
97 // onTransact
98 this->transact_code = new Variable(types->IntType(), "code");
99 this->transact_data = new Variable(types->ParcelType(), "data");
100 this->transact_reply = new Variable(types->ParcelType(), "reply");
101 this->transact_flags = new Variable(types->IntType(), "flags");
102 Method* onTransact = new Method;
103 onTransact->modifiers = PUBLIC | OVERRIDE;
104 onTransact->returnType = types->BoolType();
105 onTransact->name = "onTransact";
106 onTransact->parameters.push_back(this->transact_code);
107 onTransact->parameters.push_back(this->transact_data);
108 onTransact->parameters.push_back(this->transact_reply);
109 onTransact->parameters.push_back(this->transact_flags);
110 onTransact->statements = new StatementBlock;
111 onTransact->exceptions.push_back(types->RemoteExceptionType());
112 this->elements.push_back(onTransact);
113 this->transact_switch = new SwitchStatement(this->transact_code);
114
115 onTransact->statements->Add(this->transact_switch);
116 MethodCall* superCall = new MethodCall(
117 SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data,
118 this->transact_reply, this->transact_flags);
119 onTransact->statements->Add(new ReturnStatement(superCall));
120 }
121
make_as_interface(const InterfaceType * interfaceType,JavaTypeNamespace * types)122 void StubClass::make_as_interface(const InterfaceType* interfaceType,
123 JavaTypeNamespace* types) {
124 Variable* obj = new Variable(types->IBinderType(), "obj");
125
126 Method* m = new Method;
127 m->comment = "/**\n * Cast an IBinder object into an ";
128 m->comment += interfaceType->JavaType();
129 m->comment += " interface,\n";
130 m->comment += " * generating a proxy if needed.\n */";
131 m->modifiers = PUBLIC | STATIC;
132 m->returnType = interfaceType;
133 m->name = "asInterface";
134 m->parameters.push_back(obj);
135 m->statements = new StatementBlock;
136
137 IfStatement* ifstatement = new IfStatement();
138 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
139 ifstatement->statements = new StatementBlock;
140 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
141 m->statements->Add(ifstatement);
142
143 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
144 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
145 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
146 IInterfaceType* iinType = new IInterfaceType(types);
147 Variable* iin = new Variable(iinType, "iin");
148 VariableDeclaration* iinVd =
149 new VariableDeclaration(iin, queryLocalInterface, NULL);
150 m->statements->Add(iinVd);
151
152 // Ensure the instance type of the local object is as expected.
153 // One scenario where this is needed is if another package (with a
154 // different class loader) runs in the same process as the service.
155
156 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
157 // iin;
158 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
159 Comparison* instOfCheck =
160 new Comparison(iin, " instanceof ",
161 new LiteralExpression(interfaceType->JavaType()));
162 IfStatement* instOfStatement = new IfStatement();
163 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
164 instOfStatement->statements = new StatementBlock;
165 instOfStatement->statements->Add(
166 new ReturnStatement(new Cast(interfaceType, iin)));
167 m->statements->Add(instOfStatement);
168
169 NewExpression* ne = new NewExpression(interfaceType->GetProxy());
170 ne->arguments.push_back(obj);
171 m->statements->Add(new ReturnStatement(ne));
172
173 this->elements.push_back(m);
174 }
175
176 // =================================================
177 class ProxyClass : public Class {
178 public:
179 ProxyClass(const JavaTypeNamespace* types, const Type* type,
180 const InterfaceType* interfaceType);
181 virtual ~ProxyClass();
182
183 Variable* mRemote;
184 bool mOneWay;
185 };
186
ProxyClass(const JavaTypeNamespace * types,const Type * type,const InterfaceType * interfaceType)187 ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type,
188 const InterfaceType* interfaceType)
189 : Class() {
190 this->modifiers = PRIVATE | STATIC;
191 this->what = Class::CLASS;
192 this->type = type;
193 this->interfaces.push_back(interfaceType);
194
195 mOneWay = interfaceType->OneWay();
196
197 // IBinder mRemote
198 mRemote = new Variable(types->IBinderType(), "mRemote");
199 this->elements.push_back(new Field(PRIVATE, mRemote));
200
201 // Proxy()
202 Variable* remote = new Variable(types->IBinderType(), "remote");
203 Method* ctor = new Method;
204 ctor->name = "Proxy";
205 ctor->statements = new StatementBlock;
206 ctor->parameters.push_back(remote);
207 ctor->statements->Add(new Assignment(mRemote, remote));
208 this->elements.push_back(ctor);
209
210 // IBinder asBinder()
211 Method* asBinder = new Method;
212 asBinder->modifiers = PUBLIC | OVERRIDE;
213 asBinder->returnType = types->IBinderType();
214 asBinder->name = "asBinder";
215 asBinder->statements = new StatementBlock;
216 asBinder->statements->Add(new ReturnStatement(mRemote));
217 this->elements.push_back(asBinder);
218 }
219
~ProxyClass()220 ProxyClass::~ProxyClass() {}
221
222 // =================================================
generate_new_array(const Type * t,StatementBlock * addTo,Variable * v,Variable * parcel,JavaTypeNamespace * types)223 static void generate_new_array(const Type* t, StatementBlock* addTo,
224 Variable* v, Variable* parcel,
225 JavaTypeNamespace* types) {
226 Variable* len = new Variable(types->IntType(), v->name + "_length");
227 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
228 IfStatement* lencheck = new IfStatement();
229 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
230 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
231 lencheck->elseif = new IfStatement();
232 lencheck->elseif->statements->Add(
233 new Assignment(v, new NewArrayExpression(t, len)));
234 addTo->Add(lencheck);
235 }
236
generate_write_to_parcel(const Type * t,StatementBlock * addTo,Variable * v,Variable * parcel,int flags)237 static void generate_write_to_parcel(const Type* t, StatementBlock* addTo,
238 Variable* v, Variable* parcel, int flags) {
239 t->WriteToParcel(addTo, v, parcel, flags);
240 }
241
generate_create_from_parcel(const Type * t,StatementBlock * addTo,Variable * v,Variable * parcel,Variable ** cl)242 static void generate_create_from_parcel(const Type* t, StatementBlock* addTo,
243 Variable* v, Variable* parcel,
244 Variable** cl) {
245 t->CreateFromParcel(addTo, v, parcel, cl);
246 }
247
generate_int_constant(const AidlIntConstant & constant,Class * interface)248 static void generate_int_constant(const AidlIntConstant& constant,
249 Class* interface) {
250 IntConstant* decl = new IntConstant(constant.GetName(), constant.GetValue());
251 interface->elements.push_back(decl);
252 }
253
generate_string_constant(const AidlStringConstant & constant,Class * interface)254 static void generate_string_constant(const AidlStringConstant& constant,
255 Class* interface) {
256 StringConstant* decl = new StringConstant(constant.GetName(),
257 constant.GetValue());
258 interface->elements.push_back(decl);
259 }
260
generate_method(const AidlMethod & method,Class * interface,StubClass * stubClass,ProxyClass * proxyClass,int index,JavaTypeNamespace * types)261 static void generate_method(const AidlMethod& method, Class* interface,
262 StubClass* stubClass, ProxyClass* proxyClass,
263 int index, JavaTypeNamespace* types) {
264 int i;
265
266 const bool oneway = proxyClass->mOneWay || method.IsOneway();
267
268 // == the TRANSACT_ constant =============================================
269 string transactCodeName = "TRANSACTION_";
270 transactCodeName += method.GetName();
271
272 char transactCodeValue[60];
273 sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)",
274 index);
275
276 Field* transactCode = new Field(
277 STATIC | FINAL, new Variable(types->IntType(), transactCodeName));
278 transactCode->value = transactCodeValue;
279 stubClass->elements.push_back(transactCode);
280
281 // == the declaration in the interface ===================================
282 Method* decl = new Method;
283 decl->comment = method.GetComments();
284 decl->modifiers = PUBLIC;
285 decl->returnType = method.GetType().GetLanguageType<Type>();
286 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
287 decl->name = method.GetName();
288
289 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
290 decl->parameters.push_back(
291 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(),
292 arg->GetType().IsArray() ? 1 : 0));
293 }
294
295 decl->exceptions.push_back(types->RemoteExceptionType());
296
297 interface->elements.push_back(decl);
298
299 // == the stub method ====================================================
300
301 Case* c = new Case(transactCodeName);
302
303 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
304
305 // interface token validation is the very first thing we do
306 c->statements->Add(new MethodCall(stubClass->transact_data,
307 "enforceInterface", 1,
308 new LiteralExpression("DESCRIPTOR")));
309
310 // args
311 Variable* cl = NULL;
312 VariableFactory stubArgs("_arg");
313 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
314 const Type* t = arg->GetType().GetLanguageType<Type>();
315 Variable* v = stubArgs.Get(t);
316 v->dimension = arg->GetType().IsArray() ? 1 : 0;
317
318 c->statements->Add(new VariableDeclaration(v));
319
320 if (arg->GetDirection() & AidlArgument::IN_DIR) {
321 generate_create_from_parcel(t, c->statements, v, stubClass->transact_data,
322 &cl);
323 } else {
324 if (!arg->GetType().IsArray()) {
325 c->statements->Add(new Assignment(v, new NewExpression(v->type)));
326 } else {
327 generate_new_array(v->type, c->statements, v, stubClass->transact_data,
328 types);
329 }
330 }
331
332 realCall->arguments.push_back(v);
333 }
334
335 cl = NULL;
336
337 // the real call
338 Variable* _result = NULL;
339 if (method.GetType().GetName() == "void") {
340 c->statements->Add(realCall);
341
342 if (!oneway) {
343 // report that there were no exceptions
344 MethodCall* ex =
345 new MethodCall(stubClass->transact_reply, "writeNoException", 0);
346 c->statements->Add(ex);
347 }
348 } else {
349 _result =
350 new Variable(decl->returnType, "_result", decl->returnTypeDimension);
351 c->statements->Add(new VariableDeclaration(_result, realCall));
352
353 if (!oneway) {
354 // report that there were no exceptions
355 MethodCall* ex =
356 new MethodCall(stubClass->transact_reply, "writeNoException", 0);
357 c->statements->Add(ex);
358 }
359
360 // marshall the return value
361 generate_write_to_parcel(decl->returnType, c->statements, _result,
362 stubClass->transact_reply,
363 Type::PARCELABLE_WRITE_RETURN_VALUE);
364 }
365
366 // out parameters
367 i = 0;
368 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
369 const Type* t = arg->GetType().GetLanguageType<Type>();
370 Variable* v = stubArgs.Get(i++);
371
372 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
373 generate_write_to_parcel(t, c->statements, v, stubClass->transact_reply,
374 Type::PARCELABLE_WRITE_RETURN_VALUE);
375 }
376 }
377
378 // return true
379 c->statements->Add(new ReturnStatement(TRUE_VALUE));
380 stubClass->transact_switch->cases.push_back(c);
381
382 // == the proxy method ===================================================
383 Method* proxy = new Method;
384 proxy->comment = method.GetComments();
385 proxy->modifiers = PUBLIC | OVERRIDE;
386 proxy->returnType = method.GetType().GetLanguageType<Type>();
387 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
388 proxy->name = method.GetName();
389 proxy->statements = new StatementBlock;
390 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
391 proxy->parameters.push_back(
392 new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(),
393 arg->GetType().IsArray() ? 1 : 0));
394 }
395 proxy->exceptions.push_back(types->RemoteExceptionType());
396 proxyClass->elements.push_back(proxy);
397
398 // the parcels
399 Variable* _data = new Variable(types->ParcelType(), "_data");
400 proxy->statements->Add(new VariableDeclaration(
401 _data, new MethodCall(types->ParcelType(), "obtain")));
402 Variable* _reply = NULL;
403 if (!oneway) {
404 _reply = new Variable(types->ParcelType(), "_reply");
405 proxy->statements->Add(new VariableDeclaration(
406 _reply, new MethodCall(types->ParcelType(), "obtain")));
407 }
408
409 // the return value
410 _result = NULL;
411 if (method.GetType().GetName() != "void") {
412 _result = new Variable(proxy->returnType, "_result",
413 method.GetType().IsArray() ? 1 : 0);
414 proxy->statements->Add(new VariableDeclaration(_result));
415 }
416
417 // try and finally
418 TryStatement* tryStatement = new TryStatement();
419 proxy->statements->Add(tryStatement);
420 FinallyStatement* finallyStatement = new FinallyStatement();
421 proxy->statements->Add(finallyStatement);
422
423 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
424 // string
425 tryStatement->statements->Add(new MethodCall(
426 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR")));
427
428 // the parameters
429 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
430 const Type* t = arg->GetType().GetLanguageType<Type>();
431 Variable* v =
432 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
433 AidlArgument::Direction dir = arg->GetDirection();
434 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
435 IfStatement* checklen = new IfStatement();
436 checklen->expression = new Comparison(v, "==", NULL_VALUE);
437 checklen->statements->Add(
438 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1")));
439 checklen->elseif = new IfStatement();
440 checklen->elseif->statements->Add(
441 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length")));
442 tryStatement->statements->Add(checklen);
443 } else if (dir & AidlArgument::IN_DIR) {
444 generate_write_to_parcel(t, tryStatement->statements, v, _data, 0);
445 } else {
446 delete v;
447 }
448 }
449
450 // the transact call
451 MethodCall* call = new MethodCall(
452 proxyClass->mRemote, "transact", 4,
453 new LiteralExpression("Stub." + transactCodeName), _data,
454 _reply ? _reply : NULL_VALUE,
455 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0"));
456 tryStatement->statements->Add(call);
457
458 // throw back exceptions.
459 if (_reply) {
460 MethodCall* ex = new MethodCall(_reply, "readException", 0);
461 tryStatement->statements->Add(ex);
462 }
463
464 // returning and cleanup
465 if (_reply != NULL) {
466 if (_result != NULL) {
467 generate_create_from_parcel(proxy->returnType, tryStatement->statements,
468 _result, _reply, &cl);
469 }
470
471 // the out/inout parameters
472 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
473 const Type* t = arg->GetType().GetLanguageType<Type>();
474 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
475 Variable* v =
476 new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
477 t->ReadFromParcel(tryStatement->statements, v, _reply, &cl);
478 }
479 }
480
481 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
482 }
483 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
484
485 if (_result != NULL) {
486 proxy->statements->Add(new ReturnStatement(_result));
487 }
488 }
489
generate_interface_descriptors(StubClass * stub,ProxyClass * proxy,const JavaTypeNamespace * types)490 static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
491 const JavaTypeNamespace* types) {
492 // the interface descriptor transaction handler
493 Case* c = new Case("INTERFACE_TRANSACTION");
494 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1,
495 new LiteralExpression("DESCRIPTOR")));
496 c->statements->Add(new ReturnStatement(TRUE_VALUE));
497 stub->transact_switch->cases.push_back(c);
498
499 // and the proxy-side method returning the descriptor directly
500 Method* getDesc = new Method;
501 getDesc->modifiers = PUBLIC;
502 getDesc->returnType = types->StringType();
503 getDesc->returnTypeDimension = 0;
504 getDesc->name = "getInterfaceDescriptor";
505 getDesc->statements = new StatementBlock;
506 getDesc->statements->Add(
507 new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
508 proxy->elements.push_back(getDesc);
509 }
510
generate_binder_interface_class(const AidlInterface * iface,JavaTypeNamespace * types)511 Class* generate_binder_interface_class(const AidlInterface* iface,
512 JavaTypeNamespace* types) {
513 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>();
514
515 // the interface class
516 Class* interface = new Class;
517 interface->comment = iface->GetComments();
518 interface->modifiers = PUBLIC;
519 interface->what = Class::INTERFACE;
520 interface->type = interfaceType;
521 interface->interfaces.push_back(types->IInterfaceType());
522
523 // the stub inner class
524 StubClass* stub =
525 new StubClass(interfaceType->GetStub(), interfaceType, types);
526 interface->elements.push_back(stub);
527
528 // the proxy inner class
529 ProxyClass* proxy =
530 new ProxyClass(types, interfaceType->GetProxy(), interfaceType);
531 stub->elements.push_back(proxy);
532
533 // stub and proxy support for getInterfaceDescriptor()
534 generate_interface_descriptors(stub, proxy, types);
535
536 // all the declared constants of the interface
537 for (const auto& item : iface->GetIntConstants()) {
538 generate_int_constant(*item, interface);
539 }
540 for (const auto& item : iface->GetStringConstants()) {
541 generate_string_constant(*item, interface);
542 }
543
544 // all the declared methods of the interface
545 for (const auto& item : iface->GetMethods()) {
546 generate_method(*item, interface, stub, proxy, item->GetId(), types);
547 }
548
549 return interface;
550 }
551
552 } // namespace java
553 } // namespace android
554 } // namespace aidl
555