blob: af5f83e90ce3ea8a3aebe24ecae06ce5ed1fcf62 [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"
Christopher Wileyf690be52015-09-14 15:19:10 -070021
Adam Lesinskiffa16862014-01-23 18:17:42 -080022#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
Andreas Gampee9c816e2018-03-14 09:05:48 -070026#include <algorithm>
27#include <unordered_set>
Jiyong Park1d2df7d2018-07-23 15:22:50 +090028#include <utility>
29#include <vector>
Andreas Gampee9c816e2018-03-14 09:05:48 -070030
Elliott Hughes0a620672015-12-04 13:53:18 -080031#include <android-base/macros.h>
Andreas Gampe7d7fa602017-11-22 10:50:03 -080032#include <android-base/stringprintf.h>
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070033
Jiyong Park75e1a742018-07-04 12:31:23 +090034using android::base::Join;
Andreas Gampe7d7fa602017-11-22 10:50:03 -080035using android::base::StringPrintf;
Jiyong Park1d2df7d2018-07-23 15:22:50 +090036
Jiyong Park75e1a742018-07-04 12:31:23 +090037using std::string;
38using std::unique_ptr;
39using std::vector;
Andreas Gampe7d7fa602017-11-22 10:50:03 -080040
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070041namespace android {
42namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070043namespace java {
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070044
Adam Lesinskiffa16862014-01-23 18:17:42 -080045// =================================================
Jiyong Park2c44f072018-07-30 21:52:21 +090046class VariableFactory {
47 public:
48 using Variable = ::android::aidl::java::Variable;
Jiyong Park2c44f072018-07-30 21:52:21 +090049
50 explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
Jeongik Chaa2080bf2019-06-18 16:44:29 +090051 Variable* Get(const AidlTypeSpecifier& type) {
52 Variable* v = new Variable(JavaSignatureOf(type), StringPrintf("%s%d", base_.c_str(), index_));
Jiyong Park2c44f072018-07-30 21:52:21 +090053 vars_.push_back(v);
54 index_++;
55 return v;
56 }
57
58 Variable* Get(int index) { return vars_[index]; }
59
60 private:
61 std::vector<Variable*> vars_;
62 std::string base_;
63 int index_;
64
65 DISALLOW_COPY_AND_ASSIGN(VariableFactory);
66};
67
68// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -080069class StubClass : public Class {
70 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +090071 StubClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -070072 ~StubClass() override = default;
Adam Lesinskiffa16862014-01-23 18:17:42 -080073
Christopher Wiley67502f12016-01-29 10:57:00 -080074 Variable* transact_code;
75 Variable* transact_data;
76 Variable* transact_reply;
77 Variable* transact_flags;
78 SwitchStatement* transact_switch;
Andreas Gampe7fab0d12017-11-22 17:50:17 -080079 StatementBlock* transact_statements;
Olivier Gaillard11401402018-07-05 15:01:34 +010080 SwitchStatement* code_to_method_name_switch;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070081
Andreas Gampe1b865af2017-11-22 11:31:47 -080082 // Where onTransact cases should be generated as separate methods.
83 bool transact_outline;
Andreas Gampee9c816e2018-03-14 09:05:48 -070084 // Specific methods that should be outlined when transact_outline is true.
85 std::unordered_set<const AidlMethod*> outline_methods;
86 // Number of all methods.
87 size_t all_method_count;
Andreas Gampe1b865af2017-11-22 11:31:47 -080088
Andreas Gampea8a66fe2017-11-22 12:17:00 -080089 // Finish generation. This will add a default case to the switch.
90 void finish();
91
Jeongik Chaa2080bf2019-06-18 16:44:29 +090092 Expression* get_transact_descriptor(const AidlMethod* method);
Andreas Gampe7fab0d12017-11-22 17:50:17 -080093
Christopher Wiley67502f12016-01-29 10:57:00 -080094 private:
Jeongik Chaa2080bf2019-06-18 16:44:29 +090095 void make_as_interface(const AidlInterface* interfaceType);
Christopher Wiley67502f12016-01-29 10:57:00 -080096
Andreas Gampe7fab0d12017-11-22 17:50:17 -080097 Variable* transact_descriptor;
Jiyong Park74595c12018-07-23 15:22:50 +090098 const Options& options_;
Andreas Gampe7fab0d12017-11-22 17:50:17 -080099
Christopher Wiley67502f12016-01-29 10:57:00 -0800100 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800101};
102
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900103StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
Olivier Gaillard11401402018-07-05 15:01:34 +0100104 : Class(), options_(options) {
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800105 transact_descriptor = nullptr;
Andreas Gampe1b865af2017-11-22 11:31:47 -0800106 transact_outline = false;
Andreas Gampee9c816e2018-03-14 09:05:48 -0700107 all_method_count = 0; // Will be set when outlining may be enabled.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800108
Christopher Wiley67502f12016-01-29 10:57:00 -0800109 this->comment = "/** Local-side IPC implementation stub class. */";
110 this->modifiers = PUBLIC | ABSTRACT | STATIC;
111 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900112 this->type = interfaceType->GetCanonicalName() + ".Stub";
113 this->extends = "android.os.Binder";
114 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800115
Christopher Wiley67502f12016-01-29 10:57:00 -0800116 // descriptor
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900117 Field* descriptor =
118 new Field(STATIC | FINAL | PRIVATE, new Variable("java.lang.String", "DESCRIPTOR"));
119 descriptor->value = "\"" + interfaceType->GetCanonicalName() + "\"";
Christopher Wiley67502f12016-01-29 10:57:00 -0800120 this->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800121
Christopher Wiley67502f12016-01-29 10:57:00 -0800122 // ctor
123 Method* ctor = new Method;
124 ctor->modifiers = PUBLIC;
125 ctor->comment =
126 "/** Construct the stub at attach it to the "
127 "interface. */";
128 ctor->name = "Stub";
129 ctor->statements = new StatementBlock;
130 MethodCall* attach =
131 new MethodCall(THIS_VALUE, "attachInterface", 2, THIS_VALUE,
132 new LiteralExpression("DESCRIPTOR"));
133 ctor->statements->Add(attach);
134 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800135
Christopher Wiley67502f12016-01-29 10:57:00 -0800136 // asInterface
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900137 make_as_interface(interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800138
Christopher Wiley67502f12016-01-29 10:57:00 -0800139 // asBinder
140 Method* asBinder = new Method;
141 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900142 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800143 asBinder->name = "asBinder";
144 asBinder->statements = new StatementBlock;
145 asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
146 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800147
Jiyong Park74595c12018-07-23 15:22:50 +0900148 if (options_.GenTransactionNames()) {
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100149 // getDefaultTransactionName
150 Method* getDefaultTransactionName = new Method;
Jiyong Parke0b28032019-04-10 03:08:41 +0900151 getDefaultTransactionName->comment = "/** @hide */";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100152 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900153 getDefaultTransactionName->returnType = "java.lang.String";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100154 getDefaultTransactionName->name = "getDefaultTransactionName";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900155 Variable* code = new Variable("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100156 getDefaultTransactionName->parameters.push_back(code);
157 getDefaultTransactionName->statements = new StatementBlock;
158 this->code_to_method_name_switch = new SwitchStatement(code);
159 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
160 this->elements.push_back(getDefaultTransactionName);
161
162 // getTransactionName
Olivier Gaillard11401402018-07-05 15:01:34 +0100163 Method* getTransactionName = new Method;
Jiyong Parke0b28032019-04-10 03:08:41 +0900164 getTransactionName->comment = "/** @hide */";
Olivier Gaillard11401402018-07-05 15:01:34 +0100165 getTransactionName->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900166 getTransactionName->returnType = "java.lang.String";
Olivier Gaillard11401402018-07-05 15:01:34 +0100167 getTransactionName->name = "getTransactionName";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900168 Variable* code2 = new Variable("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100169 getTransactionName->parameters.push_back(code2);
Olivier Gaillard11401402018-07-05 15:01:34 +0100170 getTransactionName->statements = new StatementBlock;
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100171 getTransactionName->statements->Add(
172 new ReturnStatement(new MethodCall(THIS_VALUE, "getDefaultTransactionName", 1, code2)));
Olivier Gaillard11401402018-07-05 15:01:34 +0100173 this->elements.push_back(getTransactionName);
174 }
175
Christopher Wiley67502f12016-01-29 10:57:00 -0800176 // onTransact
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900177 this->transact_code = new Variable("int", "code");
178 this->transact_data = new Variable("android.os.Parcel", "data");
179 this->transact_reply = new Variable("android.os.Parcel", "reply");
180 this->transact_flags = new Variable("int", "flags");
Christopher Wiley67502f12016-01-29 10:57:00 -0800181 Method* onTransact = new Method;
182 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900183 onTransact->returnType = "boolean";
Christopher Wiley67502f12016-01-29 10:57:00 -0800184 onTransact->name = "onTransact";
185 onTransact->parameters.push_back(this->transact_code);
186 onTransact->parameters.push_back(this->transact_data);
187 onTransact->parameters.push_back(this->transact_reply);
188 onTransact->parameters.push_back(this->transact_flags);
189 onTransact->statements = new StatementBlock;
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800190 transact_statements = onTransact->statements;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900191 onTransact->exceptions.push_back("android.os.RemoteException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800192 this->elements.push_back(onTransact);
193 this->transact_switch = new SwitchStatement(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800194}
195
196void StubClass::finish() {
197 Case* default_case = new Case;
198
Christopher Wiley67502f12016-01-29 10:57:00 -0800199 MethodCall* superCall = new MethodCall(
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800200 SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data,
201 this->transact_reply, this->transact_flags);
202 default_case->statements->Add(new ReturnStatement(superCall));
203 transact_switch->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800204
205 transact_statements->Add(this->transact_switch);
Olivier Gaillard11401402018-07-05 15:01:34 +0100206
207 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900208 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100209 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
210 // Common transaction codes will not be resolved to a string by getTransactionName. The method
211 // will return NULL in this case.
212 Case* code_switch_default_case = new Case;
213 code_switch_default_case->statements->Add(new ReturnStatement(NULL_VALUE));
214 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
215 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800216}
217
Andreas Gampee9c816e2018-03-14 09:05:48 -0700218// The the expression for the interface's descriptor to be used when
219// generating code for the given method. Null is acceptable for method
220// and stands for synthetic cases.
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900221Expression* StubClass::get_transact_descriptor(const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800222 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700223 if (method != nullptr) {
224 // When outlining, each outlined method needs its own literal.
225 if (outline_methods.count(method) != 0) {
226 return new LiteralExpression("DESCRIPTOR");
227 }
228 } else {
229 // Synthetic case. A small number is assumed. Use its own descriptor
230 // if there are only synthetic cases.
231 if (outline_methods.size() == all_method_count) {
232 return new LiteralExpression("DESCRIPTOR");
233 }
234 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800235 }
236
Andreas Gampee9c816e2018-03-14 09:05:48 -0700237 // When not outlining, store the descriptor literal into a local variable, in
238 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800239 if (transact_descriptor == nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900240 transact_descriptor = new Variable("java.lang.String", "descriptor");
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800241 transact_statements->Add(
242 new VariableDeclaration(transact_descriptor,
243 new LiteralExpression("DESCRIPTOR")));
244 }
245 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800246}
247
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900248void StubClass::make_as_interface(const AidlInterface* interfaceType) {
249 Variable* obj = new Variable("android.os.IBinder", "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800250
251 Method* m = new Method;
252 m->comment = "/**\n * Cast an IBinder object into an ";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900253 m->comment += interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800254 m->comment += " interface,\n";
255 m->comment += " * generating a proxy if needed.\n */";
256 m->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900257 m->returnType = interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800258 m->name = "asInterface";
259 m->parameters.push_back(obj);
260 m->statements = new StatementBlock;
261
262 IfStatement* ifstatement = new IfStatement();
263 ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
264 ifstatement->statements = new StatementBlock;
265 ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
266 m->statements->Add(ifstatement);
267
268 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
269 MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
270 queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900271 Variable* iin = new Variable("android.os.IInterface", "iin");
Jeongik Cha9a7f21f2019-02-13 14:42:47 +0900272 VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800273 m->statements->Add(iinVd);
274
275 // Ensure the instance type of the local object is as expected.
276 // One scenario where this is needed is if another package (with a
277 // different class loader) runs in the same process as the service.
278
279 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
280 // iin;
281 Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
282 Comparison* instOfCheck =
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900283 new Comparison(iin, " instanceof ", new LiteralExpression(interfaceType->GetCanonicalName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800284 IfStatement* instOfStatement = new IfStatement();
285 instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
286 instOfStatement->statements = new StatementBlock;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900287 instOfStatement->statements->Add(
288 new ReturnStatement(new Cast(interfaceType->GetCanonicalName(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800289 m->statements->Add(instOfStatement);
290
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900291 NewExpression* ne = new NewExpression(interfaceType->GetCanonicalName() + ".Stub.Proxy");
Christopher Wiley67502f12016-01-29 10:57:00 -0800292 ne->arguments.push_back(obj);
293 m->statements->Add(new ReturnStatement(ne));
294
295 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800296}
297
Adam Lesinskiffa16862014-01-23 18:17:42 -0800298// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800299class ProxyClass : public Class {
300 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900301 ProxyClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700302 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800303
Christopher Wiley67502f12016-01-29 10:57:00 -0800304 Variable* mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800305};
306
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900307ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
Christopher Wiley67502f12016-01-29 10:57:00 -0800308 this->modifiers = PRIVATE | STATIC;
309 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900310 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
311 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800312
Christopher Wiley67502f12016-01-29 10:57:00 -0800313 // IBinder mRemote
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900314 mRemote = new Variable("android.os.IBinder", "mRemote");
Christopher Wiley67502f12016-01-29 10:57:00 -0800315 this->elements.push_back(new Field(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800316
Christopher Wiley67502f12016-01-29 10:57:00 -0800317 // Proxy()
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900318 Variable* remote = new Variable("android.os.IBinder", "remote");
Christopher Wiley67502f12016-01-29 10:57:00 -0800319 Method* ctor = new Method;
320 ctor->name = "Proxy";
321 ctor->statements = new StatementBlock;
322 ctor->parameters.push_back(remote);
323 ctor->statements->Add(new Assignment(mRemote, remote));
324 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800325
Jiyong Park309668e2018-07-28 16:55:44 +0900326 if (options.Version() > 0) {
327 std::ostringstream code;
328 code << "private int mCachedVersion = -1;\n";
329 this->elements.emplace_back(new LiteralClassElement(code.str()));
330 }
331
Christopher Wiley67502f12016-01-29 10:57:00 -0800332 // IBinder asBinder()
333 Method* asBinder = new Method;
334 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900335 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800336 asBinder->name = "asBinder";
337 asBinder->statements = new StatementBlock;
338 asBinder->statements->Add(new ReturnStatement(mRemote));
339 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800340}
341
Christopher Wiley67502f12016-01-29 10:57:00 -0800342ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800343
344// =================================================
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900345static void generate_new_array(const AidlTypeSpecifier& type, StatementBlock* addTo, Variable* v,
346 Variable* parcel) {
347 Variable* len = new Variable("int", v->name + "_length");
Christopher Wiley67502f12016-01-29 10:57:00 -0800348 addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
349 IfStatement* lencheck = new IfStatement();
350 lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
351 lencheck->statements->Add(new Assignment(v, NULL_VALUE));
352 lencheck->elseif = new IfStatement();
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900353 lencheck->elseif->statements->Add(
354 new Assignment(v, new NewArrayExpression(JavaSignatureOf(type), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800355 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800356}
357
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900358static void generate_write_to_parcel(const AidlTypeSpecifier& type, StatementBlock* addTo,
359 Variable* v, Variable* parcel, bool is_return_value,
360 const AidlTypenames& typenames) {
361 string code;
362 CodeWriterPtr writer = CodeWriter::ForString(&code);
363 CodeGeneratorContext context{
364 .writer = *(writer.get()),
365 .typenames = typenames,
366 .type = type,
367 .var = v->name,
368 .parcel = parcel->name,
369 .is_return_value = is_return_value,
370 };
371 WriteToParcelFor(context);
372 writer->Close();
373 addTo->Add(new LiteralStatement(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800374}
375
Steven Moreland693640b2018-07-19 13:46:27 -0700376static void generate_int_constant(Class* interface, const std::string& name,
377 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900378 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
379 interface->elements.push_back(new LiteralClassElement(code));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700380}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800381
Steven Moreland693640b2018-07-19 13:46:27 -0700382static void generate_string_constant(Class* interface, const std::string& name,
383 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900384 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
385 interface->elements.push_back(new LiteralClassElement(code));
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800386}
387
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900388static std::unique_ptr<Method> generate_interface_method(const AidlMethod& method) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800389 std::unique_ptr<Method> decl(new Method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800390 decl->comment = method.GetComments();
391 decl->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900392 decl->returnType = JavaSignatureOf(method.GetType());
Christopher Wiley67502f12016-01-29 10:57:00 -0800393 decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
394 decl->name = method.GetName();
Jiyong Parka6605ab2018-11-11 14:30:21 +0900395 decl->annotations = generate_java_annotations(method.GetType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800396
Christopher Wiley67502f12016-01-29 10:57:00 -0800397 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900398 decl->parameters.push_back(new Variable(JavaSignatureOf(arg->GetType()), arg->GetName(),
399 arg->GetType().IsArray() ? 1 : 0));
Christopher Wiley67502f12016-01-29 10:57:00 -0800400 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800401
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900402 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800403
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800404 return decl;
405}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800406
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900407static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
408 Variable* transact_data, Variable* transact_reply,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900409 const AidlTypenames& typenames, StatementBlock* statements,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900410 StubClass* stubClass, const Options& options) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100411 TryStatement* tryStatement = nullptr;
412 FinallyStatement* finallyStatement = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800413 MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800414
Christopher Wiley67502f12016-01-29 10:57:00 -0800415 // interface token validation is the very first thing we do
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900416 statements->Add(new MethodCall(transact_data, "enforceInterface", 1,
417 stubClass->get_transact_descriptor(&method)));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800418
Christopher Wiley67502f12016-01-29 10:57:00 -0800419 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800420 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800421 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900422 // keep this across different args in order to create the classloader
423 // at most once.
424 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800425 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900426 Variable* v = stubArgs.Get(arg->GetType());
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800427 v->dimension = arg->GetType().IsArray() ? 1 : 0;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800428
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800429 statements->Add(new VariableDeclaration(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800430
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800431 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900432 string code;
433 CodeWriterPtr writer = CodeWriter::ForString(&code);
434 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900435 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900436 .type = arg->GetType(),
437 .var = v->name,
438 .parcel = transact_data->name,
439 .is_classloader_created = &is_classloader_created};
440 CreateFromParcelFor(context);
441 writer->Close();
442 statements->Add(new LiteralStatement(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800443 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800444 if (!arg->GetType().IsArray()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900445 statements->Add(
446 new Assignment(v, new NewExpression(InstantiableJavaSignatureOf(arg->GetType()))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800447 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900448 generate_new_array(arg->GetType(), statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800449 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800450 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800451
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800452 realCall->arguments.push_back(v);
453 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800454 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800455
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900456 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100457 // try and finally, but only when generating trace code
458 tryStatement = new TryStatement();
459 finallyStatement = new FinallyStatement();
460
461 tryStatement->statements->Add(new MethodCall(
462 new LiteralExpression("android.os.Trace"), "traceBegin", 2,
463 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
464 new StringLiteralExpression(iface.GetName() + "::"
465 + method.GetName() + "::server")));
466
467 finallyStatement->statements->Add(new MethodCall(
468 new LiteralExpression("android.os.Trace"), "traceEnd", 1,
469 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
470 }
471
Christopher Wiley67502f12016-01-29 10:57:00 -0800472 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800473 if (method.GetType().GetName() == "void") {
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900474 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100475 statements->Add(tryStatement);
476 tryStatement->statements->Add(realCall);
477 statements->Add(finallyStatement);
478 } else {
479 statements->Add(realCall);
480 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800481
Adam Lesinskiffa16862014-01-23 18:17:42 -0800482 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800483 // report that there were no exceptions
484 MethodCall* ex =
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800485 new MethodCall(transact_reply, "writeNoException", 0);
486 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800487 }
488 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900489 Variable* _result = new Variable(JavaSignatureOf(method.GetType()), "_result",
490 method.GetType().IsArray() ? 1 : 0);
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900491 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100492 statements->Add(new VariableDeclaration(_result));
493 statements->Add(tryStatement);
494 tryStatement->statements->Add(new Assignment(_result, realCall));
495 statements->Add(finallyStatement);
496 } else {
497 statements->Add(new VariableDeclaration(_result, realCall));
498 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800499
500 if (!oneway) {
501 // report that there were no exceptions
502 MethodCall* ex =
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800503 new MethodCall(transact_reply, "writeNoException", 0);
504 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800505 }
506
Christopher Wiley67502f12016-01-29 10:57:00 -0800507 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900508 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900509 typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800510 }
511
512 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800513 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800514 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800515 Variable* v = stubArgs.Get(i++);
516
517 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900518 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800519 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800520 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800521
Christopher Wiley67502f12016-01-29 10:57:00 -0800522 // return true
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800523 statements->Add(new ReturnStatement(TRUE_VALUE));
524}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800525
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900526static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
527 const std::string& transactCodeName, bool oneway,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900528 StubClass* stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900529 const Options& options) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800530 Case* c = new Case(transactCodeName);
531
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900532 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900533 typenames, c->statements, stubClass, options);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800534
535 stubClass->transact_switch->cases.push_back(c);
536}
537
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900538static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
539 const std::string& transactCodeName, bool oneway,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900540 StubClass* stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900541 const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800542 std::string outline_name = "onTransact$" + method.GetName() + "$";
543 // Generate an "outlined" method with the actual code.
544 {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900545 Variable* transact_data = new Variable("android.os.Parcel", "data");
546 Variable* transact_reply = new Variable("android.os.Parcel", "reply");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800547 Method* onTransact_case = new Method;
548 onTransact_case->modifiers = PRIVATE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900549 onTransact_case->returnType = "boolean";
Andreas Gampe1b865af2017-11-22 11:31:47 -0800550 onTransact_case->name = outline_name;
551 onTransact_case->parameters.push_back(transact_data);
552 onTransact_case->parameters.push_back(transact_reply);
553 onTransact_case->statements = new StatementBlock;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900554 onTransact_case->exceptions.push_back("android.os.RemoteException");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800555 stubClass->elements.push_back(onTransact_case);
556
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900557 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900558 onTransact_case->statements, stubClass, options);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800559 }
560
561 // Generate the case dispatch.
562 {
563 Case* c = new Case(transactCodeName);
564
565 MethodCall* helper_call = new MethodCall(THIS_VALUE,
566 outline_name,
567 2,
568 stubClass->transact_data,
569 stubClass->transact_reply);
570 c->statements->Add(new ReturnStatement(helper_call));
571
572 stubClass->transact_switch->cases.push_back(c);
573 }
574}
575
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800576static std::unique_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900577 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900578 bool oneway, ProxyClass* proxyClass, const AidlTypenames& typenames, const Options& options) {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800579 std::unique_ptr<Method> proxy(new Method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800580 proxy->comment = method.GetComments();
581 proxy->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900582 proxy->returnType = JavaSignatureOf(method.GetType());
Christopher Wiley67502f12016-01-29 10:57:00 -0800583 proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
584 proxy->name = method.GetName();
585 proxy->statements = new StatementBlock;
586 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900587 proxy->parameters.push_back(new Variable(JavaSignatureOf(arg->GetType()), arg->GetName(),
588 arg->GetType().IsArray() ? 1 : 0));
Christopher Wiley67502f12016-01-29 10:57:00 -0800589 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900590 proxy->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800591
Christopher Wiley67502f12016-01-29 10:57:00 -0800592 // the parcels
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900593 Variable* _data = new Variable("android.os.Parcel", "_data");
Jeongik Cha439f2c42019-02-13 12:38:30 +0900594 proxy->statements->Add(
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900595 new VariableDeclaration(_data, new MethodCall("android.os.Parcel", "obtain")));
Yi Kong894d6ba2018-07-24 11:27:38 -0700596 Variable* _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800597 if (!oneway) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900598 _reply = new Variable("android.os.Parcel", "_reply");
Jeongik Cha439f2c42019-02-13 12:38:30 +0900599 proxy->statements->Add(
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900600 new VariableDeclaration(_reply, new MethodCall("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800601 }
602
603 // the return value
Yi Kong894d6ba2018-07-24 11:27:38 -0700604 Variable* _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800605 if (method.GetType().GetName() != "void") {
Jeongik Cha6cadc212019-02-12 18:16:03 +0900606 _result = new Variable(*proxy->returnType, "_result", method.GetType().IsArray() ? 1 : 0);
Christopher Wiley67502f12016-01-29 10:57:00 -0800607 proxy->statements->Add(new VariableDeclaration(_result));
608 }
609
610 // try and finally
611 TryStatement* tryStatement = new TryStatement();
612 proxy->statements->Add(tryStatement);
613 FinallyStatement* finallyStatement = new FinallyStatement();
614 proxy->statements->Add(finallyStatement);
615
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900616 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100617 tryStatement->statements->Add(new MethodCall(
618 new LiteralExpression("android.os.Trace"), "traceBegin", 2,
619 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
620 new StringLiteralExpression(iface.GetName() + "::" +
621 method.GetName() + "::client")));
622 }
623
Christopher Wiley67502f12016-01-29 10:57:00 -0800624 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
625 // string
626 tryStatement->statements->Add(new MethodCall(
627 _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR")));
628
629 // the parameters
630 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900631 Variable* v = new Variable(JavaSignatureOf(arg->GetType()), arg->GetName(),
632 arg->GetType().IsArray() ? 1 : 0);
Christopher Wiley67502f12016-01-29 10:57:00 -0800633 AidlArgument::Direction dir = arg->GetDirection();
634 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
635 IfStatement* checklen = new IfStatement();
636 checklen->expression = new Comparison(v, "==", NULL_VALUE);
637 checklen->statements->Add(
638 new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1")));
639 checklen->elseif = new IfStatement();
640 checklen->elseif->statements->Add(
641 new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length")));
642 tryStatement->statements->Add(checklen);
643 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900644 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900645 typenames);
Christopher Wiley5f848522016-03-01 16:29:41 -0800646 } else {
647 delete v;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800648 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800649 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800650
Christopher Wiley67502f12016-01-29 10:57:00 -0800651 // the transact call
Jiyong Park75e1a742018-07-04 12:31:23 +0900652 unique_ptr<MethodCall> call(new MethodCall(
653 proxyClass->mRemote, "transact", 4, new LiteralExpression("Stub." + transactCodeName), _data,
Christopher Wiley67502f12016-01-29 10:57:00 -0800654 _reply ? _reply : NULL_VALUE,
Jiyong Park75e1a742018-07-04 12:31:23 +0900655 new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")));
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900656 unique_ptr<Variable> _status(new Variable("boolean", "_status"));
Jiyong Park75e1a742018-07-04 12:31:23 +0900657 tryStatement->statements->Add(new VariableDeclaration(_status.release(), call.release()));
658
659 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
660 // back to the local method in the default impl, if set before.
661 vector<string> arg_names;
662 for (const auto& arg : method.GetArguments()) {
663 arg_names.emplace_back(arg->GetName());
664 }
665 bool has_return_type = method.GetType().GetName() != "void";
666 tryStatement->statements->Add(new LiteralStatement(
667 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
668 " return getDefaultImpl().%s(%s);\n"
669 "}\n"
670 : "if (!_status && getDefaultImpl() != null) {\n"
671 " getDefaultImpl().%s(%s);\n"
672 " return;\n"
673 "}\n",
674 method.GetName().c_str(), Join(arg_names, ", ").c_str())));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800675
Christopher Wiley67502f12016-01-29 10:57:00 -0800676 // throw back exceptions.
677 if (_reply) {
678 MethodCall* ex = new MethodCall(_reply, "readException", 0);
679 tryStatement->statements->Add(ex);
680 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800681
Christopher Wiley67502f12016-01-29 10:57:00 -0800682 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700683 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900684 // keep this across return value and arguments in order to create the
685 // classloader at most once.
686 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700687 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900688 string code;
689 CodeWriterPtr writer = CodeWriter::ForString(&code);
690 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900691 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900692 .type = method.GetType(),
693 .var = _result->name,
694 .parcel = _reply->name,
695 .is_classloader_created = &is_classloader_created};
696 CreateFromParcelFor(context);
697 writer->Close();
698 tryStatement->statements->Add(new LiteralStatement(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800699 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800700
701 // the out/inout parameters
702 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800703 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900704 string code;
705 CodeWriterPtr writer = CodeWriter::ForString(&code);
706 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900707 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900708 .type = arg->GetType(),
709 .var = arg->GetName(),
710 .parcel = _reply->name,
711 .is_classloader_created = &is_classloader_created};
712 ReadFromParcelFor(context);
713 writer->Close();
714 tryStatement->statements->Add(new LiteralStatement(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800715 }
716 }
717
718 finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
719 }
720 finallyStatement->statements->Add(new MethodCall(_data, "recycle"));
721
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900722 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100723 finallyStatement->statements->Add(new MethodCall(
724 new LiteralExpression("android.os.Trace"), "traceEnd", 1,
725 new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
726 }
727
Yi Kong894d6ba2018-07-24 11:27:38 -0700728 if (_result != nullptr) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800729 proxy->statements->Add(new ReturnStatement(_result));
730 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800731
732 return proxy;
733}
734
Jiyong Park74595c12018-07-23 15:22:50 +0900735static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
736 StubClass* stubClass, ProxyClass* proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900737 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800738 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800739
740 // == the TRANSACT_ constant =============================================
741 string transactCodeName = "TRANSACTION_";
742 transactCodeName += method.GetName();
743
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900744 Field* transactCode = new Field(STATIC | FINAL, new Variable("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800745 transactCode->value =
746 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
747 stubClass->elements.push_back(transactCode);
748
Olivier Gaillard11401402018-07-05 15:01:34 +0100749 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900750 if (options.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100751 Case* c = new Case(transactCodeName);
752 c->statements->Add(new ReturnStatement(new StringLiteralExpression(method.GetName())));
753 stubClass->code_to_method_name_switch->cases.push_back(c);
754 }
755
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800756 // == the declaration in the interface ===================================
Jiyong Park309668e2018-07-28 16:55:44 +0900757 ClassElement* decl;
758 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900759 decl = generate_interface_method(method).release();
Jiyong Park309668e2018-07-28 16:55:44 +0900760 } else {
761 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
762 std::ostringstream code;
763 code << "public int " << kGetInterfaceVersion << "() "
764 << "throws android.os.RemoteException;\n";
765 decl = new LiteralClassElement(code.str());
766 }
767 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800768 interface->elements.push_back(decl);
769
770 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900771 if (method.IsUserDefined()) {
772 bool outline_stub =
773 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
774 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900775 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900776 options);
777 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900778 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900779 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800780 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900781 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
782 Case* c = new Case(transactCodeName);
783 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900784 code << "data.enforceInterface(descriptor);\n"
785 << "reply.writeNoException();\n"
786 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900787 << "return true;\n";
788 c->statements->Add(new LiteralStatement(code.str()));
789 stubClass->transact_switch->cases.push_back(c);
790 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800791 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800792
793 // == the proxy method ===================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900794 ClassElement* proxy = nullptr;
795 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900796 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
797 options)
798 .release();
Jiyong Park309668e2018-07-28 16:55:44 +0900799
800 } else {
801 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
802 std::ostringstream code;
803 code << "@Override\n"
804 << "public int " << kGetInterfaceVersion << "()"
805 << " throws "
806 << "android.os.RemoteException {\n"
807 << " if (mCachedVersion == -1) {\n"
808 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
809 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
810 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900811 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900812 << " mRemote.transact(Stub." << transactCodeName << ", "
813 << "data, reply, 0);\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900814 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900815 << " mCachedVersion = reply.readInt();\n"
816 << " } finally {\n"
817 << " reply.recycle();\n"
818 << " data.recycle();\n"
819 << " }\n"
820 << " }\n"
821 << " return mCachedVersion;\n"
822 << "}\n";
823 proxy = new LiteralClassElement(code.str());
824 }
825 }
826 if (proxy != nullptr) {
827 proxyClass->elements.push_back(proxy);
828 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800829}
830
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900831static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800832 // the interface descriptor transaction handler
833 Case* c = new Case("INTERFACE_TRANSACTION");
834 c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900835 stub->get_transact_descriptor(nullptr)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800836 c->statements->Add(new ReturnStatement(TRUE_VALUE));
837 stub->transact_switch->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800838
Christopher Wiley67502f12016-01-29 10:57:00 -0800839 // and the proxy-side method returning the descriptor directly
840 Method* getDesc = new Method;
841 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900842 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800843 getDesc->returnTypeDimension = 0;
844 getDesc->name = "getInterfaceDescriptor";
845 getDesc->statements = new StatementBlock;
846 getDesc->statements->Add(
847 new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
848 proxy->elements.push_back(getDesc);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800849}
850
Andreas Gampee9c816e2018-03-14 09:05:48 -0700851// Check whether (some) methods in this interface should be "outlined," that
852// is, have specific onTransact methods for certain cases. Set up StubClass
853// metadata accordingly.
854//
855// Outlining will be enabled if the interface has more than outline_threshold
856// methods. In that case, the methods are sorted by number of arguments
857// (so that more "complex" methods come later), and the first non_outline_count
858// number of methods not outlined (are kept in the onTransact() method).
859//
860// Requirements: non_outline_count <= outline_threshold.
861static void compute_outline_methods(const AidlInterface* iface,
862 StubClass* stub,
863 size_t outline_threshold,
864 size_t non_outline_count) {
865 CHECK_LE(non_outline_count, outline_threshold);
866 // We'll outline (create sub methods) if there are more than min_methods
867 // cases.
868 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
869 if (stub->transact_outline) {
870 stub->all_method_count = iface->GetMethods().size();
871 std::vector<const AidlMethod*> methods;
872 methods.reserve(iface->GetMethods().size());
873 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
874 methods.push_back(ptr.get());
875 }
876
877 std::stable_sort(
878 methods.begin(),
879 methods.end(),
880 [](const AidlMethod* m1, const AidlMethod* m2) {
881 return m1->GetArguments().size() < m2->GetArguments().size();
882 });
883
884 stub->outline_methods.insert(methods.begin() + non_outline_count,
885 methods.end());
886 }
887}
888
Jiyong Park75e1a742018-07-04 12:31:23 +0900889static unique_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method) {
890 unique_ptr<Method> default_method(new Method);
891 default_method->comment = method.GetComments();
892 default_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900893 default_method->returnType = JavaSignatureOf(method.GetType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900894 default_method->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
895 default_method->name = method.GetName();
896 default_method->statements = new StatementBlock;
897 for (const auto& arg : method.GetArguments()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900898 default_method->parameters.push_back(new Variable(
899 JavaSignatureOf(arg->GetType()), arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
Jiyong Park75e1a742018-07-04 12:31:23 +0900900 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900901 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +0900902
903 if (method.GetType().GetName() != "void") {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900904 const string& defaultValue = DefaultJavaValueOf(method.GetType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900905 default_method->statements->Add(
906 new LiteralStatement(StringPrintf("return %s;\n", defaultValue.c_str())));
907 }
908 return default_method;
909}
910
Jiyong Park309668e2018-07-28 16:55:44 +0900911static unique_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
912 const Options& options) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900913 unique_ptr<Class> default_class(new Class);
914 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
915 default_class->modifiers = PUBLIC | STATIC;
916 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900917 default_class->type = iface.GetCanonicalName() + ".Default";
918 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +0900919
920 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900921 if (m->IsUserDefined()) {
922 default_class->elements.emplace_back(generate_default_impl_method(*(m.get())).release());
923 } else {
924 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900925 // This is called only when the remote side is not implementing this
926 // method, which is impossible in normal case, because this method is
927 // automatically declared in the interface class and not implementing
928 // it in the remote side is causing compilation error. But if the remote
929 // side somehow managed to not implement it, that's an error and we
930 // report the case by returning -1 here.
Jiyong Park309668e2018-07-28 16:55:44 +0900931 std::ostringstream code;
932 code << "@Override\n"
933 << "public int " << kGetInterfaceVersion << "() {\n"
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900934 << " return -1;\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900935 << "}\n";
936 default_class->elements.emplace_back(new LiteralClassElement(code.str()));
937 }
938 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900939 }
940
941 default_class->elements.emplace_back(
942 new LiteralClassElement("@Override\n"
943 "public android.os.IBinder asBinder() {\n"
944 " return null;\n"
945 "}\n"));
946
947 return default_class;
948}
949
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900950Class* generate_binder_interface_class(const AidlInterface* iface, const AidlTypenames& typenames,
Jiyong Park74595c12018-07-23 15:22:50 +0900951 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800952 // the interface class
953 Class* interface = new Class;
954 interface->comment = iface->GetComments();
955 interface->modifiers = PUBLIC;
956 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900957 interface->type = iface->GetCanonicalName();
958 interface->interfaces.push_back("android.os.IInterface");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900959 interface->annotations = generate_java_annotations(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800960
Jiyong Park309668e2018-07-28 16:55:44 +0900961 if (options.Version()) {
962 std::ostringstream code;
963 code << "/**\n"
964 << " * The version of this interface that the caller is built against.\n"
965 << " * This might be different from what {@link #getInterfaceVersion()\n"
966 << " * getInterfaceVersion} returns as that is the version of the interface\n"
967 << " * that the remote object is implementing.\n"
968 << " */\n"
969 << "public static final int VERSION = " << options.Version() << ";\n";
970 interface->elements.emplace_back(new LiteralClassElement(code.str()));
971 }
972
Jiyong Park75e1a742018-07-04 12:31:23 +0900973 // the default impl class
Jiyong Park309668e2018-07-28 16:55:44 +0900974 Class* default_impl = generate_default_impl_class(*iface, options).release();
975 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +0900976
Christopher Wiley67502f12016-01-29 10:57:00 -0800977 // the stub inner class
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900978 StubClass* stub = new StubClass(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -0800979 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800980
Andreas Gampee9c816e2018-03-14 09:05:48 -0700981 compute_outline_methods(iface,
982 stub,
983 options.onTransact_outline_threshold_,
984 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800985
Christopher Wiley67502f12016-01-29 10:57:00 -0800986 // the proxy inner class
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900987 ProxyClass* proxy = new ProxyClass(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -0800988 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800989
Christopher Wiley67502f12016-01-29 10:57:00 -0800990 // stub and proxy support for getInterfaceDescriptor()
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900991 generate_interface_descriptors(stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800992
Christopher Wiley67502f12016-01-29 10:57:00 -0800993 // all the declared constants of the interface
Steven Moreland693640b2018-07-19 13:46:27 -0700994 for (const auto& constant : iface->GetConstantDeclarations()) {
995 const AidlConstantValue& value = constant->GetValue();
996
997 switch (value.GetType()) {
998 case AidlConstantValue::Type::STRING: {
Steven Moreland860b1942018-08-16 14:59:28 -0700999 generate_string_constant(interface, constant->GetName(),
1000 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001001 break;
1002 }
Steven Moreland25294322018-08-07 18:13:55 -07001003 case AidlConstantValue::Type::INTEGRAL:
1004 case AidlConstantValue::Type::HEXIDECIMAL: {
Steven Moreland860b1942018-08-16 14:59:28 -07001005 generate_int_constant(interface, constant->GetName(),
1006 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001007 break;
1008 }
1009 default: {
1010 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1011 }
1012 }
Christopher Wiley67502f12016-01-29 10:57:00 -08001013 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001014
Christopher Wiley67502f12016-01-29 10:57:00 -08001015 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001016
Christopher Wiley67502f12016-01-29 10:57:00 -08001017 for (const auto& item : iface->GetMethods()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001018 generate_methods(*iface, *item, interface, stub, proxy, item->GetId(), typenames, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001019 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001020
1021 // additional static methods for the default impl set/get to the
1022 // stub class. Can't add them to the interface as the generated java files
1023 // may be compiled with Java < 1.7 where static interface method isn't
1024 // supported.
1025 // TODO(b/111417145) make this conditional depending on the Java language
1026 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001027 const string i_name = iface->GetCanonicalName();
Jiyong Park75e1a742018-07-04 12:31:23 +09001028 stub->elements.emplace_back(new LiteralClassElement(
1029 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1030 " if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
1031 " Stub.Proxy.sDefaultImpl = impl;\n"
1032 " return true;\n"
1033 " }\n"
1034 " return false;\n"
1035 "}\n",
1036 i_name.c_str())));
1037 stub->elements.emplace_back(
1038 new LiteralClassElement(StringPrintf("public static %s getDefaultImpl() {\n"
1039 " return Stub.Proxy.sDefaultImpl;\n"
1040 "}\n",
1041 i_name.c_str())));
1042
1043 // the static field is defined in the proxy class, not in the interface class
1044 // because all fields in an interface class are by default final.
1045 proxy->elements.emplace_back(new LiteralClassElement(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001046 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001047
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001048 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001049
Christopher Wiley67502f12016-01-29 10:57:00 -08001050 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001051}
1052
Christopher Wileydb154a52015-09-28 16:32:25 -07001053} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001054} // namespace android
1055} // namespace aidl