blob: d9764bed9771598c38d08872966af6490beb0292 [file] [log] [blame]
Christopher Wiley3a9da172016-01-29 11:10:49 -08001/*
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
Jiyong Park309668e2018-07-28 16:55:44 +090017#include "aidl.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090018#include "aidl_to_java.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080019#include "generate_java.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090020#include "options.h"
21#include "type_java.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070022
Adam Lesinskiffa16862014-01-23 18:17:42 -080023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
Andreas Gampee9c816e2018-03-14 09:05:48 -070027#include <algorithm>
28#include <unordered_set>
Jiyong Park1d2df7d2018-07-23 15:22:50 +090029#include <utility>
30#include <vector>
Andreas Gampee9c816e2018-03-14 09:05:48 -070031
Elliott Hughes0a620672015-12-04 13:53:18 -080032#include <android-base/macros.h>
Andreas Gampe7d7fa602017-11-22 10:50:03 -080033#include <android-base/stringprintf.h>
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070034
Jiyong Park75e1a742018-07-04 12:31:23 +090035using android::base::Join;
Andreas Gampe7d7fa602017-11-22 10:50:03 -080036using android::base::StringPrintf;
Jiyong Park1d2df7d2018-07-23 15:22:50 +090037
Jiyong Park75e1a742018-07-04 12:31:23 +090038using std::string;
39using std::unique_ptr;
40using std::vector;
Andreas Gampe7d7fa602017-11-22 10:50:03 -080041
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070042namespace android {
43namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070044namespace java {
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070045
Adam Lesinskiffa16862014-01-23 18:17:42 -080046// =================================================
Jiyong Park2c44f072018-07-30 21:52:21 +090047class VariableFactory {
48 public:
49 using Variable = ::android::aidl::java::Variable;
50 using Type = ::android::aidl::java::Type;
51
52 explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
53 Variable* Get(const Type* type) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +090054 Variable* v = new Variable(type->JavaType(), StringPrintf("%s%d", base_.c_str(), index_));
Jiyong Park2c44f072018-07-30 21:52:21 +090055 vars_.push_back(v);
56 index_++;
57 return v;
58 }
59
60 Variable* Get(int index) { return vars_[index]; }
61
62 private:
63 std::vector<Variable*> vars_;
64 std::string base_;
65 int index_;
66
67 DISALLOW_COPY_AND_ASSIGN(VariableFactory);
68};
69
70// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -080071class StubClass : public Class {
72 public:
Jiyong Park74595c12018-07-23 15:22:50 +090073 StubClass(const Type* type, const InterfaceType* interfaceType, JavaTypeNamespace* types,
74 const Options& options);
Yi Kongde138912019-03-30 01:38:17 -070075 ~StubClass() override = default;
Adam Lesinskiffa16862014-01-23 18:17:42 -080076
Christopher Wiley67502f12016-01-29 10:57:00 -080077 Variable* transact_code;
78 Variable* transact_data;
79 Variable* transact_reply;
80 Variable* transact_flags;
81 SwitchStatement* transact_switch;
Andreas Gampe7fab0d12017-11-22 17:50:17 -080082 StatementBlock* transact_statements;
Olivier Gaillard11401402018-07-05 15:01:34 +010083 SwitchStatement* code_to_method_name_switch;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070084
Andreas Gampe1b865af2017-11-22 11:31:47 -080085 // Where onTransact cases should be generated as separate methods.
86 bool transact_outline;
Andreas Gampee9c816e2018-03-14 09:05:48 -070087 // Specific methods that should be outlined when transact_outline is true.
88 std::unordered_set<const AidlMethod*> outline_methods;
89 // Number of all methods.
90 size_t all_method_count;
Andreas Gampe1b865af2017-11-22 11:31:47 -080091
Andreas Gampea8a66fe2017-11-22 12:17:00 -080092 // Finish generation. This will add a default case to the switch.
93 void finish();
94
Andreas Gampee9c816e2018-03-14 09:05:48 -070095 Expression* get_transact_descriptor(const JavaTypeNamespace* types,
96 const AidlMethod* method);
Andreas Gampe7fab0d12017-11-22 17:50:17 -080097
Christopher Wiley67502f12016-01-29 10:57:00 -080098 private:
99 void make_as_interface(const InterfaceType* interfaceType,
100 JavaTypeNamespace* types);
101
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800102 Variable* transact_descriptor;
Jiyong Park74595c12018-07-23 15:22:50 +0900103 const Options& options_;
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800104
Christopher Wiley67502f12016-01-29 10:57:00 -0800105 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800106};
107
Jiyong Park74595c12018-07-23 15:22:50 +0900108StubClass::StubClass(const Type* type, const InterfaceType* interfaceType, JavaTypeNamespace* types,
109 const Options& options)
Olivier Gaillard11401402018-07-05 15:01:34 +0100110 : Class(), options_(options) {
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800111 transact_descriptor = nullptr;
Andreas Gampe1b865af2017-11-22 11:31:47 -0800112 transact_outline = false;
Andreas Gampee9c816e2018-03-14 09:05:48 -0700113 all_method_count = 0; // Will be set when outlining may be enabled.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800114
Christopher Wiley67502f12016-01-29 10:57:00 -0800115 this->comment = "/** Local-side IPC implementation stub class. */";
116 this->modifiers = PUBLIC | ABSTRACT | STATIC;
117 this->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900118 this->type = type->JavaType();
119 this->extends = types->BinderNativeType()->JavaType();
120 this->interfaces.push_back(interfaceType->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800121
Christopher Wiley67502f12016-01-29 10:57:00 -0800122 // descriptor
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900123 Field* descriptor = new Field(STATIC | FINAL | PRIVATE,
124 new Variable(types->StringType()->JavaType(), "DESCRIPTOR"));
Christopher Wileyd21bfee2016-01-29 15:11:38 -0800125 descriptor->value = "\"" + interfaceType->JavaType() + "\"";
Christopher Wiley67502f12016-01-29 10:57:00 -0800126 this->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800127
Christopher Wiley67502f12016-01-29 10:57:00 -0800128 // ctor
129 Method* ctor = new Method;
130 ctor->modifiers = PUBLIC;
131 ctor->comment =
132 "/** Construct the stub at attach it to the "
133 "interface. */";
134 ctor->name = "Stub";
135 ctor->statements = new StatementBlock;
136 MethodCall* attach =
137 new MethodCall(THIS_VALUE, "attachInterface", 2, THIS_VALUE,
138 new LiteralExpression("DESCRIPTOR"));
139 ctor->statements->Add(attach);
140 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800141
Christopher Wiley67502f12016-01-29 10:57:00 -0800142 // asInterface
143 make_as_interface(interfaceType, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800144
Christopher Wiley67502f12016-01-29 10:57:00 -0800145 // asBinder
146 Method* asBinder = new Method;
147 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900148 asBinder->returnType = types->IBinderType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800149 asBinder->name = "asBinder";
150 asBinder->statements = new StatementBlock;
151 asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
152 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800153
Jiyong Park74595c12018-07-23 15:22:50 +0900154 if (options_.GenTransactionNames()) {
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100155 // getDefaultTransactionName
156 Method* getDefaultTransactionName = new Method;
157 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900158 getDefaultTransactionName->returnType = types->StringType()->JavaType();
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100159 getDefaultTransactionName->name = "getDefaultTransactionName";
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900160 Variable* code = new Variable(types->IntType()->JavaType(), "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100161 getDefaultTransactionName->parameters.push_back(code);
162 getDefaultTransactionName->statements = new StatementBlock;
163 this->code_to_method_name_switch = new SwitchStatement(code);
164 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
165 this->elements.push_back(getDefaultTransactionName);
166
167 // getTransactionName
Olivier Gaillard11401402018-07-05 15:01:34 +0100168 Method* getTransactionName = new Method;
169 getTransactionName->modifiers = PUBLIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900170 getTransactionName->returnType = types->StringType()->JavaType();
Olivier Gaillard11401402018-07-05 15:01:34 +0100171 getTransactionName->name = "getTransactionName";
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900172 Variable* code2 = new Variable(types->IntType()->JavaType(), "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100173 getTransactionName->parameters.push_back(code2);
Olivier Gaillard11401402018-07-05 15:01:34 +0100174 getTransactionName->statements = new StatementBlock;
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100175 getTransactionName->statements->Add(
176 new ReturnStatement(new MethodCall(THIS_VALUE, "getDefaultTransactionName", 1, code2)));
Olivier Gaillard11401402018-07-05 15:01:34 +0100177 this->elements.push_back(getTransactionName);
178 }
179
Christopher Wiley67502f12016-01-29 10:57:00 -0800180 // onTransact
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900181 this->transact_code = new Variable(types->IntType()->JavaType(), "code");
182 this->transact_data = new Variable(types->ParcelType()->JavaType(), "data");
183 this->transact_reply = new Variable(types->ParcelType()->JavaType(), "reply");
184 this->transact_flags = new Variable(types->IntType()->JavaType(), "flags");
Christopher Wiley67502f12016-01-29 10:57:00 -0800185 Method* onTransact = new Method;
186 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900187 onTransact->returnType = types->BoolType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800188 onTransact->name = "onTransact";
189 onTransact->parameters.push_back(this->transact_code);
190 onTransact->parameters.push_back(this->transact_data);
191 onTransact->parameters.push_back(this->transact_reply);
192 onTransact->parameters.push_back(this->transact_flags);
193 onTransact->statements = new StatementBlock;
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800194 transact_statements = onTransact->statements;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900195 onTransact->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Christopher Wiley67502f12016-01-29 10:57:00 -0800196 this->elements.push_back(onTransact);
197 this->transact_switch = new SwitchStatement(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800198}
199
200void StubClass::finish() {
201 Case* default_case = new Case;
202
Christopher Wiley67502f12016-01-29 10:57:00 -0800203 MethodCall* superCall = new MethodCall(
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800204 SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data,
205 this->transact_reply, this->transact_flags);
206 default_case->statements->Add(new ReturnStatement(superCall));
207 transact_switch->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800208
209 transact_statements->Add(this->transact_switch);
Olivier Gaillard11401402018-07-05 15:01:34 +0100210
211 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900212 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100213 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
214 // Common transaction codes will not be resolved to a string by getTransactionName. The method
215 // will return NULL in this case.
216 Case* code_switch_default_case = new Case;
217 code_switch_default_case->statements->Add(new ReturnStatement(NULL_VALUE));
218 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
219 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800220}
221
Andreas Gampee9c816e2018-03-14 09:05:48 -0700222// The the expression for the interface's descriptor to be used when
223// generating code for the given method. Null is acceptable for method
224// and stands for synthetic cases.
225Expression* StubClass::get_transact_descriptor(const JavaTypeNamespace* types,
226 const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800227 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700228 if (method != nullptr) {
229 // When outlining, each outlined method needs its own literal.
230 if (outline_methods.count(method) != 0) {
231 return new LiteralExpression("DESCRIPTOR");
232 }
233 } else {
234 // Synthetic case. A small number is assumed. Use its own descriptor
235 // if there are only synthetic cases.
236 if (outline_methods.size() == all_method_count) {
237 return new LiteralExpression("DESCRIPTOR");
238 }
239 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800240 }
241
Andreas Gampee9c816e2018-03-14 09:05:48 -0700242 // When not outlining, store the descriptor literal into a local variable, in
243 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800244 if (transact_descriptor == nullptr) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900245 transact_descriptor = new Variable(types->StringType()->JavaType(), "descriptor");
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800246 transact_statements->Add(
247 new VariableDeclaration(transact_descriptor,
248 new LiteralExpression("DESCRIPTOR")));
249 }
250 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800251}
252
Christopher Wiley67502f12016-01-29 10:57:00 -0800253void StubClass::make_as_interface(const InterfaceType* interfaceType,
254 JavaTypeNamespace* types) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900255 Variable* obj = new Variable(types->IBinderType()->JavaType(), "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800256
257 Method* m = new Method;
258 m->comment = "/**\n * Cast an IBinder object into an ";
Christopher Wileyd21bfee2016-01-29 15:11:38 -0800259 m->comment += interfaceType->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800260 m->comment += " interface,\n";
261 m->comment += " * generating a proxy if needed.\n */";
262 m->modifiers = PUBLIC | STATIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900263 m->returnType = interfaceType->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800264 m->name = "asInterface";
265 m->parameters.push_back(obj);
266 m->statements = new StatementBlock;
267
268 IfStatement* ifstatement = new IfStatement();
269 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
270 ifstatement->statements = new StatementBlock;
271 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
272 m->statements->Add(ifstatement);
273
274 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
275 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
276 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
George Burgess IV478cec32019-03-19 17:54:47 -0700277 IInterfaceType iinType(types);
278 Variable* iin = new Variable(iinType.JavaType(), "iin");
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900279 VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800280 m->statements->Add(iinVd);
281
282 // Ensure the instance type of the local object is as expected.
283 // One scenario where this is needed is if another package (with a
284 // different class loader) runs in the same process as the service.
285
286 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
287 // iin;
288 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
289 Comparison* instOfCheck =
290 new Comparison(iin, " instanceof ",
Christopher Wileyd21bfee2016-01-29 15:11:38 -0800291 new LiteralExpression(interfaceType->JavaType()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800292 IfStatement* instOfStatement = new IfStatement();
293 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
294 instOfStatement->statements = new StatementBlock;
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900295 instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType->JavaType(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800296 m->statements->Add(instOfStatement);
297
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900298 NewExpression* ne = new NewExpression(interfaceType->GetProxy()->InstantiableName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800299 ne->arguments.push_back(obj);
300 m->statements->Add(new ReturnStatement(ne));
301
302 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800303}
304
Adam Lesinskiffa16862014-01-23 18:17:42 -0800305// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800306class ProxyClass : public Class {
307 public:
Jiyong Park309668e2018-07-28 16:55:44 +0900308 ProxyClass(const JavaTypeNamespace* types, const Type* type, const InterfaceType* interfaceType,
309 const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700310 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800311
Christopher Wiley67502f12016-01-29 10:57:00 -0800312 Variable* mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800313};
314
Christopher Wiley67502f12016-01-29 10:57:00 -0800315ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type,
Jiyong Park309668e2018-07-28 16:55:44 +0900316 const InterfaceType* interfaceType, const Options& options)
Christopher Wiley67502f12016-01-29 10:57:00 -0800317 : Class() {
318 this->modifiers = PRIVATE | STATIC;
319 this->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900320 this->type = type->JavaType();
321 this->interfaces.push_back(interfaceType->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800322
Christopher Wiley67502f12016-01-29 10:57:00 -0800323 // IBinder mRemote
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900324 mRemote = new Variable(types->IBinderType()->JavaType(), "mRemote");
Christopher Wiley67502f12016-01-29 10:57:00 -0800325 this->elements.push_back(new Field(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800326
Christopher Wiley67502f12016-01-29 10:57:00 -0800327 // Proxy()
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900328 Variable* remote = new Variable(types->IBinderType()->JavaType(), "remote");
Christopher Wiley67502f12016-01-29 10:57:00 -0800329 Method* ctor = new Method;
330 ctor->name = "Proxy";
331 ctor->statements = new StatementBlock;
332 ctor->parameters.push_back(remote);
333 ctor->statements->Add(new Assignment(mRemote, remote));
334 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800335
Jiyong Park309668e2018-07-28 16:55:44 +0900336 if (options.Version() > 0) {
337 std::ostringstream code;
338 code << "private int mCachedVersion = -1;\n";
339 this->elements.emplace_back(new LiteralClassElement(code.str()));
340 }
341
Christopher Wiley67502f12016-01-29 10:57:00 -0800342 // IBinder asBinder()
343 Method* asBinder = new Method;
344 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900345 asBinder->returnType = types->IBinderType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800346 asBinder->name = "asBinder";
347 asBinder->statements = new StatementBlock;
348 asBinder->statements->Add(new ReturnStatement(mRemote));
349 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800350}
351
Christopher Wiley67502f12016-01-29 10:57:00 -0800352ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800353
354// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800355static void generate_new_array(const Type* t, StatementBlock* addTo,
356 Variable* v, Variable* parcel,
357 JavaTypeNamespace* types) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900358 Variable* len = new Variable(types->IntType()->JavaType(), v->name + "_length");
Christopher Wiley67502f12016-01-29 10:57:00 -0800359 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
360 IfStatement* lencheck = new IfStatement();
361 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
362 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
363 lencheck->elseif = new IfStatement();
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900364 lencheck->elseif->statements->Add(new Assignment(v, new NewArrayExpression(t->JavaType(), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800365 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800366}
367
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900368static void generate_write_to_parcel(const AidlTypeSpecifier& type, StatementBlock* addTo,
369 Variable* v, Variable* parcel, bool is_return_value,
370 const AidlTypenames& typenames) {
371 string code;
372 CodeWriterPtr writer = CodeWriter::ForString(&code);
373 CodeGeneratorContext context{
374 .writer = *(writer.get()),
375 .typenames = typenames,
376 .type = type,
377 .var = v->name,
378 .parcel = parcel->name,
379 .is_return_value = is_return_value,
380 };
381 WriteToParcelFor(context);
382 writer->Close();
383 addTo->Add(new LiteralStatement(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800384}
385
Steven Moreland693640b2018-07-19 13:46:27 -0700386static void generate_int_constant(Class* interface, const std::string& name,
387 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900388 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
389 interface->elements.push_back(new LiteralClassElement(code));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700390}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800391
Steven Moreland693640b2018-07-19 13:46:27 -0700392static void generate_string_constant(Class* interface, const std::string& name,
393 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900394 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
395 interface->elements.push_back(new LiteralClassElement(code));
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800396}
397
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800398static std::unique_ptr<Method> generate_interface_method(
399 const AidlMethod& method, JavaTypeNamespace* types) {
400 std::unique_ptr<Method> decl(new Method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800401 decl->comment = method.GetComments();
402 decl->modifiers = PUBLIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900403 decl->returnType = method.GetType().GetLanguageType<Type>()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800404 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
405 decl->name = method.GetName();
Jiyong Parka6605ab2018-11-11 14:30:21 +0900406 decl->annotations = generate_java_annotations(method.GetType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800407
Christopher Wiley67502f12016-01-29 10:57:00 -0800408 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900409 decl->parameters.push_back(new Variable(arg->GetType().GetLanguageType<Type>()->JavaType(),
410 arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
Christopher Wiley67502f12016-01-29 10:57:00 -0800411 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800412
Jeongik Cha6cadc212019-02-12 18:16:03 +0900413 decl->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800414
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800415 return decl;
416}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800417
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900418static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
419 Variable* transact_data, Variable* transact_reply,
420 JavaTypeNamespace* types, StatementBlock* statements,
421 StubClass* stubClass, const Options& options) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100422 TryStatement* tryStatement = nullptr;
423 FinallyStatement* finallyStatement = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800424 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800425
Christopher Wiley67502f12016-01-29 10:57:00 -0800426 // interface token validation is the very first thing we do
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800427 statements->Add(new MethodCall(transact_data,
428 "enforceInterface", 1,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700429 stubClass->get_transact_descriptor(types,
430 &method)));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800431
Christopher Wiley67502f12016-01-29 10:57:00 -0800432 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800433 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800434 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900435 // keep this across different args in order to create the classloader
436 // at most once.
437 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800438 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
439 const Type* t = arg->GetType().GetLanguageType<Type>();
440 Variable* v = stubArgs.Get(t);
441 v->dimension = arg->GetType().IsArray() ? 1 : 0;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800442
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800443 statements->Add(new VariableDeclaration(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800444
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800445 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900446 string code;
447 CodeWriterPtr writer = CodeWriter::ForString(&code);
448 CodeGeneratorContext context{.writer = *(writer.get()),
449 .typenames = types->typenames_,
450 .type = arg->GetType(),
451 .var = v->name,
452 .parcel = transact_data->name,
453 .is_classloader_created = &is_classloader_created};
454 CreateFromParcelFor(context);
455 writer->Close();
456 statements->Add(new LiteralStatement(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800457 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800458 if (!arg->GetType().IsArray()) {
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900459 statements->Add(new Assignment(v, new NewExpression(t->InstantiableName())));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800460 } else {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900461 generate_new_array(t, statements, v, transact_data, types);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800462 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800463 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800464
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800465 realCall->arguments.push_back(v);
466 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800467 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800468
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900469 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100470 // try and finally, but only when generating trace code
471 tryStatement = new TryStatement();
472 finallyStatement = new FinallyStatement();
473
474 tryStatement->statements->Add(new MethodCall(
475 new LiteralExpression("android.os.Trace"), "traceBegin", 2,
476 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
477 new StringLiteralExpression(iface.GetName() + "::"
478 + method.GetName() + "::server")));
479
480 finallyStatement->statements->Add(new MethodCall(
481 new LiteralExpression("android.os.Trace"), "traceEnd", 1,
482 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
483 }
484
Christopher Wiley67502f12016-01-29 10:57:00 -0800485 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800486 if (method.GetType().GetName() == "void") {
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900487 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100488 statements->Add(tryStatement);
489 tryStatement->statements->Add(realCall);
490 statements->Add(finallyStatement);
491 } else {
492 statements->Add(realCall);
493 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800494
Adam Lesinskiffa16862014-01-23 18:17:42 -0800495 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800496 // report that there were no exceptions
497 MethodCall* ex =
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800498 new MethodCall(transact_reply, "writeNoException", 0);
499 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800500 }
501 } else {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900502 Variable* _result = new Variable(method.GetType().GetLanguageType<Type>()->JavaType(),
503 "_result", method.GetType().IsArray() ? 1 : 0);
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900504 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100505 statements->Add(new VariableDeclaration(_result));
506 statements->Add(tryStatement);
507 tryStatement->statements->Add(new Assignment(_result, realCall));
508 statements->Add(finallyStatement);
509 } else {
510 statements->Add(new VariableDeclaration(_result, realCall));
511 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800512
513 if (!oneway) {
514 // report that there were no exceptions
515 MethodCall* ex =
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800516 new MethodCall(transact_reply, "writeNoException", 0);
517 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800518 }
519
Christopher Wiley67502f12016-01-29 10:57:00 -0800520 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900521 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
522 types->typenames_);
Christopher Wiley67502f12016-01-29 10:57:00 -0800523 }
524
525 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800526 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800527 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800528 Variable* v = stubArgs.Get(i++);
529
530 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900531 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true,
532 types->typenames_);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800533 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800534 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800535
Christopher Wiley67502f12016-01-29 10:57:00 -0800536 // return true
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800537 statements->Add(new ReturnStatement(TRUE_VALUE));
538}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800539
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900540static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
541 const std::string& transactCodeName, bool oneway,
542 StubClass* stubClass, JavaTypeNamespace* types,
543 const Options& options) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800544 Case* c = new Case(transactCodeName);
545
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900546 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
547 types, c->statements, stubClass, options);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800548
549 stubClass->transact_switch->cases.push_back(c);
550}
551
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900552static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
553 const std::string& transactCodeName, bool oneway,
554 StubClass* stubClass, JavaTypeNamespace* types,
555 const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800556 std::string outline_name = "onTransact$" + method.GetName() + "$";
557 // Generate an "outlined" method with the actual code.
558 {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900559 Variable* transact_data = new Variable(types->ParcelType()->JavaType(), "data");
560 Variable* transact_reply = new Variable(types->ParcelType()->JavaType(), "reply");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800561 Method* onTransact_case = new Method;
562 onTransact_case->modifiers = PRIVATE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900563 onTransact_case->returnType = types->BoolType()->JavaType();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800564 onTransact_case->name = outline_name;
565 onTransact_case->parameters.push_back(transact_data);
566 onTransact_case->parameters.push_back(transact_reply);
567 onTransact_case->statements = new StatementBlock;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900568 onTransact_case->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Andreas Gampe1b865af2017-11-22 11:31:47 -0800569 stubClass->elements.push_back(onTransact_case);
570
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900571 generate_stub_code(iface, method, oneway, transact_data, transact_reply, types,
572 onTransact_case->statements, stubClass, options);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800573 }
574
575 // Generate the case dispatch.
576 {
577 Case* c = new Case(transactCodeName);
578
579 MethodCall* helper_call = new MethodCall(THIS_VALUE,
580 outline_name,
581 2,
582 stubClass->transact_data,
583 stubClass->transact_reply);
584 c->statements->Add(new ReturnStatement(helper_call));
585
586 stubClass->transact_switch->cases.push_back(c);
587 }
588}
589
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800590static std::unique_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900591 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
592 bool oneway, ProxyClass* proxyClass, JavaTypeNamespace* types, const Options& options) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800593 std::unique_ptr<Method> proxy(new Method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800594 proxy->comment = method.GetComments();
595 proxy->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900596 proxy->returnType = method.GetType().GetLanguageType<Type>()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800597 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
598 proxy->name = method.GetName();
599 proxy->statements = new StatementBlock;
600 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900601 proxy->parameters.push_back(new Variable(arg->GetType().GetLanguageType<Type>()->JavaType(),
602 arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
Christopher Wiley67502f12016-01-29 10:57:00 -0800603 }
Jeongik Cha6cadc212019-02-12 18:16:03 +0900604 proxy->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800605
Christopher Wiley67502f12016-01-29 10:57:00 -0800606 // the parcels
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900607 Variable* _data = new Variable(types->ParcelType()->JavaType(), "_data");
Jeongik Cha439f2c42019-02-13 12:38:30 +0900608 proxy->statements->Add(
609 new VariableDeclaration(_data, new MethodCall(types->ParcelType()->JavaType(), "obtain")));
Yi Kong894d6ba2018-07-24 11:27:38 -0700610 Variable* _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800611 if (!oneway) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900612 _reply = new Variable(types->ParcelType()->JavaType(), "_reply");
Jeongik Cha439f2c42019-02-13 12:38:30 +0900613 proxy->statements->Add(
614 new VariableDeclaration(_reply, new MethodCall(types->ParcelType()->JavaType(), "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800615 }
616
617 // the return value
Yi Kong894d6ba2018-07-24 11:27:38 -0700618 Variable* _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800619 if (method.GetType().GetName() != "void") {
Jeongik Cha6cadc212019-02-12 18:16:03 +0900620 _result = new Variable(*proxy->returnType, "_result", method.GetType().IsArray() ? 1 : 0);
Christopher Wiley67502f12016-01-29 10:57:00 -0800621 proxy->statements->Add(new VariableDeclaration(_result));
622 }
623
624 // try and finally
625 TryStatement* tryStatement = new TryStatement();
626 proxy->statements->Add(tryStatement);
627 FinallyStatement* finallyStatement = new FinallyStatement();
628 proxy->statements->Add(finallyStatement);
629
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900630 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100631 tryStatement->statements->Add(new MethodCall(
632 new LiteralExpression("android.os.Trace"), "traceBegin", 2,
633 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
634 new StringLiteralExpression(iface.GetName() + "::" +
635 method.GetName() + "::client")));
636 }
637
Christopher Wiley67502f12016-01-29 10:57:00 -0800638 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
639 // string
640 tryStatement->statements->Add(new MethodCall(
641 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR")));
642
643 // the parameters
644 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
645 const Type* t = arg->GetType().GetLanguageType<Type>();
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900646 Variable* v = new Variable(t->JavaType(), arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
Christopher Wiley67502f12016-01-29 10:57:00 -0800647 AidlArgument::Direction dir = arg->GetDirection();
648 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
649 IfStatement* checklen = new IfStatement();
650 checklen->expression = new Comparison(v, "==", NULL_VALUE);
651 checklen->statements->Add(
652 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1")));
653 checklen->elseif = new IfStatement();
654 checklen->elseif->statements->Add(
655 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length")));
656 tryStatement->statements->Add(checklen);
657 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900658 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
659 types->typenames_);
Christopher Wiley5f848522016-03-01 16:29:41 -0800660 } else {
661 delete v;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800662 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800663 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800664
Christopher Wiley67502f12016-01-29 10:57:00 -0800665 // the transact call
Jiyong Park75e1a742018-07-04 12:31:23 +0900666 unique_ptr<MethodCall> call(new MethodCall(
667 proxyClass->mRemote, "transact", 4, new LiteralExpression("Stub." + transactCodeName), _data,
Christopher Wiley67502f12016-01-29 10:57:00 -0800668 _reply ? _reply : NULL_VALUE,
Jiyong Park75e1a742018-07-04 12:31:23 +0900669 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")));
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900670 unique_ptr<Variable> _status(new Variable(types->BoolType()->JavaType(), "_status"));
Jiyong Park75e1a742018-07-04 12:31:23 +0900671 tryStatement->statements->Add(new VariableDeclaration(_status.release(), call.release()));
672
673 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
674 // back to the local method in the default impl, if set before.
675 vector<string> arg_names;
676 for (const auto& arg : method.GetArguments()) {
677 arg_names.emplace_back(arg->GetName());
678 }
679 bool has_return_type = method.GetType().GetName() != "void";
680 tryStatement->statements->Add(new LiteralStatement(
681 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
682 " return getDefaultImpl().%s(%s);\n"
683 "}\n"
684 : "if (!_status && getDefaultImpl() != null) {\n"
685 " getDefaultImpl().%s(%s);\n"
686 " return;\n"
687 "}\n",
688 method.GetName().c_str(), Join(arg_names, ", ").c_str())));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800689
Christopher Wiley67502f12016-01-29 10:57:00 -0800690 // throw back exceptions.
691 if (_reply) {
692 MethodCall* ex = new MethodCall(_reply, "readException", 0);
693 tryStatement->statements->Add(ex);
694 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800695
Christopher Wiley67502f12016-01-29 10:57:00 -0800696 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700697 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900698 // keep this across return value and arguments in order to create the
699 // classloader at most once.
700 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700701 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900702 string code;
703 CodeWriterPtr writer = CodeWriter::ForString(&code);
704 CodeGeneratorContext context{.writer = *(writer.get()),
705 .typenames = types->typenames_,
706 .type = method.GetType(),
707 .var = _result->name,
708 .parcel = _reply->name,
709 .is_classloader_created = &is_classloader_created};
710 CreateFromParcelFor(context);
711 writer->Close();
712 tryStatement->statements->Add(new LiteralStatement(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800713 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800714
715 // the out/inout parameters
716 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800717 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900718 string code;
719 CodeWriterPtr writer = CodeWriter::ForString(&code);
720 CodeGeneratorContext context{.writer = *(writer.get()),
721 .typenames = types->typenames_,
722 .type = arg->GetType(),
723 .var = arg->GetName(),
724 .parcel = _reply->name,
725 .is_classloader_created = &is_classloader_created};
726 ReadFromParcelFor(context);
727 writer->Close();
728 tryStatement->statements->Add(new LiteralStatement(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800729 }
730 }
731
732 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
733 }
734 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
735
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900736 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100737 finallyStatement->statements->Add(new MethodCall(
738 new LiteralExpression("android.os.Trace"), "traceEnd", 1,
739 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
740 }
741
Yi Kong894d6ba2018-07-24 11:27:38 -0700742 if (_result != nullptr) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800743 proxy->statements->Add(new ReturnStatement(_result));
744 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800745
746 return proxy;
747}
748
Jiyong Park74595c12018-07-23 15:22:50 +0900749static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
750 StubClass* stubClass, ProxyClass* proxyClass, int index,
751 JavaTypeNamespace* types, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800752 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800753
754 // == the TRANSACT_ constant =============================================
755 string transactCodeName = "TRANSACTION_";
756 transactCodeName += method.GetName();
757
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900758 Field* transactCode =
759 new Field(STATIC | FINAL, new Variable(types->IntType()->JavaType(), transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800760 transactCode->value =
761 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
762 stubClass->elements.push_back(transactCode);
763
Olivier Gaillard11401402018-07-05 15:01:34 +0100764 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900765 if (options.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100766 Case* c = new Case(transactCodeName);
767 c->statements->Add(new ReturnStatement(new StringLiteralExpression(method.GetName())));
768 stubClass->code_to_method_name_switch->cases.push_back(c);
769 }
770
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800771 // == the declaration in the interface ===================================
Jiyong Park309668e2018-07-28 16:55:44 +0900772 ClassElement* decl;
773 if (method.IsUserDefined()) {
774 decl = generate_interface_method(method, types).release();
775 } else {
776 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
777 std::ostringstream code;
778 code << "public int " << kGetInterfaceVersion << "() "
779 << "throws android.os.RemoteException;\n";
780 decl = new LiteralClassElement(code.str());
781 }
782 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800783 interface->elements.push_back(decl);
784
785 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900786 if (method.IsUserDefined()) {
787 bool outline_stub =
788 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
789 if (outline_stub) {
790 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, types,
791 options);
792 } else {
793 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, types, options);
794 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800795 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900796 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
797 Case* c = new Case(transactCodeName);
798 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900799 code << "data.enforceInterface(descriptor);\n"
800 << "reply.writeNoException();\n"
801 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900802 << "return true;\n";
803 c->statements->Add(new LiteralStatement(code.str()));
804 stubClass->transact_switch->cases.push_back(c);
805 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800806 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800807
808 // == the proxy method ===================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900809 ClassElement* proxy = nullptr;
810 if (method.IsUserDefined()) {
811 proxy =
812 generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, types, options)
813 .release();
814
815 } else {
816 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
817 std::ostringstream code;
818 code << "@Override\n"
819 << "public int " << kGetInterfaceVersion << "()"
820 << " throws "
821 << "android.os.RemoteException {\n"
822 << " if (mCachedVersion == -1) {\n"
823 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
824 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
825 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900826 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900827 << " mRemote.transact(Stub." << transactCodeName << ", "
828 << "data, reply, 0);\n"
829 << " mCachedVersion = reply.readInt();\n"
830 << " } finally {\n"
831 << " reply.recycle();\n"
832 << " data.recycle();\n"
833 << " }\n"
834 << " }\n"
835 << " return mCachedVersion;\n"
836 << "}\n";
837 proxy = new LiteralClassElement(code.str());
838 }
839 }
840 if (proxy != nullptr) {
841 proxyClass->elements.push_back(proxy);
842 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800843}
844
Christopher Wiley67502f12016-01-29 10:57:00 -0800845static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
846 const JavaTypeNamespace* types) {
847 // the interface descriptor transaction handler
848 Case* c = new Case("INTERFACE_TRANSACTION");
849 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700850 stub->get_transact_descriptor(types,
851 nullptr)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800852 c->statements->Add(new ReturnStatement(TRUE_VALUE));
853 stub->transact_switch->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800854
Christopher Wiley67502f12016-01-29 10:57:00 -0800855 // and the proxy-side method returning the descriptor directly
856 Method* getDesc = new Method;
857 getDesc->modifiers = PUBLIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900858 getDesc->returnType = types->StringType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800859 getDesc->returnTypeDimension = 0;
860 getDesc->name = "getInterfaceDescriptor";
861 getDesc->statements = new StatementBlock;
862 getDesc->statements->Add(
863 new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
864 proxy->elements.push_back(getDesc);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800865}
866
Andreas Gampee9c816e2018-03-14 09:05:48 -0700867// Check whether (some) methods in this interface should be "outlined," that
868// is, have specific onTransact methods for certain cases. Set up StubClass
869// metadata accordingly.
870//
871// Outlining will be enabled if the interface has more than outline_threshold
872// methods. In that case, the methods are sorted by number of arguments
873// (so that more "complex" methods come later), and the first non_outline_count
874// number of methods not outlined (are kept in the onTransact() method).
875//
876// Requirements: non_outline_count <= outline_threshold.
877static void compute_outline_methods(const AidlInterface* iface,
878 StubClass* stub,
879 size_t outline_threshold,
880 size_t non_outline_count) {
881 CHECK_LE(non_outline_count, outline_threshold);
882 // We'll outline (create sub methods) if there are more than min_methods
883 // cases.
884 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
885 if (stub->transact_outline) {
886 stub->all_method_count = iface->GetMethods().size();
887 std::vector<const AidlMethod*> methods;
888 methods.reserve(iface->GetMethods().size());
889 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
890 methods.push_back(ptr.get());
891 }
892
893 std::stable_sort(
894 methods.begin(),
895 methods.end(),
896 [](const AidlMethod* m1, const AidlMethod* m2) {
897 return m1->GetArguments().size() < m2->GetArguments().size();
898 });
899
900 stub->outline_methods.insert(methods.begin() + non_outline_count,
901 methods.end());
902 }
903}
904
Jiyong Park75e1a742018-07-04 12:31:23 +0900905static unique_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method) {
906 unique_ptr<Method> default_method(new Method);
907 default_method->comment = method.GetComments();
908 default_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900909 default_method->returnType = method.GetType().GetLanguageType<Type>()->JavaType();
Jiyong Park75e1a742018-07-04 12:31:23 +0900910 default_method->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
911 default_method->name = method.GetName();
912 default_method->statements = new StatementBlock;
913 for (const auto& arg : method.GetArguments()) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900914 default_method->parameters.push_back(
915 new Variable(arg->GetType().GetLanguageType<Type>()->JavaType(), arg->GetName(),
916 arg->GetType().IsArray() ? 1 : 0));
Jiyong Park75e1a742018-07-04 12:31:23 +0900917 }
Jeongik Cha6cadc212019-02-12 18:16:03 +0900918 default_method->exceptions.push_back(method.GetType()
919 .GetLanguageType<Type>()
920 ->GetTypeNamespace()
921 ->RemoteExceptionType()
922 ->JavaType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900923
924 if (method.GetType().GetName() != "void") {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900925 const string& defaultValue = DefaultJavaValueOf(method.GetType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900926 default_method->statements->Add(
927 new LiteralStatement(StringPrintf("return %s;\n", defaultValue.c_str())));
928 }
929 return default_method;
930}
931
Jiyong Park309668e2018-07-28 16:55:44 +0900932static unique_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
933 const Options& options) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900934 unique_ptr<Class> default_class(new Class);
935 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
936 default_class->modifiers = PUBLIC | STATIC;
937 default_class->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900938 default_class->type = iface.GetLanguageType<InterfaceType>()->GetDefaultImpl()->JavaType();
939 default_class->interfaces.emplace_back(iface.GetLanguageType<InterfaceType>()->JavaType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900940
941 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900942 if (m->IsUserDefined()) {
943 default_class->elements.emplace_back(generate_default_impl_method(*(m.get())).release());
944 } else {
945 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900946 // This is called only when the remote side is not implementing this
947 // method, which is impossible in normal case, because this method is
948 // automatically declared in the interface class and not implementing
949 // it in the remote side is causing compilation error. But if the remote
950 // side somehow managed to not implement it, that's an error and we
951 // report the case by returning -1 here.
Jiyong Park309668e2018-07-28 16:55:44 +0900952 std::ostringstream code;
953 code << "@Override\n"
954 << "public int " << kGetInterfaceVersion << "() {\n"
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900955 << " return -1;\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900956 << "}\n";
957 default_class->elements.emplace_back(new LiteralClassElement(code.str()));
958 }
959 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900960 }
961
962 default_class->elements.emplace_back(
963 new LiteralClassElement("@Override\n"
964 "public android.os.IBinder asBinder() {\n"
965 " return null;\n"
966 "}\n"));
967
968 return default_class;
969}
970
Jiyong Park74595c12018-07-23 15:22:50 +0900971Class* generate_binder_interface_class(const AidlInterface* iface, JavaTypeNamespace* types,
972 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800973 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800974
Christopher Wiley67502f12016-01-29 10:57:00 -0800975 // the interface class
976 Class* interface = new Class;
977 interface->comment = iface->GetComments();
978 interface->modifiers = PUBLIC;
979 interface->what = Class::INTERFACE;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900980 interface->type = interfaceType->JavaType();
981 interface->interfaces.push_back(types->IInterfaceType()->JavaType());
Jiyong Parka6605ab2018-11-11 14:30:21 +0900982 interface->annotations = generate_java_annotations(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800983
Jiyong Park309668e2018-07-28 16:55:44 +0900984 if (options.Version()) {
985 std::ostringstream code;
986 code << "/**\n"
987 << " * The version of this interface that the caller is built against.\n"
988 << " * This might be different from what {@link #getInterfaceVersion()\n"
989 << " * getInterfaceVersion} returns as that is the version of the interface\n"
990 << " * that the remote object is implementing.\n"
991 << " */\n"
992 << "public static final int VERSION = " << options.Version() << ";\n";
993 interface->elements.emplace_back(new LiteralClassElement(code.str()));
994 }
995
Jiyong Park75e1a742018-07-04 12:31:23 +0900996 // the default impl class
Jiyong Park309668e2018-07-28 16:55:44 +0900997 Class* default_impl = generate_default_impl_class(*iface, options).release();
998 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +0900999
Christopher Wiley67502f12016-01-29 10:57:00 -08001000 // the stub inner class
1001 StubClass* stub =
Olivier Gaillard11401402018-07-05 15:01:34 +01001002 new StubClass(interfaceType->GetStub(), interfaceType, types, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001003 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001004
Andreas Gampee9c816e2018-03-14 09:05:48 -07001005 compute_outline_methods(iface,
1006 stub,
1007 options.onTransact_outline_threshold_,
1008 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001009
Christopher Wiley67502f12016-01-29 10:57:00 -08001010 // the proxy inner class
Jiyong Park309668e2018-07-28 16:55:44 +09001011 ProxyClass* proxy = new ProxyClass(types, interfaceType->GetProxy(), interfaceType, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001012 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001013
Christopher Wiley67502f12016-01-29 10:57:00 -08001014 // stub and proxy support for getInterfaceDescriptor()
1015 generate_interface_descriptors(stub, proxy, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001016
Christopher Wiley67502f12016-01-29 10:57:00 -08001017 // all the declared constants of the interface
Steven Moreland693640b2018-07-19 13:46:27 -07001018 for (const auto& constant : iface->GetConstantDeclarations()) {
1019 const AidlConstantValue& value = constant->GetValue();
1020
1021 switch (value.GetType()) {
1022 case AidlConstantValue::Type::STRING: {
Steven Moreland860b1942018-08-16 14:59:28 -07001023 generate_string_constant(interface, constant->GetName(),
1024 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001025 break;
1026 }
Steven Moreland25294322018-08-07 18:13:55 -07001027 case AidlConstantValue::Type::INTEGRAL:
1028 case AidlConstantValue::Type::HEXIDECIMAL: {
Steven Moreland860b1942018-08-16 14:59:28 -07001029 generate_int_constant(interface, constant->GetName(),
1030 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001031 break;
1032 }
1033 default: {
1034 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1035 }
1036 }
Christopher Wiley67502f12016-01-29 10:57:00 -08001037 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001038
Christopher Wiley67502f12016-01-29 10:57:00 -08001039 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001040
Christopher Wiley67502f12016-01-29 10:57:00 -08001041 for (const auto& item : iface->GetMethods()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +01001042 generate_methods(*iface,
1043 *item,
Andreas Gampe1b865af2017-11-22 11:31:47 -08001044 interface,
1045 stub,
1046 proxy,
1047 item->GetId(),
Olivier Gaillard11401402018-07-05 15:01:34 +01001048 types,
1049 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001050 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001051
1052 // additional static methods for the default impl set/get to the
1053 // stub class. Can't add them to the interface as the generated java files
1054 // may be compiled with Java < 1.7 where static interface method isn't
1055 // supported.
1056 // TODO(b/111417145) make this conditional depending on the Java language
1057 // version requested
1058 const string i_name = interfaceType->JavaType();
1059 stub->elements.emplace_back(new LiteralClassElement(
1060 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1061 " if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
1062 " Stub.Proxy.sDefaultImpl = impl;\n"
1063 " return true;\n"
1064 " }\n"
1065 " return false;\n"
1066 "}\n",
1067 i_name.c_str())));
1068 stub->elements.emplace_back(
1069 new LiteralClassElement(StringPrintf("public static %s getDefaultImpl() {\n"
1070 " return Stub.Proxy.sDefaultImpl;\n"
1071 "}\n",
1072 i_name.c_str())));
1073
1074 // the static field is defined in the proxy class, not in the interface class
1075 // because all fields in an interface class are by default final.
1076 proxy->elements.emplace_back(new LiteralClassElement(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001077 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001078
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001079 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001080
Christopher Wiley67502f12016-01-29 10:57:00 -08001081 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001082}
1083
Christopher Wileydb154a52015-09-28 16:32:25 -07001084} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001085} // namespace android
1086} // namespace aidl