blob: 7a738cd0608868974b23d24a93733cb393ca30f1 [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"
Steven Morelanda7764e52020-10-27 17:29:29 +000019#include "ast_java.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080020#include "generate_java.h"
Jeongik Cha047c5ee2019-08-07 23:16:49 +090021#include "logging.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090022#include "options.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070023
Adam Lesinskiffa16862014-01-23 18:17:42 -080024#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
Andreas Gampee9c816e2018-03-14 09:05:48 -070028#include <algorithm>
29#include <unordered_set>
Jiyong Park1d2df7d2018-07-23 15:22:50 +090030#include <utility>
31#include <vector>
Andreas Gampee9c816e2018-03-14 09:05:48 -070032
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_;
Jiyong Park2c44f072018-07-30 21:52:21 +090066};
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
Jiyong Parkd800fef2020-07-22 18:09:43 +090074 // non-copyable, non-movable
75 StubClass(const StubClass&) = delete;
76 StubClass(StubClass&&) = delete;
77 StubClass& operator=(const StubClass&) = delete;
78 StubClass& operator=(StubClass&&) = delete;
79
Steven Moreland48548e02019-09-18 15:10:22 -070080 std::shared_ptr<Variable> transact_code;
81 std::shared_ptr<Variable> transact_data;
82 std::shared_ptr<Variable> transact_reply;
83 std::shared_ptr<Variable> transact_flags;
Jiyong Parka7ea8bf2021-01-05 10:36:18 +090084 std::shared_ptr<SwitchStatement> transact_switch_meta;
85 std::shared_ptr<SwitchStatement> transact_switch_user;
Steven Moreland48548e02019-09-18 15:10:22 -070086 std::shared_ptr<StatementBlock> transact_statements;
87 std::shared_ptr<SwitchStatement> code_to_method_name_switch;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070088
Andreas Gampe1b865af2017-11-22 11:31:47 -080089 // Where onTransact cases should be generated as separate methods.
90 bool transact_outline;
Andreas Gampee9c816e2018-03-14 09:05:48 -070091 // Specific methods that should be outlined when transact_outline is true.
92 std::unordered_set<const AidlMethod*> outline_methods;
93 // Number of all methods.
94 size_t all_method_count;
Andreas Gampe1b865af2017-11-22 11:31:47 -080095
Andreas Gampea8a66fe2017-11-22 12:17:00 -080096 // Finish generation. This will add a default case to the switch.
97 void finish();
98
Steven Moreland48548e02019-09-18 15:10:22 -070099 std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800100
Christopher Wiley67502f12016-01-29 10:57:00 -0800101 private:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900102 void make_as_interface(const AidlInterface* interfaceType);
Christopher Wiley67502f12016-01-29 10:57:00 -0800103
Steven Moreland48548e02019-09-18 15:10:22 -0700104 std::shared_ptr<Variable> transact_descriptor;
Jiyong Park74595c12018-07-23 15:22:50 +0900105 const Options& options_;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800106};
107
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900108StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
Olivier Gaillard11401402018-07-05 15:01:34 +0100109 : Class(), options_(options) {
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800110 transact_descriptor = nullptr;
Andreas Gampe1b865af2017-11-22 11:31:47 -0800111 transact_outline = false;
Andreas Gampee9c816e2018-03-14 09:05:48 -0700112 all_method_count = 0; // Will be set when outlining may be enabled.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800113
Christopher Wiley67502f12016-01-29 10:57:00 -0800114 this->comment = "/** Local-side IPC implementation stub class. */";
115 this->modifiers = PUBLIC | ABSTRACT | STATIC;
116 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900117 this->type = interfaceType->GetCanonicalName() + ".Stub";
118 this->extends = "android.os.Binder";
119 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800120
Christopher Wiley67502f12016-01-29 10:57:00 -0800121 // ctor
Steven Moreland48548e02019-09-18 15:10:22 -0700122 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800123 ctor->modifiers = PUBLIC;
124 ctor->comment =
125 "/** Construct the stub at attach it to the "
126 "interface. */";
127 ctor->name = "Stub";
Steven Moreland48548e02019-09-18 15:10:22 -0700128 ctor->statements = std::make_shared<StatementBlock>();
Steven Morelande2fcb8e2019-11-27 18:09:15 -0800129 if (interfaceType->IsVintfStability()) {
130 auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
131 ctor->statements->Add(stability);
132 }
Steven Moreland48548e02019-09-18 15:10:22 -0700133 auto attach = std::make_shared<MethodCall>(
134 THIS_VALUE, "attachInterface",
135 std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
136 std::make_shared<LiteralExpression>("DESCRIPTOR")});
Christopher Wiley67502f12016-01-29 10:57:00 -0800137 ctor->statements->Add(attach);
138 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800139
Christopher Wiley67502f12016-01-29 10:57:00 -0800140 // asInterface
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900141 make_as_interface(interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800142
Christopher Wiley67502f12016-01-29 10:57:00 -0800143 // asBinder
Steven Moreland48548e02019-09-18 15:10:22 -0700144 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800145 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900146 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800147 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700148 asBinder->statements = std::make_shared<StatementBlock>();
149 asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800150 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800151
Jiyong Park74595c12018-07-23 15:22:50 +0900152 if (options_.GenTransactionNames()) {
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100153 // getDefaultTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700154 auto getDefaultTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900155 getDefaultTransactionName->comment = "/** @hide */";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100156 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900157 getDefaultTransactionName->returnType = "java.lang.String";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100158 getDefaultTransactionName->name = "getDefaultTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700159 auto code = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100160 getDefaultTransactionName->parameters.push_back(code);
Steven Moreland48548e02019-09-18 15:10:22 -0700161 getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
162 this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100163 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
164 this->elements.push_back(getDefaultTransactionName);
165
166 // getTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700167 auto getTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900168 getTransactionName->comment = "/** @hide */";
Olivier Gaillard11401402018-07-05 15:01:34 +0100169 getTransactionName->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900170 getTransactionName->returnType = "java.lang.String";
Olivier Gaillard11401402018-07-05 15:01:34 +0100171 getTransactionName->name = "getTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700172 auto code2 = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100173 getTransactionName->parameters.push_back(code2);
Steven Moreland48548e02019-09-18 15:10:22 -0700174 getTransactionName->statements = std::make_shared<StatementBlock>();
175 getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
176 std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
177 std::vector<std::shared_ptr<Expression>>{code2})));
Olivier Gaillard11401402018-07-05 15:01:34 +0100178 this->elements.push_back(getTransactionName);
179 }
180
Christopher Wiley67502f12016-01-29 10:57:00 -0800181 // onTransact
Steven Moreland48548e02019-09-18 15:10:22 -0700182 this->transact_code = std::make_shared<Variable>("int", "code");
183 this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
184 this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
185 this->transact_flags = std::make_shared<Variable>("int", "flags");
186 auto onTransact = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800187 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900188 onTransact->returnType = "boolean";
Christopher Wiley67502f12016-01-29 10:57:00 -0800189 onTransact->name = "onTransact";
190 onTransact->parameters.push_back(this->transact_code);
191 onTransact->parameters.push_back(this->transact_data);
192 onTransact->parameters.push_back(this->transact_reply);
193 onTransact->parameters.push_back(this->transact_flags);
Steven Moreland48548e02019-09-18 15:10:22 -0700194 onTransact->statements = std::make_shared<StatementBlock>();
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800195 transact_statements = onTransact->statements;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900196 onTransact->exceptions.push_back("android.os.RemoteException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800197 this->elements.push_back(onTransact);
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900198 this->transact_switch_meta = std::make_shared<SwitchStatement>(this->transact_code);
199 this->transact_switch_user = std::make_shared<SwitchStatement>(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800200}
201
202void StubClass::finish() {
Steven Moreland48548e02019-09-18 15:10:22 -0700203 auto default_case = std::make_shared<Case>();
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800204
Steven Moreland48548e02019-09-18 15:10:22 -0700205 auto superCall = std::make_shared<MethodCall>(
206 SUPER_VALUE, "onTransact",
207 std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
208 this->transact_reply, this->transact_flags});
209 default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
Kevin Jeonf2551d82021-07-27 16:06:07 +0000210
211 auto case_count = transact_switch_user->cases.size();
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900212 transact_switch_user->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800213
Kevin Jeonf2551d82021-07-27 16:06:07 +0000214 // Interface token validation is done for user-defined transactions.
215 if (case_count > 0) {
216 auto ifStatement = std::make_shared<IfStatement>();
217 ifStatement->expression = std::make_shared<LiteralExpression>(
218 "code >= android.os.IBinder.FIRST_CALL_TRANSACTION && "
219 "code <= android.os.IBinder.LAST_CALL_TRANSACTION");
220 ifStatement->statements = std::make_shared<StatementBlock>();
221 ifStatement->statements->Add(std::make_shared<MethodCall>(
222 this->transact_data, "enforceInterface",
223 std::vector<std::shared_ptr<Expression>>{this->get_transact_descriptor(nullptr)}));
224 transact_statements->Add(ifStatement);
225 }
226
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900227 // Meta transactions are looked up prior to user-defined transactions.
228 transact_statements->Add(this->transact_switch_meta);
229 transact_statements->Add(this->transact_switch_user);
Olivier Gaillard11401402018-07-05 15:01:34 +0100230
231 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900232 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100233 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
234 // Common transaction codes will not be resolved to a string by getTransactionName. The method
235 // will return NULL in this case.
Steven Moreland48548e02019-09-18 15:10:22 -0700236 auto code_switch_default_case = std::make_shared<Case>();
237 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Olivier Gaillard11401402018-07-05 15:01:34 +0100238 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
239 }
Kevin Jeonf2551d82021-07-27 16:06:07 +0000240
241 // There will be at least one statement for the default, but if we emit a
242 // return true after that default, it will be unreachable.
243 if (case_count > 0) {
244 transact_statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
245 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800246}
247
Andreas Gampee9c816e2018-03-14 09:05:48 -0700248// The the expression for the interface's descriptor to be used when
249// generating code for the given method. Null is acceptable for method
250// and stands for synthetic cases.
Steven Moreland48548e02019-09-18 15:10:22 -0700251std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800252 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700253 if (method != nullptr) {
254 // When outlining, each outlined method needs its own literal.
255 if (outline_methods.count(method) != 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700256 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700257 }
258 } else {
259 // Synthetic case. A small number is assumed. Use its own descriptor
260 // if there are only synthetic cases.
261 if (outline_methods.size() == all_method_count) {
Steven Moreland48548e02019-09-18 15:10:22 -0700262 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700263 }
264 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800265 }
266
Andreas Gampee9c816e2018-03-14 09:05:48 -0700267 // When not outlining, store the descriptor literal into a local variable, in
268 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800269 if (transact_descriptor == nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700270 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
271 transact_statements->Add(std::make_shared<VariableDeclaration>(
272 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800273 }
274 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800275}
276
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900277void StubClass::make_as_interface(const AidlInterface* interfaceType) {
Steven Moreland48548e02019-09-18 15:10:22 -0700278 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800279
Steven Moreland48548e02019-09-18 15:10:22 -0700280 auto m = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800281 m->comment = "/**\n * Cast an IBinder object into an ";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900282 m->comment += interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800283 m->comment += " interface,\n";
284 m->comment += " * generating a proxy if needed.\n */";
285 m->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900286 m->returnType = interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800287 m->name = "asInterface";
288 m->parameters.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700289 m->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800290
Steven Moreland48548e02019-09-18 15:10:22 -0700291 auto ifstatement = std::make_shared<IfStatement>();
292 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
293 ifstatement->statements = std::make_shared<StatementBlock>();
294 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800295 m->statements->Add(ifstatement);
296
297 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
Steven Moreland48548e02019-09-18 15:10:22 -0700298 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
299 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
300 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
301 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800302 m->statements->Add(iinVd);
303
304 // Ensure the instance type of the local object is as expected.
305 // One scenario where this is needed is if another package (with a
306 // different class loader) runs in the same process as the service.
307
308 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
309 // iin;
Steven Moreland48548e02019-09-18 15:10:22 -0700310 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
311 auto instOfCheck = std::make_shared<Comparison>(
312 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
313 auto instOfStatement = std::make_shared<IfStatement>();
314 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
315 instOfStatement->statements = std::make_shared<StatementBlock>();
316 instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
317 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800318 m->statements->Add(instOfStatement);
319
Steven Moreland48548e02019-09-18 15:10:22 -0700320 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
Christopher Wiley67502f12016-01-29 10:57:00 -0800321 ne->arguments.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700322 m->statements->Add(std::make_shared<ReturnStatement>(ne));
Christopher Wiley67502f12016-01-29 10:57:00 -0800323
324 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800325}
326
Adam Lesinskiffa16862014-01-23 18:17:42 -0800327// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800328class ProxyClass : public Class {
329 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900330 ProxyClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700331 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800332
Steven Moreland48548e02019-09-18 15:10:22 -0700333 std::shared_ptr<Variable> mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800334};
335
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900336ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
Christopher Wiley67502f12016-01-29 10:57:00 -0800337 this->modifiers = PRIVATE | STATIC;
338 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900339 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
340 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800341
Christopher Wiley67502f12016-01-29 10:57:00 -0800342 // IBinder mRemote
Steven Moreland48548e02019-09-18 15:10:22 -0700343 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
344 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800345
Christopher Wiley67502f12016-01-29 10:57:00 -0800346 // Proxy()
Steven Moreland48548e02019-09-18 15:10:22 -0700347 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
348 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800349 ctor->name = "Proxy";
Steven Moreland48548e02019-09-18 15:10:22 -0700350 ctor->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800351 ctor->parameters.push_back(remote);
Steven Moreland48548e02019-09-18 15:10:22 -0700352 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800353 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800354
Jiyong Park309668e2018-07-28 16:55:44 +0900355 if (options.Version() > 0) {
356 std::ostringstream code;
357 code << "private int mCachedVersion = -1;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700358 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900359 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900360 if (!options.Hash().empty()) {
361 std::ostringstream code;
362 code << "private String mCachedHash = \"-1\";\n";
363 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
364 }
Jiyong Park309668e2018-07-28 16:55:44 +0900365
Christopher Wiley67502f12016-01-29 10:57:00 -0800366 // IBinder asBinder()
Steven Moreland48548e02019-09-18 15:10:22 -0700367 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800368 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900369 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800370 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700371 asBinder->statements = std::make_shared<StatementBlock>();
372 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800373 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800374}
375
Christopher Wiley67502f12016-01-29 10:57:00 -0800376ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800377
378// =================================================
Daniel Norman716d3112019-09-10 13:11:56 -0700379static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
380 std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
381 std::shared_ptr<Variable> parcel) {
Steven Moreland48548e02019-09-18 15:10:22 -0700382 auto len = std::make_shared<Variable>("int", v->name + "_length");
383 addTo->Add(
384 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
385 auto lencheck = std::make_shared<IfStatement>();
386 lencheck->expression =
387 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
388 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
389 lencheck->elseif = std::make_shared<IfStatement>();
390 lencheck->elseif->statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700391 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800392 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800393}
394
Steven Moreland48548e02019-09-18 15:10:22 -0700395static void generate_write_to_parcel(const AidlTypeSpecifier& type,
396 std::shared_ptr<StatementBlock> addTo,
397 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
398 bool is_return_value, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900399 string code;
400 CodeWriterPtr writer = CodeWriter::ForString(&code);
401 CodeGeneratorContext context{
402 .writer = *(writer.get()),
403 .typenames = typenames,
404 .type = type,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900405 .parcel = parcel->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700406 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900407 .is_return_value = is_return_value,
408 };
409 WriteToParcelFor(context);
410 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700411 addTo->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800412}
413
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900414void generate_constant_declarations(CodeWriter& out, const AidlDefinedType& type) {
415 for (const auto& constant : type.GetConstantDeclarations()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +0900416 const AidlTypeSpecifier& type = constant->GetType();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900417 out << GenerateComments(*constant);
418 out << GenerateAnnotations(*constant);
Jooyung Han3f347ca2020-12-01 12:41:50 +0900419 out << "public static final " << type.Signature() << " " << constant->GetName() << " = "
420 << constant->ValueString(ConstantValueDecorator) << ";\n";
421 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800422}
423
Daniel Norman716d3112019-09-10 13:11:56 -0700424static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
425 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -0700426 auto decl = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900427 decl->comment = GenerateComments(method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800428 decl->modifiers = PUBLIC;
Daniel Norman716d3112019-09-10 13:11:56 -0700429 decl->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800430 decl->name = method.GetName();
Jooyung Han720253d2021-01-05 19:13:17 +0900431 decl->annotations = JavaAnnotationsFor(method);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800432
Christopher Wiley67502f12016-01-29 10:57:00 -0800433 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900434 auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Jooyung Han720253d2021-01-05 19:13:17 +0900435 var->annotations = JavaAnnotationsFor(arg->GetType());
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900436 decl->parameters.push_back(var);
Christopher Wiley67502f12016-01-29 10:57:00 -0800437 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800438
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900439 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800440
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800441 return decl;
442}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800443
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900444static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700445 std::shared_ptr<Variable> transact_data,
446 std::shared_ptr<Variable> transact_reply,
447 const AidlTypenames& typenames,
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700448 std::shared_ptr<StatementBlock> statement_block,
Kevin Jeonf2551d82021-07-27 16:06:07 +0000449 const Options& options) {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700450 // try and finally
451 auto tryStatement = std::make_shared<TryStatement>();
452 auto finallyStatement = std::make_shared<FinallyStatement>();
453 auto& statements = statement_block;
454
455 if (options.GenTraces()) {
456 statements->Add(tryStatement);
457 statements->Add(finallyStatement);
458 statements = tryStatement->statements;
459 tryStatement->statements->Add(std::make_shared<MethodCall>(
460 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
461 std::vector<std::shared_ptr<Expression>>{
462 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
463 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
464 "::" + method.GetName() + "::server")}));
465 finallyStatement->statements->Add(std::make_shared<MethodCall>(
466 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
467 std::vector<std::shared_ptr<Expression>>{
468 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
469 }
470
Steven Moreland48548e02019-09-18 15:10:22 -0700471 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800472
Christopher Wiley67502f12016-01-29 10:57:00 -0800473 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800474 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800475 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900476 // keep this across different args in order to create the classloader
477 // at most once.
478 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800479 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700480 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800481
Steven Moreland48548e02019-09-18 15:10:22 -0700482 statements->Add(std::make_shared<VariableDeclaration>(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800483
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800484 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900485 string code;
486 CodeWriterPtr writer = CodeWriter::ForString(&code);
487 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900488 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900489 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900490 .parcel = transact_data->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700491 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900492 .is_classloader_created = &is_classloader_created};
493 CreateFromParcelFor(context);
494 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700495 statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800496 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800497 if (!arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700498 statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700499 v, std::make_shared<NewExpression>(
500 InstantiableJavaSignatureOf(arg->GetType(), typenames))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800501 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700502 generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800503 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800504 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800505
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800506 realCall->arguments.push_back(v);
507 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800508 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800509
Christopher Wiley67502f12016-01-29 10:57:00 -0800510 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800511 if (method.GetType().GetName() == "void") {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700512 statements->Add(realCall);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800513
Adam Lesinskiffa16862014-01-23 18:17:42 -0800514 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800515 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700516 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800517 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800518 }
519 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700520 auto _result =
521 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
Steven Moreland48548e02019-09-18 15:10:22 -0700522 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
Christopher Wiley67502f12016-01-29 10:57:00 -0800523
524 if (!oneway) {
525 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700526 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800527 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800528 }
529
Christopher Wiley67502f12016-01-29 10:57:00 -0800530 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900531 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900532 typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800533 }
534
535 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800536 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800537 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700538 std::shared_ptr<Variable> v = stubArgs.Get(i++);
Christopher Wiley67502f12016-01-29 10:57:00 -0800539
540 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900541 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800542 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800543 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800544}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800545
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900546static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
547 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700548 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900549 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700550 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800551
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900552 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
Kevin Jeonf2551d82021-07-27 16:06:07 +0000553 typenames, c->statements, options);
554 c->statements->Add(std::make_shared<BreakStatement>());
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800555
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900556 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800557}
558
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900559static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
560 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700561 std::shared_ptr<StubClass> stubClass,
562 const AidlTypenames& typenames, const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800563 std::string outline_name = "onTransact$" + method.GetName() + "$";
564 // Generate an "outlined" method with the actual code.
565 {
Steven Moreland48548e02019-09-18 15:10:22 -0700566 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
567 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
568 auto onTransact_case = std::make_shared<Method>();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800569 onTransact_case->modifiers = PRIVATE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900570 onTransact_case->returnType = "boolean";
Andreas Gampe1b865af2017-11-22 11:31:47 -0800571 onTransact_case->name = outline_name;
572 onTransact_case->parameters.push_back(transact_data);
573 onTransact_case->parameters.push_back(transact_reply);
Steven Moreland48548e02019-09-18 15:10:22 -0700574 onTransact_case->statements = std::make_shared<StatementBlock>();
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900575 onTransact_case->exceptions.push_back("android.os.RemoteException");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800576 stubClass->elements.push_back(onTransact_case);
577
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900578 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
Kevin Jeonf2551d82021-07-27 16:06:07 +0000579 onTransact_case->statements, options);
580 onTransact_case->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800581 }
582
583 // Generate the case dispatch.
584 {
Steven Moreland48548e02019-09-18 15:10:22 -0700585 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800586
Steven Moreland48548e02019-09-18 15:10:22 -0700587 auto helper_call =
588 std::make_shared<MethodCall>(THIS_VALUE, outline_name,
589 std::vector<std::shared_ptr<Expression>>{
590 stubClass->transact_data, stubClass->transact_reply});
591 c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800592
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900593 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800594 }
595}
596
Steven Moreland48548e02019-09-18 15:10:22 -0700597static std::shared_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900598 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
Steven Moreland48548e02019-09-18 15:10:22 -0700599 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
600 const Options& options) {
601 auto proxy = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900602 proxy->comment = GenerateComments(method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800603 proxy->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -0700604 proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800605 proxy->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700606 proxy->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800607 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700608 proxy->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700609 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800610 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900611 proxy->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800612
Christopher Wiley67502f12016-01-29 10:57:00 -0800613 // the parcels
Steven Moreland48548e02019-09-18 15:10:22 -0700614 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
615 proxy->statements->Add(std::make_shared<VariableDeclaration>(
616 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Steven Morelanda7764e52020-10-27 17:29:29 +0000617
Steven Morelanda4b6b292021-09-01 12:35:28 -0700618 if (options.GenRpc()) {
619 proxy->statements->Add(
620 std::make_shared<LiteralStatement>("_data.markForBinder(asBinder());\n"));
621 }
622
Steven Morelanda7764e52020-10-27 17:29:29 +0000623 if (iface.IsSensitiveData()) {
Steven Morelanda4b6b292021-09-01 12:35:28 -0700624 proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();\n"));
Steven Morelanda7764e52020-10-27 17:29:29 +0000625 }
626
Steven Moreland48548e02019-09-18 15:10:22 -0700627 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800628 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700629 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
630 proxy->statements->Add(std::make_shared<VariableDeclaration>(
631 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800632 }
633
634 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700635 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800636 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700637 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
638 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800639 }
640
641 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700642 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800643 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700644 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800645 proxy->statements->Add(finallyStatement);
646
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900647 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700648 tryStatement->statements->Add(std::make_shared<MethodCall>(
649 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
650 std::vector<std::shared_ptr<Expression>>{
651 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700652 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
653 "::" + method.GetName() + "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100654 }
655
Christopher Wiley67502f12016-01-29 10:57:00 -0800656 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
657 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700658 tryStatement->statements->Add(std::make_shared<MethodCall>(
659 _data, "writeInterfaceToken",
660 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800661
662 // the parameters
663 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700664 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800665 AidlArgument::Direction dir = arg->GetDirection();
666 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700667 auto checklen = std::make_shared<IfStatement>();
668 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
669 checklen->statements->Add(std::make_shared<MethodCall>(
670 _data, "writeInt",
671 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
672 checklen->elseif = std::make_shared<IfStatement>();
673 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
674 _data, "writeInt",
675 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800676 tryStatement->statements->Add(checklen);
677 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900678 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900679 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800680 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800681 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800682
Steven Morelanda7764e52020-10-27 17:29:29 +0000683 std::vector<std::string> flags;
684 if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
685 if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
686
Christopher Wiley67502f12016-01-29 10:57:00 -0800687 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700688 auto call = std::make_shared<MethodCall>(
689 proxyClass->mRemote, "transact",
690 std::vector<std::shared_ptr<Expression>>{
691 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
692 _reply ? _reply : NULL_VALUE,
Steven Morelanda7764e52020-10-27 17:29:29 +0000693 std::make_shared<LiteralExpression>(flags.empty() ? "0" : Join(flags, " | "))});
Steven Moreland48548e02019-09-18 15:10:22 -0700694 auto _status = std::make_shared<Variable>("boolean", "_status");
695 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900696
Jiyong Parkcf999d62020-09-15 11:57:04 +0900697 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
698 // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
699 // is versioned. We can't throw the exception for unversioned interface because that would be an
700 // app breaking change.
Jiyong Park75e1a742018-07-04 12:31:23 +0900701 vector<string> arg_names;
702 for (const auto& arg : method.GetArguments()) {
703 arg_names.emplace_back(arg->GetName());
704 }
705 bool has_return_type = method.GetType().GetName() != "void";
Jiyong Parkcf999d62020-09-15 11:57:04 +0900706
707 auto checkDefaultImpl = std::make_shared<IfStatement>();
708 checkDefaultImpl->expression = std::make_shared<LiteralExpression>("getDefaultImpl() != null");
709 if (has_return_type) {
710 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
711 android::base::StringPrintf("return getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
712 Join(arg_names, ", ").c_str())));
713 } else {
714 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
715 android::base::StringPrintf("getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
716 Join(arg_names, ", ").c_str())));
717 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
718 }
719 if (options.Version() > 0) {
720 checkDefaultImpl->elseif = std::make_shared<IfStatement>();
721 checkDefaultImpl->elseif->statements->Add(
722 std::make_shared<LiteralStatement>(android::base::StringPrintf(
Jiyong Park1fd40782020-09-15 13:09:52 +0900723 "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
Jiyong Parkcf999d62020-09-15 11:57:04 +0900724 method.GetName().c_str())));
725 }
726
727 auto checkTransactionError = std::make_shared<IfStatement>();
728 checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
729 checkTransactionError->statements->Add(checkDefaultImpl);
730
731 tryStatement->statements->Add(checkTransactionError);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800732
Christopher Wiley67502f12016-01-29 10:57:00 -0800733 // throw back exceptions.
734 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700735 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800736 tryStatement->statements->Add(ex);
737 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800738
Christopher Wiley67502f12016-01-29 10:57:00 -0800739 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700740 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900741 // keep this across return value and arguments in order to create the
742 // classloader at most once.
743 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700744 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900745 string code;
746 CodeWriterPtr writer = CodeWriter::ForString(&code);
747 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900748 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900749 .type = method.GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900750 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700751 .var = _result->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900752 .is_classloader_created = &is_classloader_created};
753 CreateFromParcelFor(context);
754 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700755 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800756 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800757
758 // the out/inout parameters
759 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800760 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900761 string code;
762 CodeWriterPtr writer = CodeWriter::ForString(&code);
763 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900764 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900765 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900766 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700767 .var = arg->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900768 .is_classloader_created = &is_classloader_created};
769 ReadFromParcelFor(context);
770 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700771 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800772 }
773 }
774
Steven Moreland48548e02019-09-18 15:10:22 -0700775 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800776 }
Steven Moreland48548e02019-09-18 15:10:22 -0700777 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800778
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900779 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700780 finallyStatement->statements->Add(std::make_shared<MethodCall>(
781 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
782 std::vector<std::shared_ptr<Expression>>{
783 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100784 }
785
Yi Kong894d6ba2018-07-24 11:27:38 -0700786 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700787 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800788 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800789
790 return proxy;
791}
792
Jiyong Park74595c12018-07-23 15:22:50 +0900793static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700794 std::shared_ptr<StubClass> stubClass,
795 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900796 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800797 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800798
799 // == the TRANSACT_ constant =============================================
800 string transactCodeName = "TRANSACTION_";
801 transactCodeName += method.GetName();
802
Steven Moreland48548e02019-09-18 15:10:22 -0700803 auto transactCode =
804 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800805 transactCode->value =
806 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
807 stubClass->elements.push_back(transactCode);
808
Olivier Gaillard11401402018-07-05 15:01:34 +0100809 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900810 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700811 auto c = std::make_shared<Case>(transactCodeName);
812 c->statements->Add(std::make_shared<ReturnStatement>(
813 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100814 stubClass->code_to_method_name_switch->cases.push_back(c);
815 }
816
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800817 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700818 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900819 if (method.IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700820 decl = generate_interface_method(method, typenames);
Jiyong Park309668e2018-07-28 16:55:44 +0900821 } else {
822 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
823 std::ostringstream code;
824 code << "public int " << kGetInterfaceVersion << "() "
825 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700826 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900827 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900828 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
829 std::ostringstream code;
830 code << "public String " << kGetInterfaceHash << "() "
831 << "throws android.os.RemoteException;\n";
832 decl = std::make_shared<LiteralClassElement>(code.str());
833 }
Jiyong Park309668e2018-07-28 16:55:44 +0900834 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800835 interface->elements.push_back(decl);
836
837 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900838 if (method.IsUserDefined()) {
839 bool outline_stub =
840 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
841 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900842 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900843 options);
844 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900845 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900846 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800847 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900848 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700849 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900850 std::ostringstream code;
Kevin Jeonf2551d82021-07-27 16:06:07 +0000851 code << "reply.writeNoException();\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900852 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900853 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700854 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900855 stubClass->transact_switch_meta->cases.push_back(c);
Jiyong Park309668e2018-07-28 16:55:44 +0900856 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900857 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
858 auto c = std::make_shared<Case>(transactCodeName);
859 std::ostringstream code;
Kevin Jeonf2551d82021-07-27 16:06:07 +0000860 code << "reply.writeNoException();\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900861 << "reply.writeString(" << kGetInterfaceHash << "());\n"
862 << "return true;\n";
863 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900864 stubClass->transact_switch_meta->cases.push_back(c);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900865 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800866 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800867
868 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700869 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900870 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900871 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700872 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900873
874 } else {
875 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
876 std::ostringstream code;
877 code << "@Override\n"
878 << "public int " << kGetInterfaceVersion << "()"
879 << " throws "
880 << "android.os.RemoteException {\n"
881 << " if (mCachedVersion == -1) {\n"
882 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
Steven Morelanda4b6b292021-09-01 12:35:28 -0700883 << " android.os.Parcel reply = android.os.Parcel.obtain();\n";
884 if (options.GenRpc()) {
885 code << " data.markForBinder(asBinder());\n";
886 }
887 code << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900888 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900889 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900890 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900891 << " if (!_status) {\n"
892 << " if (getDefaultImpl() != null) {\n"
893 << " return getDefaultImpl().getInterfaceVersion();\n"
894 << " }\n"
895 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900896 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900897 << " mCachedVersion = reply.readInt();\n"
898 << " } finally {\n"
899 << " reply.recycle();\n"
900 << " data.recycle();\n"
901 << " }\n"
902 << " }\n"
903 << " return mCachedVersion;\n"
904 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700905 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900906 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900907 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
908 std::ostringstream code;
909 code << "@Override\n"
910 << "public synchronized String " << kGetInterfaceHash << "()"
911 << " throws "
912 << "android.os.RemoteException {\n"
Jeongik Chab1428182020-05-13 19:49:30 +0900913 << " if (\"-1\".equals(mCachedHash)) {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900914 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
Steven Morelanda4b6b292021-09-01 12:35:28 -0700915 << " android.os.Parcel reply = android.os.Parcel.obtain();\n";
916 if (options.GenRpc()) {
917 code << " data.markForBinder(asBinder());\n";
918 }
919 code << " try {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900920 << " data.writeInterfaceToken(DESCRIPTOR);\n"
921 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
922 << "data, reply, 0);\n"
923 << " if (!_status) {\n"
924 << " if (getDefaultImpl() != null) {\n"
925 << " return getDefaultImpl().getInterfaceHash();\n"
926 << " }\n"
927 << " }\n"
928 << " reply.readException();\n"
929 << " mCachedHash = reply.readString();\n"
930 << " } finally {\n"
931 << " reply.recycle();\n"
932 << " data.recycle();\n"
933 << " }\n"
934 << " }\n"
935 << " return mCachedHash;\n"
936 << "}\n";
937 proxy = std::make_shared<LiteralClassElement>(code.str());
938 }
Jiyong Park309668e2018-07-28 16:55:44 +0900939 }
940 if (proxy != nullptr) {
941 proxyClass->elements.push_back(proxy);
942 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800943}
944
Jiyong Park5faba3e2020-04-24 17:08:37 +0900945static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
946 Class* interface, std::shared_ptr<StubClass> stub,
Steven Moreland48548e02019-09-18 15:10:22 -0700947 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800948 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -0700949 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
950 c->statements->Add(std::make_shared<MethodCall>(
951 stub->transact_reply, "writeString",
952 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
953 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900954 stub->transact_switch_meta->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800955
Christopher Wiley67502f12016-01-29 10:57:00 -0800956 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -0700957 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800958 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900959 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800960 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -0700961 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800962 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700963 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800964 proxy->elements.push_back(getDesc);
Jiyong Park5faba3e2020-04-24 17:08:37 +0900965
966 // add the DESCRIPTOR field to the interface class
967 Class* classToAddDescriptor = interface;
968 static std::set<std::string> greylist = {
969#include "hiddenapi-greylist"
970 };
971 if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
972 // For app compatibility, we keep DESCRIPTOR to the stub class for
973 // the interfaces that are in the greylist.
974 classToAddDescriptor = stub.get();
975 }
976 auto descriptor = std::make_shared<Field>(
977 STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900978 std::string name = iface->GetDescriptor();
Jiyong Park5faba3e2020-04-24 17:08:37 +0900979 if (options.IsStructured()) {
980 // mangle the interface name at build time and demangle it at runtime, to avoid
981 // being renamed by jarjar. See b/153843174
Jiyong Park5faba3e2020-04-24 17:08:37 +0900982 std::replace(name.begin(), name.end(), '.', '$');
983 descriptor->value = "\"" + name + "\".replace('$', '.')";
984 } else {
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900985 descriptor->value = "\"" + name + "\"";
Jiyong Park5faba3e2020-04-24 17:08:37 +0900986 }
987 classToAddDescriptor->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800988}
989
Andreas Gampee9c816e2018-03-14 09:05:48 -0700990// Check whether (some) methods in this interface should be "outlined," that
991// is, have specific onTransact methods for certain cases. Set up StubClass
992// metadata accordingly.
993//
994// Outlining will be enabled if the interface has more than outline_threshold
995// methods. In that case, the methods are sorted by number of arguments
996// (so that more "complex" methods come later), and the first non_outline_count
997// number of methods not outlined (are kept in the onTransact() method).
998//
999// Requirements: non_outline_count <= outline_threshold.
1000static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -07001001 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -07001002 size_t non_outline_count) {
Steven Moreland21780812020-09-11 01:29:45 +00001003 AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
Andreas Gampee9c816e2018-03-14 09:05:48 -07001004 // We'll outline (create sub methods) if there are more than min_methods
1005 // cases.
1006 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
1007 if (stub->transact_outline) {
1008 stub->all_method_count = iface->GetMethods().size();
1009 std::vector<const AidlMethod*> methods;
1010 methods.reserve(iface->GetMethods().size());
Jooyung Han3f347ca2020-12-01 12:41:50 +09001011 for (const auto& ptr : iface->GetMethods()) {
Andreas Gampee9c816e2018-03-14 09:05:48 -07001012 methods.push_back(ptr.get());
1013 }
1014
1015 std::stable_sort(
1016 methods.begin(),
1017 methods.end(),
1018 [](const AidlMethod* m1, const AidlMethod* m2) {
1019 return m1->GetArguments().size() < m2->GetArguments().size();
1020 });
1021
1022 stub->outline_methods.insert(methods.begin() + non_outline_count,
1023 methods.end());
1024 }
1025}
1026
Daniel Norman716d3112019-09-10 13:11:56 -07001027static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
1028 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -07001029 auto default_method = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001030 default_method->comment = GenerateComments(method);
Jiyong Park75e1a742018-07-04 12:31:23 +09001031 default_method->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -07001032 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001033 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -07001034 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001035 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -07001036 default_method->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -07001037 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +09001038 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001039 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +09001040
1041 if (method.GetType().GetName() != "void") {
Daniel Norman716d3112019-09-10 13:11:56 -07001042 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001043 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -07001044 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001045 }
1046 return default_method;
1047}
1048
Steven Moreland48548e02019-09-18 15:10:22 -07001049static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Daniel Norman716d3112019-09-10 13:11:56 -07001050 const AidlTypenames& typenames,
Jiyong Park309668e2018-07-28 16:55:44 +09001051 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -07001052 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001053 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1054 default_class->modifiers = PUBLIC | STATIC;
1055 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001056 default_class->type = iface.GetCanonicalName() + ".Default";
1057 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +09001058
1059 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001060 if (m->IsUserDefined()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001061 default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
Jiyong Park309668e2018-07-28 16:55:44 +09001062 } else {
Paul Trautrimb77048c2020-01-21 16:39:32 +09001063 // These are called only when the remote side does not implement these
1064 // methods, which is normally impossible, because these methods are
1065 // automatically declared in the interface class and not implementing
1066 // them on the remote side causes a compilation error. But if the remote
1067 // side somehow managed to not implement it, that's an error and we
1068 // report the case by returning an invalid value here.
Jiyong Park309668e2018-07-28 16:55:44 +09001069 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1070 std::ostringstream code;
1071 code << "@Override\n"
1072 << "public int " << kGetInterfaceVersion << "() {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001073 << " return 0;\n"
1074 << "}\n";
1075 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1076 }
1077 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1078 std::ostringstream code;
1079 code << "@Override\n"
1080 << "public String " << kGetInterfaceHash << "() {\n"
1081 << " return \"\";\n"
Jiyong Park309668e2018-07-28 16:55:44 +09001082 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001083 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001084 }
1085 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001086 }
1087
1088 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001089 std::make_shared<LiteralClassElement>("@Override\n"
1090 "public android.os.IBinder asBinder() {\n"
1091 " return null;\n"
1092 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +09001093
1094 return default_class;
1095}
1096
Steven Moreland48548e02019-09-18 15:10:22 -07001097std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1098 const AidlTypenames& typenames,
1099 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001100 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -07001101 auto interface = std::make_unique<Class>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001102 interface->comment = GenerateComments(*iface);
Christopher Wiley67502f12016-01-29 10:57:00 -08001103 interface->modifiers = PUBLIC;
1104 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001105 interface->type = iface->GetCanonicalName();
1106 interface->interfaces.push_back("android.os.IInterface");
Jooyung Han720253d2021-01-05 19:13:17 +09001107 interface->annotations = JavaAnnotationsFor(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001108
Jiyong Park309668e2018-07-28 16:55:44 +09001109 if (options.Version()) {
1110 std::ostringstream code;
1111 code << "/**\n"
1112 << " * The version of this interface that the caller is built against.\n"
1113 << " * This might be different from what {@link #getInterfaceVersion()\n"
1114 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1115 << " * that the remote object is implementing.\n"
1116 << " */\n"
1117 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001118 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001119 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001120 if (!options.Hash().empty()) {
1121 std::ostringstream code;
1122 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1123 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1124 }
Jiyong Park309668e2018-07-28 16:55:44 +09001125
Jiyong Park75e1a742018-07-04 12:31:23 +09001126 // the default impl class
Daniel Norman716d3112019-09-10 13:11:56 -07001127 auto default_impl = generate_default_impl_class(*iface, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +09001128 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001129
Christopher Wiley67502f12016-01-29 10:57:00 -08001130 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001131 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001132 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001133
Andreas Gampee9c816e2018-03-14 09:05:48 -07001134 compute_outline_methods(iface,
1135 stub,
1136 options.onTransact_outline_threshold_,
1137 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001138
Christopher Wiley67502f12016-01-29 10:57:00 -08001139 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001140 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001141 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001142
Christopher Wiley67502f12016-01-29 10:57:00 -08001143 // stub and proxy support for getInterfaceDescriptor()
Jiyong Park5faba3e2020-04-24 17:08:37 +09001144 generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001145
Christopher Wiley67502f12016-01-29 10:57:00 -08001146 // all the declared constants of the interface
Jooyung Hanb43a61c2020-12-02 14:18:53 +09001147 string constants;
1148 generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
Jooyung Han3f347ca2020-12-01 12:41:50 +09001149 interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001150
Christopher Wiley67502f12016-01-29 10:57:00 -08001151 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001152
Christopher Wiley67502f12016-01-29 10:57:00 -08001153 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001154 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1155 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001156 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001157
1158 // additional static methods for the default impl set/get to the
1159 // stub class. Can't add them to the interface as the generated java files
1160 // may be compiled with Java < 1.7 where static interface method isn't
1161 // supported.
1162 // TODO(b/111417145) make this conditional depending on the Java language
1163 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001164 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001165 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001166 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
Jooyung Han4a044662020-05-13 17:17:07 +09001167 " // Only one user of this interface can use this function\n"
1168 " // at a time. This is a heuristic to detect if two different\n"
1169 " // users in the same process use this function.\n"
1170 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1171 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1172 " }\n"
1173 " if (impl != null) {\n"
Jiyong Park75e1a742018-07-04 12:31:23 +09001174 " Stub.Proxy.sDefaultImpl = impl;\n"
1175 " return true;\n"
1176 " }\n"
1177 " return false;\n"
1178 "}\n",
1179 i_name.c_str())));
1180 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001181 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1182 " return Stub.Proxy.sDefaultImpl;\n"
1183 "}\n",
1184 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001185
1186 // the static field is defined in the proxy class, not in the interface class
1187 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001188 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001189 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001190
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001191 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001192
Christopher Wiley67502f12016-01-29 10:57:00 -08001193 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001194}
1195
Christopher Wileydb154a52015-09-28 16:32:25 -07001196} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001197} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001198} // namespace android