blob: 12aee22fe326addeffeb918e125c342cf4084b1e [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"
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +020019#include "aidl_typenames.h"
Steven Morelanda7764e52020-10-27 17:29:29 +000020#include "ast_java.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include "generate_java.h"
Jeongik Cha047c5ee2019-08-07 23:16:49 +090022#include "logging.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090023#include "options.h"
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +020024#include "parser.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070025
Adam Lesinskiffa16862014-01-23 18:17:42 -080026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
Andreas Gampee9c816e2018-03-14 09:05:48 -070030#include <algorithm>
31#include <unordered_set>
Jiyong Park1d2df7d2018-07-23 15:22:50 +090032#include <utility>
33#include <vector>
Andreas Gampee9c816e2018-03-14 09:05:48 -070034
Andreas Gampe7d7fa602017-11-22 10:50:03 -080035#include <android-base/stringprintf.h>
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070036
Jiyong Park75e1a742018-07-04 12:31:23 +090037using android::base::Join;
Andreas Gampe7d7fa602017-11-22 10:50:03 -080038using android::base::StringPrintf;
Jiyong Park1d2df7d2018-07-23 15:22:50 +090039
Jiyong Park75e1a742018-07-04 12:31:23 +090040using std::string;
41using std::unique_ptr;
42using std::vector;
Andreas Gampe7d7fa602017-11-22 10:50:03 -080043
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070044namespace android {
45namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070046namespace java {
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070047
Adam Lesinskiffa16862014-01-23 18:17:42 -080048// =================================================
Jiyong Park2c44f072018-07-30 21:52:21 +090049class VariableFactory {
50 public:
51 using Variable = ::android::aidl::java::Variable;
Jiyong Park2c44f072018-07-30 21:52:21 +090052
53 explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
Daniel Norman716d3112019-09-10 13:11:56 -070054 std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
55 auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
Steven Moreland48548e02019-09-18 15:10:22 -070056 StringPrintf("%s%d", base_.c_str(), index_));
Jiyong Park2c44f072018-07-30 21:52:21 +090057 vars_.push_back(v);
58 index_++;
59 return v;
60 }
61
Steven Moreland48548e02019-09-18 15:10:22 -070062 std::shared_ptr<Variable> Get(int index) { return vars_[index]; }
Jiyong Park2c44f072018-07-30 21:52:21 +090063
64 private:
Steven Moreland48548e02019-09-18 15:10:22 -070065 std::vector<std::shared_ptr<Variable>> vars_;
Jiyong Park2c44f072018-07-30 21:52:21 +090066 std::string base_;
67 int index_;
Jiyong Park2c44f072018-07-30 21:52:21 +090068};
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
Jiyong Parkd800fef2020-07-22 18:09:43 +090076 // non-copyable, non-movable
77 StubClass(const StubClass&) = delete;
78 StubClass(StubClass&&) = delete;
79 StubClass& operator=(const StubClass&) = delete;
80 StubClass& operator=(StubClass&&) = delete;
81
Steven Moreland48548e02019-09-18 15:10:22 -070082 std::shared_ptr<Variable> transact_code;
83 std::shared_ptr<Variable> transact_data;
84 std::shared_ptr<Variable> transact_reply;
85 std::shared_ptr<Variable> transact_flags;
Jiyong Parka7ea8bf2021-01-05 10:36:18 +090086 std::shared_ptr<SwitchStatement> transact_switch_meta;
87 std::shared_ptr<SwitchStatement> transact_switch_user;
Steven Moreland48548e02019-09-18 15:10:22 -070088 std::shared_ptr<StatementBlock> transact_statements;
89 std::shared_ptr<SwitchStatement> code_to_method_name_switch;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070090
Andreas Gampe1b865af2017-11-22 11:31:47 -080091 // Where onTransact cases should be generated as separate methods.
92 bool transact_outline;
Andreas Gampee9c816e2018-03-14 09:05:48 -070093 // Specific methods that should be outlined when transact_outline is true.
94 std::unordered_set<const AidlMethod*> outline_methods;
95 // Number of all methods.
96 size_t all_method_count;
Andreas Gampe1b865af2017-11-22 11:31:47 -080097
Andreas Gampea8a66fe2017-11-22 12:17:00 -080098 // Finish generation. This will add a default case to the switch.
99 void finish();
100
Steven Moreland48548e02019-09-18 15:10:22 -0700101 std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800102
Christopher Wiley67502f12016-01-29 10:57:00 -0800103 private:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900104 void make_as_interface(const AidlInterface* interfaceType);
Christopher Wiley67502f12016-01-29 10:57:00 -0800105
Steven Moreland48548e02019-09-18 15:10:22 -0700106 std::shared_ptr<Variable> transact_descriptor;
Jiyong Park74595c12018-07-23 15:22:50 +0900107 const Options& options_;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800108};
109
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900110StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
Olivier Gaillard11401402018-07-05 15:01:34 +0100111 : Class(), options_(options) {
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800112 transact_descriptor = nullptr;
Andreas Gampe1b865af2017-11-22 11:31:47 -0800113 transact_outline = false;
Andreas Gampee9c816e2018-03-14 09:05:48 -0700114 all_method_count = 0; // Will be set when outlining may be enabled.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800115
Christopher Wiley67502f12016-01-29 10:57:00 -0800116 this->comment = "/** Local-side IPC implementation stub class. */";
117 this->modifiers = PUBLIC | ABSTRACT | STATIC;
118 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900119 this->type = interfaceType->GetCanonicalName() + ".Stub";
120 this->extends = "android.os.Binder";
121 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800122
Christopher Wiley67502f12016-01-29 10:57:00 -0800123 // ctor
Steven Moreland48548e02019-09-18 15:10:22 -0700124 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800125 ctor->modifiers = PUBLIC;
126 ctor->comment =
127 "/** Construct the stub at attach it to the "
128 "interface. */";
129 ctor->name = "Stub";
Steven Moreland48548e02019-09-18 15:10:22 -0700130 ctor->statements = std::make_shared<StatementBlock>();
Steven Morelande2fcb8e2019-11-27 18:09:15 -0800131 if (interfaceType->IsVintfStability()) {
132 auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
133 ctor->statements->Add(stability);
134 }
Steven Moreland48548e02019-09-18 15:10:22 -0700135 auto attach = std::make_shared<MethodCall>(
136 THIS_VALUE, "attachInterface",
137 std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
138 std::make_shared<LiteralExpression>("DESCRIPTOR")});
Christopher Wiley67502f12016-01-29 10:57:00 -0800139 ctor->statements->Add(attach);
140 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800141
Christopher Wiley67502f12016-01-29 10:57:00 -0800142 // asInterface
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900143 make_as_interface(interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800144
Christopher Wiley67502f12016-01-29 10:57:00 -0800145 // asBinder
Steven Moreland48548e02019-09-18 15:10:22 -0700146 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800147 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900148 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800149 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700150 asBinder->statements = std::make_shared<StatementBlock>();
151 asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800152 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800153
Jiyong Park74595c12018-07-23 15:22:50 +0900154 if (options_.GenTransactionNames()) {
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100155 // getDefaultTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700156 auto getDefaultTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900157 getDefaultTransactionName->comment = "/** @hide */";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100158 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900159 getDefaultTransactionName->returnType = "java.lang.String";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100160 getDefaultTransactionName->name = "getDefaultTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700161 auto code = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100162 getDefaultTransactionName->parameters.push_back(code);
Steven Moreland48548e02019-09-18 15:10:22 -0700163 getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
164 this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100165 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
166 this->elements.push_back(getDefaultTransactionName);
167
168 // getTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700169 auto getTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900170 getTransactionName->comment = "/** @hide */";
Olivier Gaillard11401402018-07-05 15:01:34 +0100171 getTransactionName->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900172 getTransactionName->returnType = "java.lang.String";
Olivier Gaillard11401402018-07-05 15:01:34 +0100173 getTransactionName->name = "getTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700174 auto code2 = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100175 getTransactionName->parameters.push_back(code2);
Steven Moreland48548e02019-09-18 15:10:22 -0700176 getTransactionName->statements = std::make_shared<StatementBlock>();
177 getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
178 std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
179 std::vector<std::shared_ptr<Expression>>{code2})));
Olivier Gaillard11401402018-07-05 15:01:34 +0100180 this->elements.push_back(getTransactionName);
181 }
182
Christopher Wiley67502f12016-01-29 10:57:00 -0800183 // onTransact
Steven Moreland48548e02019-09-18 15:10:22 -0700184 this->transact_code = std::make_shared<Variable>("int", "code");
185 this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
186 this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
187 this->transact_flags = std::make_shared<Variable>("int", "flags");
188 auto onTransact = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800189 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900190 onTransact->returnType = "boolean";
Christopher Wiley67502f12016-01-29 10:57:00 -0800191 onTransact->name = "onTransact";
192 onTransact->parameters.push_back(this->transact_code);
193 onTransact->parameters.push_back(this->transact_data);
194 onTransact->parameters.push_back(this->transact_reply);
195 onTransact->parameters.push_back(this->transact_flags);
Steven Moreland48548e02019-09-18 15:10:22 -0700196 onTransact->statements = std::make_shared<StatementBlock>();
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800197 transact_statements = onTransact->statements;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900198 onTransact->exceptions.push_back("android.os.RemoteException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800199 this->elements.push_back(onTransact);
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900200 this->transact_switch_meta = std::make_shared<SwitchStatement>(this->transact_code);
201 this->transact_switch_user = std::make_shared<SwitchStatement>(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800202}
203
204void StubClass::finish() {
Steven Moreland48548e02019-09-18 15:10:22 -0700205 auto default_case = std::make_shared<Case>();
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800206
Steven Moreland48548e02019-09-18 15:10:22 -0700207 auto superCall = std::make_shared<MethodCall>(
208 SUPER_VALUE, "onTransact",
209 std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
210 this->transact_reply, this->transact_flags});
211 default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
Kevin Jeonf2551d82021-07-27 16:06:07 +0000212
213 auto case_count = transact_switch_user->cases.size();
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900214 transact_switch_user->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800215
Kevin Jeonf2551d82021-07-27 16:06:07 +0000216 // Interface token validation is done for user-defined transactions.
217 if (case_count > 0) {
218 auto ifStatement = std::make_shared<IfStatement>();
219 ifStatement->expression = std::make_shared<LiteralExpression>(
220 "code >= android.os.IBinder.FIRST_CALL_TRANSACTION && "
221 "code <= android.os.IBinder.LAST_CALL_TRANSACTION");
222 ifStatement->statements = std::make_shared<StatementBlock>();
223 ifStatement->statements->Add(std::make_shared<MethodCall>(
224 this->transact_data, "enforceInterface",
225 std::vector<std::shared_ptr<Expression>>{this->get_transact_descriptor(nullptr)}));
226 transact_statements->Add(ifStatement);
227 }
228
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900229 // Meta transactions are looked up prior to user-defined transactions.
230 transact_statements->Add(this->transact_switch_meta);
231 transact_statements->Add(this->transact_switch_user);
Olivier Gaillard11401402018-07-05 15:01:34 +0100232
233 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900234 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100235 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
236 // Common transaction codes will not be resolved to a string by getTransactionName. The method
237 // will return NULL in this case.
Steven Moreland48548e02019-09-18 15:10:22 -0700238 auto code_switch_default_case = std::make_shared<Case>();
239 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Olivier Gaillard11401402018-07-05 15:01:34 +0100240 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
241 }
Kevin Jeonf2551d82021-07-27 16:06:07 +0000242
243 // There will be at least one statement for the default, but if we emit a
244 // return true after that default, it will be unreachable.
245 if (case_count > 0) {
246 transact_statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
247 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800248}
249
Andreas Gampee9c816e2018-03-14 09:05:48 -0700250// The the expression for the interface's descriptor to be used when
251// generating code for the given method. Null is acceptable for method
252// and stands for synthetic cases.
Steven Moreland48548e02019-09-18 15:10:22 -0700253std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800254 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700255 if (method != nullptr) {
256 // When outlining, each outlined method needs its own literal.
257 if (outline_methods.count(method) != 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700258 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700259 }
260 } else {
261 // Synthetic case. A small number is assumed. Use its own descriptor
262 // if there are only synthetic cases.
263 if (outline_methods.size() == all_method_count) {
Steven Moreland48548e02019-09-18 15:10:22 -0700264 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700265 }
266 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800267 }
268
Andreas Gampee9c816e2018-03-14 09:05:48 -0700269 // When not outlining, store the descriptor literal into a local variable, in
270 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800271 if (transact_descriptor == nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700272 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
273 transact_statements->Add(std::make_shared<VariableDeclaration>(
274 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800275 }
276 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800277}
278
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900279void StubClass::make_as_interface(const AidlInterface* interfaceType) {
Steven Moreland48548e02019-09-18 15:10:22 -0700280 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800281
Steven Moreland48548e02019-09-18 15:10:22 -0700282 auto m = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800283 m->comment = "/**\n * Cast an IBinder object into an ";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900284 m->comment += interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800285 m->comment += " interface,\n";
286 m->comment += " * generating a proxy if needed.\n */";
287 m->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900288 m->returnType = interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800289 m->name = "asInterface";
290 m->parameters.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700291 m->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800292
Steven Moreland48548e02019-09-18 15:10:22 -0700293 auto ifstatement = std::make_shared<IfStatement>();
294 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
295 ifstatement->statements = std::make_shared<StatementBlock>();
296 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800297 m->statements->Add(ifstatement);
298
299 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
Steven Moreland48548e02019-09-18 15:10:22 -0700300 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
301 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
302 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
303 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800304 m->statements->Add(iinVd);
305
306 // Ensure the instance type of the local object is as expected.
307 // One scenario where this is needed is if another package (with a
308 // different class loader) runs in the same process as the service.
309
310 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
311 // iin;
Steven Moreland48548e02019-09-18 15:10:22 -0700312 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
313 auto instOfCheck = std::make_shared<Comparison>(
314 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
315 auto instOfStatement = std::make_shared<IfStatement>();
316 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
317 instOfStatement->statements = std::make_shared<StatementBlock>();
318 instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
319 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800320 m->statements->Add(instOfStatement);
321
Steven Moreland48548e02019-09-18 15:10:22 -0700322 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
Christopher Wiley67502f12016-01-29 10:57:00 -0800323 ne->arguments.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700324 m->statements->Add(std::make_shared<ReturnStatement>(ne));
Christopher Wiley67502f12016-01-29 10:57:00 -0800325
326 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800327}
328
Adam Lesinskiffa16862014-01-23 18:17:42 -0800329// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800330class ProxyClass : public Class {
331 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900332 ProxyClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700333 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800334
Steven Moreland48548e02019-09-18 15:10:22 -0700335 std::shared_ptr<Variable> mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800336};
337
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900338ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
Christopher Wiley67502f12016-01-29 10:57:00 -0800339 this->modifiers = PRIVATE | STATIC;
340 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900341 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
342 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800343
Christopher Wiley67502f12016-01-29 10:57:00 -0800344 // IBinder mRemote
Steven Moreland48548e02019-09-18 15:10:22 -0700345 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
346 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800347
Christopher Wiley67502f12016-01-29 10:57:00 -0800348 // Proxy()
Steven Moreland48548e02019-09-18 15:10:22 -0700349 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
350 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800351 ctor->name = "Proxy";
Steven Moreland48548e02019-09-18 15:10:22 -0700352 ctor->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800353 ctor->parameters.push_back(remote);
Steven Moreland48548e02019-09-18 15:10:22 -0700354 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800355 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800356
Jiyong Park309668e2018-07-28 16:55:44 +0900357 if (options.Version() > 0) {
358 std::ostringstream code;
359 code << "private int mCachedVersion = -1;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700360 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900361 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900362 if (!options.Hash().empty()) {
363 std::ostringstream code;
364 code << "private String mCachedHash = \"-1\";\n";
365 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
366 }
Jiyong Park309668e2018-07-28 16:55:44 +0900367
Christopher Wiley67502f12016-01-29 10:57:00 -0800368 // IBinder asBinder()
Steven Moreland48548e02019-09-18 15:10:22 -0700369 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800370 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900371 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800372 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700373 asBinder->statements = std::make_shared<StatementBlock>();
374 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800375 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800376}
377
Christopher Wiley67502f12016-01-29 10:57:00 -0800378ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800379
380// =================================================
Daniel Norman716d3112019-09-10 13:11:56 -0700381static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
382 std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
383 std::shared_ptr<Variable> parcel) {
Steven Moreland48548e02019-09-18 15:10:22 -0700384 auto len = std::make_shared<Variable>("int", v->name + "_length");
385 addTo->Add(
386 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
387 auto lencheck = std::make_shared<IfStatement>();
388 lencheck->expression =
389 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
390 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
391 lencheck->elseif = std::make_shared<IfStatement>();
392 lencheck->elseif->statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700393 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800394 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800395}
396
Steven Moreland48548e02019-09-18 15:10:22 -0700397static void generate_write_to_parcel(const AidlTypeSpecifier& type,
398 std::shared_ptr<StatementBlock> addTo,
399 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
400 bool is_return_value, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900401 string code;
402 CodeWriterPtr writer = CodeWriter::ForString(&code);
403 CodeGeneratorContext context{
404 .writer = *(writer.get()),
405 .typenames = typenames,
406 .type = type,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900407 .parcel = parcel->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700408 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900409 .is_return_value = is_return_value,
410 };
411 WriteToParcelFor(context);
412 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700413 addTo->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800414}
415
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900416void generate_constant_declarations(CodeWriter& out, const AidlDefinedType& type) {
417 for (const auto& constant : type.GetConstantDeclarations()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +0900418 const AidlTypeSpecifier& type = constant->GetType();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900419 out << GenerateComments(*constant);
420 out << GenerateAnnotations(*constant);
Jooyung Han3f347ca2020-12-01 12:41:50 +0900421 out << "public static final " << type.Signature() << " " << constant->GetName() << " = "
422 << constant->ValueString(ConstantValueDecorator) << ";\n";
423 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800424}
425
Daniel Norman716d3112019-09-10 13:11:56 -0700426static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
427 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -0700428 auto decl = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900429 decl->comment = GenerateComments(method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800430 decl->modifiers = PUBLIC;
Daniel Norman716d3112019-09-10 13:11:56 -0700431 decl->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800432 decl->name = method.GetName();
Jooyung Han720253d2021-01-05 19:13:17 +0900433 decl->annotations = JavaAnnotationsFor(method);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800434
Christopher Wiley67502f12016-01-29 10:57:00 -0800435 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900436 auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Jooyung Han720253d2021-01-05 19:13:17 +0900437 var->annotations = JavaAnnotationsFor(arg->GetType());
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900438 decl->parameters.push_back(var);
Christopher Wiley67502f12016-01-29 10:57:00 -0800439 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800440
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900441 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800442
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800443 return decl;
444}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800445
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +0200446// Visitor for the permission declared in the @Enforce annotation.
447// The visitor pattern evaluates one node at a time, recursive evaluations should be dispatched
448// by creating a new instance of the visitor. Visit methods should use SetResult to return their
449// current value. For example:
450//
451// Visit(const perm::Expression& permissionExpression) {
452// std::shared_ptr<Expression> expr = Evaluate(permissionExpression.FirstChild());
453// ...
454// SetResult(TRUE_VALUE);
455// }
456class PermissionVisitor : public perm::Visitor {
457 public:
458 // Converts a permission expression (e.g., "permission = CALL_PHONE") into an equivalent Java
459 // expression (e.g., "(checkPermission("CALL_PHONE", ...) == GRANTED").
460 static std::shared_ptr<Expression> Evaluate(const perm::Expression& expr) {
461 PermissionVisitor visitor;
462 expr.DispatchVisit(visitor);
463 return visitor.GetResult();
464 }
465
466 private:
467 void Visit(const perm::AndQuantifier& quantifier) {
468 std::shared_ptr<Expression> result;
469 for (const auto& operand : quantifier.GetOperands()) {
470 auto expr = Evaluate(*operand);
471 if (result) {
472 result = std::make_shared<Comparison>(result, "&&", expr);
473 } else {
474 result = expr;
475 }
476 }
477 SetResult(result);
478 }
479
480 void Visit(const perm::OrQuantifier& quantifier) {
481 std::shared_ptr<Expression> result;
482 for (const auto& operand : quantifier.GetOperands()) {
483 auto expr = Evaluate(*operand);
484 if (result) {
485 result = std::make_shared<Comparison>(result, "||", expr);
486 } else {
487 result = expr;
488 }
489 }
490 SetResult(result);
491 }
492
493 void Visit(const perm::Predicate& p) {
494 switch (p.GetType()) {
495 case perm::Predicate::Type::kPermission: {
496 auto permissionGranted = std::make_shared<LiteralExpression>(
497 "android.content.pm.PackageManager.PERMISSION_GRANTED");
498 auto checkPermission = std::make_shared<MethodCall>(
499 std::make_shared<LiteralExpression>("android.permission.PermissionManager"),
500 "checkPermission",
501 std::vector<std::shared_ptr<Expression>>{
502 std::make_shared<LiteralExpression>("android.Manifest.permission." + p.GetValue()),
503 std::make_shared<MethodCall>(THIS_VALUE, "getCallingPid"),
504 std::make_shared<MethodCall>(THIS_VALUE, "getCallingUid")});
505 SetResult(std::make_shared<Comparison>(checkPermission, "==", permissionGranted));
506 break;
507 }
508 case perm::Predicate::Type::kUid: {
509 auto uid = std::make_shared<LiteralExpression>("android.os.Process." + p.GetValue());
510 auto getCallingUid = std::make_shared<MethodCall>(THIS_VALUE, "getCallingUid");
511 SetResult(std::make_shared<Comparison>(getCallingUid, "==", uid));
512 break;
513 }
514 default: {
515 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unsupported predicate: " << p.ToString();
516 break;
517 }
518 }
519 }
520
521 std::shared_ptr<Expression> GetResult() { return result_; }
522 void SetResult(std::shared_ptr<Expression> expr) { result_ = expr; }
523 std::shared_ptr<Expression> result_;
524};
525
526static void generate_permission_checks(const AidlMethod& method,
527 std::shared_ptr<StatementBlock> addTo) {
528 auto expr = method.GetType().EnforceExpression(method);
529 if (expr) {
530 auto ifstatement = std::make_shared<IfStatement>();
531 auto permissionExpression = PermissionVisitor::Evaluate(*expr.get());
532 ifstatement->expression = std::make_shared<Comparison>(permissionExpression, "!=", TRUE_VALUE);
533 ifstatement->statements = std::make_shared<StatementBlock>();
534 ifstatement->statements->Add(std::make_shared<LiteralStatement>(android::base::StringPrintf(
535 "throw new SecurityException(\"Access denied, requires: %s\");\n",
536 expr->ToString().c_str())));
537 addTo->Add(ifstatement);
538 }
539}
540
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900541static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700542 std::shared_ptr<Variable> transact_data,
543 std::shared_ptr<Variable> transact_reply,
544 const AidlTypenames& typenames,
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700545 std::shared_ptr<StatementBlock> statement_block,
Kevin Jeonf2551d82021-07-27 16:06:07 +0000546 const Options& options) {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700547 // try and finally
548 auto tryStatement = std::make_shared<TryStatement>();
549 auto finallyStatement = std::make_shared<FinallyStatement>();
550 auto& statements = statement_block;
551
552 if (options.GenTraces()) {
553 statements->Add(tryStatement);
554 statements->Add(finallyStatement);
555 statements = tryStatement->statements;
556 tryStatement->statements->Add(std::make_shared<MethodCall>(
557 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
558 std::vector<std::shared_ptr<Expression>>{
559 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
560 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
561 "::" + method.GetName() + "::server")}));
562 finallyStatement->statements->Add(std::make_shared<MethodCall>(
563 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
564 std::vector<std::shared_ptr<Expression>>{
565 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
566 }
567
ThiƩbaud Weksteen5a4db212021-09-02 17:09:34 +0200568 generate_permission_checks(method, statements);
569
Steven Moreland48548e02019-09-18 15:10:22 -0700570 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800571
Christopher Wiley67502f12016-01-29 10:57:00 -0800572 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800573 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800574 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900575 // keep this across different args in order to create the classloader
576 // at most once.
577 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800578 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700579 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800580
Steven Moreland48548e02019-09-18 15:10:22 -0700581 statements->Add(std::make_shared<VariableDeclaration>(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800582
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800583 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900584 string code;
585 CodeWriterPtr writer = CodeWriter::ForString(&code);
586 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900587 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900588 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900589 .parcel = transact_data->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700590 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900591 .is_classloader_created = &is_classloader_created};
592 CreateFromParcelFor(context);
593 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700594 statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800595 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800596 if (!arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700597 statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700598 v, std::make_shared<NewExpression>(
599 InstantiableJavaSignatureOf(arg->GetType(), typenames))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800600 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700601 generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800602 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800603 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800604
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800605 realCall->arguments.push_back(v);
606 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800607 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800608
Christopher Wiley67502f12016-01-29 10:57:00 -0800609 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800610 if (method.GetType().GetName() == "void") {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700611 statements->Add(realCall);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800612
Adam Lesinskiffa16862014-01-23 18:17:42 -0800613 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800614 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700615 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800616 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800617 }
618 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700619 auto _result =
620 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
Steven Moreland48548e02019-09-18 15:10:22 -0700621 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
Christopher Wiley67502f12016-01-29 10:57:00 -0800622
623 if (!oneway) {
624 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700625 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800626 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800627 }
628
Christopher Wiley67502f12016-01-29 10:57:00 -0800629 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900630 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900631 typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800632 }
633
634 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800635 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800636 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700637 std::shared_ptr<Variable> v = stubArgs.Get(i++);
Christopher Wiley67502f12016-01-29 10:57:00 -0800638
639 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900640 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800641 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800642 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800643}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800644
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900645static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
646 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700647 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900648 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700649 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800650
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900651 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
Kevin Jeonf2551d82021-07-27 16:06:07 +0000652 typenames, c->statements, options);
653 c->statements->Add(std::make_shared<BreakStatement>());
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800654
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900655 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800656}
657
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900658static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
659 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700660 std::shared_ptr<StubClass> stubClass,
661 const AidlTypenames& typenames, const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800662 std::string outline_name = "onTransact$" + method.GetName() + "$";
663 // Generate an "outlined" method with the actual code.
664 {
Steven Moreland48548e02019-09-18 15:10:22 -0700665 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
666 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
667 auto onTransact_case = std::make_shared<Method>();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800668 onTransact_case->modifiers = PRIVATE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900669 onTransact_case->returnType = "boolean";
Andreas Gampe1b865af2017-11-22 11:31:47 -0800670 onTransact_case->name = outline_name;
671 onTransact_case->parameters.push_back(transact_data);
672 onTransact_case->parameters.push_back(transact_reply);
Steven Moreland48548e02019-09-18 15:10:22 -0700673 onTransact_case->statements = std::make_shared<StatementBlock>();
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900674 onTransact_case->exceptions.push_back("android.os.RemoteException");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800675 stubClass->elements.push_back(onTransact_case);
676
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900677 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
Kevin Jeonf2551d82021-07-27 16:06:07 +0000678 onTransact_case->statements, options);
679 onTransact_case->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800680 }
681
682 // Generate the case dispatch.
683 {
Steven Moreland48548e02019-09-18 15:10:22 -0700684 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800685
Steven Moreland48548e02019-09-18 15:10:22 -0700686 auto helper_call =
687 std::make_shared<MethodCall>(THIS_VALUE, outline_name,
688 std::vector<std::shared_ptr<Expression>>{
689 stubClass->transact_data, stubClass->transact_reply});
690 c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800691
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900692 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800693 }
694}
695
Steven Moreland48548e02019-09-18 15:10:22 -0700696static std::shared_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900697 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
Steven Moreland48548e02019-09-18 15:10:22 -0700698 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
699 const Options& options) {
700 auto proxy = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900701 proxy->comment = GenerateComments(method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800702 proxy->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -0700703 proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800704 proxy->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700705 proxy->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800706 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700707 proxy->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700708 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800709 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900710 proxy->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800711
Christopher Wiley67502f12016-01-29 10:57:00 -0800712 // the parcels
Steven Moreland48548e02019-09-18 15:10:22 -0700713 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
714 proxy->statements->Add(std::make_shared<VariableDeclaration>(
715 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Steven Morelanda7764e52020-10-27 17:29:29 +0000716
Steven Morelanda4b6b292021-09-01 12:35:28 -0700717 if (options.GenRpc()) {
718 proxy->statements->Add(
719 std::make_shared<LiteralStatement>("_data.markForBinder(asBinder());\n"));
720 }
721
Steven Morelanda7764e52020-10-27 17:29:29 +0000722 if (iface.IsSensitiveData()) {
Steven Morelanda4b6b292021-09-01 12:35:28 -0700723 proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();\n"));
Steven Morelanda7764e52020-10-27 17:29:29 +0000724 }
725
Steven Moreland48548e02019-09-18 15:10:22 -0700726 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800727 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700728 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
729 proxy->statements->Add(std::make_shared<VariableDeclaration>(
730 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800731 }
732
733 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700734 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800735 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700736 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
737 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800738 }
739
740 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700741 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800742 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700743 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800744 proxy->statements->Add(finallyStatement);
745
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900746 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700747 tryStatement->statements->Add(std::make_shared<MethodCall>(
748 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
749 std::vector<std::shared_ptr<Expression>>{
750 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700751 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
752 "::" + method.GetName() + "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100753 }
754
Christopher Wiley67502f12016-01-29 10:57:00 -0800755 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
756 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700757 tryStatement->statements->Add(std::make_shared<MethodCall>(
758 _data, "writeInterfaceToken",
759 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800760
761 // the parameters
762 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700763 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800764 AidlArgument::Direction dir = arg->GetDirection();
765 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700766 auto checklen = std::make_shared<IfStatement>();
767 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
768 checklen->statements->Add(std::make_shared<MethodCall>(
769 _data, "writeInt",
770 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
771 checklen->elseif = std::make_shared<IfStatement>();
772 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
773 _data, "writeInt",
774 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800775 tryStatement->statements->Add(checklen);
776 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900777 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900778 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800779 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800780 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800781
Steven Morelanda7764e52020-10-27 17:29:29 +0000782 std::vector<std::string> flags;
783 if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
784 if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
785
Christopher Wiley67502f12016-01-29 10:57:00 -0800786 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700787 auto call = std::make_shared<MethodCall>(
788 proxyClass->mRemote, "transact",
789 std::vector<std::shared_ptr<Expression>>{
790 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
791 _reply ? _reply : NULL_VALUE,
Steven Morelanda7764e52020-10-27 17:29:29 +0000792 std::make_shared<LiteralExpression>(flags.empty() ? "0" : Join(flags, " | "))});
Steven Moreland48548e02019-09-18 15:10:22 -0700793 auto _status = std::make_shared<Variable>("boolean", "_status");
794 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900795
Jiyong Parkcf999d62020-09-15 11:57:04 +0900796 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
797 // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
798 // is versioned. We can't throw the exception for unversioned interface because that would be an
799 // app breaking change.
Jiyong Park75e1a742018-07-04 12:31:23 +0900800 vector<string> arg_names;
801 for (const auto& arg : method.GetArguments()) {
802 arg_names.emplace_back(arg->GetName());
803 }
804 bool has_return_type = method.GetType().GetName() != "void";
Jiyong Parkcf999d62020-09-15 11:57:04 +0900805
806 auto checkDefaultImpl = std::make_shared<IfStatement>();
807 checkDefaultImpl->expression = std::make_shared<LiteralExpression>("getDefaultImpl() != null");
808 if (has_return_type) {
809 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
810 android::base::StringPrintf("return getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
811 Join(arg_names, ", ").c_str())));
812 } else {
813 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
814 android::base::StringPrintf("getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
815 Join(arg_names, ", ").c_str())));
816 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
817 }
818 if (options.Version() > 0) {
819 checkDefaultImpl->elseif = std::make_shared<IfStatement>();
820 checkDefaultImpl->elseif->statements->Add(
821 std::make_shared<LiteralStatement>(android::base::StringPrintf(
Jiyong Park1fd40782020-09-15 13:09:52 +0900822 "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
Jiyong Parkcf999d62020-09-15 11:57:04 +0900823 method.GetName().c_str())));
824 }
825
826 auto checkTransactionError = std::make_shared<IfStatement>();
827 checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
828 checkTransactionError->statements->Add(checkDefaultImpl);
829
830 tryStatement->statements->Add(checkTransactionError);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800831
Christopher Wiley67502f12016-01-29 10:57:00 -0800832 // throw back exceptions.
833 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700834 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800835 tryStatement->statements->Add(ex);
836 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800837
Christopher Wiley67502f12016-01-29 10:57:00 -0800838 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700839 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900840 // keep this across return value and arguments in order to create the
841 // classloader at most once.
842 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700843 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900844 string code;
845 CodeWriterPtr writer = CodeWriter::ForString(&code);
846 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900847 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900848 .type = method.GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900849 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700850 .var = _result->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900851 .is_classloader_created = &is_classloader_created};
852 CreateFromParcelFor(context);
853 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700854 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800855 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800856
857 // the out/inout parameters
858 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800859 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900860 string code;
861 CodeWriterPtr writer = CodeWriter::ForString(&code);
862 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900863 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900864 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900865 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700866 .var = arg->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900867 .is_classloader_created = &is_classloader_created};
868 ReadFromParcelFor(context);
869 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700870 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800871 }
872 }
873
Steven Moreland48548e02019-09-18 15:10:22 -0700874 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800875 }
Steven Moreland48548e02019-09-18 15:10:22 -0700876 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800877
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900878 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700879 finallyStatement->statements->Add(std::make_shared<MethodCall>(
880 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
881 std::vector<std::shared_ptr<Expression>>{
882 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100883 }
884
Yi Kong894d6ba2018-07-24 11:27:38 -0700885 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700886 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800887 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800888
889 return proxy;
890}
891
Jiyong Park74595c12018-07-23 15:22:50 +0900892static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700893 std::shared_ptr<StubClass> stubClass,
894 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900895 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800896 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800897
898 // == the TRANSACT_ constant =============================================
899 string transactCodeName = "TRANSACTION_";
900 transactCodeName += method.GetName();
901
Steven Moreland48548e02019-09-18 15:10:22 -0700902 auto transactCode =
903 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800904 transactCode->value =
905 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
906 stubClass->elements.push_back(transactCode);
907
Olivier Gaillard11401402018-07-05 15:01:34 +0100908 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900909 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700910 auto c = std::make_shared<Case>(transactCodeName);
911 c->statements->Add(std::make_shared<ReturnStatement>(
912 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100913 stubClass->code_to_method_name_switch->cases.push_back(c);
914 }
915
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800916 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700917 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900918 if (method.IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700919 decl = generate_interface_method(method, typenames);
Jiyong Park309668e2018-07-28 16:55:44 +0900920 } else {
921 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
922 std::ostringstream code;
923 code << "public int " << kGetInterfaceVersion << "() "
924 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700925 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900926 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900927 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
928 std::ostringstream code;
929 code << "public String " << kGetInterfaceHash << "() "
930 << "throws android.os.RemoteException;\n";
931 decl = std::make_shared<LiteralClassElement>(code.str());
932 }
Jiyong Park309668e2018-07-28 16:55:44 +0900933 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800934 interface->elements.push_back(decl);
935
936 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900937 if (method.IsUserDefined()) {
938 bool outline_stub =
939 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
940 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900941 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900942 options);
943 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900944 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900945 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800946 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900947 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700948 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900949 std::ostringstream code;
Kevin Jeonf2551d82021-07-27 16:06:07 +0000950 code << "reply.writeNoException();\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900951 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900952 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700953 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900954 stubClass->transact_switch_meta->cases.push_back(c);
Jiyong Park309668e2018-07-28 16:55:44 +0900955 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900956 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
957 auto c = std::make_shared<Case>(transactCodeName);
958 std::ostringstream code;
Kevin Jeonf2551d82021-07-27 16:06:07 +0000959 code << "reply.writeNoException();\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900960 << "reply.writeString(" << kGetInterfaceHash << "());\n"
961 << "return true;\n";
962 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900963 stubClass->transact_switch_meta->cases.push_back(c);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900964 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800965 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800966
967 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700968 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900969 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900970 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700971 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900972
973 } else {
974 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
975 std::ostringstream code;
976 code << "@Override\n"
977 << "public int " << kGetInterfaceVersion << "()"
978 << " throws "
979 << "android.os.RemoteException {\n"
980 << " if (mCachedVersion == -1) {\n"
981 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
Steven Morelanda4b6b292021-09-01 12:35:28 -0700982 << " android.os.Parcel reply = android.os.Parcel.obtain();\n";
983 if (options.GenRpc()) {
984 code << " data.markForBinder(asBinder());\n";
985 }
986 code << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900987 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900988 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900989 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900990 << " if (!_status) {\n"
991 << " if (getDefaultImpl() != null) {\n"
992 << " return getDefaultImpl().getInterfaceVersion();\n"
993 << " }\n"
994 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900995 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900996 << " mCachedVersion = reply.readInt();\n"
997 << " } finally {\n"
998 << " reply.recycle();\n"
999 << " data.recycle();\n"
1000 << " }\n"
1001 << " }\n"
1002 << " return mCachedVersion;\n"
1003 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001004 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +09001005 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001006 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1007 std::ostringstream code;
1008 code << "@Override\n"
1009 << "public synchronized String " << kGetInterfaceHash << "()"
1010 << " throws "
1011 << "android.os.RemoteException {\n"
Jeongik Chab1428182020-05-13 19:49:30 +09001012 << " if (\"-1\".equals(mCachedHash)) {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001013 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
Steven Morelanda4b6b292021-09-01 12:35:28 -07001014 << " android.os.Parcel reply = android.os.Parcel.obtain();\n";
1015 if (options.GenRpc()) {
1016 code << " data.markForBinder(asBinder());\n";
1017 }
1018 code << " try {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001019 << " data.writeInterfaceToken(DESCRIPTOR);\n"
1020 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
1021 << "data, reply, 0);\n"
1022 << " if (!_status) {\n"
1023 << " if (getDefaultImpl() != null) {\n"
1024 << " return getDefaultImpl().getInterfaceHash();\n"
1025 << " }\n"
1026 << " }\n"
1027 << " reply.readException();\n"
1028 << " mCachedHash = reply.readString();\n"
1029 << " } finally {\n"
1030 << " reply.recycle();\n"
1031 << " data.recycle();\n"
1032 << " }\n"
1033 << " }\n"
1034 << " return mCachedHash;\n"
1035 << "}\n";
1036 proxy = std::make_shared<LiteralClassElement>(code.str());
1037 }
Jiyong Park309668e2018-07-28 16:55:44 +09001038 }
1039 if (proxy != nullptr) {
1040 proxyClass->elements.push_back(proxy);
1041 }
Adam Lesinskiffa16862014-01-23 18:17:42 -08001042}
1043
Jiyong Park5faba3e2020-04-24 17:08:37 +09001044static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
1045 Class* interface, std::shared_ptr<StubClass> stub,
Steven Moreland48548e02019-09-18 15:10:22 -07001046 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001047 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -07001048 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
1049 c->statements->Add(std::make_shared<MethodCall>(
1050 stub->transact_reply, "writeString",
1051 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
1052 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +09001053 stub->transact_switch_meta->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001054
Christopher Wiley67502f12016-01-29 10:57:00 -08001055 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -07001056 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -08001057 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001058 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -08001059 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -07001060 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -08001061 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -07001062 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -08001063 proxy->elements.push_back(getDesc);
Jiyong Park5faba3e2020-04-24 17:08:37 +09001064
1065 // add the DESCRIPTOR field to the interface class
1066 Class* classToAddDescriptor = interface;
1067 static std::set<std::string> greylist = {
1068#include "hiddenapi-greylist"
1069 };
1070 if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
1071 // For app compatibility, we keep DESCRIPTOR to the stub class for
1072 // the interfaces that are in the greylist.
1073 classToAddDescriptor = stub.get();
1074 }
1075 auto descriptor = std::make_shared<Field>(
1076 STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001077 std::string name = iface->GetDescriptor();
Jiyong Park5faba3e2020-04-24 17:08:37 +09001078 if (options.IsStructured()) {
1079 // mangle the interface name at build time and demangle it at runtime, to avoid
1080 // being renamed by jarjar. See b/153843174
Jiyong Park5faba3e2020-04-24 17:08:37 +09001081 std::replace(name.begin(), name.end(), '.', '$');
1082 descriptor->value = "\"" + name + "\".replace('$', '.')";
1083 } else {
Jiyong Park27fd7fd2020-08-27 16:25:09 +09001084 descriptor->value = "\"" + name + "\"";
Jiyong Park5faba3e2020-04-24 17:08:37 +09001085 }
1086 classToAddDescriptor->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001087}
1088
Andreas Gampee9c816e2018-03-14 09:05:48 -07001089// Check whether (some) methods in this interface should be "outlined," that
1090// is, have specific onTransact methods for certain cases. Set up StubClass
1091// metadata accordingly.
1092//
1093// Outlining will be enabled if the interface has more than outline_threshold
1094// methods. In that case, the methods are sorted by number of arguments
1095// (so that more "complex" methods come later), and the first non_outline_count
1096// number of methods not outlined (are kept in the onTransact() method).
1097//
1098// Requirements: non_outline_count <= outline_threshold.
1099static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -07001100 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -07001101 size_t non_outline_count) {
Steven Moreland21780812020-09-11 01:29:45 +00001102 AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
Andreas Gampee9c816e2018-03-14 09:05:48 -07001103 // We'll outline (create sub methods) if there are more than min_methods
1104 // cases.
1105 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
1106 if (stub->transact_outline) {
1107 stub->all_method_count = iface->GetMethods().size();
1108 std::vector<const AidlMethod*> methods;
1109 methods.reserve(iface->GetMethods().size());
Jooyung Han3f347ca2020-12-01 12:41:50 +09001110 for (const auto& ptr : iface->GetMethods()) {
Andreas Gampee9c816e2018-03-14 09:05:48 -07001111 methods.push_back(ptr.get());
1112 }
1113
1114 std::stable_sort(
1115 methods.begin(),
1116 methods.end(),
1117 [](const AidlMethod* m1, const AidlMethod* m2) {
1118 return m1->GetArguments().size() < m2->GetArguments().size();
1119 });
1120
1121 stub->outline_methods.insert(methods.begin() + non_outline_count,
1122 methods.end());
1123 }
1124}
1125
Daniel Norman716d3112019-09-10 13:11:56 -07001126static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
1127 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -07001128 auto default_method = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001129 default_method->comment = GenerateComments(method);
Jiyong Park75e1a742018-07-04 12:31:23 +09001130 default_method->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -07001131 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001132 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -07001133 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001134 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -07001135 default_method->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -07001136 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +09001137 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001138 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +09001139
1140 if (method.GetType().GetName() != "void") {
Daniel Norman716d3112019-09-10 13:11:56 -07001141 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001142 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -07001143 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001144 }
1145 return default_method;
1146}
1147
Steven Moreland48548e02019-09-18 15:10:22 -07001148static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Daniel Norman716d3112019-09-10 13:11:56 -07001149 const AidlTypenames& typenames,
Jiyong Park309668e2018-07-28 16:55:44 +09001150 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -07001151 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001152 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1153 default_class->modifiers = PUBLIC | STATIC;
1154 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001155 default_class->type = iface.GetCanonicalName() + ".Default";
1156 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +09001157
1158 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001159 if (m->IsUserDefined()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001160 default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
Jiyong Park309668e2018-07-28 16:55:44 +09001161 } else {
Paul Trautrimb77048c2020-01-21 16:39:32 +09001162 // These are called only when the remote side does not implement these
1163 // methods, which is normally impossible, because these methods are
1164 // automatically declared in the interface class and not implementing
1165 // them on the remote side causes a compilation error. But if the remote
1166 // side somehow managed to not implement it, that's an error and we
1167 // report the case by returning an invalid value here.
Jiyong Park309668e2018-07-28 16:55:44 +09001168 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1169 std::ostringstream code;
1170 code << "@Override\n"
1171 << "public int " << kGetInterfaceVersion << "() {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001172 << " return 0;\n"
1173 << "}\n";
1174 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1175 }
1176 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1177 std::ostringstream code;
1178 code << "@Override\n"
1179 << "public String " << kGetInterfaceHash << "() {\n"
1180 << " return \"\";\n"
Jiyong Park309668e2018-07-28 16:55:44 +09001181 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001182 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001183 }
1184 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001185 }
1186
1187 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001188 std::make_shared<LiteralClassElement>("@Override\n"
1189 "public android.os.IBinder asBinder() {\n"
1190 " return null;\n"
1191 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +09001192
1193 return default_class;
1194}
1195
Steven Moreland48548e02019-09-18 15:10:22 -07001196std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1197 const AidlTypenames& typenames,
1198 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001199 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -07001200 auto interface = std::make_unique<Class>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001201 interface->comment = GenerateComments(*iface);
Christopher Wiley67502f12016-01-29 10:57:00 -08001202 interface->modifiers = PUBLIC;
1203 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001204 interface->type = iface->GetCanonicalName();
1205 interface->interfaces.push_back("android.os.IInterface");
Jooyung Han720253d2021-01-05 19:13:17 +09001206 interface->annotations = JavaAnnotationsFor(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001207
Jiyong Park309668e2018-07-28 16:55:44 +09001208 if (options.Version()) {
1209 std::ostringstream code;
1210 code << "/**\n"
1211 << " * The version of this interface that the caller is built against.\n"
1212 << " * This might be different from what {@link #getInterfaceVersion()\n"
1213 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1214 << " * that the remote object is implementing.\n"
1215 << " */\n"
1216 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001217 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001218 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001219 if (!options.Hash().empty()) {
1220 std::ostringstream code;
1221 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1222 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1223 }
Jiyong Park309668e2018-07-28 16:55:44 +09001224
Jiyong Park75e1a742018-07-04 12:31:23 +09001225 // the default impl class
Daniel Norman716d3112019-09-10 13:11:56 -07001226 auto default_impl = generate_default_impl_class(*iface, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +09001227 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001228
Christopher Wiley67502f12016-01-29 10:57:00 -08001229 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001230 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001231 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001232
Andreas Gampee9c816e2018-03-14 09:05:48 -07001233 compute_outline_methods(iface,
1234 stub,
1235 options.onTransact_outline_threshold_,
1236 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001237
Christopher Wiley67502f12016-01-29 10:57:00 -08001238 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001239 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001240 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001241
Christopher Wiley67502f12016-01-29 10:57:00 -08001242 // stub and proxy support for getInterfaceDescriptor()
Jiyong Park5faba3e2020-04-24 17:08:37 +09001243 generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001244
Christopher Wiley67502f12016-01-29 10:57:00 -08001245 // all the declared constants of the interface
Jooyung Hanb43a61c2020-12-02 14:18:53 +09001246 string constants;
1247 generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
Jooyung Han3f347ca2020-12-01 12:41:50 +09001248 interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001249
Christopher Wiley67502f12016-01-29 10:57:00 -08001250 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001251
Christopher Wiley67502f12016-01-29 10:57:00 -08001252 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001253 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1254 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001255 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001256
1257 // additional static methods for the default impl set/get to the
1258 // stub class. Can't add them to the interface as the generated java files
1259 // may be compiled with Java < 1.7 where static interface method isn't
1260 // supported.
1261 // TODO(b/111417145) make this conditional depending on the Java language
1262 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001263 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001264 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001265 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
Jooyung Han4a044662020-05-13 17:17:07 +09001266 " // Only one user of this interface can use this function\n"
1267 " // at a time. This is a heuristic to detect if two different\n"
1268 " // users in the same process use this function.\n"
1269 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1270 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1271 " }\n"
1272 " if (impl != null) {\n"
Jiyong Park75e1a742018-07-04 12:31:23 +09001273 " Stub.Proxy.sDefaultImpl = impl;\n"
1274 " return true;\n"
1275 " }\n"
1276 " return false;\n"
1277 "}\n",
1278 i_name.c_str())));
1279 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001280 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1281 " return Stub.Proxy.sDefaultImpl;\n"
1282 "}\n",
1283 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001284
1285 // the static field is defined in the proxy class, not in the interface class
1286 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001287 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001288 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001289
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001290 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001291
Christopher Wiley67502f12016-01-29 10:57:00 -08001292 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001293}
1294
Christopher Wileydb154a52015-09-28 16:32:25 -07001295} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001296} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001297} // namespace android