blob: 01e88db274c64c116b7e15b15e1d96e9bbcabbb5 [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"
Jeongik Cha047c5ee2019-08-07 23:16:49 +090020#include "logging.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090021#include "options.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;
Jiyong Park2c44f072018-07-30 21:52:21 +090050
51 explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
Daniel Norman716d3112019-09-10 13:11:56 -070052 std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
53 auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
Steven Moreland48548e02019-09-18 15:10:22 -070054 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
Steven Moreland48548e02019-09-18 15:10:22 -070060 std::shared_ptr<Variable> Get(int index) { return vars_[index]; }
Jiyong Park2c44f072018-07-30 21:52:21 +090061
62 private:
Steven Moreland48548e02019-09-18 15:10:22 -070063 std::vector<std::shared_ptr<Variable>> vars_;
Jiyong Park2c44f072018-07-30 21:52:21 +090064 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:
Jeongik Chaa2080bf2019-06-18 16:44:29 +090073 StubClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -070074 ~StubClass() override = default;
Adam Lesinskiffa16862014-01-23 18:17:42 -080075
Steven Moreland48548e02019-09-18 15:10:22 -070076 std::shared_ptr<Variable> transact_code;
77 std::shared_ptr<Variable> transact_data;
78 std::shared_ptr<Variable> transact_reply;
79 std::shared_ptr<Variable> transact_flags;
80 std::shared_ptr<SwitchStatement> transact_switch;
81 std::shared_ptr<StatementBlock> transact_statements;
82 std::shared_ptr<SwitchStatement> code_to_method_name_switch;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070083
Andreas Gampe1b865af2017-11-22 11:31:47 -080084 // Where onTransact cases should be generated as separate methods.
85 bool transact_outline;
Andreas Gampee9c816e2018-03-14 09:05:48 -070086 // Specific methods that should be outlined when transact_outline is true.
87 std::unordered_set<const AidlMethod*> outline_methods;
88 // Number of all methods.
89 size_t all_method_count;
Andreas Gampe1b865af2017-11-22 11:31:47 -080090
Andreas Gampea8a66fe2017-11-22 12:17:00 -080091 // Finish generation. This will add a default case to the switch.
92 void finish();
93
Steven Moreland48548e02019-09-18 15:10:22 -070094 std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
Andreas Gampe7fab0d12017-11-22 17:50:17 -080095
Christopher Wiley67502f12016-01-29 10:57:00 -080096 private:
Jeongik Chaa2080bf2019-06-18 16:44:29 +090097 void make_as_interface(const AidlInterface* interfaceType);
Christopher Wiley67502f12016-01-29 10:57:00 -080098
Steven Moreland48548e02019-09-18 15:10:22 -070099 std::shared_ptr<Variable> transact_descriptor;
Jiyong Park74595c12018-07-23 15:22:50 +0900100 const Options& options_;
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800101
Christopher Wiley67502f12016-01-29 10:57:00 -0800102 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800103};
104
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900105StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
Olivier Gaillard11401402018-07-05 15:01:34 +0100106 : Class(), options_(options) {
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800107 transact_descriptor = nullptr;
Andreas Gampe1b865af2017-11-22 11:31:47 -0800108 transact_outline = false;
Andreas Gampee9c816e2018-03-14 09:05:48 -0700109 all_method_count = 0; // Will be set when outlining may be enabled.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800110
Christopher Wiley67502f12016-01-29 10:57:00 -0800111 this->comment = "/** Local-side IPC implementation stub class. */";
112 this->modifiers = PUBLIC | ABSTRACT | STATIC;
113 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900114 this->type = interfaceType->GetCanonicalName() + ".Stub";
115 this->extends = "android.os.Binder";
116 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800117
Christopher Wiley67502f12016-01-29 10:57:00 -0800118 // descriptor
Steven Moreland48548e02019-09-18 15:10:22 -0700119 auto descriptor = std::make_shared<Field>(
120 STATIC | FINAL | PRIVATE, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jiyong Parkd49d2bb2020-04-13 22:33:54 +0900121 if (options.IsStructured()) {
122 // mangle the interface name at build time and demangle it at runtime, to avoid
123 // being renamed by jarjar. See b/153843174
124 std::string name = interfaceType->GetCanonicalName();
125 std::replace(name.begin(), name.end(), '.', '$');
126 descriptor->value = "\"" + name + "\".replace('$', '.')";
127 } else {
128 descriptor->value = "\"" + interfaceType->GetCanonicalName() + "\"";
129 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800130 this->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800131
Christopher Wiley67502f12016-01-29 10:57:00 -0800132 // ctor
Steven Moreland48548e02019-09-18 15:10:22 -0700133 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800134 ctor->modifiers = PUBLIC;
135 ctor->comment =
136 "/** Construct the stub at attach it to the "
137 "interface. */";
138 ctor->name = "Stub";
Steven Moreland48548e02019-09-18 15:10:22 -0700139 ctor->statements = std::make_shared<StatementBlock>();
Steven Morelande2fcb8e2019-11-27 18:09:15 -0800140 if (interfaceType->IsVintfStability()) {
141 auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
142 ctor->statements->Add(stability);
143 }
Steven Moreland48548e02019-09-18 15:10:22 -0700144 auto attach = std::make_shared<MethodCall>(
145 THIS_VALUE, "attachInterface",
146 std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
147 std::make_shared<LiteralExpression>("DESCRIPTOR")});
Christopher Wiley67502f12016-01-29 10:57:00 -0800148 ctor->statements->Add(attach);
149 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800150
Christopher Wiley67502f12016-01-29 10:57:00 -0800151 // asInterface
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900152 make_as_interface(interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800153
Christopher Wiley67502f12016-01-29 10:57:00 -0800154 // asBinder
Steven Moreland48548e02019-09-18 15:10:22 -0700155 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800156 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900157 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800158 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700159 asBinder->statements = std::make_shared<StatementBlock>();
160 asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800161 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800162
Jiyong Park74595c12018-07-23 15:22:50 +0900163 if (options_.GenTransactionNames()) {
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100164 // getDefaultTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700165 auto getDefaultTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900166 getDefaultTransactionName->comment = "/** @hide */";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100167 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900168 getDefaultTransactionName->returnType = "java.lang.String";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100169 getDefaultTransactionName->name = "getDefaultTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700170 auto code = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100171 getDefaultTransactionName->parameters.push_back(code);
Steven Moreland48548e02019-09-18 15:10:22 -0700172 getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
173 this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100174 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
175 this->elements.push_back(getDefaultTransactionName);
176
177 // getTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700178 auto getTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900179 getTransactionName->comment = "/** @hide */";
Olivier Gaillard11401402018-07-05 15:01:34 +0100180 getTransactionName->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900181 getTransactionName->returnType = "java.lang.String";
Olivier Gaillard11401402018-07-05 15:01:34 +0100182 getTransactionName->name = "getTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700183 auto code2 = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100184 getTransactionName->parameters.push_back(code2);
Steven Moreland48548e02019-09-18 15:10:22 -0700185 getTransactionName->statements = std::make_shared<StatementBlock>();
186 getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
187 std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
188 std::vector<std::shared_ptr<Expression>>{code2})));
Olivier Gaillard11401402018-07-05 15:01:34 +0100189 this->elements.push_back(getTransactionName);
190 }
191
Christopher Wiley67502f12016-01-29 10:57:00 -0800192 // onTransact
Steven Moreland48548e02019-09-18 15:10:22 -0700193 this->transact_code = std::make_shared<Variable>("int", "code");
194 this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
195 this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
196 this->transact_flags = std::make_shared<Variable>("int", "flags");
197 auto onTransact = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800198 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900199 onTransact->returnType = "boolean";
Christopher Wiley67502f12016-01-29 10:57:00 -0800200 onTransact->name = "onTransact";
201 onTransact->parameters.push_back(this->transact_code);
202 onTransact->parameters.push_back(this->transact_data);
203 onTransact->parameters.push_back(this->transact_reply);
204 onTransact->parameters.push_back(this->transact_flags);
Steven Moreland48548e02019-09-18 15:10:22 -0700205 onTransact->statements = std::make_shared<StatementBlock>();
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800206 transact_statements = onTransact->statements;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900207 onTransact->exceptions.push_back("android.os.RemoteException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800208 this->elements.push_back(onTransact);
Steven Moreland48548e02019-09-18 15:10:22 -0700209 this->transact_switch = std::make_shared<SwitchStatement>(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800210}
211
212void StubClass::finish() {
Steven Moreland48548e02019-09-18 15:10:22 -0700213 auto default_case = std::make_shared<Case>();
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800214
Steven Moreland48548e02019-09-18 15:10:22 -0700215 auto superCall = std::make_shared<MethodCall>(
216 SUPER_VALUE, "onTransact",
217 std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
218 this->transact_reply, this->transact_flags});
219 default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800220 transact_switch->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800221
222 transact_statements->Add(this->transact_switch);
Olivier Gaillard11401402018-07-05 15:01:34 +0100223
224 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900225 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100226 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
227 // Common transaction codes will not be resolved to a string by getTransactionName. The method
228 // will return NULL in this case.
Steven Moreland48548e02019-09-18 15:10:22 -0700229 auto code_switch_default_case = std::make_shared<Case>();
230 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Olivier Gaillard11401402018-07-05 15:01:34 +0100231 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
232 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800233}
234
Andreas Gampee9c816e2018-03-14 09:05:48 -0700235// The the expression for the interface's descriptor to be used when
236// generating code for the given method. Null is acceptable for method
237// and stands for synthetic cases.
Steven Moreland48548e02019-09-18 15:10:22 -0700238std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800239 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700240 if (method != nullptr) {
241 // When outlining, each outlined method needs its own literal.
242 if (outline_methods.count(method) != 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700243 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700244 }
245 } else {
246 // Synthetic case. A small number is assumed. Use its own descriptor
247 // if there are only synthetic cases.
248 if (outline_methods.size() == all_method_count) {
Steven Moreland48548e02019-09-18 15:10:22 -0700249 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700250 }
251 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800252 }
253
Andreas Gampee9c816e2018-03-14 09:05:48 -0700254 // When not outlining, store the descriptor literal into a local variable, in
255 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800256 if (transact_descriptor == nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700257 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
258 transact_statements->Add(std::make_shared<VariableDeclaration>(
259 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800260 }
261 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800262}
263
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900264void StubClass::make_as_interface(const AidlInterface* interfaceType) {
Steven Moreland48548e02019-09-18 15:10:22 -0700265 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800266
Steven Moreland48548e02019-09-18 15:10:22 -0700267 auto m = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800268 m->comment = "/**\n * Cast an IBinder object into an ";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900269 m->comment += interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800270 m->comment += " interface,\n";
271 m->comment += " * generating a proxy if needed.\n */";
272 m->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900273 m->returnType = interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800274 m->name = "asInterface";
275 m->parameters.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700276 m->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800277
Steven Moreland48548e02019-09-18 15:10:22 -0700278 auto ifstatement = std::make_shared<IfStatement>();
279 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
280 ifstatement->statements = std::make_shared<StatementBlock>();
281 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800282 m->statements->Add(ifstatement);
283
284 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
Steven Moreland48548e02019-09-18 15:10:22 -0700285 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
286 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
287 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
288 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800289 m->statements->Add(iinVd);
290
291 // Ensure the instance type of the local object is as expected.
292 // One scenario where this is needed is if another package (with a
293 // different class loader) runs in the same process as the service.
294
295 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
296 // iin;
Steven Moreland48548e02019-09-18 15:10:22 -0700297 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
298 auto instOfCheck = std::make_shared<Comparison>(
299 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
300 auto instOfStatement = std::make_shared<IfStatement>();
301 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
302 instOfStatement->statements = std::make_shared<StatementBlock>();
303 instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
304 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800305 m->statements->Add(instOfStatement);
306
Steven Moreland48548e02019-09-18 15:10:22 -0700307 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
Christopher Wiley67502f12016-01-29 10:57:00 -0800308 ne->arguments.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700309 m->statements->Add(std::make_shared<ReturnStatement>(ne));
Christopher Wiley67502f12016-01-29 10:57:00 -0800310
311 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800312}
313
Adam Lesinskiffa16862014-01-23 18:17:42 -0800314// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800315class ProxyClass : public Class {
316 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900317 ProxyClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700318 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800319
Steven Moreland48548e02019-09-18 15:10:22 -0700320 std::shared_ptr<Variable> mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800321};
322
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900323ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
Christopher Wiley67502f12016-01-29 10:57:00 -0800324 this->modifiers = PRIVATE | STATIC;
325 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900326 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
327 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800328
Christopher Wiley67502f12016-01-29 10:57:00 -0800329 // IBinder mRemote
Steven Moreland48548e02019-09-18 15:10:22 -0700330 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
331 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800332
Christopher Wiley67502f12016-01-29 10:57:00 -0800333 // Proxy()
Steven Moreland48548e02019-09-18 15:10:22 -0700334 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
335 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800336 ctor->name = "Proxy";
Steven Moreland48548e02019-09-18 15:10:22 -0700337 ctor->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800338 ctor->parameters.push_back(remote);
Steven Moreland48548e02019-09-18 15:10:22 -0700339 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800340 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800341
Jiyong Park309668e2018-07-28 16:55:44 +0900342 if (options.Version() > 0) {
343 std::ostringstream code;
344 code << "private int mCachedVersion = -1;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700345 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900346 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900347 if (!options.Hash().empty()) {
348 std::ostringstream code;
349 code << "private String mCachedHash = \"-1\";\n";
350 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
351 }
Jiyong Park309668e2018-07-28 16:55:44 +0900352
Christopher Wiley67502f12016-01-29 10:57:00 -0800353 // IBinder asBinder()
Steven Moreland48548e02019-09-18 15:10:22 -0700354 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800355 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900356 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800357 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700358 asBinder->statements = std::make_shared<StatementBlock>();
359 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800360 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800361}
362
Christopher Wiley67502f12016-01-29 10:57:00 -0800363ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800364
365// =================================================
Daniel Norman716d3112019-09-10 13:11:56 -0700366static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
367 std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
368 std::shared_ptr<Variable> parcel) {
Steven Moreland48548e02019-09-18 15:10:22 -0700369 auto len = std::make_shared<Variable>("int", v->name + "_length");
370 addTo->Add(
371 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
372 auto lencheck = std::make_shared<IfStatement>();
373 lencheck->expression =
374 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
375 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
376 lencheck->elseif = std::make_shared<IfStatement>();
377 lencheck->elseif->statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700378 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800379 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800380}
381
Steven Moreland48548e02019-09-18 15:10:22 -0700382static void generate_write_to_parcel(const AidlTypeSpecifier& type,
383 std::shared_ptr<StatementBlock> addTo,
384 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
385 bool is_return_value, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900386 string code;
387 CodeWriterPtr writer = CodeWriter::ForString(&code);
388 CodeGeneratorContext context{
389 .writer = *(writer.get()),
390 .typenames = typenames,
391 .type = type,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900392 .parcel = parcel->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700393 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900394 .is_return_value = is_return_value,
395 };
396 WriteToParcelFor(context);
397 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700398 addTo->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800399}
400
Steven Moreland693640b2018-07-19 13:46:27 -0700401static void generate_int_constant(Class* interface, const std::string& name,
402 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900403 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
Steven Moreland48548e02019-09-18 15:10:22 -0700404 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700405}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800406
Steven Moreland693640b2018-07-19 13:46:27 -0700407static void generate_string_constant(Class* interface, const std::string& name,
408 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900409 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
Steven Moreland48548e02019-09-18 15:10:22 -0700410 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800411}
412
Daniel Norman716d3112019-09-10 13:11:56 -0700413static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
414 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -0700415 auto decl = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800416 decl->comment = method.GetComments();
417 decl->modifiers = PUBLIC;
Daniel Norman716d3112019-09-10 13:11:56 -0700418 decl->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800419 decl->name = method.GetName();
Jiyong Parka6605ab2018-11-11 14:30:21 +0900420 decl->annotations = generate_java_annotations(method.GetType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800421
Christopher Wiley67502f12016-01-29 10:57:00 -0800422 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700423 decl->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700424 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800425 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800426
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900427 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800428
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800429 return decl;
430}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800431
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900432static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700433 std::shared_ptr<Variable> transact_data,
434 std::shared_ptr<Variable> transact_reply,
435 const AidlTypenames& typenames,
436 std::shared_ptr<StatementBlock> statements,
437 std::shared_ptr<StubClass> stubClass, const Options& options) {
438 std::shared_ptr<TryStatement> tryStatement;
439 std::shared_ptr<FinallyStatement> finallyStatement;
440 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800441
Christopher Wiley67502f12016-01-29 10:57:00 -0800442 // interface token validation is the very first thing we do
Steven Moreland48548e02019-09-18 15:10:22 -0700443 statements->Add(std::make_shared<MethodCall>(
444 transact_data, "enforceInterface",
445 std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800446
Christopher Wiley67502f12016-01-29 10:57:00 -0800447 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800448 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800449 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900450 // keep this across different args in order to create the classloader
451 // at most once.
452 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800453 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700454 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800455
Steven Moreland48548e02019-09-18 15:10:22 -0700456 statements->Add(std::make_shared<VariableDeclaration>(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800457
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800458 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900459 string code;
460 CodeWriterPtr writer = CodeWriter::ForString(&code);
461 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900462 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900463 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900464 .parcel = transact_data->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700465 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900466 .is_classloader_created = &is_classloader_created};
467 CreateFromParcelFor(context);
468 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700469 statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800470 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800471 if (!arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700472 statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700473 v, std::make_shared<NewExpression>(
474 InstantiableJavaSignatureOf(arg->GetType(), typenames))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800475 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700476 generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800477 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800478 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800479
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800480 realCall->arguments.push_back(v);
481 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800482 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800483
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900484 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100485 // try and finally, but only when generating trace code
Steven Moreland48548e02019-09-18 15:10:22 -0700486 tryStatement = std::make_shared<TryStatement>();
487 finallyStatement = std::make_shared<FinallyStatement>();
Martijn Coenenf1b50782018-02-21 21:06:23 +0100488
Steven Moreland48548e02019-09-18 15:10:22 -0700489 tryStatement->statements->Add(std::make_shared<MethodCall>(
490 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
491 std::vector<std::shared_ptr<Expression>>{
492 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
493 std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
494 "::server")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100495
Steven Moreland48548e02019-09-18 15:10:22 -0700496 finallyStatement->statements->Add(std::make_shared<MethodCall>(
497 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
498 std::vector<std::shared_ptr<Expression>>{
499 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100500 }
501
Christopher Wiley67502f12016-01-29 10:57:00 -0800502 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800503 if (method.GetType().GetName() == "void") {
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900504 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100505 statements->Add(tryStatement);
506 tryStatement->statements->Add(realCall);
507 statements->Add(finallyStatement);
508 } else {
509 statements->Add(realCall);
510 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800511
Adam Lesinskiffa16862014-01-23 18:17:42 -0800512 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800513 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700514 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800515 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800516 }
517 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700518 auto _result =
519 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900520 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700521 statements->Add(std::make_shared<VariableDeclaration>(_result));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100522 statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700523 tryStatement->statements->Add(std::make_shared<Assignment>(_result, realCall));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100524 statements->Add(finallyStatement);
525 } else {
Steven Moreland48548e02019-09-18 15:10:22 -0700526 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100527 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800528
529 if (!oneway) {
530 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700531 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800532 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800533 }
534
Christopher Wiley67502f12016-01-29 10:57:00 -0800535 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900536 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900537 typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800538 }
539
540 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800541 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800542 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700543 std::shared_ptr<Variable> v = stubArgs.Get(i++);
Christopher Wiley67502f12016-01-29 10:57:00 -0800544
545 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900546 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800547 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800548 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800549
Christopher Wiley67502f12016-01-29 10:57:00 -0800550 // return true
Steven Moreland48548e02019-09-18 15:10:22 -0700551 statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800552}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800553
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900554static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
555 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700556 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900557 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700558 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800559
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900560 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900561 typenames, c->statements, stubClass, options);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800562
563 stubClass->transact_switch->cases.push_back(c);
564}
565
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900566static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
567 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700568 std::shared_ptr<StubClass> stubClass,
569 const AidlTypenames& typenames, const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800570 std::string outline_name = "onTransact$" + method.GetName() + "$";
571 // Generate an "outlined" method with the actual code.
572 {
Steven Moreland48548e02019-09-18 15:10:22 -0700573 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
574 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
575 auto onTransact_case = std::make_shared<Method>();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800576 onTransact_case->modifiers = PRIVATE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900577 onTransact_case->returnType = "boolean";
Andreas Gampe1b865af2017-11-22 11:31:47 -0800578 onTransact_case->name = outline_name;
579 onTransact_case->parameters.push_back(transact_data);
580 onTransact_case->parameters.push_back(transact_reply);
Steven Moreland48548e02019-09-18 15:10:22 -0700581 onTransact_case->statements = std::make_shared<StatementBlock>();
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900582 onTransact_case->exceptions.push_back("android.os.RemoteException");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800583 stubClass->elements.push_back(onTransact_case);
584
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900585 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900586 onTransact_case->statements, stubClass, options);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800587 }
588
589 // Generate the case dispatch.
590 {
Steven Moreland48548e02019-09-18 15:10:22 -0700591 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800592
Steven Moreland48548e02019-09-18 15:10:22 -0700593 auto helper_call =
594 std::make_shared<MethodCall>(THIS_VALUE, outline_name,
595 std::vector<std::shared_ptr<Expression>>{
596 stubClass->transact_data, stubClass->transact_reply});
597 c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800598
599 stubClass->transact_switch->cases.push_back(c);
600 }
601}
602
Steven Moreland48548e02019-09-18 15:10:22 -0700603static std::shared_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900604 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
Steven Moreland48548e02019-09-18 15:10:22 -0700605 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
606 const Options& options) {
607 auto proxy = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800608 proxy->comment = method.GetComments();
609 proxy->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -0700610 proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800611 proxy->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700612 proxy->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800613 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700614 proxy->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700615 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800616 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900617 proxy->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800618
Christopher Wiley67502f12016-01-29 10:57:00 -0800619 // the parcels
Steven Moreland48548e02019-09-18 15:10:22 -0700620 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
621 proxy->statements->Add(std::make_shared<VariableDeclaration>(
622 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
623 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800624 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700625 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
626 proxy->statements->Add(std::make_shared<VariableDeclaration>(
627 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800628 }
629
630 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700631 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800632 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700633 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
634 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800635 }
636
637 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700638 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800639 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700640 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800641 proxy->statements->Add(finallyStatement);
642
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900643 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700644 tryStatement->statements->Add(std::make_shared<MethodCall>(
645 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
646 std::vector<std::shared_ptr<Expression>>{
647 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
648 std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
649 "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100650 }
651
Christopher Wiley67502f12016-01-29 10:57:00 -0800652 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
653 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700654 tryStatement->statements->Add(std::make_shared<MethodCall>(
655 _data, "writeInterfaceToken",
656 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800657
658 // the parameters
659 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700660 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800661 AidlArgument::Direction dir = arg->GetDirection();
662 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700663 auto checklen = std::make_shared<IfStatement>();
664 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
665 checklen->statements->Add(std::make_shared<MethodCall>(
666 _data, "writeInt",
667 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
668 checklen->elseif = std::make_shared<IfStatement>();
669 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
670 _data, "writeInt",
671 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800672 tryStatement->statements->Add(checklen);
673 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900674 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900675 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800676 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800677 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800678
Christopher Wiley67502f12016-01-29 10:57:00 -0800679 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700680 auto call = std::make_shared<MethodCall>(
681 proxyClass->mRemote, "transact",
682 std::vector<std::shared_ptr<Expression>>{
683 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
684 _reply ? _reply : NULL_VALUE,
685 std::make_shared<LiteralExpression>(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")});
686 auto _status = std::make_shared<Variable>("boolean", "_status");
687 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900688
689 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
690 // back to the local method in the default impl, if set before.
691 vector<string> arg_names;
692 for (const auto& arg : method.GetArguments()) {
693 arg_names.emplace_back(arg->GetName());
694 }
695 bool has_return_type = method.GetType().GetName() != "void";
Steven Moreland48548e02019-09-18 15:10:22 -0700696 tryStatement->statements->Add(std::make_shared<LiteralStatement>(
Jiyong Park75e1a742018-07-04 12:31:23 +0900697 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
698 " return getDefaultImpl().%s(%s);\n"
699 "}\n"
700 : "if (!_status && getDefaultImpl() != null) {\n"
701 " getDefaultImpl().%s(%s);\n"
702 " return;\n"
703 "}\n",
704 method.GetName().c_str(), Join(arg_names, ", ").c_str())));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800705
Christopher Wiley67502f12016-01-29 10:57:00 -0800706 // throw back exceptions.
707 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700708 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800709 tryStatement->statements->Add(ex);
710 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800711
Christopher Wiley67502f12016-01-29 10:57:00 -0800712 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700713 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900714 // keep this across return value and arguments in order to create the
715 // classloader at most once.
716 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700717 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900718 string code;
719 CodeWriterPtr writer = CodeWriter::ForString(&code);
720 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900721 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900722 .type = method.GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900723 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700724 .var = _result->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900725 .is_classloader_created = &is_classloader_created};
726 CreateFromParcelFor(context);
727 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700728 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800729 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800730
731 // the out/inout parameters
732 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800733 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900734 string code;
735 CodeWriterPtr writer = CodeWriter::ForString(&code);
736 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900737 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900738 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900739 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700740 .var = arg->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900741 .is_classloader_created = &is_classloader_created};
742 ReadFromParcelFor(context);
743 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700744 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800745 }
746 }
747
Steven Moreland48548e02019-09-18 15:10:22 -0700748 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800749 }
Steven Moreland48548e02019-09-18 15:10:22 -0700750 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800751
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900752 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700753 finallyStatement->statements->Add(std::make_shared<MethodCall>(
754 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
755 std::vector<std::shared_ptr<Expression>>{
756 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100757 }
758
Yi Kong894d6ba2018-07-24 11:27:38 -0700759 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700760 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800761 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800762
763 return proxy;
764}
765
Jiyong Park74595c12018-07-23 15:22:50 +0900766static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700767 std::shared_ptr<StubClass> stubClass,
768 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900769 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800770 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800771
772 // == the TRANSACT_ constant =============================================
773 string transactCodeName = "TRANSACTION_";
774 transactCodeName += method.GetName();
775
Steven Moreland48548e02019-09-18 15:10:22 -0700776 auto transactCode =
777 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800778 transactCode->value =
779 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
780 stubClass->elements.push_back(transactCode);
781
Olivier Gaillard11401402018-07-05 15:01:34 +0100782 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900783 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700784 auto c = std::make_shared<Case>(transactCodeName);
785 c->statements->Add(std::make_shared<ReturnStatement>(
786 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100787 stubClass->code_to_method_name_switch->cases.push_back(c);
788 }
789
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800790 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700791 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900792 if (method.IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700793 decl = generate_interface_method(method, typenames);
Jiyong Park309668e2018-07-28 16:55:44 +0900794 } else {
795 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
796 std::ostringstream code;
797 code << "public int " << kGetInterfaceVersion << "() "
798 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700799 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900800 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900801 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
802 std::ostringstream code;
803 code << "public String " << kGetInterfaceHash << "() "
804 << "throws android.os.RemoteException;\n";
805 decl = std::make_shared<LiteralClassElement>(code.str());
806 }
Jiyong Park309668e2018-07-28 16:55:44 +0900807 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800808 interface->elements.push_back(decl);
809
810 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900811 if (method.IsUserDefined()) {
812 bool outline_stub =
813 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
814 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900815 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900816 options);
817 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900818 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900819 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800820 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900821 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700822 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900823 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900824 code << "data.enforceInterface(descriptor);\n"
825 << "reply.writeNoException();\n"
826 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900827 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700828 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900829 stubClass->transact_switch->cases.push_back(c);
830 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900831 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
832 auto c = std::make_shared<Case>(transactCodeName);
833 std::ostringstream code;
834 code << "data.enforceInterface(descriptor);\n"
835 << "reply.writeNoException();\n"
836 << "reply.writeString(" << kGetInterfaceHash << "());\n"
837 << "return true;\n";
838 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
839 stubClass->transact_switch->cases.push_back(c);
840 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800841 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800842
843 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700844 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900845 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900846 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700847 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900848
849 } else {
850 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
851 std::ostringstream code;
852 code << "@Override\n"
853 << "public int " << kGetInterfaceVersion << "()"
854 << " throws "
855 << "android.os.RemoteException {\n"
856 << " if (mCachedVersion == -1) {\n"
857 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
858 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
859 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900860 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900861 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900862 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900863 << " if (!_status) {\n"
864 << " if (getDefaultImpl() != null) {\n"
865 << " return getDefaultImpl().getInterfaceVersion();\n"
866 << " }\n"
867 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900868 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900869 << " mCachedVersion = reply.readInt();\n"
870 << " } finally {\n"
871 << " reply.recycle();\n"
872 << " data.recycle();\n"
873 << " }\n"
874 << " }\n"
875 << " return mCachedVersion;\n"
876 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700877 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900878 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900879 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
880 std::ostringstream code;
881 code << "@Override\n"
882 << "public synchronized String " << kGetInterfaceHash << "()"
883 << " throws "
884 << "android.os.RemoteException {\n"
Jeongik Cha0d96af32020-05-13 19:49:30 +0900885 << " if (\"-1\".equals(mCachedHash)) {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900886 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
887 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
888 << " try {\n"
889 << " data.writeInterfaceToken(DESCRIPTOR);\n"
890 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
891 << "data, reply, 0);\n"
892 << " if (!_status) {\n"
893 << " if (getDefaultImpl() != null) {\n"
894 << " return getDefaultImpl().getInterfaceHash();\n"
895 << " }\n"
896 << " }\n"
897 << " reply.readException();\n"
898 << " mCachedHash = reply.readString();\n"
899 << " } finally {\n"
900 << " reply.recycle();\n"
901 << " data.recycle();\n"
902 << " }\n"
903 << " }\n"
904 << " return mCachedHash;\n"
905 << "}\n";
906 proxy = std::make_shared<LiteralClassElement>(code.str());
907 }
Jiyong Park309668e2018-07-28 16:55:44 +0900908 }
909 if (proxy != nullptr) {
910 proxyClass->elements.push_back(proxy);
911 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800912}
913
Steven Moreland48548e02019-09-18 15:10:22 -0700914static void generate_interface_descriptors(std::shared_ptr<StubClass> stub,
915 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800916 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -0700917 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
918 c->statements->Add(std::make_shared<MethodCall>(
919 stub->transact_reply, "writeString",
920 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
921 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800922 stub->transact_switch->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800923
Christopher Wiley67502f12016-01-29 10:57:00 -0800924 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -0700925 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800926 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900927 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800928 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -0700929 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800930 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700931 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800932 proxy->elements.push_back(getDesc);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800933}
934
Andreas Gampee9c816e2018-03-14 09:05:48 -0700935// Check whether (some) methods in this interface should be "outlined," that
936// is, have specific onTransact methods for certain cases. Set up StubClass
937// metadata accordingly.
938//
939// Outlining will be enabled if the interface has more than outline_threshold
940// methods. In that case, the methods are sorted by number of arguments
941// (so that more "complex" methods come later), and the first non_outline_count
942// number of methods not outlined (are kept in the onTransact() method).
943//
944// Requirements: non_outline_count <= outline_threshold.
945static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -0700946 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700947 size_t non_outline_count) {
948 CHECK_LE(non_outline_count, outline_threshold);
949 // We'll outline (create sub methods) if there are more than min_methods
950 // cases.
951 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
952 if (stub->transact_outline) {
953 stub->all_method_count = iface->GetMethods().size();
954 std::vector<const AidlMethod*> methods;
955 methods.reserve(iface->GetMethods().size());
956 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
957 methods.push_back(ptr.get());
958 }
959
960 std::stable_sort(
961 methods.begin(),
962 methods.end(),
963 [](const AidlMethod* m1, const AidlMethod* m2) {
964 return m1->GetArguments().size() < m2->GetArguments().size();
965 });
966
967 stub->outline_methods.insert(methods.begin() + non_outline_count,
968 methods.end());
969 }
970}
971
Daniel Norman716d3112019-09-10 13:11:56 -0700972static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
973 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -0700974 auto default_method = std::make_shared<Method>();
Jiyong Park75e1a742018-07-04 12:31:23 +0900975 default_method->comment = method.GetComments();
976 default_method->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -0700977 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +0900978 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700979 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +0900980 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -0700981 default_method->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700982 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +0900983 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900984 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +0900985
986 if (method.GetType().GetName() != "void") {
Daniel Norman716d3112019-09-10 13:11:56 -0700987 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +0900988 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700989 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +0900990 }
991 return default_method;
992}
993
Steven Moreland48548e02019-09-18 15:10:22 -0700994static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Daniel Norman716d3112019-09-10 13:11:56 -0700995 const AidlTypenames& typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900996 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700997 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +0900998 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
999 default_class->modifiers = PUBLIC | STATIC;
1000 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001001 default_class->type = iface.GetCanonicalName() + ".Default";
1002 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +09001003
1004 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001005 if (m->IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -07001006 default_class->elements.emplace_back(generate_default_impl_method(*m.get(), typenames));
Jiyong Park309668e2018-07-28 16:55:44 +09001007 } else {
Paul Trautrimb77048c2020-01-21 16:39:32 +09001008 // These are called only when the remote side does not implement these
1009 // methods, which is normally impossible, because these methods are
1010 // automatically declared in the interface class and not implementing
1011 // them on the remote side causes a compilation error. But if the remote
1012 // side somehow managed to not implement it, that's an error and we
1013 // report the case by returning an invalid value here.
Jiyong Park309668e2018-07-28 16:55:44 +09001014 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1015 std::ostringstream code;
1016 code << "@Override\n"
1017 << "public int " << kGetInterfaceVersion << "() {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001018 << " return 0;\n"
1019 << "}\n";
1020 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1021 }
1022 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1023 std::ostringstream code;
1024 code << "@Override\n"
1025 << "public String " << kGetInterfaceHash << "() {\n"
1026 << " return \"\";\n"
Jiyong Park309668e2018-07-28 16:55:44 +09001027 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001028 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001029 }
1030 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001031 }
1032
1033 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001034 std::make_shared<LiteralClassElement>("@Override\n"
1035 "public android.os.IBinder asBinder() {\n"
1036 " return null;\n"
1037 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +09001038
1039 return default_class;
1040}
1041
Steven Moreland48548e02019-09-18 15:10:22 -07001042std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1043 const AidlTypenames& typenames,
1044 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001045 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -07001046 auto interface = std::make_unique<Class>();
Christopher Wiley67502f12016-01-29 10:57:00 -08001047 interface->comment = iface->GetComments();
1048 interface->modifiers = PUBLIC;
1049 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001050 interface->type = iface->GetCanonicalName();
1051 interface->interfaces.push_back("android.os.IInterface");
Jiyong Parka6605ab2018-11-11 14:30:21 +09001052 interface->annotations = generate_java_annotations(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001053
Jiyong Park309668e2018-07-28 16:55:44 +09001054 if (options.Version()) {
1055 std::ostringstream code;
1056 code << "/**\n"
1057 << " * The version of this interface that the caller is built against.\n"
1058 << " * This might be different from what {@link #getInterfaceVersion()\n"
1059 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1060 << " * that the remote object is implementing.\n"
1061 << " */\n"
1062 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001063 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001064 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001065 if (!options.Hash().empty()) {
1066 std::ostringstream code;
1067 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1068 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1069 }
Jiyong Park309668e2018-07-28 16:55:44 +09001070
Jiyong Park75e1a742018-07-04 12:31:23 +09001071 // the default impl class
Daniel Norman716d3112019-09-10 13:11:56 -07001072 auto default_impl = generate_default_impl_class(*iface, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +09001073 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001074
Christopher Wiley67502f12016-01-29 10:57:00 -08001075 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001076 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001077 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001078
Andreas Gampee9c816e2018-03-14 09:05:48 -07001079 compute_outline_methods(iface,
1080 stub,
1081 options.onTransact_outline_threshold_,
1082 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001083
Christopher Wiley67502f12016-01-29 10:57:00 -08001084 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001085 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001086 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001087
Christopher Wiley67502f12016-01-29 10:57:00 -08001088 // stub and proxy support for getInterfaceDescriptor()
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001089 generate_interface_descriptors(stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001090
Christopher Wiley67502f12016-01-29 10:57:00 -08001091 // all the declared constants of the interface
Steven Moreland693640b2018-07-19 13:46:27 -07001092 for (const auto& constant : iface->GetConstantDeclarations()) {
1093 const AidlConstantValue& value = constant->GetValue();
Jeongik Cha997281d2020-01-16 15:23:59 +09001094 auto comment = constant->GetType().GetComments();
1095 if (comment.length() != 0) {
1096 auto code = StringPrintf("%s\n", comment.c_str());
1097 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
1098 }
Steven Moreland693640b2018-07-19 13:46:27 -07001099 switch (value.GetType()) {
1100 case AidlConstantValue::Type::STRING: {
Steven Moreland48548e02019-09-18 15:10:22 -07001101 generate_string_constant(interface.get(), constant->GetName(),
Steven Moreland860b1942018-08-16 14:59:28 -07001102 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001103 break;
1104 }
Will McVickerd7d18df2019-09-12 13:40:50 -07001105 case AidlConstantValue::Type::BOOLEAN: // fall-through
1106 case AidlConstantValue::Type::INT8: // fall-through
1107 case AidlConstantValue::Type::INT32: {
Steven Moreland48548e02019-09-18 15:10:22 -07001108 generate_int_constant(interface.get(), constant->GetName(),
Steven Moreland860b1942018-08-16 14:59:28 -07001109 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001110 break;
1111 }
1112 default: {
1113 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1114 }
1115 }
Christopher Wiley67502f12016-01-29 10:57:00 -08001116 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001117
Christopher Wiley67502f12016-01-29 10:57:00 -08001118 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001119
Christopher Wiley67502f12016-01-29 10:57:00 -08001120 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001121 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1122 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001123 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001124
1125 // additional static methods for the default impl set/get to the
1126 // stub class. Can't add them to the interface as the generated java files
1127 // may be compiled with Java < 1.7 where static interface method isn't
1128 // supported.
1129 // TODO(b/111417145) make this conditional depending on the Java language
1130 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001131 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001132 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001133 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
Jooyung Hand4d65342020-05-13 17:17:07 +09001134 " // Only one user of this interface can use this function\n"
1135 " // at a time. This is a heuristic to detect if two different\n"
1136 " // users in the same process use this function.\n"
1137 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1138 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1139 " }\n"
1140 " if (impl != null) {\n"
Jiyong Park75e1a742018-07-04 12:31:23 +09001141 " Stub.Proxy.sDefaultImpl = impl;\n"
1142 " return true;\n"
1143 " }\n"
1144 " return false;\n"
1145 "}\n",
1146 i_name.c_str())));
1147 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001148 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1149 " return Stub.Proxy.sDefaultImpl;\n"
1150 "}\n",
1151 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001152
1153 // the static field is defined in the proxy class, not in the interface class
1154 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001155 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001156 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001157
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001158 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001159
Christopher Wiley67502f12016-01-29 10:57:00 -08001160 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001161}
1162
Christopher Wileydb154a52015-09-28 16:32:25 -07001163} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001164} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001165} // namespace android