blob: 04887fc6c159ae46a6134e62bf255eaec3a960a0 [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
618 if (iface.IsSensitiveData()) {
619 proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();"));
620 }
621
Steven Moreland48548e02019-09-18 15:10:22 -0700622 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800623 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700624 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
625 proxy->statements->Add(std::make_shared<VariableDeclaration>(
626 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800627 }
628
629 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700630 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800631 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700632 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
633 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800634 }
635
636 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700637 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800638 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700639 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800640 proxy->statements->Add(finallyStatement);
641
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900642 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700643 tryStatement->statements->Add(std::make_shared<MethodCall>(
644 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
645 std::vector<std::shared_ptr<Expression>>{
646 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700647 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
648 "::" + method.GetName() + "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100649 }
650
Christopher Wiley67502f12016-01-29 10:57:00 -0800651 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
652 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700653 tryStatement->statements->Add(std::make_shared<MethodCall>(
654 _data, "writeInterfaceToken",
655 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800656
657 // the parameters
658 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700659 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800660 AidlArgument::Direction dir = arg->GetDirection();
661 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700662 auto checklen = std::make_shared<IfStatement>();
663 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
664 checklen->statements->Add(std::make_shared<MethodCall>(
665 _data, "writeInt",
666 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
667 checklen->elseif = std::make_shared<IfStatement>();
668 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
669 _data, "writeInt",
670 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800671 tryStatement->statements->Add(checklen);
672 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900673 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900674 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800675 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800676 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800677
Steven Morelanda7764e52020-10-27 17:29:29 +0000678 std::vector<std::string> flags;
679 if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
680 if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
681
Christopher Wiley67502f12016-01-29 10:57:00 -0800682 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700683 auto call = std::make_shared<MethodCall>(
684 proxyClass->mRemote, "transact",
685 std::vector<std::shared_ptr<Expression>>{
686 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
687 _reply ? _reply : NULL_VALUE,
Steven Morelanda7764e52020-10-27 17:29:29 +0000688 std::make_shared<LiteralExpression>(flags.empty() ? "0" : Join(flags, " | "))});
Steven Moreland48548e02019-09-18 15:10:22 -0700689 auto _status = std::make_shared<Variable>("boolean", "_status");
690 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900691
Jiyong Parkcf999d62020-09-15 11:57:04 +0900692 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
693 // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
694 // is versioned. We can't throw the exception for unversioned interface because that would be an
695 // app breaking change.
Jiyong Park75e1a742018-07-04 12:31:23 +0900696 vector<string> arg_names;
697 for (const auto& arg : method.GetArguments()) {
698 arg_names.emplace_back(arg->GetName());
699 }
700 bool has_return_type = method.GetType().GetName() != "void";
Jiyong Parkcf999d62020-09-15 11:57:04 +0900701
702 auto checkDefaultImpl = std::make_shared<IfStatement>();
703 checkDefaultImpl->expression = std::make_shared<LiteralExpression>("getDefaultImpl() != null");
704 if (has_return_type) {
705 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
706 android::base::StringPrintf("return getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
707 Join(arg_names, ", ").c_str())));
708 } else {
709 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
710 android::base::StringPrintf("getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
711 Join(arg_names, ", ").c_str())));
712 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
713 }
714 if (options.Version() > 0) {
715 checkDefaultImpl->elseif = std::make_shared<IfStatement>();
716 checkDefaultImpl->elseif->statements->Add(
717 std::make_shared<LiteralStatement>(android::base::StringPrintf(
Jiyong Park1fd40782020-09-15 13:09:52 +0900718 "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
Jiyong Parkcf999d62020-09-15 11:57:04 +0900719 method.GetName().c_str())));
720 }
721
722 auto checkTransactionError = std::make_shared<IfStatement>();
723 checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
724 checkTransactionError->statements->Add(checkDefaultImpl);
725
726 tryStatement->statements->Add(checkTransactionError);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800727
Christopher Wiley67502f12016-01-29 10:57:00 -0800728 // throw back exceptions.
729 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700730 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800731 tryStatement->statements->Add(ex);
732 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800733
Christopher Wiley67502f12016-01-29 10:57:00 -0800734 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700735 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900736 // keep this across return value and arguments in order to create the
737 // classloader at most once.
738 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700739 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900740 string code;
741 CodeWriterPtr writer = CodeWriter::ForString(&code);
742 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900743 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900744 .type = method.GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900745 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700746 .var = _result->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900747 .is_classloader_created = &is_classloader_created};
748 CreateFromParcelFor(context);
749 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700750 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800751 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800752
753 // the out/inout parameters
754 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800755 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900756 string code;
757 CodeWriterPtr writer = CodeWriter::ForString(&code);
758 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900759 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900760 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900761 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700762 .var = arg->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900763 .is_classloader_created = &is_classloader_created};
764 ReadFromParcelFor(context);
765 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700766 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800767 }
768 }
769
Steven Moreland48548e02019-09-18 15:10:22 -0700770 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800771 }
Steven Moreland48548e02019-09-18 15:10:22 -0700772 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800773
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900774 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700775 finallyStatement->statements->Add(std::make_shared<MethodCall>(
776 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
777 std::vector<std::shared_ptr<Expression>>{
778 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100779 }
780
Yi Kong894d6ba2018-07-24 11:27:38 -0700781 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700782 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800783 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800784
785 return proxy;
786}
787
Jiyong Park74595c12018-07-23 15:22:50 +0900788static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700789 std::shared_ptr<StubClass> stubClass,
790 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900791 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800792 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800793
794 // == the TRANSACT_ constant =============================================
795 string transactCodeName = "TRANSACTION_";
796 transactCodeName += method.GetName();
797
Steven Moreland48548e02019-09-18 15:10:22 -0700798 auto transactCode =
799 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800800 transactCode->value =
801 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
802 stubClass->elements.push_back(transactCode);
803
Olivier Gaillard11401402018-07-05 15:01:34 +0100804 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900805 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700806 auto c = std::make_shared<Case>(transactCodeName);
807 c->statements->Add(std::make_shared<ReturnStatement>(
808 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100809 stubClass->code_to_method_name_switch->cases.push_back(c);
810 }
811
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800812 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700813 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900814 if (method.IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700815 decl = generate_interface_method(method, typenames);
Jiyong Park309668e2018-07-28 16:55:44 +0900816 } else {
817 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
818 std::ostringstream code;
819 code << "public int " << kGetInterfaceVersion << "() "
820 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700821 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900822 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900823 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
824 std::ostringstream code;
825 code << "public String " << kGetInterfaceHash << "() "
826 << "throws android.os.RemoteException;\n";
827 decl = std::make_shared<LiteralClassElement>(code.str());
828 }
Jiyong Park309668e2018-07-28 16:55:44 +0900829 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800830 interface->elements.push_back(decl);
831
832 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900833 if (method.IsUserDefined()) {
834 bool outline_stub =
835 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
836 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900837 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900838 options);
839 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900840 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900841 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800842 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900843 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700844 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900845 std::ostringstream code;
Kevin Jeonf2551d82021-07-27 16:06:07 +0000846 code << "reply.writeNoException();\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900847 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900848 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700849 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900850 stubClass->transact_switch_meta->cases.push_back(c);
Jiyong Park309668e2018-07-28 16:55:44 +0900851 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900852 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
853 auto c = std::make_shared<Case>(transactCodeName);
854 std::ostringstream code;
Kevin Jeonf2551d82021-07-27 16:06:07 +0000855 code << "reply.writeNoException();\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900856 << "reply.writeString(" << kGetInterfaceHash << "());\n"
857 << "return true;\n";
858 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900859 stubClass->transact_switch_meta->cases.push_back(c);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900860 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800861 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800862
863 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700864 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900865 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900866 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700867 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900868
869 } else {
870 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
871 std::ostringstream code;
872 code << "@Override\n"
873 << "public int " << kGetInterfaceVersion << "()"
874 << " throws "
875 << "android.os.RemoteException {\n"
876 << " if (mCachedVersion == -1) {\n"
877 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
878 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
879 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900880 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900881 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900882 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900883 << " if (!_status) {\n"
884 << " if (getDefaultImpl() != null) {\n"
885 << " return getDefaultImpl().getInterfaceVersion();\n"
886 << " }\n"
887 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900888 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900889 << " mCachedVersion = reply.readInt();\n"
890 << " } finally {\n"
891 << " reply.recycle();\n"
892 << " data.recycle();\n"
893 << " }\n"
894 << " }\n"
895 << " return mCachedVersion;\n"
896 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700897 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900898 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900899 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
900 std::ostringstream code;
901 code << "@Override\n"
902 << "public synchronized String " << kGetInterfaceHash << "()"
903 << " throws "
904 << "android.os.RemoteException {\n"
Jeongik Chab1428182020-05-13 19:49:30 +0900905 << " if (\"-1\".equals(mCachedHash)) {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900906 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
907 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
908 << " try {\n"
909 << " data.writeInterfaceToken(DESCRIPTOR);\n"
910 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
911 << "data, reply, 0);\n"
912 << " if (!_status) {\n"
913 << " if (getDefaultImpl() != null) {\n"
914 << " return getDefaultImpl().getInterfaceHash();\n"
915 << " }\n"
916 << " }\n"
917 << " reply.readException();\n"
918 << " mCachedHash = reply.readString();\n"
919 << " } finally {\n"
920 << " reply.recycle();\n"
921 << " data.recycle();\n"
922 << " }\n"
923 << " }\n"
924 << " return mCachedHash;\n"
925 << "}\n";
926 proxy = std::make_shared<LiteralClassElement>(code.str());
927 }
Jiyong Park309668e2018-07-28 16:55:44 +0900928 }
929 if (proxy != nullptr) {
930 proxyClass->elements.push_back(proxy);
931 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800932}
933
Jiyong Park5faba3e2020-04-24 17:08:37 +0900934static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
935 Class* interface, std::shared_ptr<StubClass> stub,
Steven Moreland48548e02019-09-18 15:10:22 -0700936 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800937 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -0700938 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
939 c->statements->Add(std::make_shared<MethodCall>(
940 stub->transact_reply, "writeString",
941 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
942 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900943 stub->transact_switch_meta->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800944
Christopher Wiley67502f12016-01-29 10:57:00 -0800945 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -0700946 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800947 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900948 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800949 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -0700950 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800951 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700952 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800953 proxy->elements.push_back(getDesc);
Jiyong Park5faba3e2020-04-24 17:08:37 +0900954
955 // add the DESCRIPTOR field to the interface class
956 Class* classToAddDescriptor = interface;
957 static std::set<std::string> greylist = {
958#include "hiddenapi-greylist"
959 };
960 if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
961 // For app compatibility, we keep DESCRIPTOR to the stub class for
962 // the interfaces that are in the greylist.
963 classToAddDescriptor = stub.get();
964 }
965 auto descriptor = std::make_shared<Field>(
966 STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900967 std::string name = iface->GetDescriptor();
Jiyong Park5faba3e2020-04-24 17:08:37 +0900968 if (options.IsStructured()) {
969 // mangle the interface name at build time and demangle it at runtime, to avoid
970 // being renamed by jarjar. See b/153843174
Jiyong Park5faba3e2020-04-24 17:08:37 +0900971 std::replace(name.begin(), name.end(), '.', '$');
972 descriptor->value = "\"" + name + "\".replace('$', '.')";
973 } else {
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900974 descriptor->value = "\"" + name + "\"";
Jiyong Park5faba3e2020-04-24 17:08:37 +0900975 }
976 classToAddDescriptor->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800977}
978
Andreas Gampee9c816e2018-03-14 09:05:48 -0700979// Check whether (some) methods in this interface should be "outlined," that
980// is, have specific onTransact methods for certain cases. Set up StubClass
981// metadata accordingly.
982//
983// Outlining will be enabled if the interface has more than outline_threshold
984// methods. In that case, the methods are sorted by number of arguments
985// (so that more "complex" methods come later), and the first non_outline_count
986// number of methods not outlined (are kept in the onTransact() method).
987//
988// Requirements: non_outline_count <= outline_threshold.
989static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -0700990 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700991 size_t non_outline_count) {
Steven Moreland21780812020-09-11 01:29:45 +0000992 AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
Andreas Gampee9c816e2018-03-14 09:05:48 -0700993 // We'll outline (create sub methods) if there are more than min_methods
994 // cases.
995 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
996 if (stub->transact_outline) {
997 stub->all_method_count = iface->GetMethods().size();
998 std::vector<const AidlMethod*> methods;
999 methods.reserve(iface->GetMethods().size());
Jooyung Han3f347ca2020-12-01 12:41:50 +09001000 for (const auto& ptr : iface->GetMethods()) {
Andreas Gampee9c816e2018-03-14 09:05:48 -07001001 methods.push_back(ptr.get());
1002 }
1003
1004 std::stable_sort(
1005 methods.begin(),
1006 methods.end(),
1007 [](const AidlMethod* m1, const AidlMethod* m2) {
1008 return m1->GetArguments().size() < m2->GetArguments().size();
1009 });
1010
1011 stub->outline_methods.insert(methods.begin() + non_outline_count,
1012 methods.end());
1013 }
1014}
1015
Daniel Norman716d3112019-09-10 13:11:56 -07001016static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
1017 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -07001018 auto default_method = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001019 default_method->comment = GenerateComments(method);
Jiyong Park75e1a742018-07-04 12:31:23 +09001020 default_method->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -07001021 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001022 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -07001023 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001024 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -07001025 default_method->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -07001026 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +09001027 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001028 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +09001029
1030 if (method.GetType().GetName() != "void") {
Daniel Norman716d3112019-09-10 13:11:56 -07001031 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001032 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -07001033 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001034 }
1035 return default_method;
1036}
1037
Steven Moreland48548e02019-09-18 15:10:22 -07001038static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Daniel Norman716d3112019-09-10 13:11:56 -07001039 const AidlTypenames& typenames,
Jiyong Park309668e2018-07-28 16:55:44 +09001040 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -07001041 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001042 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1043 default_class->modifiers = PUBLIC | STATIC;
1044 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001045 default_class->type = iface.GetCanonicalName() + ".Default";
1046 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +09001047
1048 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001049 if (m->IsUserDefined()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001050 default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
Jiyong Park309668e2018-07-28 16:55:44 +09001051 } else {
Paul Trautrimb77048c2020-01-21 16:39:32 +09001052 // These are called only when the remote side does not implement these
1053 // methods, which is normally impossible, because these methods are
1054 // automatically declared in the interface class and not implementing
1055 // them on the remote side causes a compilation error. But if the remote
1056 // side somehow managed to not implement it, that's an error and we
1057 // report the case by returning an invalid value here.
Jiyong Park309668e2018-07-28 16:55:44 +09001058 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1059 std::ostringstream code;
1060 code << "@Override\n"
1061 << "public int " << kGetInterfaceVersion << "() {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001062 << " return 0;\n"
1063 << "}\n";
1064 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1065 }
1066 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1067 std::ostringstream code;
1068 code << "@Override\n"
1069 << "public String " << kGetInterfaceHash << "() {\n"
1070 << " return \"\";\n"
Jiyong Park309668e2018-07-28 16:55:44 +09001071 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001072 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001073 }
1074 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001075 }
1076
1077 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001078 std::make_shared<LiteralClassElement>("@Override\n"
1079 "public android.os.IBinder asBinder() {\n"
1080 " return null;\n"
1081 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +09001082
1083 return default_class;
1084}
1085
Steven Moreland48548e02019-09-18 15:10:22 -07001086std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1087 const AidlTypenames& typenames,
1088 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001089 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -07001090 auto interface = std::make_unique<Class>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001091 interface->comment = GenerateComments(*iface);
Christopher Wiley67502f12016-01-29 10:57:00 -08001092 interface->modifiers = PUBLIC;
1093 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001094 interface->type = iface->GetCanonicalName();
1095 interface->interfaces.push_back("android.os.IInterface");
Jooyung Han720253d2021-01-05 19:13:17 +09001096 interface->annotations = JavaAnnotationsFor(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001097
Jiyong Park309668e2018-07-28 16:55:44 +09001098 if (options.Version()) {
1099 std::ostringstream code;
1100 code << "/**\n"
1101 << " * The version of this interface that the caller is built against.\n"
1102 << " * This might be different from what {@link #getInterfaceVersion()\n"
1103 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1104 << " * that the remote object is implementing.\n"
1105 << " */\n"
1106 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001107 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001108 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001109 if (!options.Hash().empty()) {
1110 std::ostringstream code;
1111 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1112 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1113 }
Jiyong Park309668e2018-07-28 16:55:44 +09001114
Jiyong Park75e1a742018-07-04 12:31:23 +09001115 // the default impl class
Daniel Norman716d3112019-09-10 13:11:56 -07001116 auto default_impl = generate_default_impl_class(*iface, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +09001117 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001118
Christopher Wiley67502f12016-01-29 10:57:00 -08001119 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001120 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001121 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001122
Andreas Gampee9c816e2018-03-14 09:05:48 -07001123 compute_outline_methods(iface,
1124 stub,
1125 options.onTransact_outline_threshold_,
1126 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001127
Christopher Wiley67502f12016-01-29 10:57:00 -08001128 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001129 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001130 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001131
Christopher Wiley67502f12016-01-29 10:57:00 -08001132 // stub and proxy support for getInterfaceDescriptor()
Jiyong Park5faba3e2020-04-24 17:08:37 +09001133 generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001134
Christopher Wiley67502f12016-01-29 10:57:00 -08001135 // all the declared constants of the interface
Jooyung Hanb43a61c2020-12-02 14:18:53 +09001136 string constants;
1137 generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
Jooyung Han3f347ca2020-12-01 12:41:50 +09001138 interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001139
Christopher Wiley67502f12016-01-29 10:57:00 -08001140 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001141
Christopher Wiley67502f12016-01-29 10:57:00 -08001142 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001143 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1144 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001145 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001146
1147 // additional static methods for the default impl set/get to the
1148 // stub class. Can't add them to the interface as the generated java files
1149 // may be compiled with Java < 1.7 where static interface method isn't
1150 // supported.
1151 // TODO(b/111417145) make this conditional depending on the Java language
1152 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001153 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001154 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001155 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
Jooyung Han4a044662020-05-13 17:17:07 +09001156 " // Only one user of this interface can use this function\n"
1157 " // at a time. This is a heuristic to detect if two different\n"
1158 " // users in the same process use this function.\n"
1159 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1160 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1161 " }\n"
1162 " if (impl != null) {\n"
Jiyong Park75e1a742018-07-04 12:31:23 +09001163 " Stub.Proxy.sDefaultImpl = impl;\n"
1164 " return true;\n"
1165 " }\n"
1166 " return false;\n"
1167 "}\n",
1168 i_name.c_str())));
1169 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001170 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1171 " return Stub.Proxy.sDefaultImpl;\n"
1172 "}\n",
1173 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001174
1175 // the static field is defined in the proxy class, not in the interface class
1176 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001177 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001178 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001179
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001180 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001181
Christopher Wiley67502f12016-01-29 10:57:00 -08001182 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001183}
1184
Christopher Wileydb154a52015-09-28 16:32:25 -07001185} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001186} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001187} // namespace android