blob: 8ced119f6c40945d41fcdea744ed6d21e851c176 [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;
Jiyong Parkcd3c04b2019-04-10 03:08:41 +0900157 getDefaultTransactionName->comment = "/** @hide */";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100158 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900159 getDefaultTransactionName->returnType = types->StringType()->JavaType();
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100160 getDefaultTransactionName->name = "getDefaultTransactionName";
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900161 Variable* code = new Variable(types->IntType()->JavaType(), "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100162 getDefaultTransactionName->parameters.push_back(code);
163 getDefaultTransactionName->statements = new StatementBlock;
164 this->code_to_method_name_switch = new SwitchStatement(code);
165 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
166 this->elements.push_back(getDefaultTransactionName);
167
168 // getTransactionName
Olivier Gaillard11401402018-07-05 15:01:34 +0100169 Method* getTransactionName = new Method;
Jiyong Parkcd3c04b2019-04-10 03:08:41 +0900170 getTransactionName->comment = "/** @hide */";
Olivier Gaillard11401402018-07-05 15:01:34 +0100171 getTransactionName->modifiers = PUBLIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900172 getTransactionName->returnType = types->StringType()->JavaType();
Olivier Gaillard11401402018-07-05 15:01:34 +0100173 getTransactionName->name = "getTransactionName";
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900174 Variable* code2 = new Variable(types->IntType()->JavaType(), "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100175 getTransactionName->parameters.push_back(code2);
Olivier Gaillard11401402018-07-05 15:01:34 +0100176 getTransactionName->statements = new StatementBlock;
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100177 getTransactionName->statements->Add(
178 new ReturnStatement(new MethodCall(THIS_VALUE, "getDefaultTransactionName", 1, code2)));
Olivier Gaillard11401402018-07-05 15:01:34 +0100179 this->elements.push_back(getTransactionName);
180 }
181
Christopher Wiley67502f12016-01-29 10:57:00 -0800182 // onTransact
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900183 this->transact_code = new Variable(types->IntType()->JavaType(), "code");
184 this->transact_data = new Variable(types->ParcelType()->JavaType(), "data");
185 this->transact_reply = new Variable(types->ParcelType()->JavaType(), "reply");
186 this->transact_flags = new Variable(types->IntType()->JavaType(), "flags");
Christopher Wiley67502f12016-01-29 10:57:00 -0800187 Method* onTransact = new Method;
188 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900189 onTransact->returnType = types->BoolType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800190 onTransact->name = "onTransact";
191 onTransact->parameters.push_back(this->transact_code);
192 onTransact->parameters.push_back(this->transact_data);
193 onTransact->parameters.push_back(this->transact_reply);
194 onTransact->parameters.push_back(this->transact_flags);
195 onTransact->statements = new StatementBlock;
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800196 transact_statements = onTransact->statements;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900197 onTransact->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Christopher Wiley67502f12016-01-29 10:57:00 -0800198 this->elements.push_back(onTransact);
199 this->transact_switch = new SwitchStatement(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800200}
201
202void StubClass::finish() {
203 Case* default_case = new Case;
204
Christopher Wiley67502f12016-01-29 10:57:00 -0800205 MethodCall* superCall = new MethodCall(
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800206 SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data,
207 this->transact_reply, this->transact_flags);
208 default_case->statements->Add(new ReturnStatement(superCall));
209 transact_switch->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800210
211 transact_statements->Add(this->transact_switch);
Olivier Gaillard11401402018-07-05 15:01:34 +0100212
213 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900214 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100215 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
216 // Common transaction codes will not be resolved to a string by getTransactionName. The method
217 // will return NULL in this case.
218 Case* code_switch_default_case = new Case;
219 code_switch_default_case->statements->Add(new ReturnStatement(NULL_VALUE));
220 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
221 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800222}
223
Andreas Gampee9c816e2018-03-14 09:05:48 -0700224// The the expression for the interface's descriptor to be used when
225// generating code for the given method. Null is acceptable for method
226// and stands for synthetic cases.
227Expression* StubClass::get_transact_descriptor(const JavaTypeNamespace* types,
228 const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800229 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700230 if (method != nullptr) {
231 // When outlining, each outlined method needs its own literal.
232 if (outline_methods.count(method) != 0) {
233 return new LiteralExpression("DESCRIPTOR");
234 }
235 } else {
236 // Synthetic case. A small number is assumed. Use its own descriptor
237 // if there are only synthetic cases.
238 if (outline_methods.size() == all_method_count) {
239 return new LiteralExpression("DESCRIPTOR");
240 }
241 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800242 }
243
Andreas Gampee9c816e2018-03-14 09:05:48 -0700244 // When not outlining, store the descriptor literal into a local variable, in
245 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800246 if (transact_descriptor == nullptr) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900247 transact_descriptor = new Variable(types->StringType()->JavaType(), "descriptor");
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800248 transact_statements->Add(
249 new VariableDeclaration(transact_descriptor,
250 new LiteralExpression("DESCRIPTOR")));
251 }
252 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800253}
254
Christopher Wiley67502f12016-01-29 10:57:00 -0800255void StubClass::make_as_interface(const InterfaceType* interfaceType,
256 JavaTypeNamespace* types) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900257 Variable* obj = new Variable(types->IBinderType()->JavaType(), "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800258
259 Method* m = new Method;
260 m->comment = "/**\n * Cast an IBinder object into an ";
Christopher Wileyd21bfee2016-01-29 15:11:38 -0800261 m->comment += interfaceType->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800262 m->comment += " interface,\n";
263 m->comment += " * generating a proxy if needed.\n */";
264 m->modifiers = PUBLIC | STATIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900265 m->returnType = interfaceType->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800266 m->name = "asInterface";
267 m->parameters.push_back(obj);
268 m->statements = new StatementBlock;
269
270 IfStatement* ifstatement = new IfStatement();
271 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
272 ifstatement->statements = new StatementBlock;
273 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
274 m->statements->Add(ifstatement);
275
276 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
277 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
278 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
George Burgess IV478cec32019-03-19 17:54:47 -0700279 IInterfaceType iinType(types);
280 Variable* iin = new Variable(iinType.JavaType(), "iin");
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900281 VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800282 m->statements->Add(iinVd);
283
284 // Ensure the instance type of the local object is as expected.
285 // One scenario where this is needed is if another package (with a
286 // different class loader) runs in the same process as the service.
287
288 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
289 // iin;
290 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
291 Comparison* instOfCheck =
292 new Comparison(iin, " instanceof ",
Christopher Wileyd21bfee2016-01-29 15:11:38 -0800293 new LiteralExpression(interfaceType->JavaType()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800294 IfStatement* instOfStatement = new IfStatement();
295 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
296 instOfStatement->statements = new StatementBlock;
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900297 instOfStatement->statements->Add(new ReturnStatement(new Cast(interfaceType->JavaType(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800298 m->statements->Add(instOfStatement);
299
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900300 NewExpression* ne = new NewExpression(interfaceType->GetProxy()->InstantiableName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800301 ne->arguments.push_back(obj);
302 m->statements->Add(new ReturnStatement(ne));
303
304 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800305}
306
Adam Lesinskiffa16862014-01-23 18:17:42 -0800307// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800308class ProxyClass : public Class {
309 public:
Jiyong Park309668e2018-07-28 16:55:44 +0900310 ProxyClass(const JavaTypeNamespace* types, const Type* type, const InterfaceType* interfaceType,
311 const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700312 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800313
Christopher Wiley67502f12016-01-29 10:57:00 -0800314 Variable* mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800315};
316
Christopher Wiley67502f12016-01-29 10:57:00 -0800317ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type,
Jiyong Park309668e2018-07-28 16:55:44 +0900318 const InterfaceType* interfaceType, const Options& options)
Christopher Wiley67502f12016-01-29 10:57:00 -0800319 : Class() {
320 this->modifiers = PRIVATE | STATIC;
321 this->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900322 this->type = type->JavaType();
323 this->interfaces.push_back(interfaceType->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800324
Christopher Wiley67502f12016-01-29 10:57:00 -0800325 // IBinder mRemote
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900326 mRemote = new Variable(types->IBinderType()->JavaType(), "mRemote");
Christopher Wiley67502f12016-01-29 10:57:00 -0800327 this->elements.push_back(new Field(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800328
Christopher Wiley67502f12016-01-29 10:57:00 -0800329 // Proxy()
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900330 Variable* remote = new Variable(types->IBinderType()->JavaType(), "remote");
Christopher Wiley67502f12016-01-29 10:57:00 -0800331 Method* ctor = new Method;
332 ctor->name = "Proxy";
333 ctor->statements = new StatementBlock;
334 ctor->parameters.push_back(remote);
335 ctor->statements->Add(new Assignment(mRemote, remote));
336 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800337
Jiyong Park309668e2018-07-28 16:55:44 +0900338 if (options.Version() > 0) {
339 std::ostringstream code;
340 code << "private int mCachedVersion = -1;\n";
341 this->elements.emplace_back(new LiteralClassElement(code.str()));
342 }
343
Christopher Wiley67502f12016-01-29 10:57:00 -0800344 // IBinder asBinder()
345 Method* asBinder = new Method;
346 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900347 asBinder->returnType = types->IBinderType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800348 asBinder->name = "asBinder";
349 asBinder->statements = new StatementBlock;
350 asBinder->statements->Add(new ReturnStatement(mRemote));
351 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800352}
353
Christopher Wiley67502f12016-01-29 10:57:00 -0800354ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800355
356// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800357static void generate_new_array(const Type* t, StatementBlock* addTo,
358 Variable* v, Variable* parcel,
359 JavaTypeNamespace* types) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900360 Variable* len = new Variable(types->IntType()->JavaType(), v->name + "_length");
Christopher Wiley67502f12016-01-29 10:57:00 -0800361 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
362 IfStatement* lencheck = new IfStatement();
363 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
364 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
365 lencheck->elseif = new IfStatement();
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900366 lencheck->elseif->statements->Add(new Assignment(v, new NewArrayExpression(t->JavaType(), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800367 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800368}
369
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900370static void generate_write_to_parcel(const AidlTypeSpecifier& type, StatementBlock* addTo,
371 Variable* v, Variable* parcel, bool is_return_value,
372 const AidlTypenames& typenames) {
373 string code;
374 CodeWriterPtr writer = CodeWriter::ForString(&code);
375 CodeGeneratorContext context{
376 .writer = *(writer.get()),
377 .typenames = typenames,
378 .type = type,
379 .var = v->name,
380 .parcel = parcel->name,
381 .is_return_value = is_return_value,
382 };
383 WriteToParcelFor(context);
384 writer->Close();
385 addTo->Add(new LiteralStatement(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800386}
387
Steven Moreland693640b2018-07-19 13:46:27 -0700388static void generate_int_constant(Class* interface, const std::string& name,
389 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900390 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
391 interface->elements.push_back(new LiteralClassElement(code));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700392}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800393
Steven Moreland693640b2018-07-19 13:46:27 -0700394static void generate_string_constant(Class* interface, const std::string& name,
395 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900396 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
397 interface->elements.push_back(new LiteralClassElement(code));
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800398}
399
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800400static std::unique_ptr<Method> generate_interface_method(
401 const AidlMethod& method, JavaTypeNamespace* types) {
402 std::unique_ptr<Method> decl(new Method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800403 decl->comment = method.GetComments();
404 decl->modifiers = PUBLIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900405 decl->returnType = method.GetType().GetLanguageType<Type>()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800406 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
407 decl->name = method.GetName();
Jiyong Parka6605ab2018-11-11 14:30:21 +0900408 decl->annotations = generate_java_annotations(method.GetType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800409
Christopher Wiley67502f12016-01-29 10:57:00 -0800410 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900411 decl->parameters.push_back(new Variable(arg->GetType().GetLanguageType<Type>()->JavaType(),
412 arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
Christopher Wiley67502f12016-01-29 10:57:00 -0800413 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800414
Jeongik Cha6cadc212019-02-12 18:16:03 +0900415 decl->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800416
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800417 return decl;
418}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800419
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900420static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
421 Variable* transact_data, Variable* transact_reply,
422 JavaTypeNamespace* types, StatementBlock* statements,
423 StubClass* stubClass, const Options& options) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100424 TryStatement* tryStatement = nullptr;
425 FinallyStatement* finallyStatement = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800426 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800427
Christopher Wiley67502f12016-01-29 10:57:00 -0800428 // interface token validation is the very first thing we do
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800429 statements->Add(new MethodCall(transact_data,
430 "enforceInterface", 1,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700431 stubClass->get_transact_descriptor(types,
432 &method)));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800433
Christopher Wiley67502f12016-01-29 10:57:00 -0800434 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800435 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800436 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900437 // keep this across different args in order to create the classloader
438 // at most once.
439 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800440 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
441 const Type* t = arg->GetType().GetLanguageType<Type>();
442 Variable* v = stubArgs.Get(t);
443 v->dimension = arg->GetType().IsArray() ? 1 : 0;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800444
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800445 statements->Add(new VariableDeclaration(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800446
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800447 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900448 string code;
449 CodeWriterPtr writer = CodeWriter::ForString(&code);
450 CodeGeneratorContext context{.writer = *(writer.get()),
451 .typenames = types->typenames_,
452 .type = arg->GetType(),
453 .var = v->name,
454 .parcel = transact_data->name,
455 .is_classloader_created = &is_classloader_created};
456 CreateFromParcelFor(context);
457 writer->Close();
458 statements->Add(new LiteralStatement(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800459 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800460 if (!arg->GetType().IsArray()) {
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900461 statements->Add(new Assignment(v, new NewExpression(t->InstantiableName())));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800462 } else {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900463 generate_new_array(t, statements, v, transact_data, types);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800464 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800465 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800466
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800467 realCall->arguments.push_back(v);
468 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800469 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800470
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900471 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100472 // try and finally, but only when generating trace code
473 tryStatement = new TryStatement();
474 finallyStatement = new FinallyStatement();
475
476 tryStatement->statements->Add(new MethodCall(
477 new LiteralExpression("android.os.Trace"), "traceBegin", 2,
478 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
479 new StringLiteralExpression(iface.GetName() + "::"
480 + method.GetName() + "::server")));
481
482 finallyStatement->statements->Add(new MethodCall(
483 new LiteralExpression("android.os.Trace"), "traceEnd", 1,
484 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
485 }
486
Christopher Wiley67502f12016-01-29 10:57:00 -0800487 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800488 if (method.GetType().GetName() == "void") {
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900489 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100490 statements->Add(tryStatement);
491 tryStatement->statements->Add(realCall);
492 statements->Add(finallyStatement);
493 } else {
494 statements->Add(realCall);
495 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800496
Adam Lesinskiffa16862014-01-23 18:17:42 -0800497 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800498 // report that there were no exceptions
499 MethodCall* ex =
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800500 new MethodCall(transact_reply, "writeNoException", 0);
501 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800502 }
503 } else {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900504 Variable* _result = new Variable(method.GetType().GetLanguageType<Type>()->JavaType(),
505 "_result", method.GetType().IsArray() ? 1 : 0);
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900506 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100507 statements->Add(new VariableDeclaration(_result));
508 statements->Add(tryStatement);
509 tryStatement->statements->Add(new Assignment(_result, realCall));
510 statements->Add(finallyStatement);
511 } else {
512 statements->Add(new VariableDeclaration(_result, realCall));
513 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800514
515 if (!oneway) {
516 // report that there were no exceptions
517 MethodCall* ex =
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800518 new MethodCall(transact_reply, "writeNoException", 0);
519 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800520 }
521
Christopher Wiley67502f12016-01-29 10:57:00 -0800522 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900523 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
524 types->typenames_);
Christopher Wiley67502f12016-01-29 10:57:00 -0800525 }
526
527 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800528 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800529 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800530 Variable* v = stubArgs.Get(i++);
531
532 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900533 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true,
534 types->typenames_);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800535 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800536 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800537
Christopher Wiley67502f12016-01-29 10:57:00 -0800538 // return true
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800539 statements->Add(new ReturnStatement(TRUE_VALUE));
540}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800541
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900542static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
543 const std::string& transactCodeName, bool oneway,
544 StubClass* stubClass, JavaTypeNamespace* types,
545 const Options& options) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800546 Case* c = new Case(transactCodeName);
547
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900548 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
549 types, c->statements, stubClass, options);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800550
551 stubClass->transact_switch->cases.push_back(c);
552}
553
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900554static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
555 const std::string& transactCodeName, bool oneway,
556 StubClass* stubClass, JavaTypeNamespace* types,
557 const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800558 std::string outline_name = "onTransact$" + method.GetName() + "$";
559 // Generate an "outlined" method with the actual code.
560 {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900561 Variable* transact_data = new Variable(types->ParcelType()->JavaType(), "data");
562 Variable* transact_reply = new Variable(types->ParcelType()->JavaType(), "reply");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800563 Method* onTransact_case = new Method;
564 onTransact_case->modifiers = PRIVATE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900565 onTransact_case->returnType = types->BoolType()->JavaType();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800566 onTransact_case->name = outline_name;
567 onTransact_case->parameters.push_back(transact_data);
568 onTransact_case->parameters.push_back(transact_reply);
569 onTransact_case->statements = new StatementBlock;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900570 onTransact_case->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Andreas Gampe1b865af2017-11-22 11:31:47 -0800571 stubClass->elements.push_back(onTransact_case);
572
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900573 generate_stub_code(iface, method, oneway, transact_data, transact_reply, types,
574 onTransact_case->statements, stubClass, options);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800575 }
576
577 // Generate the case dispatch.
578 {
579 Case* c = new Case(transactCodeName);
580
581 MethodCall* helper_call = new MethodCall(THIS_VALUE,
582 outline_name,
583 2,
584 stubClass->transact_data,
585 stubClass->transact_reply);
586 c->statements->Add(new ReturnStatement(helper_call));
587
588 stubClass->transact_switch->cases.push_back(c);
589 }
590}
591
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800592static std::unique_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900593 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
594 bool oneway, ProxyClass* proxyClass, JavaTypeNamespace* types, const Options& options) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800595 std::unique_ptr<Method> proxy(new Method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800596 proxy->comment = method.GetComments();
597 proxy->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900598 proxy->returnType = method.GetType().GetLanguageType<Type>()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800599 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
600 proxy->name = method.GetName();
601 proxy->statements = new StatementBlock;
602 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900603 proxy->parameters.push_back(new Variable(arg->GetType().GetLanguageType<Type>()->JavaType(),
604 arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
Christopher Wiley67502f12016-01-29 10:57:00 -0800605 }
Jeongik Cha6cadc212019-02-12 18:16:03 +0900606 proxy->exceptions.push_back(types->RemoteExceptionType()->JavaType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800607
Christopher Wiley67502f12016-01-29 10:57:00 -0800608 // the parcels
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900609 Variable* _data = new Variable(types->ParcelType()->JavaType(), "_data");
Jeongik Cha439f2c42019-02-13 12:38:30 +0900610 proxy->statements->Add(
611 new VariableDeclaration(_data, new MethodCall(types->ParcelType()->JavaType(), "obtain")));
Yi Kong894d6ba2018-07-24 11:27:38 -0700612 Variable* _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800613 if (!oneway) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900614 _reply = new Variable(types->ParcelType()->JavaType(), "_reply");
Jeongik Cha439f2c42019-02-13 12:38:30 +0900615 proxy->statements->Add(
616 new VariableDeclaration(_reply, new MethodCall(types->ParcelType()->JavaType(), "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800617 }
618
619 // the return value
Yi Kong894d6ba2018-07-24 11:27:38 -0700620 Variable* _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800621 if (method.GetType().GetName() != "void") {
Jeongik Cha6cadc212019-02-12 18:16:03 +0900622 _result = new Variable(*proxy->returnType, "_result", method.GetType().IsArray() ? 1 : 0);
Christopher Wiley67502f12016-01-29 10:57:00 -0800623 proxy->statements->Add(new VariableDeclaration(_result));
624 }
625
626 // try and finally
627 TryStatement* tryStatement = new TryStatement();
628 proxy->statements->Add(tryStatement);
629 FinallyStatement* finallyStatement = new FinallyStatement();
630 proxy->statements->Add(finallyStatement);
631
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900632 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100633 tryStatement->statements->Add(new MethodCall(
634 new LiteralExpression("android.os.Trace"), "traceBegin", 2,
635 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
636 new StringLiteralExpression(iface.GetName() + "::" +
637 method.GetName() + "::client")));
638 }
639
Christopher Wiley67502f12016-01-29 10:57:00 -0800640 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
641 // string
642 tryStatement->statements->Add(new MethodCall(
643 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR")));
644
645 // the parameters
646 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
647 const Type* t = arg->GetType().GetLanguageType<Type>();
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900648 Variable* v = new Variable(t->JavaType(), arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
Christopher Wiley67502f12016-01-29 10:57:00 -0800649 AidlArgument::Direction dir = arg->GetDirection();
650 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
651 IfStatement* checklen = new IfStatement();
652 checklen->expression = new Comparison(v, "==", NULL_VALUE);
653 checklen->statements->Add(
654 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1")));
655 checklen->elseif = new IfStatement();
656 checklen->elseif->statements->Add(
657 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length")));
658 tryStatement->statements->Add(checklen);
659 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900660 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
661 types->typenames_);
Christopher Wiley5f848522016-03-01 16:29:41 -0800662 } else {
663 delete v;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800664 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800665 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800666
Christopher Wiley67502f12016-01-29 10:57:00 -0800667 // the transact call
Jiyong Park75e1a742018-07-04 12:31:23 +0900668 unique_ptr<MethodCall> call(new MethodCall(
669 proxyClass->mRemote, "transact", 4, new LiteralExpression("Stub." + transactCodeName), _data,
Christopher Wiley67502f12016-01-29 10:57:00 -0800670 _reply ? _reply : NULL_VALUE,
Jiyong Park75e1a742018-07-04 12:31:23 +0900671 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")));
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900672 unique_ptr<Variable> _status(new Variable(types->BoolType()->JavaType(), "_status"));
Jiyong Park75e1a742018-07-04 12:31:23 +0900673 tryStatement->statements->Add(new VariableDeclaration(_status.release(), call.release()));
674
675 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
676 // back to the local method in the default impl, if set before.
677 vector<string> arg_names;
678 for (const auto& arg : method.GetArguments()) {
679 arg_names.emplace_back(arg->GetName());
680 }
681 bool has_return_type = method.GetType().GetName() != "void";
682 tryStatement->statements->Add(new LiteralStatement(
683 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
684 " return getDefaultImpl().%s(%s);\n"
685 "}\n"
686 : "if (!_status && getDefaultImpl() != null) {\n"
687 " getDefaultImpl().%s(%s);\n"
688 " return;\n"
689 "}\n",
690 method.GetName().c_str(), Join(arg_names, ", ").c_str())));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800691
Christopher Wiley67502f12016-01-29 10:57:00 -0800692 // throw back exceptions.
693 if (_reply) {
694 MethodCall* ex = new MethodCall(_reply, "readException", 0);
695 tryStatement->statements->Add(ex);
696 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800697
Christopher Wiley67502f12016-01-29 10:57:00 -0800698 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700699 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900700 // keep this across return value and arguments in order to create the
701 // classloader at most once.
702 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700703 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900704 string code;
705 CodeWriterPtr writer = CodeWriter::ForString(&code);
706 CodeGeneratorContext context{.writer = *(writer.get()),
707 .typenames = types->typenames_,
708 .type = method.GetType(),
709 .var = _result->name,
710 .parcel = _reply->name,
711 .is_classloader_created = &is_classloader_created};
712 CreateFromParcelFor(context);
713 writer->Close();
714 tryStatement->statements->Add(new LiteralStatement(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800715 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800716
717 // the out/inout parameters
718 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800719 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900720 string code;
721 CodeWriterPtr writer = CodeWriter::ForString(&code);
722 CodeGeneratorContext context{.writer = *(writer.get()),
723 .typenames = types->typenames_,
724 .type = arg->GetType(),
725 .var = arg->GetName(),
726 .parcel = _reply->name,
727 .is_classloader_created = &is_classloader_created};
728 ReadFromParcelFor(context);
729 writer->Close();
730 tryStatement->statements->Add(new LiteralStatement(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800731 }
732 }
733
734 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
735 }
736 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
737
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900738 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100739 finallyStatement->statements->Add(new MethodCall(
740 new LiteralExpression("android.os.Trace"), "traceEnd", 1,
741 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
742 }
743
Yi Kong894d6ba2018-07-24 11:27:38 -0700744 if (_result != nullptr) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800745 proxy->statements->Add(new ReturnStatement(_result));
746 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800747
748 return proxy;
749}
750
Jiyong Park74595c12018-07-23 15:22:50 +0900751static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
752 StubClass* stubClass, ProxyClass* proxyClass, int index,
753 JavaTypeNamespace* types, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800754 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800755
756 // == the TRANSACT_ constant =============================================
757 string transactCodeName = "TRANSACTION_";
758 transactCodeName += method.GetName();
759
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900760 Field* transactCode =
761 new Field(STATIC | FINAL, new Variable(types->IntType()->JavaType(), transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800762 transactCode->value =
763 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
764 stubClass->elements.push_back(transactCode);
765
Olivier Gaillard11401402018-07-05 15:01:34 +0100766 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900767 if (options.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100768 Case* c = new Case(transactCodeName);
769 c->statements->Add(new ReturnStatement(new StringLiteralExpression(method.GetName())));
770 stubClass->code_to_method_name_switch->cases.push_back(c);
771 }
772
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800773 // == the declaration in the interface ===================================
Jiyong Park309668e2018-07-28 16:55:44 +0900774 ClassElement* decl;
775 if (method.IsUserDefined()) {
776 decl = generate_interface_method(method, types).release();
777 } else {
778 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
779 std::ostringstream code;
780 code << "public int " << kGetInterfaceVersion << "() "
781 << "throws android.os.RemoteException;\n";
782 decl = new LiteralClassElement(code.str());
783 }
784 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800785 interface->elements.push_back(decl);
786
787 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900788 if (method.IsUserDefined()) {
789 bool outline_stub =
790 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
791 if (outline_stub) {
792 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, types,
793 options);
794 } else {
795 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, types, options);
796 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800797 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900798 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
799 Case* c = new Case(transactCodeName);
800 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900801 code << "data.enforceInterface(descriptor);\n"
802 << "reply.writeNoException();\n"
803 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900804 << "return true;\n";
805 c->statements->Add(new LiteralStatement(code.str()));
806 stubClass->transact_switch->cases.push_back(c);
807 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800808 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800809
810 // == the proxy method ===================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900811 ClassElement* proxy = nullptr;
812 if (method.IsUserDefined()) {
813 proxy =
814 generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, types, options)
815 .release();
816
817 } else {
818 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
819 std::ostringstream code;
820 code << "@Override\n"
821 << "public int " << kGetInterfaceVersion << "()"
822 << " throws "
823 << "android.os.RemoteException {\n"
824 << " if (mCachedVersion == -1) {\n"
825 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
826 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
827 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900828 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900829 << " mRemote.transact(Stub." << transactCodeName << ", "
830 << "data, reply, 0);\n"
Jeongik Chae58e2ae2019-05-20 18:45:05 +0900831 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900832 << " mCachedVersion = reply.readInt();\n"
833 << " } finally {\n"
834 << " reply.recycle();\n"
835 << " data.recycle();\n"
836 << " }\n"
837 << " }\n"
838 << " return mCachedVersion;\n"
839 << "}\n";
840 proxy = new LiteralClassElement(code.str());
841 }
842 }
843 if (proxy != nullptr) {
844 proxyClass->elements.push_back(proxy);
845 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800846}
847
Christopher Wiley67502f12016-01-29 10:57:00 -0800848static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
849 const JavaTypeNamespace* types) {
850 // the interface descriptor transaction handler
851 Case* c = new Case("INTERFACE_TRANSACTION");
852 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700853 stub->get_transact_descriptor(types,
854 nullptr)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800855 c->statements->Add(new ReturnStatement(TRUE_VALUE));
856 stub->transact_switch->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800857
Christopher Wiley67502f12016-01-29 10:57:00 -0800858 // and the proxy-side method returning the descriptor directly
859 Method* getDesc = new Method;
860 getDesc->modifiers = PUBLIC;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900861 getDesc->returnType = types->StringType()->JavaType();
Christopher Wiley67502f12016-01-29 10:57:00 -0800862 getDesc->returnTypeDimension = 0;
863 getDesc->name = "getInterfaceDescriptor";
864 getDesc->statements = new StatementBlock;
865 getDesc->statements->Add(
866 new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
867 proxy->elements.push_back(getDesc);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800868}
869
Andreas Gampee9c816e2018-03-14 09:05:48 -0700870// Check whether (some) methods in this interface should be "outlined," that
871// is, have specific onTransact methods for certain cases. Set up StubClass
872// metadata accordingly.
873//
874// Outlining will be enabled if the interface has more than outline_threshold
875// methods. In that case, the methods are sorted by number of arguments
876// (so that more "complex" methods come later), and the first non_outline_count
877// number of methods not outlined (are kept in the onTransact() method).
878//
879// Requirements: non_outline_count <= outline_threshold.
880static void compute_outline_methods(const AidlInterface* iface,
881 StubClass* stub,
882 size_t outline_threshold,
883 size_t non_outline_count) {
884 CHECK_LE(non_outline_count, outline_threshold);
885 // We'll outline (create sub methods) if there are more than min_methods
886 // cases.
887 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
888 if (stub->transact_outline) {
889 stub->all_method_count = iface->GetMethods().size();
890 std::vector<const AidlMethod*> methods;
891 methods.reserve(iface->GetMethods().size());
892 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
893 methods.push_back(ptr.get());
894 }
895
896 std::stable_sort(
897 methods.begin(),
898 methods.end(),
899 [](const AidlMethod* m1, const AidlMethod* m2) {
900 return m1->GetArguments().size() < m2->GetArguments().size();
901 });
902
903 stub->outline_methods.insert(methods.begin() + non_outline_count,
904 methods.end());
905 }
906}
907
Jiyong Park75e1a742018-07-04 12:31:23 +0900908static unique_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method) {
909 unique_ptr<Method> default_method(new Method);
910 default_method->comment = method.GetComments();
911 default_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900912 default_method->returnType = method.GetType().GetLanguageType<Type>()->JavaType();
Jiyong Park75e1a742018-07-04 12:31:23 +0900913 default_method->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
914 default_method->name = method.GetName();
915 default_method->statements = new StatementBlock;
916 for (const auto& arg : method.GetArguments()) {
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900917 default_method->parameters.push_back(
918 new Variable(arg->GetType().GetLanguageType<Type>()->JavaType(), arg->GetName(),
919 arg->GetType().IsArray() ? 1 : 0));
Jiyong Park75e1a742018-07-04 12:31:23 +0900920 }
Jeongik Cha6cadc212019-02-12 18:16:03 +0900921 default_method->exceptions.push_back(method.GetType()
922 .GetLanguageType<Type>()
923 ->GetTypeNamespace()
924 ->RemoteExceptionType()
925 ->JavaType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900926
927 if (method.GetType().GetName() != "void") {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900928 const string& defaultValue = DefaultJavaValueOf(method.GetType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900929 default_method->statements->Add(
930 new LiteralStatement(StringPrintf("return %s;\n", defaultValue.c_str())));
931 }
932 return default_method;
933}
934
Jiyong Park309668e2018-07-28 16:55:44 +0900935static unique_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
936 const Options& options) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900937 unique_ptr<Class> default_class(new Class);
938 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
939 default_class->modifiers = PUBLIC | STATIC;
940 default_class->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900941 default_class->type = iface.GetLanguageType<InterfaceType>()->GetDefaultImpl()->JavaType();
942 default_class->interfaces.emplace_back(iface.GetLanguageType<InterfaceType>()->JavaType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900943
944 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900945 if (m->IsUserDefined()) {
946 default_class->elements.emplace_back(generate_default_impl_method(*(m.get())).release());
947 } else {
948 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900949 // This is called only when the remote side is not implementing this
950 // method, which is impossible in normal case, because this method is
951 // automatically declared in the interface class and not implementing
952 // it in the remote side is causing compilation error. But if the remote
953 // side somehow managed to not implement it, that's an error and we
954 // report the case by returning -1 here.
Jiyong Park309668e2018-07-28 16:55:44 +0900955 std::ostringstream code;
956 code << "@Override\n"
957 << "public int " << kGetInterfaceVersion << "() {\n"
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900958 << " return -1;\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900959 << "}\n";
960 default_class->elements.emplace_back(new LiteralClassElement(code.str()));
961 }
962 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900963 }
964
965 default_class->elements.emplace_back(
966 new LiteralClassElement("@Override\n"
967 "public android.os.IBinder asBinder() {\n"
968 " return null;\n"
969 "}\n"));
970
971 return default_class;
972}
973
Jiyong Park74595c12018-07-23 15:22:50 +0900974Class* generate_binder_interface_class(const AidlInterface* iface, JavaTypeNamespace* types,
975 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800976 const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800977
Christopher Wiley67502f12016-01-29 10:57:00 -0800978 // the interface class
979 Class* interface = new Class;
980 interface->comment = iface->GetComments();
981 interface->modifiers = PUBLIC;
982 interface->what = Class::INTERFACE;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900983 interface->type = interfaceType->JavaType();
984 interface->interfaces.push_back(types->IInterfaceType()->JavaType());
Jiyong Parka6605ab2018-11-11 14:30:21 +0900985 interface->annotations = generate_java_annotations(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800986
Jiyong Park309668e2018-07-28 16:55:44 +0900987 if (options.Version()) {
988 std::ostringstream code;
989 code << "/**\n"
990 << " * The version of this interface that the caller is built against.\n"
991 << " * This might be different from what {@link #getInterfaceVersion()\n"
992 << " * getInterfaceVersion} returns as that is the version of the interface\n"
993 << " * that the remote object is implementing.\n"
994 << " */\n"
995 << "public static final int VERSION = " << options.Version() << ";\n";
996 interface->elements.emplace_back(new LiteralClassElement(code.str()));
997 }
998
Jiyong Park75e1a742018-07-04 12:31:23 +0900999 // the default impl class
Jiyong Park309668e2018-07-28 16:55:44 +09001000 Class* default_impl = generate_default_impl_class(*iface, options).release();
1001 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001002
Christopher Wiley67502f12016-01-29 10:57:00 -08001003 // the stub inner class
1004 StubClass* stub =
Olivier Gaillard11401402018-07-05 15:01:34 +01001005 new StubClass(interfaceType->GetStub(), interfaceType, types, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001006 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001007
Andreas Gampee9c816e2018-03-14 09:05:48 -07001008 compute_outline_methods(iface,
1009 stub,
1010 options.onTransact_outline_threshold_,
1011 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001012
Christopher Wiley67502f12016-01-29 10:57:00 -08001013 // the proxy inner class
Jiyong Park309668e2018-07-28 16:55:44 +09001014 ProxyClass* proxy = new ProxyClass(types, interfaceType->GetProxy(), interfaceType, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001015 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001016
Christopher Wiley67502f12016-01-29 10:57:00 -08001017 // stub and proxy support for getInterfaceDescriptor()
1018 generate_interface_descriptors(stub, proxy, types);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001019
Christopher Wiley67502f12016-01-29 10:57:00 -08001020 // all the declared constants of the interface
Steven Moreland693640b2018-07-19 13:46:27 -07001021 for (const auto& constant : iface->GetConstantDeclarations()) {
1022 const AidlConstantValue& value = constant->GetValue();
1023
1024 switch (value.GetType()) {
1025 case AidlConstantValue::Type::STRING: {
Steven Moreland860b1942018-08-16 14:59:28 -07001026 generate_string_constant(interface, constant->GetName(),
1027 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001028 break;
1029 }
Steven Moreland25294322018-08-07 18:13:55 -07001030 case AidlConstantValue::Type::INTEGRAL:
1031 case AidlConstantValue::Type::HEXIDECIMAL: {
Steven Moreland860b1942018-08-16 14:59:28 -07001032 generate_int_constant(interface, constant->GetName(),
1033 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001034 break;
1035 }
1036 default: {
1037 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1038 }
1039 }
Christopher Wiley67502f12016-01-29 10:57:00 -08001040 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001041
Christopher Wiley67502f12016-01-29 10:57:00 -08001042 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001043
Christopher Wiley67502f12016-01-29 10:57:00 -08001044 for (const auto& item : iface->GetMethods()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +01001045 generate_methods(*iface,
1046 *item,
Andreas Gampe1b865af2017-11-22 11:31:47 -08001047 interface,
1048 stub,
1049 proxy,
1050 item->GetId(),
Olivier Gaillard11401402018-07-05 15:01:34 +01001051 types,
1052 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001053 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001054
1055 // additional static methods for the default impl set/get to the
1056 // stub class. Can't add them to the interface as the generated java files
1057 // may be compiled with Java < 1.7 where static interface method isn't
1058 // supported.
1059 // TODO(b/111417145) make this conditional depending on the Java language
1060 // version requested
1061 const string i_name = interfaceType->JavaType();
1062 stub->elements.emplace_back(new LiteralClassElement(
1063 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1064 " if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
1065 " Stub.Proxy.sDefaultImpl = impl;\n"
1066 " return true;\n"
1067 " }\n"
1068 " return false;\n"
1069 "}\n",
1070 i_name.c_str())));
1071 stub->elements.emplace_back(
1072 new LiteralClassElement(StringPrintf("public static %s getDefaultImpl() {\n"
1073 " return Stub.Proxy.sDefaultImpl;\n"
1074 "}\n",
1075 i_name.c_str())));
1076
1077 // the static field is defined in the proxy class, not in the interface class
1078 // because all fields in an interface class are by default final.
1079 proxy->elements.emplace_back(new LiteralClassElement(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001080 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001081
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001082 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001083
Christopher Wiley67502f12016-01-29 10:57:00 -08001084 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001085}
1086
Christopher Wileydb154a52015-09-28 16:32:25 -07001087} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001088} // namespace android
1089} // namespace aidl