blob: f1c0dc6d3111ccffad8d2637fea81aaff22c2807 [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"
Adam Lesinskiffa16862014-01-23 18:17:42 -080019#include "generate_java.h"
Jeongik Cha047c5ee2019-08-07 23:16:49 +090020#include "logging.h"
Jiyong Park1d2df7d2018-07-23 15:22:50 +090021#include "options.h"
Christopher Wileyf690be52015-09-14 15:19:10 -070022
Adam Lesinskiffa16862014-01-23 18:17:42 -080023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
Andreas Gampee9c816e2018-03-14 09:05:48 -070027#include <algorithm>
28#include <unordered_set>
Jiyong Park1d2df7d2018-07-23 15:22:50 +090029#include <utility>
30#include <vector>
Andreas Gampee9c816e2018-03-14 09:05:48 -070031
Elliott Hughes0a620672015-12-04 13:53:18 -080032#include <android-base/macros.h>
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) {}
Steven Moreland48548e02019-09-18 15:10:22 -070052 std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type) {
53 auto v = std::make_shared<Variable>(JavaSignatureOf(type),
54 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_;
66
67 DISALLOW_COPY_AND_ASSIGN(VariableFactory);
68};
69
70// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -080071class StubClass : public Class {
72 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +090073 StubClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -070074 ~StubClass() override = default;
Adam Lesinskiffa16862014-01-23 18:17:42 -080075
Steven Moreland48548e02019-09-18 15:10:22 -070076 std::shared_ptr<Variable> transact_code;
77 std::shared_ptr<Variable> transact_data;
78 std::shared_ptr<Variable> transact_reply;
79 std::shared_ptr<Variable> transact_flags;
80 std::shared_ptr<SwitchStatement> transact_switch;
81 std::shared_ptr<StatementBlock> transact_statements;
82 std::shared_ptr<SwitchStatement> code_to_method_name_switch;
Christopher Wiley8b2d3ee2015-09-23 15:43:01 -070083
Andreas Gampe1b865af2017-11-22 11:31:47 -080084 // Where onTransact cases should be generated as separate methods.
85 bool transact_outline;
Andreas Gampee9c816e2018-03-14 09:05:48 -070086 // Specific methods that should be outlined when transact_outline is true.
87 std::unordered_set<const AidlMethod*> outline_methods;
88 // Number of all methods.
89 size_t all_method_count;
Andreas Gampe1b865af2017-11-22 11:31:47 -080090
Andreas Gampea8a66fe2017-11-22 12:17:00 -080091 // Finish generation. This will add a default case to the switch.
92 void finish();
93
Steven Moreland48548e02019-09-18 15:10:22 -070094 std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
Andreas Gampe7fab0d12017-11-22 17:50:17 -080095
Christopher Wiley67502f12016-01-29 10:57:00 -080096 private:
Jeongik Chaa2080bf2019-06-18 16:44:29 +090097 void make_as_interface(const AidlInterface* interfaceType);
Christopher Wiley67502f12016-01-29 10:57:00 -080098
Steven Moreland48548e02019-09-18 15:10:22 -070099 std::shared_ptr<Variable> transact_descriptor;
Jiyong Park74595c12018-07-23 15:22:50 +0900100 const Options& options_;
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800101
Christopher Wiley67502f12016-01-29 10:57:00 -0800102 DISALLOW_COPY_AND_ASSIGN(StubClass);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800103};
104
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900105StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
Olivier Gaillard11401402018-07-05 15:01:34 +0100106 : Class(), options_(options) {
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800107 transact_descriptor = nullptr;
Andreas Gampe1b865af2017-11-22 11:31:47 -0800108 transact_outline = false;
Andreas Gampee9c816e2018-03-14 09:05:48 -0700109 all_method_count = 0; // Will be set when outlining may be enabled.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800110
Christopher Wiley67502f12016-01-29 10:57:00 -0800111 this->comment = "/** Local-side IPC implementation stub class. */";
112 this->modifiers = PUBLIC | ABSTRACT | STATIC;
113 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900114 this->type = interfaceType->GetCanonicalName() + ".Stub";
115 this->extends = "android.os.Binder";
116 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800117
Christopher Wiley67502f12016-01-29 10:57:00 -0800118 // descriptor
Steven Moreland48548e02019-09-18 15:10:22 -0700119 auto descriptor = std::make_shared<Field>(
120 STATIC | FINAL | PRIVATE, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900121 descriptor->value = "\"" + interfaceType->GetCanonicalName() + "\"";
Christopher Wiley67502f12016-01-29 10:57:00 -0800122 this->elements.push_back(descriptor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800123
Christopher Wiley67502f12016-01-29 10:57:00 -0800124 // ctor
Steven Moreland48548e02019-09-18 15:10:22 -0700125 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800126 ctor->modifiers = PUBLIC;
127 ctor->comment =
128 "/** Construct the stub at attach it to the "
129 "interface. */";
130 ctor->name = "Stub";
Steven Moreland48548e02019-09-18 15:10:22 -0700131 ctor->statements = std::make_shared<StatementBlock>();
132 auto attach = std::make_shared<MethodCall>(
133 THIS_VALUE, "attachInterface",
134 std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
135 std::make_shared<LiteralExpression>("DESCRIPTOR")});
Christopher Wiley67502f12016-01-29 10:57:00 -0800136 ctor->statements->Add(attach);
137 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800138
Christopher Wiley67502f12016-01-29 10:57:00 -0800139 // asInterface
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900140 make_as_interface(interfaceType);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800141
Christopher Wiley67502f12016-01-29 10:57:00 -0800142 // asBinder
Steven Moreland48548e02019-09-18 15:10:22 -0700143 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800144 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900145 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800146 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700147 asBinder->statements = std::make_shared<StatementBlock>();
148 asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800149 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800150
Jiyong Park74595c12018-07-23 15:22:50 +0900151 if (options_.GenTransactionNames()) {
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100152 // getDefaultTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700153 auto getDefaultTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900154 getDefaultTransactionName->comment = "/** @hide */";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100155 getDefaultTransactionName->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900156 getDefaultTransactionName->returnType = "java.lang.String";
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100157 getDefaultTransactionName->name = "getDefaultTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700158 auto code = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100159 getDefaultTransactionName->parameters.push_back(code);
Steven Moreland48548e02019-09-18 15:10:22 -0700160 getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
161 this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100162 getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
163 this->elements.push_back(getDefaultTransactionName);
164
165 // getTransactionName
Steven Moreland48548e02019-09-18 15:10:22 -0700166 auto getTransactionName = std::make_shared<Method>();
Jiyong Parke0b28032019-04-10 03:08:41 +0900167 getTransactionName->comment = "/** @hide */";
Olivier Gaillard11401402018-07-05 15:01:34 +0100168 getTransactionName->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900169 getTransactionName->returnType = "java.lang.String";
Olivier Gaillard11401402018-07-05 15:01:34 +0100170 getTransactionName->name = "getTransactionName";
Steven Moreland48548e02019-09-18 15:10:22 -0700171 auto code2 = std::make_shared<Variable>("int", "transactionCode");
Olivier Gaillard83d7cd32018-07-30 16:20:57 +0100172 getTransactionName->parameters.push_back(code2);
Steven Moreland48548e02019-09-18 15:10:22 -0700173 getTransactionName->statements = std::make_shared<StatementBlock>();
174 getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
175 std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
176 std::vector<std::shared_ptr<Expression>>{code2})));
Olivier Gaillard11401402018-07-05 15:01:34 +0100177 this->elements.push_back(getTransactionName);
178 }
179
Christopher Wiley67502f12016-01-29 10:57:00 -0800180 // onTransact
Steven Moreland48548e02019-09-18 15:10:22 -0700181 this->transact_code = std::make_shared<Variable>("int", "code");
182 this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
183 this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
184 this->transact_flags = std::make_shared<Variable>("int", "flags");
185 auto onTransact = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800186 onTransact->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900187 onTransact->returnType = "boolean";
Christopher Wiley67502f12016-01-29 10:57:00 -0800188 onTransact->name = "onTransact";
189 onTransact->parameters.push_back(this->transact_code);
190 onTransact->parameters.push_back(this->transact_data);
191 onTransact->parameters.push_back(this->transact_reply);
192 onTransact->parameters.push_back(this->transact_flags);
Steven Moreland48548e02019-09-18 15:10:22 -0700193 onTransact->statements = std::make_shared<StatementBlock>();
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800194 transact_statements = onTransact->statements;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900195 onTransact->exceptions.push_back("android.os.RemoteException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800196 this->elements.push_back(onTransact);
Steven Moreland48548e02019-09-18 15:10:22 -0700197 this->transact_switch = std::make_shared<SwitchStatement>(this->transact_code);
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800198}
199
200void StubClass::finish() {
Steven Moreland48548e02019-09-18 15:10:22 -0700201 auto default_case = std::make_shared<Case>();
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800202
Steven Moreland48548e02019-09-18 15:10:22 -0700203 auto superCall = std::make_shared<MethodCall>(
204 SUPER_VALUE, "onTransact",
205 std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
206 this->transact_reply, this->transact_flags});
207 default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
Andreas Gampea8a66fe2017-11-22 12:17:00 -0800208 transact_switch->cases.push_back(default_case);
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800209
210 transact_statements->Add(this->transact_switch);
Olivier Gaillard11401402018-07-05 15:01:34 +0100211
212 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900213 if (options_.GenTransactionNames()) {
Olivier Gaillard11401402018-07-05 15:01:34 +0100214 // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
215 // Common transaction codes will not be resolved to a string by getTransactionName. The method
216 // will return NULL in this case.
Steven Moreland48548e02019-09-18 15:10:22 -0700217 auto code_switch_default_case = std::make_shared<Case>();
218 code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Olivier Gaillard11401402018-07-05 15:01:34 +0100219 this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
220 }
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800221}
222
Andreas Gampee9c816e2018-03-14 09:05:48 -0700223// The the expression for the interface's descriptor to be used when
224// generating code for the given method. Null is acceptable for method
225// and stands for synthetic cases.
Steven Moreland48548e02019-09-18 15:10:22 -0700226std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
Andreas Gampe1b865af2017-11-22 11:31:47 -0800227 if (transact_outline) {
Andreas Gampee9c816e2018-03-14 09:05:48 -0700228 if (method != nullptr) {
229 // When outlining, each outlined method needs its own literal.
230 if (outline_methods.count(method) != 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700231 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700232 }
233 } else {
234 // Synthetic case. A small number is assumed. Use its own descriptor
235 // if there are only synthetic cases.
236 if (outline_methods.size() == all_method_count) {
Steven Moreland48548e02019-09-18 15:10:22 -0700237 return std::make_shared<LiteralExpression>("DESCRIPTOR");
Andreas Gampee9c816e2018-03-14 09:05:48 -0700238 }
239 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800240 }
241
Andreas Gampee9c816e2018-03-14 09:05:48 -0700242 // When not outlining, store the descriptor literal into a local variable, in
243 // an effort to save const-string instructions in each switch case.
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800244 if (transact_descriptor == nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700245 transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
246 transact_statements->Add(std::make_shared<VariableDeclaration>(
247 transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
Andreas Gampe7fab0d12017-11-22 17:50:17 -0800248 }
249 return transact_descriptor;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800250}
251
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900252void StubClass::make_as_interface(const AidlInterface* interfaceType) {
Steven Moreland48548e02019-09-18 15:10:22 -0700253 auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
Christopher Wiley67502f12016-01-29 10:57:00 -0800254
Steven Moreland48548e02019-09-18 15:10:22 -0700255 auto m = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800256 m->comment = "/**\n * Cast an IBinder object into an ";
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900257 m->comment += interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800258 m->comment += " interface,\n";
259 m->comment += " * generating a proxy if needed.\n */";
260 m->modifiers = PUBLIC | STATIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900261 m->returnType = interfaceType->GetCanonicalName();
Christopher Wiley67502f12016-01-29 10:57:00 -0800262 m->name = "asInterface";
263 m->parameters.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700264 m->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800265
Steven Moreland48548e02019-09-18 15:10:22 -0700266 auto ifstatement = std::make_shared<IfStatement>();
267 ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
268 ifstatement->statements = std::make_shared<StatementBlock>();
269 ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800270 m->statements->Add(ifstatement);
271
272 // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
Steven Moreland48548e02019-09-18 15:10:22 -0700273 auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
274 queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
275 auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
276 auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
Christopher Wiley67502f12016-01-29 10:57:00 -0800277 m->statements->Add(iinVd);
278
279 // Ensure the instance type of the local object is as expected.
280 // One scenario where this is needed is if another package (with a
281 // different class loader) runs in the same process as the service.
282
283 // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
284 // iin;
Steven Moreland48548e02019-09-18 15:10:22 -0700285 auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
286 auto instOfCheck = std::make_shared<Comparison>(
287 iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
288 auto instOfStatement = std::make_shared<IfStatement>();
289 instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
290 instOfStatement->statements = std::make_shared<StatementBlock>();
291 instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
292 std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800293 m->statements->Add(instOfStatement);
294
Steven Moreland48548e02019-09-18 15:10:22 -0700295 auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
Christopher Wiley67502f12016-01-29 10:57:00 -0800296 ne->arguments.push_back(obj);
Steven Moreland48548e02019-09-18 15:10:22 -0700297 m->statements->Add(std::make_shared<ReturnStatement>(ne));
Christopher Wiley67502f12016-01-29 10:57:00 -0800298
299 this->elements.push_back(m);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800300}
301
Adam Lesinskiffa16862014-01-23 18:17:42 -0800302// =================================================
Christopher Wiley67502f12016-01-29 10:57:00 -0800303class ProxyClass : public Class {
304 public:
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900305 ProxyClass(const AidlInterface* interfaceType, const Options& options);
Yi Kongde138912019-03-30 01:38:17 -0700306 ~ProxyClass() override;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800307
Steven Moreland48548e02019-09-18 15:10:22 -0700308 std::shared_ptr<Variable> mRemote;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800309};
310
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900311ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
Christopher Wiley67502f12016-01-29 10:57:00 -0800312 this->modifiers = PRIVATE | STATIC;
313 this->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900314 this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
315 this->interfaces.push_back(interfaceType->GetCanonicalName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800316
Christopher Wiley67502f12016-01-29 10:57:00 -0800317 // IBinder mRemote
Steven Moreland48548e02019-09-18 15:10:22 -0700318 mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
319 this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800320
Christopher Wiley67502f12016-01-29 10:57:00 -0800321 // Proxy()
Steven Moreland48548e02019-09-18 15:10:22 -0700322 auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
323 auto ctor = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800324 ctor->name = "Proxy";
Steven Moreland48548e02019-09-18 15:10:22 -0700325 ctor->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800326 ctor->parameters.push_back(remote);
Steven Moreland48548e02019-09-18 15:10:22 -0700327 ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800328 this->elements.push_back(ctor);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800329
Jiyong Park309668e2018-07-28 16:55:44 +0900330 if (options.Version() > 0) {
331 std::ostringstream code;
332 code << "private int mCachedVersion = -1;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700333 this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900334 }
335
Christopher Wiley67502f12016-01-29 10:57:00 -0800336 // IBinder asBinder()
Steven Moreland48548e02019-09-18 15:10:22 -0700337 auto asBinder = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800338 asBinder->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900339 asBinder->returnType = "android.os.IBinder";
Christopher Wiley67502f12016-01-29 10:57:00 -0800340 asBinder->name = "asBinder";
Steven Moreland48548e02019-09-18 15:10:22 -0700341 asBinder->statements = std::make_shared<StatementBlock>();
342 asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
Christopher Wiley67502f12016-01-29 10:57:00 -0800343 this->elements.push_back(asBinder);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800344}
345
Christopher Wiley67502f12016-01-29 10:57:00 -0800346ProxyClass::~ProxyClass() {}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800347
348// =================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700349static void generate_new_array(const AidlTypeSpecifier& type, std::shared_ptr<StatementBlock> addTo,
350 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel) {
351 auto len = std::make_shared<Variable>("int", v->name + "_length");
352 addTo->Add(
353 std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
354 auto lencheck = std::make_shared<IfStatement>();
355 lencheck->expression =
356 std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
357 lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
358 lencheck->elseif = std::make_shared<IfStatement>();
359 lencheck->elseif->statements->Add(std::make_shared<Assignment>(
360 v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type), len)));
Christopher Wiley67502f12016-01-29 10:57:00 -0800361 addTo->Add(lencheck);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800362}
363
Steven Moreland48548e02019-09-18 15:10:22 -0700364static void generate_write_to_parcel(const AidlTypeSpecifier& type,
365 std::shared_ptr<StatementBlock> addTo,
366 std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
367 bool is_return_value, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900368 string code;
369 CodeWriterPtr writer = CodeWriter::ForString(&code);
370 CodeGeneratorContext context{
371 .writer = *(writer.get()),
372 .typenames = typenames,
373 .type = type,
374 .var = v->name,
375 .parcel = parcel->name,
376 .is_return_value = is_return_value,
377 };
378 WriteToParcelFor(context);
379 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700380 addTo->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800381}
382
Steven Moreland693640b2018-07-19 13:46:27 -0700383static void generate_int_constant(Class* interface, const std::string& name,
384 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900385 auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
Steven Moreland48548e02019-09-18 15:10:22 -0700386 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700387}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800388
Steven Moreland693640b2018-07-19 13:46:27 -0700389static void generate_string_constant(Class* interface, const std::string& name,
390 const std::string& value) {
Jeongik Chade157cc2019-02-12 12:41:27 +0900391 auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
Steven Moreland48548e02019-09-18 15:10:22 -0700392 interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800393}
394
Steven Moreland48548e02019-09-18 15:10:22 -0700395static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method) {
396 auto decl = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800397 decl->comment = method.GetComments();
398 decl->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900399 decl->returnType = JavaSignatureOf(method.GetType());
Christopher Wiley67502f12016-01-29 10:57:00 -0800400 decl->name = method.GetName();
Jiyong Parka6605ab2018-11-11 14:30:21 +0900401 decl->annotations = generate_java_annotations(method.GetType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800402
Christopher Wiley67502f12016-01-29 10:57:00 -0800403 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700404 decl->parameters.push_back(
405 std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
Christopher Wiley67502f12016-01-29 10:57:00 -0800406 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800407
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900408 decl->exceptions.push_back("android.os.RemoteException");
Adam Lesinskiffa16862014-01-23 18:17:42 -0800409
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800410 return decl;
411}
Adam Lesinskiffa16862014-01-23 18:17:42 -0800412
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900413static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
Steven Moreland48548e02019-09-18 15:10:22 -0700414 std::shared_ptr<Variable> transact_data,
415 std::shared_ptr<Variable> transact_reply,
416 const AidlTypenames& typenames,
417 std::shared_ptr<StatementBlock> statements,
418 std::shared_ptr<StubClass> stubClass, const Options& options) {
419 std::shared_ptr<TryStatement> tryStatement;
420 std::shared_ptr<FinallyStatement> finallyStatement;
421 auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800422
Christopher Wiley67502f12016-01-29 10:57:00 -0800423 // interface token validation is the very first thing we do
Steven Moreland48548e02019-09-18 15:10:22 -0700424 statements->Add(std::make_shared<MethodCall>(
425 transact_data, "enforceInterface",
426 std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800427
Christopher Wiley67502f12016-01-29 10:57:00 -0800428 // args
Christopher Wiley67502f12016-01-29 10:57:00 -0800429 VariableFactory stubArgs("_arg");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800430 {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900431 // keep this across different args in order to create the classloader
432 // at most once.
433 bool is_classloader_created = false;
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800434 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700435 std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800436
Steven Moreland48548e02019-09-18 15:10:22 -0700437 statements->Add(std::make_shared<VariableDeclaration>(v));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800438
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800439 if (arg->GetDirection() & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900440 string code;
441 CodeWriterPtr writer = CodeWriter::ForString(&code);
442 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900443 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900444 .type = arg->GetType(),
445 .var = v->name,
446 .parcel = transact_data->name,
447 .is_classloader_created = &is_classloader_created};
448 CreateFromParcelFor(context);
449 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700450 statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800451 } else {
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800452 if (!arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700453 statements->Add(std::make_shared<Assignment>(
454 v, std::make_shared<NewExpression>(InstantiableJavaSignatureOf(arg->GetType()))));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800455 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900456 generate_new_array(arg->GetType(), statements, v, transact_data);
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800457 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800458 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800459
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800460 realCall->arguments.push_back(v);
461 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800462 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800463
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900464 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100465 // try and finally, but only when generating trace code
Steven Moreland48548e02019-09-18 15:10:22 -0700466 tryStatement = std::make_shared<TryStatement>();
467 finallyStatement = std::make_shared<FinallyStatement>();
Martijn Coenenf1b50782018-02-21 21:06:23 +0100468
Steven Moreland48548e02019-09-18 15:10:22 -0700469 tryStatement->statements->Add(std::make_shared<MethodCall>(
470 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
471 std::vector<std::shared_ptr<Expression>>{
472 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
473 std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
474 "::server")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100475
Steven Moreland48548e02019-09-18 15:10:22 -0700476 finallyStatement->statements->Add(std::make_shared<MethodCall>(
477 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
478 std::vector<std::shared_ptr<Expression>>{
479 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100480 }
481
Christopher Wiley67502f12016-01-29 10:57:00 -0800482 // the real call
Christopher Wiley67502f12016-01-29 10:57:00 -0800483 if (method.GetType().GetName() == "void") {
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900484 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100485 statements->Add(tryStatement);
486 tryStatement->statements->Add(realCall);
487 statements->Add(finallyStatement);
488 } else {
489 statements->Add(realCall);
490 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800491
Adam Lesinskiffa16862014-01-23 18:17:42 -0800492 if (!oneway) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800493 // report that there were no exceptions
Steven Moreland48548e02019-09-18 15:10:22 -0700494 auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800495 statements->Add(ex);
Christopher Wiley67502f12016-01-29 10:57:00 -0800496 }
497 } else {
Steven Moreland48548e02019-09-18 15:10:22 -0700498 auto _result = std::make_shared<Variable>(JavaSignatureOf(method.GetType()), "_result");
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900499 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700500 statements->Add(std::make_shared<VariableDeclaration>(_result));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100501 statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700502 tryStatement->statements->Add(std::make_shared<Assignment>(_result, realCall));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100503 statements->Add(finallyStatement);
504 } else {
Steven Moreland48548e02019-09-18 15:10:22 -0700505 statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100506 }
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
542 stubClass->transact_switch->cases.push_back(c);
543}
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
578 stubClass->transact_switch->cases.push_back(c);
579 }
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>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800587 proxy->comment = method.GetComments();
588 proxy->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900589 proxy->returnType = JavaSignatureOf(method.GetType());
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(
594 std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), 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")));
602 std::shared_ptr<Variable> _reply = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800603 if (!oneway) {
Steven Moreland48548e02019-09-18 15:10:22 -0700604 _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
605 proxy->statements->Add(std::make_shared<VariableDeclaration>(
606 _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800607 }
608
609 // the return value
Steven Moreland48548e02019-09-18 15:10:22 -0700610 std::shared_ptr<Variable> _result = nullptr;
Christopher Wiley67502f12016-01-29 10:57:00 -0800611 if (method.GetType().GetName() != "void") {
Steven Moreland48548e02019-09-18 15:10:22 -0700612 _result = std::make_shared<Variable>(*proxy->returnType, "_result");
613 proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800614 }
615
616 // try and finally
Steven Moreland48548e02019-09-18 15:10:22 -0700617 auto tryStatement = std::make_shared<TryStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800618 proxy->statements->Add(tryStatement);
Steven Moreland48548e02019-09-18 15:10:22 -0700619 auto finallyStatement = std::make_shared<FinallyStatement>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800620 proxy->statements->Add(finallyStatement);
621
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900622 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700623 tryStatement->statements->Add(std::make_shared<MethodCall>(
624 std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
625 std::vector<std::shared_ptr<Expression>>{
626 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
627 std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
628 "::client")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100629 }
630
Christopher Wiley67502f12016-01-29 10:57:00 -0800631 // the interface identifier token: the DESCRIPTOR constant, marshalled as a
632 // string
Steven Moreland48548e02019-09-18 15:10:22 -0700633 tryStatement->statements->Add(std::make_shared<MethodCall>(
634 _data, "writeInterfaceToken",
635 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800636
637 // the parameters
638 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700639 auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName());
Christopher Wiley67502f12016-01-29 10:57:00 -0800640 AidlArgument::Direction dir = arg->GetDirection();
641 if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700642 auto checklen = std::make_shared<IfStatement>();
643 checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
644 checklen->statements->Add(std::make_shared<MethodCall>(
645 _data, "writeInt",
646 std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
647 checklen->elseif = std::make_shared<IfStatement>();
648 checklen->elseif->statements->Add(std::make_shared<MethodCall>(
649 _data, "writeInt",
650 std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
Christopher Wiley67502f12016-01-29 10:57:00 -0800651 tryStatement->statements->Add(checklen);
652 } else if (dir & AidlArgument::IN_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900653 generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900654 typenames);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800655 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800656 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800657
Christopher Wiley67502f12016-01-29 10:57:00 -0800658 // the transact call
Steven Moreland48548e02019-09-18 15:10:22 -0700659 auto call = std::make_shared<MethodCall>(
660 proxyClass->mRemote, "transact",
661 std::vector<std::shared_ptr<Expression>>{
662 std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
663 _reply ? _reply : NULL_VALUE,
664 std::make_shared<LiteralExpression>(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")});
665 auto _status = std::make_shared<Variable>("boolean", "_status");
666 tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
Jiyong Park75e1a742018-07-04 12:31:23 +0900667
668 // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
669 // back to the local method in the default impl, if set before.
670 vector<string> arg_names;
671 for (const auto& arg : method.GetArguments()) {
672 arg_names.emplace_back(arg->GetName());
673 }
674 bool has_return_type = method.GetType().GetName() != "void";
Steven Moreland48548e02019-09-18 15:10:22 -0700675 tryStatement->statements->Add(std::make_shared<LiteralStatement>(
Jiyong Park75e1a742018-07-04 12:31:23 +0900676 android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
677 " return getDefaultImpl().%s(%s);\n"
678 "}\n"
679 : "if (!_status && getDefaultImpl() != null) {\n"
680 " getDefaultImpl().%s(%s);\n"
681 " return;\n"
682 "}\n",
683 method.GetName().c_str(), Join(arg_names, ", ").c_str())));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800684
Christopher Wiley67502f12016-01-29 10:57:00 -0800685 // throw back exceptions.
686 if (_reply) {
Steven Moreland48548e02019-09-18 15:10:22 -0700687 auto ex = std::make_shared<MethodCall>(_reply, "readException");
Christopher Wiley67502f12016-01-29 10:57:00 -0800688 tryStatement->statements->Add(ex);
689 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800690
Christopher Wiley67502f12016-01-29 10:57:00 -0800691 // returning and cleanup
Yi Kong894d6ba2018-07-24 11:27:38 -0700692 if (_reply != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900693 // keep this across return value and arguments in order to create the
694 // classloader at most once.
695 bool is_classloader_created = false;
Yi Kong894d6ba2018-07-24 11:27:38 -0700696 if (_result != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900697 string code;
698 CodeWriterPtr writer = CodeWriter::ForString(&code);
699 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900700 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900701 .type = method.GetType(),
702 .var = _result->name,
703 .parcel = _reply->name,
704 .is_classloader_created = &is_classloader_created};
705 CreateFromParcelFor(context);
706 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700707 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800708 }
Christopher Wiley67502f12016-01-29 10:57:00 -0800709
710 // the out/inout parameters
711 for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800712 if (arg->GetDirection() & AidlArgument::OUT_DIR) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900713 string code;
714 CodeWriterPtr writer = CodeWriter::ForString(&code);
715 CodeGeneratorContext context{.writer = *(writer.get()),
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900716 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900717 .type = arg->GetType(),
718 .var = arg->GetName(),
719 .parcel = _reply->name,
720 .is_classloader_created = &is_classloader_created};
721 ReadFromParcelFor(context);
722 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700723 tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
Christopher Wiley67502f12016-01-29 10:57:00 -0800724 }
725 }
726
Steven Moreland48548e02019-09-18 15:10:22 -0700727 finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800728 }
Steven Moreland48548e02019-09-18 15:10:22 -0700729 finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
Christopher Wiley67502f12016-01-29 10:57:00 -0800730
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900731 if (options.GenTraces()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700732 finallyStatement->statements->Add(std::make_shared<MethodCall>(
733 std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
734 std::vector<std::shared_ptr<Expression>>{
735 std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100736 }
737
Yi Kong894d6ba2018-07-24 11:27:38 -0700738 if (_result != nullptr) {
Steven Moreland48548e02019-09-18 15:10:22 -0700739 proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
Christopher Wiley67502f12016-01-29 10:57:00 -0800740 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800741
742 return proxy;
743}
744
Jiyong Park74595c12018-07-23 15:22:50 +0900745static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
Steven Moreland48548e02019-09-18 15:10:22 -0700746 std::shared_ptr<StubClass> stubClass,
747 std::shared_ptr<ProxyClass> proxyClass, int index,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900748 const AidlTypenames& typenames, const Options& options) {
Steven Morelandacd53472018-12-14 10:17:26 -0800749 const bool oneway = method.IsOneway();
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800750
751 // == the TRANSACT_ constant =============================================
752 string transactCodeName = "TRANSACTION_";
753 transactCodeName += method.GetName();
754
Steven Moreland48548e02019-09-18 15:10:22 -0700755 auto transactCode =
756 std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800757 transactCode->value =
758 StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
759 stubClass->elements.push_back(transactCode);
760
Olivier Gaillard11401402018-07-05 15:01:34 +0100761 // getTransactionName
Jiyong Park74595c12018-07-23 15:22:50 +0900762 if (options.GenTransactionNames()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700763 auto c = std::make_shared<Case>(transactCodeName);
764 c->statements->Add(std::make_shared<ReturnStatement>(
765 std::make_shared<StringLiteralExpression>(method.GetName())));
Olivier Gaillard11401402018-07-05 15:01:34 +0100766 stubClass->code_to_method_name_switch->cases.push_back(c);
767 }
768
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800769 // == the declaration in the interface ===================================
Steven Moreland48548e02019-09-18 15:10:22 -0700770 std::shared_ptr<ClassElement> decl;
Jiyong Park309668e2018-07-28 16:55:44 +0900771 if (method.IsUserDefined()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700772 decl = generate_interface_method(method);
Jiyong Park309668e2018-07-28 16:55:44 +0900773 } else {
774 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
775 std::ostringstream code;
776 code << "public int " << kGetInterfaceVersion << "() "
777 << "throws android.os.RemoteException;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700778 decl = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900779 }
780 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800781 interface->elements.push_back(decl);
782
783 // == the stub method ====================================================
Jiyong Park309668e2018-07-28 16:55:44 +0900784 if (method.IsUserDefined()) {
785 bool outline_stub =
786 stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
787 if (outline_stub) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900788 generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
Jiyong Park309668e2018-07-28 16:55:44 +0900789 options);
790 } else {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900791 generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900792 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800793 } else {
Jiyong Park309668e2018-07-28 16:55:44 +0900794 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland48548e02019-09-18 15:10:22 -0700795 auto c = std::make_shared<Case>(transactCodeName);
Jiyong Park309668e2018-07-28 16:55:44 +0900796 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900797 code << "data.enforceInterface(descriptor);\n"
798 << "reply.writeNoException();\n"
799 << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900800 << "return true;\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700801 c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900802 stubClass->transact_switch->cases.push_back(c);
803 }
Andreas Gampe1b865af2017-11-22 11:31:47 -0800804 }
Andreas Gampe7d7fa602017-11-22 10:50:03 -0800805
806 // == the proxy method ===================================================
Steven Moreland48548e02019-09-18 15:10:22 -0700807 std::shared_ptr<ClassElement> proxy = nullptr;
Jiyong Park309668e2018-07-28 16:55:44 +0900808 if (method.IsUserDefined()) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900809 proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
Steven Moreland48548e02019-09-18 15:10:22 -0700810 options);
Jiyong Park309668e2018-07-28 16:55:44 +0900811
812 } else {
813 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
814 std::ostringstream code;
815 code << "@Override\n"
816 << "public int " << kGetInterfaceVersion << "()"
817 << " throws "
818 << "android.os.RemoteException {\n"
819 << " if (mCachedVersion == -1) {\n"
820 << " android.os.Parcel data = android.os.Parcel.obtain();\n"
821 << " android.os.Parcel reply = android.os.Parcel.obtain();\n"
822 << " try {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900823 << " data.writeInterfaceToken(DESCRIPTOR);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900824 << " boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
Jiyong Park309668e2018-07-28 16:55:44 +0900825 << "data, reply, 0);\n"
Jiyong Park6b39de42019-08-27 13:04:57 +0900826 << " if (!_status) {\n"
827 << " if (getDefaultImpl() != null) {\n"
828 << " return getDefaultImpl().getInterfaceVersion();\n"
829 << " }\n"
830 << " }\n"
Jeongik Chaf1470e22019-05-20 18:45:05 +0900831 << " reply.readException();\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900832 << " mCachedVersion = reply.readInt();\n"
833 << " } finally {\n"
834 << " reply.recycle();\n"
835 << " data.recycle();\n"
836 << " }\n"
837 << " }\n"
838 << " return mCachedVersion;\n"
839 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700840 proxy = std::make_shared<LiteralClassElement>(code.str());
Jiyong Park309668e2018-07-28 16:55:44 +0900841 }
842 }
843 if (proxy != nullptr) {
844 proxyClass->elements.push_back(proxy);
845 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800846}
847
Steven Moreland48548e02019-09-18 15:10:22 -0700848static void generate_interface_descriptors(std::shared_ptr<StubClass> stub,
849 std::shared_ptr<ProxyClass> proxy) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800850 // the interface descriptor transaction handler
Steven Moreland48548e02019-09-18 15:10:22 -0700851 auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
852 c->statements->Add(std::make_shared<MethodCall>(
853 stub->transact_reply, "writeString",
854 std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
855 c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
Christopher Wiley67502f12016-01-29 10:57:00 -0800856 stub->transact_switch->cases.push_back(c);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800857
Christopher Wiley67502f12016-01-29 10:57:00 -0800858 // and the proxy-side method returning the descriptor directly
Steven Moreland48548e02019-09-18 15:10:22 -0700859 auto getDesc = std::make_shared<Method>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800860 getDesc->modifiers = PUBLIC;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900861 getDesc->returnType = "java.lang.String";
Christopher Wiley67502f12016-01-29 10:57:00 -0800862 getDesc->name = "getInterfaceDescriptor";
Steven Moreland48548e02019-09-18 15:10:22 -0700863 getDesc->statements = std::make_shared<StatementBlock>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800864 getDesc->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700865 std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
Christopher Wiley67502f12016-01-29 10:57:00 -0800866 proxy->elements.push_back(getDesc);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800867}
868
Andreas Gampee9c816e2018-03-14 09:05:48 -0700869// Check whether (some) methods in this interface should be "outlined," that
870// is, have specific onTransact methods for certain cases. Set up StubClass
871// metadata accordingly.
872//
873// Outlining will be enabled if the interface has more than outline_threshold
874// methods. In that case, the methods are sorted by number of arguments
875// (so that more "complex" methods come later), and the first non_outline_count
876// number of methods not outlined (are kept in the onTransact() method).
877//
878// Requirements: non_outline_count <= outline_threshold.
879static void compute_outline_methods(const AidlInterface* iface,
Steven Moreland48548e02019-09-18 15:10:22 -0700880 const std::shared_ptr<StubClass> stub, size_t outline_threshold,
Andreas Gampee9c816e2018-03-14 09:05:48 -0700881 size_t non_outline_count) {
882 CHECK_LE(non_outline_count, outline_threshold);
883 // We'll outline (create sub methods) if there are more than min_methods
884 // cases.
885 stub->transact_outline = iface->GetMethods().size() > outline_threshold;
886 if (stub->transact_outline) {
887 stub->all_method_count = iface->GetMethods().size();
888 std::vector<const AidlMethod*> methods;
889 methods.reserve(iface->GetMethods().size());
890 for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
891 methods.push_back(ptr.get());
892 }
893
894 std::stable_sort(
895 methods.begin(),
896 methods.end(),
897 [](const AidlMethod* m1, const AidlMethod* m2) {
898 return m1->GetArguments().size() < m2->GetArguments().size();
899 });
900
901 stub->outline_methods.insert(methods.begin() + non_outline_count,
902 methods.end());
903 }
904}
905
Steven Moreland48548e02019-09-18 15:10:22 -0700906static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method) {
907 auto default_method = std::make_shared<Method>();
Jiyong Park75e1a742018-07-04 12:31:23 +0900908 default_method->comment = method.GetComments();
909 default_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900910 default_method->returnType = JavaSignatureOf(method.GetType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900911 default_method->name = method.GetName();
Steven Moreland48548e02019-09-18 15:10:22 -0700912 default_method->statements = std::make_shared<StatementBlock>();
Jiyong Park75e1a742018-07-04 12:31:23 +0900913 for (const auto& arg : method.GetArguments()) {
Steven Moreland3dc29d82019-08-21 17:23:11 -0700914 default_method->parameters.push_back(
Steven Moreland48548e02019-09-18 15:10:22 -0700915 std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
Jiyong Park75e1a742018-07-04 12:31:23 +0900916 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900917 default_method->exceptions.push_back("android.os.RemoteException");
Jiyong Park75e1a742018-07-04 12:31:23 +0900918
919 if (method.GetType().GetName() != "void") {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900920 const string& defaultValue = DefaultJavaValueOf(method.GetType());
Jiyong Park75e1a742018-07-04 12:31:23 +0900921 default_method->statements->Add(
Steven Moreland48548e02019-09-18 15:10:22 -0700922 std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +0900923 }
924 return default_method;
925}
926
Steven Moreland48548e02019-09-18 15:10:22 -0700927static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
Jiyong Park309668e2018-07-28 16:55:44 +0900928 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700929 auto default_class = std::make_shared<Class>();
Jiyong Park75e1a742018-07-04 12:31:23 +0900930 default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
931 default_class->modifiers = PUBLIC | STATIC;
932 default_class->what = Class::CLASS;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900933 default_class->type = iface.GetCanonicalName() + ".Default";
934 default_class->interfaces.emplace_back(iface.GetCanonicalName());
Jiyong Park75e1a742018-07-04 12:31:23 +0900935
936 for (const auto& m : iface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900937 if (m->IsUserDefined()) {
Steven Moreland48548e02019-09-18 15:10:22 -0700938 default_class->elements.emplace_back(generate_default_impl_method(*m.get()));
Jiyong Park309668e2018-07-28 16:55:44 +0900939 } else {
940 if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900941 // This is called only when the remote side is not implementing this
942 // method, which is impossible in normal case, because this method is
943 // automatically declared in the interface class and not implementing
944 // it in the remote side is causing compilation error. But if the remote
945 // side somehow managed to not implement it, that's an error and we
946 // report the case by returning -1 here.
Jiyong Park309668e2018-07-28 16:55:44 +0900947 std::ostringstream code;
948 code << "@Override\n"
949 << "public int " << kGetInterfaceVersion << "() {\n"
Jiyong Parka2f9ca32018-08-01 21:04:11 +0900950 << " return -1;\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900951 << "}\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700952 default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900953 }
954 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900955 }
956
957 default_class->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -0700958 std::make_shared<LiteralClassElement>("@Override\n"
959 "public android.os.IBinder asBinder() {\n"
960 " return null;\n"
961 "}\n"));
Jiyong Park75e1a742018-07-04 12:31:23 +0900962
963 return default_class;
964}
965
Steven Moreland48548e02019-09-18 15:10:22 -0700966std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
967 const AidlTypenames& typenames,
968 const Options& options) {
Christopher Wiley67502f12016-01-29 10:57:00 -0800969 // the interface class
Steven Moreland48548e02019-09-18 15:10:22 -0700970 auto interface = std::make_unique<Class>();
Christopher Wiley67502f12016-01-29 10:57:00 -0800971 interface->comment = iface->GetComments();
972 interface->modifiers = PUBLIC;
973 interface->what = Class::INTERFACE;
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900974 interface->type = iface->GetCanonicalName();
975 interface->interfaces.push_back("android.os.IInterface");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900976 interface->annotations = generate_java_annotations(*iface);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800977
Jiyong Park309668e2018-07-28 16:55:44 +0900978 if (options.Version()) {
979 std::ostringstream code;
980 code << "/**\n"
981 << " * The version of this interface that the caller is built against.\n"
982 << " * This might be different from what {@link #getInterfaceVersion()\n"
983 << " * getInterfaceVersion} returns as that is the version of the interface\n"
984 << " * that the remote object is implementing.\n"
985 << " */\n"
986 << "public static final int VERSION = " << options.Version() << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700987 interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
Jiyong Park309668e2018-07-28 16:55:44 +0900988 }
989
Jiyong Park75e1a742018-07-04 12:31:23 +0900990 // the default impl class
Steven Moreland48548e02019-09-18 15:10:22 -0700991 auto default_impl = generate_default_impl_class(*iface, options);
Jiyong Park309668e2018-07-28 16:55:44 +0900992 interface->elements.emplace_back(default_impl);
Jiyong Park75e1a742018-07-04 12:31:23 +0900993
Christopher Wiley67502f12016-01-29 10:57:00 -0800994 // the stub inner class
Steven Moreland48548e02019-09-18 15:10:22 -0700995 auto stub = std::make_shared<StubClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -0800996 interface->elements.push_back(stub);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800997
Andreas Gampee9c816e2018-03-14 09:05:48 -0700998 compute_outline_methods(iface,
999 stub,
1000 options.onTransact_outline_threshold_,
1001 options.onTransact_non_outline_count_);
Andreas Gampe1b865af2017-11-22 11:31:47 -08001002
Christopher Wiley67502f12016-01-29 10:57:00 -08001003 // the proxy inner class
Steven Moreland48548e02019-09-18 15:10:22 -07001004 auto proxy = std::make_shared<ProxyClass>(iface, options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001005 stub->elements.push_back(proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001006
Christopher Wiley67502f12016-01-29 10:57:00 -08001007 // stub and proxy support for getInterfaceDescriptor()
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001008 generate_interface_descriptors(stub, proxy);
Adam Lesinskiffa16862014-01-23 18:17:42 -08001009
Christopher Wiley67502f12016-01-29 10:57:00 -08001010 // all the declared constants of the interface
Steven Moreland693640b2018-07-19 13:46:27 -07001011 for (const auto& constant : iface->GetConstantDeclarations()) {
1012 const AidlConstantValue& value = constant->GetValue();
1013
1014 switch (value.GetType()) {
1015 case AidlConstantValue::Type::STRING: {
Steven Moreland48548e02019-09-18 15:10:22 -07001016 generate_string_constant(interface.get(), constant->GetName(),
Steven Moreland860b1942018-08-16 14:59:28 -07001017 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001018 break;
1019 }
Steven Moreland25294322018-08-07 18:13:55 -07001020 case AidlConstantValue::Type::INTEGRAL:
1021 case AidlConstantValue::Type::HEXIDECIMAL: {
Steven Moreland48548e02019-09-18 15:10:22 -07001022 generate_int_constant(interface.get(), constant->GetName(),
Steven Moreland860b1942018-08-16 14:59:28 -07001023 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -07001024 break;
1025 }
1026 default: {
1027 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1028 }
1029 }
Christopher Wiley67502f12016-01-29 10:57:00 -08001030 }
Casey Dahlind40e2fe2015-11-24 14:06:52 -08001031
Christopher Wiley67502f12016-01-29 10:57:00 -08001032 // all the declared methods of the interface
Andreas Gampe1b865af2017-11-22 11:31:47 -08001033
Christopher Wiley67502f12016-01-29 10:57:00 -08001034 for (const auto& item : iface->GetMethods()) {
Steven Moreland48548e02019-09-18 15:10:22 -07001035 generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1036 options);
Christopher Wiley67502f12016-01-29 10:57:00 -08001037 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001038
1039 // additional static methods for the default impl set/get to the
1040 // stub class. Can't add them to the interface as the generated java files
1041 // may be compiled with Java < 1.7 where static interface method isn't
1042 // supported.
1043 // TODO(b/111417145) make this conditional depending on the Java language
1044 // version requested
Jeongik Chaa2080bf2019-06-18 16:44:29 +09001045 const string i_name = iface->GetCanonicalName();
Steven Moreland48548e02019-09-18 15:10:22 -07001046 stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park75e1a742018-07-04 12:31:23 +09001047 StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1048 " if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
1049 " Stub.Proxy.sDefaultImpl = impl;\n"
1050 " return true;\n"
1051 " }\n"
1052 " return false;\n"
1053 "}\n",
1054 i_name.c_str())));
1055 stub->elements.emplace_back(
Steven Moreland48548e02019-09-18 15:10:22 -07001056 std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1057 " return Stub.Proxy.sDefaultImpl;\n"
1058 "}\n",
1059 i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001060
1061 // the static field is defined in the proxy class, not in the interface class
1062 // because all fields in an interface class are by default final.
Steven Moreland48548e02019-09-18 15:10:22 -07001063 proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
Jiyong Park47fb0d62018-11-17 10:12:15 +09001064 StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
Jiyong Park75e1a742018-07-04 12:31:23 +09001065
Andreas Gampea8a66fe2017-11-22 12:17:00 -08001066 stub->finish();
Adam Lesinskiffa16862014-01-23 18:17:42 -08001067
Christopher Wiley67502f12016-01-29 10:57:00 -08001068 return interface;
Adam Lesinskiffa16862014-01-23 18:17:42 -08001069}
1070
Christopher Wileydb154a52015-09-28 16:32:25 -07001071} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001072} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001073} // namespace android