blob: fa1c14acd3104936bd2ae7e8e14aa9ee79cf2421 [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();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900396 out << GenerateComments(*constant);
397 out << GenerateAnnotations(*constant);
Jooyung Han3f347ca2020-12-01 12:41:50 +0900398 out << "public static final " << type.Signature() << " " << constant->GetName() << " = "
399 << constant->ValueString(ConstantValueDecorator) << ";\n";
400 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800401}
402
Daniel Norman716d3112019-09-10 13:11:56 -0700403static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
404 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -0700405 auto decl = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900406 decl->comment = GenerateComments(method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800407 decl->modifiers = PUBLIC;
Daniel Norman716d3112019-09-10 13:11:56 -0700408 decl->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800409 decl->name = method.GetName();
Jooyung Han720253d2021-01-05 19:13:17 +0900410 decl->annotations = JavaAnnotationsFor(method);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800411
Christopher Wiley67502f12016-01-29 10:57:00 -0800412 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900413 auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Jooyung Han720253d2021-01-05 19:13:17 +0900414 var->annotations = JavaAnnotationsFor(arg->GetType());
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900415 decl->parameters.push_back(var);
Christopher Wiley67502f12016-01-29 10:57:00 -0800416 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800417
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900418 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800419
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800420 return decl;
421}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800422
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900423static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700424 std::shared_ptr<Variable> transact_data,
425 std::shared_ptr<Variable> transact_reply,
426 const AidlTypenames& typenames,
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700427 std::shared_ptr<StatementBlock> statement_block,
Steven Moreland48548e02019-09-18 15:10:22 -0700428 std::shared_ptr<StubClass> stubClass, const Options& options) {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700429 // try and finally
430 auto tryStatement = std::make_shared<TryStatement>();
431 auto finallyStatement = std::make_shared<FinallyStatement>();
432 auto& statements = statement_block;
433
434 if (options.GenTraces()) {
435 statements->Add(tryStatement);
436 statements->Add(finallyStatement);
437 statements = tryStatement->statements;
438 tryStatement->statements->Add(std::make_shared<MethodCall>(
439 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
440 std::vector<std::shared_ptr<Expression>>{
441 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
442 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
443 "::" + method.GetName() + "::server")}));
444 finallyStatement->statements->Add(std::make_shared<MethodCall>(
445 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
446 std::vector<std::shared_ptr<Expression>>{
447 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
448 }
449
Steven Moreland48548e02019-09-18 15:10:22 -0700450 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800451
Christopher Wiley67502f12016-01-29 10:57:00 -0800452 // interface token validation is the very first thing we do
Steven Moreland48548e02019-09-18 15:10:22 -0700453 statements->Add(std::make_shared<MethodCall>(
454 transact_data, "enforceInterface",
455 std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800456
Christopher Wiley67502f12016-01-29 10:57:00 -0800457 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800458 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800459 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900460 // keep this across different args in order to create the classloader
461 // at most once.
462 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800463 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700464 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800465
Steven Moreland48548e02019-09-18 15:10:22 -0700466 statements->Add(std::make_shared<VariableDeclaration>(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800467
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800468 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900469 string code;
470 CodeWriterPtr writer = CodeWriter::ForString(&code);
471 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900472 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900473 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900474 .parcel = transact_data->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700475 .var = v->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900476 .is_classloader_created = &is_classloader_created};
477 CreateFromParcelFor(context);
478 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700479 statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800480 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800481 if (!arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700482 statements->Add(std::make_shared<Assignment>(
Daniel Norman716d3112019-09-10 13:11:56 -0700483 v, std::make_shared<NewExpression>(
484 InstantiableJavaSignatureOf(arg->GetType(), typenames))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800485 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700486 generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800487 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800488 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800489
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800490 realCall->arguments.push_back(v);
491 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800492 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800493
Christopher Wiley67502f12016-01-29 10:57:00 -0800494 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800495 if (method.GetType().GetName() == "void") {
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700496 statements->Add(realCall);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800497
Adam Lesinskiffa16862014-01-23 18:17:42 -0800498 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800499 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700500 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800501 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800502 }
503 } else {
Daniel Norman716d3112019-09-10 13:11:56 -0700504 auto _result =
505 std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
Steven Moreland48548e02019-09-18 15:10:22 -0700506 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
Christopher Wiley67502f12016-01-29 10:57:00 -0800507
508 if (!oneway) {
509 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700510 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800511 statements->Add(ex);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800512 }
513
Christopher Wiley67502f12016-01-29 10:57:00 -0800514 // marshall the return value
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900515 generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900516 typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800517 }
518
519 // out parameters
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800520 int i = 0;
Christopher Wiley67502f12016-01-29 10:57:00 -0800521 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700522 std::shared_ptr<Variable> v = stubArgs.Get(i++);
Christopher Wiley67502f12016-01-29 10:57:00 -0800523
524 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900525 generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800526 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800527 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800528
Christopher Wiley67502f12016-01-29 10:57:00 -0800529 // return true
Steven Moreland48548e02019-09-18 15:10:22 -0700530 statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800531}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800532
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900533static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
534 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700535 std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900536 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700537 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800538
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900539 generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900540 typenames, c->statements, stubClass, options);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800541
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900542 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800543}
544
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900545static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
546 const std::string& transactCodeName, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700547 std::shared_ptr<StubClass> stubClass,
548 const AidlTypenames& typenames, const Options& options) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800549 std::string outline_name = "onTransact$" + method.GetName() + "$";
550 // Generate an "outlined" method with the actual code.
551 {
Steven Moreland48548e02019-09-18 15:10:22 -0700552 auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
553 auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
554 auto onTransact_case = std::make_shared<Method>();
Andreas Gampe1b865af2017-11-22 11:31:47 -0800555 onTransact_case->modifiers = PRIVATE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900556 onTransact_case->returnType = "boolean";
Andreas Gampe1b865af2017-11-22 11:31:47 -0800557 onTransact_case->name = outline_name;
558 onTransact_case->parameters.push_back(transact_data);
559 onTransact_case->parameters.push_back(transact_reply);
Steven Moreland48548e02019-09-18 15:10:22 -0700560 onTransact_case->statements = std::make_shared<StatementBlock>();
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900561 onTransact_case->exceptions.push_back("android.os.RemoteException");
Andreas Gampe1b865af2017-11-22 11:31:47 -0800562 stubClass->elements.push_back(onTransact_case);
563
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900564 generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900565 onTransact_case->statements, stubClass, options);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800566 }
567
568 // Generate the case dispatch.
569 {
Steven Moreland48548e02019-09-18 15:10:22 -0700570 auto c = std::make_shared<Case>(transactCodeName);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800571
Steven Moreland48548e02019-09-18 15:10:22 -0700572 auto helper_call =
573 std::make_shared<MethodCall>(THIS_VALUE, outline_name,
574 std::vector<std::shared_ptr<Expression>>{
575 stubClass->transact_data, stubClass->transact_reply});
576 c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
Andreas Gampe1b865af2017-11-22 11:31:47 -0800577
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900578 stubClass->transact_switch_user->cases.push_back(c);
Andreas Gampe1b865af2017-11-22 11:31:47 -0800579 }
580}
581
Steven Moreland48548e02019-09-18 15:10:22 -0700582static std::shared_ptr<Method> generate_proxy_method(
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900583 const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
Steven Moreland48548e02019-09-18 15:10:22 -0700584 bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
585 const Options& options) {
586 auto proxy = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900587 proxy->comment = GenerateComments(method);
Christopher Wiley67502f12016-01-29 10:57:00 -0800588 proxy->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -0700589 proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
Christopher Wiley67502f12016-01-29 10:57:00 -0800590 proxy->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700591 proxy->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800592 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700593 proxy->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -0700594 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800595 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900596 proxy->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800597
Christopher Wiley67502f12016-01-29 10:57:00 -0800598 // the parcels
Steven Moreland48548e02019-09-18 15:10:22 -0700599 auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
600 proxy->statements->Add(std::make_shared<VariableDeclaration>(
601 _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Steven Morelanda7764e52020-10-27 17:29:29 +0000602
603 if (iface.IsSensitiveData()) {
604 proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();"));
605 }
606
Steven Moreland48548e02019-09-18 15:10:22 -0700607 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800608 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700609 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
610 proxy->statements->Add(std::make_shared<VariableDeclaration>(
611 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800612 }
613
614 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700615 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800616 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700617 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
618 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800619 }
620
621 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700622 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800623 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700624 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800625 proxy->statements->Add(finallyStatement);
626
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900627 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700628 tryStatement->statements->Add(std::make_shared<MethodCall>(
629 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
630 std::vector<std::shared_ptr<Expression>>{
631 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
Devin Mooree2ccf8a2020-05-13 14:28:20 -0700632 std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
633 "::" + method.GetName() + "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100634 }
635
Christopher Wiley67502f12016-01-29 10:57:00 -0800636 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
637 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700638 tryStatement->statements->Add(std::make_shared<MethodCall>(
639 _data, "writeInterfaceToken",
640 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800641
642 // the parameters
643 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700644 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800645 AidlArgument::Direction dir = arg->GetDirection();
646 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700647 auto checklen = std::make_shared<IfStatement>();
648 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
649 checklen->statements->Add(std::make_shared<MethodCall>(
650 _data, "writeInt",
651 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
652 checklen->elseif = std::make_shared<IfStatement>();
653 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
654 _data, "writeInt",
655 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800656 tryStatement->statements->Add(checklen);
657 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900658 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900659 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800660 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800661 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800662
Steven Morelanda7764e52020-10-27 17:29:29 +0000663 std::vector<std::string> flags;
664 if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
665 if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
666
Christopher Wiley67502f12016-01-29 10:57:00 -0800667 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700668 auto call = std::make_shared<MethodCall>(
669 proxyClass->mRemote, "transact",
670 std::vector<std::shared_ptr<Expression>>{
671 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
672 _reply ? _reply : NULL_VALUE,
Steven Morelanda7764e52020-10-27 17:29:29 +0000673 std::make_shared<LiteralExpression>(flags.empty() ? "0" : Join(flags, " | "))});
Steven Moreland48548e02019-09-18 15:10:22 -0700674 auto _status = std::make_shared<Variable>("boolean", "_status");
675 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900676
Jiyong Parkcf999d62020-09-15 11:57:04 +0900677 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
678 // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
679 // is versioned. We can't throw the exception for unversioned interface because that would be an
680 // app breaking change.
Jiyong Park75e1a742018-07-04 12:31:23 +0900681 vector<string> arg_names;
682 for (const auto& arg : method.GetArguments()) {
683 arg_names.emplace_back(arg->GetName());
684 }
685 bool has_return_type = method.GetType().GetName() != "void";
Jiyong Parkcf999d62020-09-15 11:57:04 +0900686
687 auto checkDefaultImpl = std::make_shared<IfStatement>();
688 checkDefaultImpl->expression = std::make_shared<LiteralExpression>("getDefaultImpl() != null");
689 if (has_return_type) {
690 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
691 android::base::StringPrintf("return getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
692 Join(arg_names, ", ").c_str())));
693 } else {
694 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
695 android::base::StringPrintf("getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
696 Join(arg_names, ", ").c_str())));
697 checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
698 }
699 if (options.Version() > 0) {
700 checkDefaultImpl->elseif = std::make_shared<IfStatement>();
701 checkDefaultImpl->elseif->statements->Add(
702 std::make_shared<LiteralStatement>(android::base::StringPrintf(
Jiyong Park1fd40782020-09-15 13:09:52 +0900703 "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
Jiyong Parkcf999d62020-09-15 11:57:04 +0900704 method.GetName().c_str())));
705 }
706
707 auto checkTransactionError = std::make_shared<IfStatement>();
708 checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
709 checkTransactionError->statements->Add(checkDefaultImpl);
710
711 tryStatement->statements->Add(checkTransactionError);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800712
Christopher Wiley67502f12016-01-29 10:57:00 -0800713 // throw back exceptions.
714 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700715 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800716 tryStatement->statements->Add(ex);
717 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800718
Christopher Wiley67502f12016-01-29 10:57:00 -0800719 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700720 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900721 // keep this across return value and arguments in order to create the
722 // classloader at most once.
723 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700724 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900725 string code;
726 CodeWriterPtr writer = CodeWriter::ForString(&code);
727 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900728 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900729 .type = method.GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900730 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700731 .var = _result->name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900732 .is_classloader_created = &is_classloader_created};
733 CreateFromParcelFor(context);
734 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700735 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800736 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800737
738 // the out/inout parameters
739 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800740 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900741 string code;
742 CodeWriterPtr writer = CodeWriter::ForString(&code);
743 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900744 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900745 .type = arg->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900746 .parcel = _reply->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700747 .var = arg->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900748 .is_classloader_created = &is_classloader_created};
749 ReadFromParcelFor(context);
750 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700751 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800752 }
753 }
754
Steven Moreland48548e02019-09-18 15:10:22 -0700755 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800756 }
Steven Moreland48548e02019-09-18 15:10:22 -0700757 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800758
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900759 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700760 finallyStatement->statements->Add(std::make_shared<MethodCall>(
761 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
762 std::vector<std::shared_ptr<Expression>>{
763 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100764 }
765
Yi Kong894d6ba2018-07-24 11:27:38 -0700766 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700767 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800768 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800769
770 return proxy;
771}
772
Jiyong Park74595c12018-07-23 15:22:50 +0900773static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700774 std::shared_ptr<StubClass> stubClass,
775 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900776 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800777 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800778
779 // == the TRANSACT_ constant =============================================
780 string transactCodeName = "TRANSACTION_";
781 transactCodeName += method.GetName();
782
Steven Moreland48548e02019-09-18 15:10:22 -0700783 auto transactCode =
784 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800785 transactCode->value =
786 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
787 stubClass->elements.push_back(transactCode);
788
Olivier Gaillard11401402018-07-05 15:01:34 +0100789 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900790 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700791 auto c = std::make_shared<Case>(transactCodeName);
792 c->statements->Add(std::make_shared<ReturnStatement>(
793 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100794 stubClass->code_to_method_name_switch->cases.push_back(c);
795 }
796
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800797 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700798 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900799 if (method.IsUserDefined()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700800 decl = generate_interface_method(method, typenames);
Jiyong Park309668e2018-07-28 16:55:44 +0900801 } else {
802 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
803 std::ostringstream code;
804 code << "public int " << kGetInterfaceVersion << "() "
805 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700806 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900807 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900808 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
809 std::ostringstream code;
810 code << "public String " << kGetInterfaceHash << "() "
811 << "throws android.os.RemoteException;\n";
812 decl = std::make_shared<LiteralClassElement>(code.str());
813 }
Jiyong Park309668e2018-07-28 16:55:44 +0900814 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800815 interface->elements.push_back(decl);
816
817 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900818 if (method.IsUserDefined()) {
819 bool outline_stub =
820 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
821 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900822 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900823 options);
824 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900825 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900826 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800827 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900828 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700829 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900830 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900831 code << "data.enforceInterface(descriptor);\n"
832 << "reply.writeNoException();\n"
833 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900834 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700835 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900836 stubClass->transact_switch_meta->cases.push_back(c);
Jiyong Park309668e2018-07-28 16:55:44 +0900837 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900838 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
839 auto c = std::make_shared<Case>(transactCodeName);
840 std::ostringstream code;
841 code << "data.enforceInterface(descriptor);\n"
842 << "reply.writeNoException();\n"
843 << "reply.writeString(" << kGetInterfaceHash << "());\n"
844 << "return true;\n";
845 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900846 stubClass->transact_switch_meta->cases.push_back(c);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900847 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800848 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800849
850 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700851 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900852 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900853 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700854 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900855
856 } else {
857 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
858 std::ostringstream code;
859 code << "@Override\n"
860 << "public int " << kGetInterfaceVersion << "()"
861 << " throws "
862 << "android.os.RemoteException {\n"
863 << " if (mCachedVersion == -1) {\n"
864 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
865 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
866 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900867 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900868 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900869 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900870 << " if (!_status) {\n"
871 << " if (getDefaultImpl() != null) {\n"
872 << " return getDefaultImpl().getInterfaceVersion();\n"
873 << " }\n"
874 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900875 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900876 << " mCachedVersion = reply.readInt();\n"
877 << " } finally {\n"
878 << " reply.recycle();\n"
879 << " data.recycle();\n"
880 << " }\n"
881 << " }\n"
882 << " return mCachedVersion;\n"
883 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700884 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900885 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900886 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
887 std::ostringstream code;
888 code << "@Override\n"
889 << "public synchronized String " << kGetInterfaceHash << "()"
890 << " throws "
891 << "android.os.RemoteException {\n"
Jeongik Chab1428182020-05-13 19:49:30 +0900892 << " if (\"-1\".equals(mCachedHash)) {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +0900893 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
894 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
895 << " try {\n"
896 << " data.writeInterfaceToken(DESCRIPTOR);\n"
897 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
898 << "data, reply, 0);\n"
899 << " if (!_status) {\n"
900 << " if (getDefaultImpl() != null) {\n"
901 << " return getDefaultImpl().getInterfaceHash();\n"
902 << " }\n"
903 << " }\n"
904 << " reply.readException();\n"
905 << " mCachedHash = reply.readString();\n"
906 << " } finally {\n"
907 << " reply.recycle();\n"
908 << " data.recycle();\n"
909 << " }\n"
910 << " }\n"
911 << " return mCachedHash;\n"
912 << "}\n";
913 proxy = std::make_shared<LiteralClassElement>(code.str());
914 }
Jiyong Park309668e2018-07-28 16:55:44 +0900915 }
916 if (proxy != nullptr) {
917 proxyClass->elements.push_back(proxy);
918 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800919}
920
Jiyong Park5faba3e2020-04-24 17:08:37 +0900921static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
922 Class* interface, std::shared_ptr<StubClass> stub,
Steven Moreland48548e02019-09-18 15:10:22 -0700923 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800924 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -0700925 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
926 c->statements->Add(std::make_shared<MethodCall>(
927 stub->transact_reply, "writeString",
928 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
929 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Jiyong Parka7ea8bf2021-01-05 10:36:18 +0900930 stub->transact_switch_meta->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800931
Christopher Wiley67502f12016-01-29 10:57:00 -0800932 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -0700933 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800934 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900935 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800936 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -0700937 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800938 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700939 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800940 proxy->elements.push_back(getDesc);
Jiyong Park5faba3e2020-04-24 17:08:37 +0900941
942 // add the DESCRIPTOR field to the interface class
943 Class* classToAddDescriptor = interface;
944 static std::set<std::string> greylist = {
945#include "hiddenapi-greylist"
946 };
947 if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
948 // For app compatibility, we keep DESCRIPTOR to the stub class for
949 // the interfaces that are in the greylist.
950 classToAddDescriptor = stub.get();
951 }
952 auto descriptor = std::make_shared<Field>(
953 STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900954 std::string name = iface->GetDescriptor();
Jiyong Park5faba3e2020-04-24 17:08:37 +0900955 if (options.IsStructured()) {
956 // mangle the interface name at build time and demangle it at runtime, to avoid
957 // being renamed by jarjar. See b/153843174
Jiyong Park5faba3e2020-04-24 17:08:37 +0900958 std::replace(name.begin(), name.end(), '.', '$');
959 descriptor->value = "\"" + name + "\".replace('$', '.')";
960 } else {
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900961 descriptor->value = "\"" + name + "\"";
Jiyong Park5faba3e2020-04-24 17:08:37 +0900962 }
963 classToAddDescriptor->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800964}
965
Andreas Gampee9c816e2018-03-14 09:05:48 -0700966// Check whether (some) methods in this interface should be "outlined," that
967// is, have specific onTransact methods for certain cases. Set up StubClass
968// metadata accordingly.
969//
970// Outlining will be enabled if the interface has more than outline_threshold
971// methods. In that case, the methods are sorted by number of arguments
972// (so that more "complex" methods come later), and the first non_outline_count
973// number of methods not outlined (are kept in the onTransact() method).
974//
975// Requirements: non_outline_count <= outline_threshold.
976static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -0700977 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700978 size_t non_outline_count) {
Steven Moreland21780812020-09-11 01:29:45 +0000979 AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
Andreas Gampee9c816e2018-03-14 09:05:48 -0700980 // We'll outline (create sub methods) if there are more than min_methods
981 // cases.
982 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
983 if (stub->transact_outline) {
984 stub->all_method_count = iface->GetMethods().size();
985 std::vector<const AidlMethod*> methods;
986 methods.reserve(iface->GetMethods().size());
Jooyung Han3f347ca2020-12-01 12:41:50 +0900987 for (const auto& ptr : iface->GetMethods()) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700988 methods.push_back(ptr.get());
989 }
990
991 std::stable_sort(
992 methods.begin(),
993 methods.end(),
994 [](const AidlMethod* m1, const AidlMethod* m2) {
995 return m1->GetArguments().size() < m2->GetArguments().size();
996 });
997
998 stub->outline_methods.insert(methods.begin() + non_outline_count,
999 methods.end());
1000 }
1001}
1002
Daniel Norman716d3112019-09-10 13:11:56 -07001003static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
1004 const AidlTypenames& typenames) {
Steven Moreland48548e02019-09-18 15:10:22 -07001005 auto default_method = std::make_shared<Method>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001006 default_method->comment = GenerateComments(method);
Jiyong Park75e1a742018-07-04 12:31:23 +09001007 default_method->modifiers = PUBLIC | OVERRIDE;
Daniel Norman716d3112019-09-10 13:11:56 -07001008 default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001009 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -07001010 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001011 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -07001012 default_method->parameters.push_back(
Daniel Norman716d3112019-09-10 13:11:56 -07001013 std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +09001014 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001015 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +09001016
1017 if (method.GetType().GetName() != "void") {
Daniel Norman716d3112019-09-10 13:11:56 -07001018 const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
Jiyong Park75e1a742018-07-04 12:31:23 +09001019 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -07001020 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001021 }
1022 return default_method;
1023}
1024
Steven Moreland48548e02019-09-18 15:10:22 -07001025static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Daniel Norman716d3112019-09-10 13:11:56 -07001026 const AidlTypenames& typenames,
Jiyong Park309668e2018-07-28 16:55:44 +09001027 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -07001028 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +09001029 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1030 default_class->modifiers = PUBLIC | STATIC;
1031 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001032 default_class->type = iface.GetCanonicalName() + ".Default";
1033 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +09001034
1035 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001036 if (m->IsUserDefined()) {
Jooyung Han3f347ca2020-12-01 12:41:50 +09001037 default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
Jiyong Park309668e2018-07-28 16:55:44 +09001038 } else {
Paul Trautrimb77048c2020-01-21 16:39:32 +09001039 // These are called only when the remote side does not implement these
1040 // methods, which is normally impossible, because these methods are
1041 // automatically declared in the interface class and not implementing
1042 // them on the remote side causes a compilation error. But if the remote
1043 // side somehow managed to not implement it, that's an error and we
1044 // report the case by returning an invalid value here.
Jiyong Park309668e2018-07-28 16:55:44 +09001045 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1046 std::ostringstream code;
1047 code << "@Override\n"
1048 << "public int " << kGetInterfaceVersion << "() {\n"
Paul Trautrimb77048c2020-01-21 16:39:32 +09001049 << " return 0;\n"
1050 << "}\n";
1051 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1052 }
1053 if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1054 std::ostringstream code;
1055 code << "@Override\n"
1056 << "public String " << kGetInterfaceHash << "() {\n"
1057 << " return \"\";\n"
Jiyong Park309668e2018-07-28 16:55:44 +09001058 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001059 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001060 }
1061 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001062 }
1063
1064 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001065 std::make_shared<LiteralClassElement>("@Override\n"
1066 "public android.os.IBinder asBinder() {\n"
1067 " return null;\n"
1068 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +09001069
1070 return default_class;
1071}
1072
Steven Moreland48548e02019-09-18 15:10:22 -07001073std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1074 const AidlTypenames& typenames,
1075 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -08001076 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -07001077 auto interface = std::make_unique<Class>();
Jooyung Hanbd9db442021-01-14 01:45:55 +09001078 interface->comment = GenerateComments(*iface);
Christopher Wiley67502f12016-01-29 10:57:00 -08001079 interface->modifiers = PUBLIC;
1080 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001081 interface->type = iface->GetCanonicalName();
1082 interface->interfaces.push_back("android.os.IInterface");
Jooyung Han720253d2021-01-05 19:13:17 +09001083 interface->annotations = JavaAnnotationsFor(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001084
Jiyong Park309668e2018-07-28 16:55:44 +09001085 if (options.Version()) {
1086 std::ostringstream code;
1087 code << "/**\n"
1088 << " * The version of this interface that the caller is built against.\n"
1089 << " * This might be different from what {@link #getInterfaceVersion()\n"
1090 << " * getInterfaceVersion} returns as that is the version of the interface\n"
1091 << " * that the remote object is implementing.\n"
1092 << " */\n"
1093 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -07001094 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +09001095 }
Paul Trautrimb77048c2020-01-21 16:39:32 +09001096 if (!options.Hash().empty()) {
1097 std::ostringstream code;
1098 code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1099 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1100 }
Jiyong Park309668e2018-07-28 16:55:44 +09001101
Jiyong Park75e1a742018-07-04 12:31:23 +09001102 // the default impl class
Daniel Norman716d3112019-09-10 13:11:56 -07001103 auto default_impl = generate_default_impl_class(*iface, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +09001104 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +09001105
Christopher Wiley67502f12016-01-29 10:57:00 -08001106 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001107 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001108 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001109
Andreas Gampee9c816e2018-03-14 09:05:48 -07001110 compute_outline_methods(iface,
1111 stub,
1112 options.onTransact_outline_threshold_,
1113 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001114
Christopher Wiley67502f12016-01-29 10:57:00 -08001115 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001116 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001117 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001118
Christopher Wiley67502f12016-01-29 10:57:00 -08001119 // stub and proxy support for getInterfaceDescriptor()
Jiyong Park5faba3e2020-04-24 17:08:37 +09001120 generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001121
Christopher Wiley67502f12016-01-29 10:57:00 -08001122 // all the declared constants of the interface
Jooyung Hanb43a61c2020-12-02 14:18:53 +09001123 string constants;
1124 generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
Jooyung Han3f347ca2020-12-01 12:41:50 +09001125 interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001126
Christopher Wiley67502f12016-01-29 10:57:00 -08001127 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001128
Christopher Wiley67502f12016-01-29 10:57:00 -08001129 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001130 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1131 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001132 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001133
1134 // additional static methods for the default impl set/get to the
1135 // stub class. Can't add them to the interface as the generated java files
1136 // may be compiled with Java < 1.7 where static interface method isn't
1137 // supported.
1138 // TODO(b/111417145) make this conditional depending on the Java language
1139 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001140 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001141 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001142 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
Jooyung Han4a044662020-05-13 17:17:07 +09001143 " // Only one user of this interface can use this function\n"
1144 " // at a time. This is a heuristic to detect if two different\n"
1145 " // users in the same process use this function.\n"
1146 " if (Stub.Proxy.sDefaultImpl != null) {\n"
1147 " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1148 " }\n"
1149 " if (impl != null) {\n"
Jiyong Park75e1a742018-07-04 12:31:23 +09001150 " Stub.Proxy.sDefaultImpl = impl;\n"
1151 " return true;\n"
1152 " }\n"
1153 " return false;\n"
1154 "}\n",
1155 i_name.c_str())));
1156 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001157 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1158 " return Stub.Proxy.sDefaultImpl;\n"
1159 "}\n",
1160 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001161
1162 // the static field is defined in the proxy class, not in the interface class
1163 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001164 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001165 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001166
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001167 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001168
Christopher Wiley67502f12016-01-29 10:57:00 -08001169 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001170}
1171
Christopher Wileydb154a52015-09-28 16:32:25 -07001172} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001173} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001174} // namespace android