blob: a1f56b70a8d15002f19b013bf284ae15dcc79b8a [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));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900210 transact_switch_user->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800211
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900212 // Meta transactions are looked up prior to user-defined transactions.
213 transact_statements->Add(this->transact_switch_meta);
214 transact_statements->Add(this->transact_switch_user);
Olivier Gaillard11401402018-07-05 15:01:34 +0100215
216 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900217 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100218 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
219 // Common transaction codes will not be resolved to a string by getTransactionName. The method
220 // will return NULL in this case.
Steven Moreland48548e02019-09-18 15:10:22 -0700221 auto code_switch_default_case = std::make_shared<Case>();
222 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Olivier Gaillard11401402018-07-05 15:01:34 +0100223 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
224 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800225}
226
Andreas Gampee9c816e2018-03-14 09:05:48 -0700227// The the expression for the interface's descriptor to be used when
228// generating code for the given method. Null is acceptable for method
229// and stands for synthetic cases.
Steven Moreland48548e02019-09-18 15:10:22 -0700230std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800231 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700232 if (method != nullptr) {
233 // When outlining, each outlined method needs its own literal.
234 if (outline_methods.count(method) != 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700235 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700236 }
237 } else {
238 // Synthetic case. A small number is assumed. Use its own descriptor
239 // if there are only synthetic cases.
240 if (outline_methods.size() == all_method_count) {
Steven Moreland48548e02019-09-18 15:10:22 -0700241 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700242 }
243 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800244 }
245
Andreas Gampee9c816e2018-03-14 09:05:48 -0700246 // When not outlining, store the descriptor literal into a local variable, in
247 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800248 if (transact_descriptor == nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700249 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
250 transact_statements->Add(std::make_shared<VariableDeclaration>(
251 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800252 }
253 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800254}
255
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900256void StubClass::make_as_interface(const AidlInterface* interfaceType) {
Steven Moreland48548e02019-09-18 15:10:22 -0700257 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800258
Steven Moreland48548e02019-09-18 15:10:22 -0700259 auto m = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800260 m->comment = "/**\n * Cast an IBinder object into an ";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900261 m->comment += interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800262 m->comment += " interface,\n";
263 m->comment += " * generating a proxy if needed.\n */";
264 m->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900265 m->returnType = interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800266 m->name = "asInterface";
267 m->parameters.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700268 m->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800269
Steven Moreland48548e02019-09-18 15:10:22 -0700270 auto ifstatement = std::make_shared<IfStatement>();
271 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
272 ifstatement->statements = std::make_shared<StatementBlock>();
273 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800274 m->statements->Add(ifstatement);
275
276 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
Steven Moreland48548e02019-09-18 15:10:22 -0700277 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
278 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
279 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
280 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800281 m->statements->Add(iinVd);
282
283 // Ensure the instance type of the local object is as expected.
284 // One scenario where this is needed is if another package (with a
285 // different class loader) runs in the same process as the service.
286
287 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
288 // iin;
Steven Moreland48548e02019-09-18 15:10:22 -0700289 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
290 auto instOfCheck = std::make_shared<Comparison>(
291 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
292 auto instOfStatement = std::make_shared<IfStatement>();
293 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
294 instOfStatement->statements = std::make_shared<StatementBlock>();
295 instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
296 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800297 m->statements->Add(instOfStatement);
298
Steven Moreland48548e02019-09-18 15:10:22 -0700299 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
Christopher Wiley67502f12016-01-29 10:57:00 -0800300 ne->arguments.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700301 m->statements->Add(std::make_shared<ReturnStatement>(ne));
Christopher Wiley67502f12016-01-29 10:57:00 -0800302
303 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800304}
305
Adam Lesinskiffa16862014-01-23 18:17:42 -0800306// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800307class ProxyClass : public Class {
308 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900309 ProxyClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700310 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800311
Steven Moreland48548e02019-09-18 15:10:22 -0700312 std::shared_ptr<Variable> mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800313};
314
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900315ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
Christopher Wiley67502f12016-01-29 10:57:00 -0800316 this->modifiers = PRIVATE | STATIC;
317 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900318 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
319 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800320
Christopher Wiley67502f12016-01-29 10:57:00 -0800321 // IBinder mRemote
Steven Moreland48548e02019-09-18 15:10:22 -0700322 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
323 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800324
Christopher Wiley67502f12016-01-29 10:57:00 -0800325 // Proxy()
Steven Moreland48548e02019-09-18 15:10:22 -0700326 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
327 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800328 ctor->name = "Proxy";
Steven Moreland48548e02019-09-18 15:10:22 -0700329 ctor->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800330 ctor->parameters.push_back(remote);
Steven Moreland48548e02019-09-18 15:10:22 -0700331 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800332 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800333
Jiyong Park309668e2018-07-28 16:55:44 +0900334 if (options.Version() > 0) {
335 std::ostringstream code;
336 code << "private int mCachedVersion = -1;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700337 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900338 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900339 if (!options.Hash().empty()) {
340 std::ostringstream code;
341 code << "private String mCachedHash = \"-1\";\n";
342 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
343 }
Jiyong Park309668e2018-07-28 16:55:44 +0900344
Christopher Wiley67502f12016-01-29 10:57:00 -0800345 // IBinder asBinder()
Steven Moreland48548e02019-09-18 15:10:22 -0700346 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800347 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900348 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800349 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700350 asBinder->statements = std::make_shared<StatementBlock>();
351 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800352 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800353}
354
Christopher Wiley67502f12016-01-29 10:57:00 -0800355ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800356
357// =================================================
Daniel Norman716d3112019-09-10 13:11:56 -0700358static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
359 std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
360 std::shared_ptr<Variable> parcel) {
Steven Moreland48548e02019-09-18 15:10:22 -0700361 auto len = std::make_shared<Variable>("int", v->name + "_length");
362 addTo->Add(
363 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
364 auto lencheck = std::make_shared<IfStatement>();
365 lencheck->expression =
366 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
367 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
368 lencheck->elseif = std::make_shared<IfStatement>();
369 lencheck->elseif->statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700370 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800371 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800372}
373
Steven Moreland48548e02019-09-18 15:10:22 -0700374static void generate_write_to_parcel(const AidlTypeSpecifier& type,
375 std::shared_ptr<StatementBlock> addTo,
376 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
377 bool is_return_value, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900378 string code;
379 CodeWriterPtr writer = CodeWriter::ForString(&code);
380 CodeGeneratorContext context{
381 .writer = *(writer.get()),
382 .typenames = typenames,
383 .type = type,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900384 .parcel = parcel->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700385 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900386 .is_return_value = is_return_value,
387 };
388 WriteToParcelFor(context);
389 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700390 addTo->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800391}
392
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900393void generate_constant_declarations(CodeWriter& out, const AidlDefinedType& type) {
394 for (const auto& constant : type.GetConstantDeclarations()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +0900395 const AidlTypeSpecifier& type = constant->GetType();
396 auto comment = base::Trim(constant->GetType().GetComments());
397 if (comment.length() != 0) {
398 out << comment << "\n";
399 }
Jooyung Han720253d2021-01-05 19:13:17 +0900400 for (const auto& annotation : JavaAnnotationsFor(*constant)) {
Jooyung Han3f347ca2020-12-01 12:41:50 +0900401 out << annotation << "\n";
402 }
403 out << "public static final " << type.Signature() << " " << constant->GetName() << " = "
404 << constant->ValueString(ConstantValueDecorator) << ";\n";
405 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800406}
407
Daniel Norman716d3112019-09-10 13:11:56 -0700408static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
409 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -0700410 auto decl = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800411 decl->comment = method.GetComments();
412 decl->modifiers = PUBLIC;
Daniel Norman716d3112019-09-10 13:11:56 -0700413 decl->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800414 decl->name = method.GetName();
Jooyung Han720253d2021-01-05 19:13:17 +0900415 decl->annotations = JavaAnnotationsFor(method);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800416
Christopher Wiley67502f12016-01-29 10:57:00 -0800417 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900418 auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Jooyung Han720253d2021-01-05 19:13:17 +0900419 var->annotations = JavaAnnotationsFor(arg->GetType());
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900420 decl->parameters.push_back(var);
Christopher Wiley67502f12016-01-29 10:57:00 -0800421 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800422
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900423 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800424
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800425 return decl;
426}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800427
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900428static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700429 std::shared_ptr<Variable> transact_data,
430 std::shared_ptr<Variable> transact_reply,
431 const AidlTypenames& typenames,
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700432 std::shared_ptr<StatementBlock> statement_block,
Steven Moreland48548e02019-09-18 15:10:22 -0700433 std::shared_ptr<StubClass> stubClass, const Options& options) {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700434 // try and finally
435 auto tryStatement = std::make_shared<TryStatement>();
436 auto finallyStatement = std::make_shared<FinallyStatement>();
437 auto& statements = statement_block;
438
439 if (options.GenTraces()) {
440 statements->Add(tryStatement);
441 statements->Add(finallyStatement);
442 statements = tryStatement->statements;
443 tryStatement->statements->Add(std::make_shared<MethodCall>(
444 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
445 std::vector<std::shared_ptr<Expression>>{
446 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
447 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
448 "::" + method.GetName() + "::server")}));
449 finallyStatement->statements->Add(std::make_shared<MethodCall>(
450 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
451 std::vector<std::shared_ptr<Expression>>{
452 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
453 }
454
Steven Moreland48548e02019-09-18 15:10:22 -0700455 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800456
Christopher Wiley67502f12016-01-29 10:57:00 -0800457 // interface token validation is the very first thing we do
Steven Moreland48548e02019-09-18 15:10:22 -0700458 statements->Add(std::make_shared<MethodCall>(
459 transact_data, "enforceInterface",
460 std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800461
Christopher Wiley67502f12016-01-29 10:57:00 -0800462 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800463 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800464 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900465 // keep this across different args in order to create the classloader
466 // at most once.
467 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800468 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700469 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800470
Steven Moreland48548e02019-09-18 15:10:22 -0700471 statements->Add(std::make_shared<VariableDeclaration>(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800472
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800473 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900474 string code;
475 CodeWriterPtr writer = CodeWriter::ForString(&code);
476 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900477 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900478 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900479 .parcel = transact_data->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700480 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900481 .is_classloader_created = &is_classloader_created};
482 CreateFromParcelFor(context);
483 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700484 statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800485 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800486 if (!arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700487 statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700488 v, std::make_shared<NewExpression>(
489 InstantiableJavaSignatureOf(arg->GetType(), typenames))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800490 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700491 generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800492 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800493 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800494
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800495 realCall->arguments.push_back(v);
496 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800497 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800498
Christopher Wiley67502f12016-01-29 10:57:00 -0800499 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800500 if (method.GetType().GetName() == "void") {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700501 statements->Add(realCall);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800502
Adam Lesinskiffa16862014-01-23 18:17:42 -0800503 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800504 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700505 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800506 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800507 }
508 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700509 auto _result =
510 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
Steven Moreland48548e02019-09-18 15:10:22 -0700511 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
Christopher Wiley67502f12016-01-29 10:57:00 -0800512
513 if (!oneway) {
514 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700515 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800516 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800517 }
518
Christopher Wiley67502f12016-01-29 10:57:00 -0800519 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900520 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900521 typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800522 }
523
524 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800525 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800526 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700527 std::shared_ptr<Variable> v = stubArgs.Get(i++);
Christopher Wiley67502f12016-01-29 10:57:00 -0800528
529 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900530 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800531 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800532 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800533
Christopher Wiley67502f12016-01-29 10:57:00 -0800534 // return true
Steven Moreland48548e02019-09-18 15:10:22 -0700535 statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800536}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800537
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900538static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
539 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700540 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900541 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700542 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800543
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900544 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900545 typenames, c->statements, stubClass, options);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800546
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900547 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800548}
549
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900550static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
551 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700552 std::shared_ptr<StubClass> stubClass,
553 const AidlTypenames& typenames, const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800554 std::string outline_name = "onTransact$" + method.GetName() + "$";
555 // Generate an "outlined" method with the actual code.
556 {
Steven Moreland48548e02019-09-18 15:10:22 -0700557 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
558 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
559 auto onTransact_case = std::make_shared<Method>();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800560 onTransact_case->modifiers = PRIVATE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900561 onTransact_case->returnType = "boolean";
Andreas Gampe1b865af2017-11-22 11:31:47 -0800562 onTransact_case->name = outline_name;
563 onTransact_case->parameters.push_back(transact_data);
564 onTransact_case->parameters.push_back(transact_reply);
Steven Moreland48548e02019-09-18 15:10:22 -0700565 onTransact_case->statements = std::make_shared<StatementBlock>();
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900566 onTransact_case->exceptions.push_back("android.os.RemoteException");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800567 stubClass->elements.push_back(onTransact_case);
568
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900569 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900570 onTransact_case->statements, stubClass, options);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800571 }
572
573 // Generate the case dispatch.
574 {
Steven Moreland48548e02019-09-18 15:10:22 -0700575 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800576
Steven Moreland48548e02019-09-18 15:10:22 -0700577 auto helper_call =
578 std::make_shared<MethodCall>(THIS_VALUE, outline_name,
579 std::vector<std::shared_ptr<Expression>>{
580 stubClass->transact_data, stubClass->transact_reply});
581 c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800582
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900583 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800584 }
585}
586
Steven Moreland48548e02019-09-18 15:10:22 -0700587static std::shared_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900588 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
Steven Moreland48548e02019-09-18 15:10:22 -0700589 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
590 const Options& options) {
591 auto proxy = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800592 proxy->comment = method.GetComments();
593 proxy->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -0700594 proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800595 proxy->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700596 proxy->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800597 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700598 proxy->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700599 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800600 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900601 proxy->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800602
Christopher Wiley67502f12016-01-29 10:57:00 -0800603 // the parcels
Steven Moreland48548e02019-09-18 15:10:22 -0700604 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
605 proxy->statements->Add(std::make_shared<VariableDeclaration>(
606 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Steven Morelanda7764e52020-10-27 17:29:29 +0000607
608 if (iface.IsSensitiveData()) {
609 proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();"));
610 }
611
Steven Moreland48548e02019-09-18 15:10:22 -0700612 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800613 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700614 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
615 proxy->statements->Add(std::make_shared<VariableDeclaration>(
616 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800617 }
618
619 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700620 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800621 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700622 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
623 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800624 }
625
626 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700627 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800628 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700629 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800630 proxy->statements->Add(finallyStatement);
631
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900632 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700633 tryStatement->statements->Add(std::make_shared<MethodCall>(
634 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
635 std::vector<std::shared_ptr<Expression>>{
636 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700637 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
638 "::" + method.GetName() + "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100639 }
640
Christopher Wiley67502f12016-01-29 10:57:00 -0800641 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
642 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700643 tryStatement->statements->Add(std::make_shared<MethodCall>(
644 _data, "writeInterfaceToken",
645 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800646
647 // the parameters
648 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700649 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800650 AidlArgument::Direction dir = arg->GetDirection();
651 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700652 auto checklen = std::make_shared<IfStatement>();
653 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
654 checklen->statements->Add(std::make_shared<MethodCall>(
655 _data, "writeInt",
656 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
657 checklen->elseif = std::make_shared<IfStatement>();
658 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
659 _data, "writeInt",
660 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800661 tryStatement->statements->Add(checklen);
662 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900663 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900664 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800665 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800666 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800667
Steven Morelanda7764e52020-10-27 17:29:29 +0000668 std::vector<std::string> flags;
669 if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
670 if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
671
Christopher Wiley67502f12016-01-29 10:57:00 -0800672 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700673 auto call = std::make_shared<MethodCall>(
674 proxyClass->mRemote, "transact",
675 std::vector<std::shared_ptr<Expression>>{
676 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
677 _reply ? _reply : NULL_VALUE,
Steven Morelanda7764e52020-10-27 17:29:29 +0000678 std::make_shared<LiteralExpression>(flags.empty() ? "0" : Join(flags, " | "))});
Steven Moreland48548e02019-09-18 15:10:22 -0700679 auto _status = std::make_shared<Variable>("boolean", "_status");
680 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900681
Jiyong Parkcf999d62020-09-15 11:57:04 +0900682 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
683 // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
684 // is versioned. We can't throw the exception for unversioned interface because that would be an
685 // app breaking change.
Jiyong Park75e1a742018-07-04 12:31:23 +0900686 vector<string> arg_names;
687 for (const auto& arg : method.GetArguments()) {
688 arg_names.emplace_back(arg->GetName());
689 }
690 bool has_return_type = method.GetType().GetName() != "void";
Jiyong Parkcf999d62020-09-15 11:57:04 +0900691
692 auto checkDefaultImpl = std::make_shared<IfStatement>();
693 checkDefaultImpl->expression = std::make_shared<LiteralExpression>("getDefaultImpl() != null");
694 if (has_return_type) {
695 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
696 android::base::StringPrintf("return getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
697 Join(arg_names, ", ").c_str())));
698 } else {
699 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
700 android::base::StringPrintf("getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
701 Join(arg_names, ", ").c_str())));
702 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
703 }
704 if (options.Version() > 0) {
705 checkDefaultImpl->elseif = std::make_shared<IfStatement>();
706 checkDefaultImpl->elseif->statements->Add(
707 std::make_shared<LiteralStatement>(android::base::StringPrintf(
Jiyong Park1fd40782020-09-15 13:09:52 +0900708 "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
Jiyong Parkcf999d62020-09-15 11:57:04 +0900709 method.GetName().c_str())));
710 }
711
712 auto checkTransactionError = std::make_shared<IfStatement>();
713 checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
714 checkTransactionError->statements->Add(checkDefaultImpl);
715
716 tryStatement->statements->Add(checkTransactionError);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800717
Christopher Wiley67502f12016-01-29 10:57:00 -0800718 // throw back exceptions.
719 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700720 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800721 tryStatement->statements->Add(ex);
722 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800723
Christopher Wiley67502f12016-01-29 10:57:00 -0800724 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700725 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900726 // keep this across return value and arguments in order to create the
727 // classloader at most once.
728 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700729 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900730 string code;
731 CodeWriterPtr writer = CodeWriter::ForString(&code);
732 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900733 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900734 .type = method.GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900735 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700736 .var = _result->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900737 .is_classloader_created = &is_classloader_created};
738 CreateFromParcelFor(context);
739 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700740 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800741 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800742
743 // the out/inout parameters
744 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800745 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900746 string code;
747 CodeWriterPtr writer = CodeWriter::ForString(&code);
748 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900749 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900750 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900751 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700752 .var = arg->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900753 .is_classloader_created = &is_classloader_created};
754 ReadFromParcelFor(context);
755 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700756 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800757 }
758 }
759
Steven Moreland48548e02019-09-18 15:10:22 -0700760 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800761 }
Steven Moreland48548e02019-09-18 15:10:22 -0700762 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800763
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900764 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700765 finallyStatement->statements->Add(std::make_shared<MethodCall>(
766 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
767 std::vector<std::shared_ptr<Expression>>{
768 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100769 }
770
Yi Kong894d6ba2018-07-24 11:27:38 -0700771 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700772 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800773 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800774
775 return proxy;
776}
777
Jiyong Park74595c12018-07-23 15:22:50 +0900778static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700779 std::shared_ptr<StubClass> stubClass,
780 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900781 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800782 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800783
784 // == the TRANSACT_ constant =============================================
785 string transactCodeName = "TRANSACTION_";
786 transactCodeName += method.GetName();
787
Steven Moreland48548e02019-09-18 15:10:22 -0700788 auto transactCode =
789 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800790 transactCode->value =
791 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
792 stubClass->elements.push_back(transactCode);
793
Olivier Gaillard11401402018-07-05 15:01:34 +0100794 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900795 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700796 auto c = std::make_shared<Case>(transactCodeName);
797 c->statements->Add(std::make_shared<ReturnStatement>(
798 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100799 stubClass->code_to_method_name_switch->cases.push_back(c);
800 }
801
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800802 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700803 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900804 if (method.IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700805 decl = generate_interface_method(method, typenames);
Jiyong Park309668e2018-07-28 16:55:44 +0900806 } else {
807 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
808 std::ostringstream code;
809 code << "public int " << kGetInterfaceVersion << "() "
810 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700811 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900812 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900813 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
814 std::ostringstream code;
815 code << "public String " << kGetInterfaceHash << "() "
816 << "throws android.os.RemoteException;\n";
817 decl = std::make_shared<LiteralClassElement>(code.str());
818 }
Jiyong Park309668e2018-07-28 16:55:44 +0900819 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800820 interface->elements.push_back(decl);
821
822 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900823 if (method.IsUserDefined()) {
824 bool outline_stub =
825 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
826 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900827 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900828 options);
829 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900830 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900831 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800832 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900833 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700834 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900835 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900836 code << "data.enforceInterface(descriptor);\n"
837 << "reply.writeNoException();\n"
838 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900839 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700840 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900841 stubClass->transact_switch_meta->cases.push_back(c);
Jiyong Park309668e2018-07-28 16:55:44 +0900842 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900843 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
844 auto c = std::make_shared<Case>(transactCodeName);
845 std::ostringstream code;
846 code << "data.enforceInterface(descriptor);\n"
847 << "reply.writeNoException();\n"
848 << "reply.writeString(" << kGetInterfaceHash << "());\n"
849 << "return true;\n";
850 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900851 stubClass->transact_switch_meta->cases.push_back(c);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900852 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800853 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800854
855 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700856 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900857 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900858 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700859 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900860
861 } else {
862 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
863 std::ostringstream code;
864 code << "@Override\n"
865 << "public int " << kGetInterfaceVersion << "()"
866 << " throws "
867 << "android.os.RemoteException {\n"
868 << " if (mCachedVersion == -1) {\n"
869 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
870 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
871 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900872 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900873 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900874 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900875 << " if (!_status) {\n"
876 << " if (getDefaultImpl() != null) {\n"
877 << " return getDefaultImpl().getInterfaceVersion();\n"
878 << " }\n"
879 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900880 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900881 << " mCachedVersion = reply.readInt();\n"
882 << " } finally {\n"
883 << " reply.recycle();\n"
884 << " data.recycle();\n"
885 << " }\n"
886 << " }\n"
887 << " return mCachedVersion;\n"
888 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700889 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900890 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900891 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
892 std::ostringstream code;
893 code << "@Override\n"
894 << "public synchronized String " << kGetInterfaceHash << "()"
895 << " throws "
896 << "android.os.RemoteException {\n"
Jeongik Chab1428182020-05-13 19:49:30 +0900897 << " if (\"-1\".equals(mCachedHash)) {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900898 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
899 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
900 << " try {\n"
901 << " data.writeInterfaceToken(DESCRIPTOR);\n"
902 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
903 << "data, reply, 0);\n"
904 << " if (!_status) {\n"
905 << " if (getDefaultImpl() != null) {\n"
906 << " return getDefaultImpl().getInterfaceHash();\n"
907 << " }\n"
908 << " }\n"
909 << " reply.readException();\n"
910 << " mCachedHash = reply.readString();\n"
911 << " } finally {\n"
912 << " reply.recycle();\n"
913 << " data.recycle();\n"
914 << " }\n"
915 << " }\n"
916 << " return mCachedHash;\n"
917 << "}\n";
918 proxy = std::make_shared<LiteralClassElement>(code.str());
919 }
Jiyong Park309668e2018-07-28 16:55:44 +0900920 }
921 if (proxy != nullptr) {
922 proxyClass->elements.push_back(proxy);
923 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800924}
925
Jiyong Park5faba3e2020-04-24 17:08:37 +0900926static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
927 Class* interface, std::shared_ptr<StubClass> stub,
Steven Moreland48548e02019-09-18 15:10:22 -0700928 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800929 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -0700930 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
931 c->statements->Add(std::make_shared<MethodCall>(
932 stub->transact_reply, "writeString",
933 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
934 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900935 stub->transact_switch_meta->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800936
Christopher Wiley67502f12016-01-29 10:57:00 -0800937 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -0700938 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800939 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900940 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800941 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -0700942 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800943 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700944 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800945 proxy->elements.push_back(getDesc);
Jiyong Park5faba3e2020-04-24 17:08:37 +0900946
947 // add the DESCRIPTOR field to the interface class
948 Class* classToAddDescriptor = interface;
949 static std::set<std::string> greylist = {
950#include "hiddenapi-greylist"
951 };
952 if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
953 // For app compatibility, we keep DESCRIPTOR to the stub class for
954 // the interfaces that are in the greylist.
955 classToAddDescriptor = stub.get();
956 }
957 auto descriptor = std::make_shared<Field>(
958 STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900959 std::string name = iface->GetDescriptor();
Jiyong Park5faba3e2020-04-24 17:08:37 +0900960 if (options.IsStructured()) {
961 // mangle the interface name at build time and demangle it at runtime, to avoid
962 // being renamed by jarjar. See b/153843174
Jiyong Park5faba3e2020-04-24 17:08:37 +0900963 std::replace(name.begin(), name.end(), '.', '$');
964 descriptor->value = "\"" + name + "\".replace('$', '.')";
965 } else {
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900966 descriptor->value = "\"" + name + "\"";
Jiyong Park5faba3e2020-04-24 17:08:37 +0900967 }
968 classToAddDescriptor->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800969}
970
Andreas Gampee9c816e2018-03-14 09:05:48 -0700971// Check whether (some) methods in this interface should be "outlined," that
972// is, have specific onTransact methods for certain cases. Set up StubClass
973// metadata accordingly.
974//
975// Outlining will be enabled if the interface has more than outline_threshold
976// methods. In that case, the methods are sorted by number of arguments
977// (so that more "complex" methods come later), and the first non_outline_count
978// number of methods not outlined (are kept in the onTransact() method).
979//
980// Requirements: non_outline_count <= outline_threshold.
981static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -0700982 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700983 size_t non_outline_count) {
Steven Moreland21780812020-09-11 01:29:45 +0000984 AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
Andreas Gampee9c816e2018-03-14 09:05:48 -0700985 // We'll outline (create sub methods) if there are more than min_methods
986 // cases.
987 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
988 if (stub->transact_outline) {
989 stub->all_method_count = iface->GetMethods().size();
990 std::vector<const AidlMethod*> methods;
991 methods.reserve(iface->GetMethods().size());
Jooyung Han3f347ca2020-12-01 12:41:50 +0900992 for (const auto& ptr : iface->GetMethods()) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700993 methods.push_back(ptr.get());
994 }
995
996 std::stable_sort(
997 methods.begin(),
998 methods.end(),
999 [](const AidlMethod* m1, const AidlMethod* m2) {
1000 return m1->GetArguments().size() < m2->GetArguments().size();
1001 });
1002
1003 stub->outline_methods.insert(methods.begin() + non_outline_count,
1004 methods.end());
1005 }
1006}
1007
Daniel Norman716d3112019-09-10 13:11:56 -07001008static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
1009 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -07001010 auto default_method = std::make_shared<Method>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001011 default_method->comment = method.GetComments();
1012 default_method->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -07001013 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001014 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -07001015 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001016 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -07001017 default_method->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -07001018 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +09001019 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001020 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +09001021
1022 if (method.GetType().GetName() != "void") {
Daniel Norman716d3112019-09-10 13:11:56 -07001023 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001024 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -07001025 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001026 }
1027 return default_method;
1028}
1029
Steven Moreland48548e02019-09-18 15:10:22 -07001030static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Daniel Norman716d3112019-09-10 13:11:56 -07001031 const AidlTypenames& typenames,
Jiyong Park309668e2018-07-28 16:55:44 +09001032 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -07001033 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001034 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1035 default_class->modifiers = PUBLIC | STATIC;
1036 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001037 default_class->type = iface.GetCanonicalName() + ".Default";
1038 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +09001039
1040 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001041 if (m->IsUserDefined()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001042 default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
Jiyong Park309668e2018-07-28 16:55:44 +09001043 } else {
Paul Trautrimb77048c2020-01-21 16:39:32 +09001044 // These are called only when the remote side does not implement these
1045 // methods, which is normally impossible, because these methods are
1046 // automatically declared in the interface class and not implementing
1047 // them on the remote side causes a compilation error. But if the remote
1048 // side somehow managed to not implement it, that's an error and we
1049 // report the case by returning an invalid value here.
Jiyong Park309668e2018-07-28 16:55:44 +09001050 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1051 std::ostringstream code;
1052 code << "@Override\n"
1053 << "public int " << kGetInterfaceVersion << "() {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001054 << " return 0;\n"
1055 << "}\n";
1056 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1057 }
1058 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1059 std::ostringstream code;
1060 code << "@Override\n"
1061 << "public String " << kGetInterfaceHash << "() {\n"
1062 << " return \"\";\n"
Jiyong Park309668e2018-07-28 16:55:44 +09001063 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001064 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001065 }
1066 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001067 }
1068
1069 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001070 std::make_shared<LiteralClassElement>("@Override\n"
1071 "public android.os.IBinder asBinder() {\n"
1072 " return null;\n"
1073 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +09001074
1075 return default_class;
1076}
1077
Steven Moreland48548e02019-09-18 15:10:22 -07001078std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1079 const AidlTypenames& typenames,
1080 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001081 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -07001082 auto interface = std::make_unique<Class>();
Christopher Wiley67502f12016-01-29 10:57:00 -08001083 interface->comment = iface->GetComments();
1084 interface->modifiers = PUBLIC;
1085 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001086 interface->type = iface->GetCanonicalName();
1087 interface->interfaces.push_back("android.os.IInterface");
Jooyung Han720253d2021-01-05 19:13:17 +09001088 interface->annotations = JavaAnnotationsFor(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001089
Jiyong Park309668e2018-07-28 16:55:44 +09001090 if (options.Version()) {
1091 std::ostringstream code;
1092 code << "/**\n"
1093 << " * The version of this interface that the caller is built against.\n"
1094 << " * This might be different from what {@link #getInterfaceVersion()\n"
1095 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1096 << " * that the remote object is implementing.\n"
1097 << " */\n"
1098 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001099 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001100 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001101 if (!options.Hash().empty()) {
1102 std::ostringstream code;
1103 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1104 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1105 }
Jiyong Park309668e2018-07-28 16:55:44 +09001106
Jiyong Park75e1a742018-07-04 12:31:23 +09001107 // the default impl class
Daniel Norman716d3112019-09-10 13:11:56 -07001108 auto default_impl = generate_default_impl_class(*iface, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +09001109 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001110
Christopher Wiley67502f12016-01-29 10:57:00 -08001111 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001112 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001113 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001114
Andreas Gampee9c816e2018-03-14 09:05:48 -07001115 compute_outline_methods(iface,
1116 stub,
1117 options.onTransact_outline_threshold_,
1118 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001119
Christopher Wiley67502f12016-01-29 10:57:00 -08001120 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001121 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001122 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001123
Christopher Wiley67502f12016-01-29 10:57:00 -08001124 // stub and proxy support for getInterfaceDescriptor()
Jiyong Park5faba3e2020-04-24 17:08:37 +09001125 generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001126
Christopher Wiley67502f12016-01-29 10:57:00 -08001127 // all the declared constants of the interface
Jooyung Hanb43a61c2020-12-02 14:18:53 +09001128 string constants;
1129 generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
Jooyung Han3f347ca2020-12-01 12:41:50 +09001130 interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001131
Christopher Wiley67502f12016-01-29 10:57:00 -08001132 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001133
Christopher Wiley67502f12016-01-29 10:57:00 -08001134 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001135 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1136 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001137 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001138
1139 // additional static methods for the default impl set/get to the
1140 // stub class. Can't add them to the interface as the generated java files
1141 // may be compiled with Java < 1.7 where static interface method isn't
1142 // supported.
1143 // TODO(b/111417145) make this conditional depending on the Java language
1144 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001145 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001146 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001147 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
Jooyung Han4a044662020-05-13 17:17:07 +09001148 " // Only one user of this interface can use this function\n"
1149 " // at a time. This is a heuristic to detect if two different\n"
1150 " // users in the same process use this function.\n"
1151 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1152 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1153 " }\n"
1154 " if (impl != null) {\n"
Jiyong Park75e1a742018-07-04 12:31:23 +09001155 " Stub.Proxy.sDefaultImpl = impl;\n"
1156 " return true;\n"
1157 " }\n"
1158 " return false;\n"
1159 "}\n",
1160 i_name.c_str())));
1161 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001162 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1163 " return Stub.Proxy.sDefaultImpl;\n"
1164 "}\n",
1165 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001166
1167 // the static field is defined in the proxy class, not in the interface class
1168 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001169 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001170 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001171
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001172 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001173
Christopher Wiley67502f12016-01-29 10:57:00 -08001174 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001175}
1176
Christopher Wileydb154a52015-09-28 16:32:25 -07001177} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001178} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001179} // namespace android