blob: f3b7a9375181a0343f2dadfc7a04dd7a690520ef [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
Adam Lesinskiffa16862014-01-23 18:17:42 -080017#include "generate_java.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070018
Adam Lesinskiffa16862014-01-23 18:17:42 -080019#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
Jeongik Cha91180252020-07-31 15:43:11 +090022
23#include <algorithm>
Andrei Onea9445fc62019-06-27 18:11:59 +010024#include <map>
Steven Moreland5557f1c2018-07-02 13:50:23 -070025#include <memory>
Jooyung Hand2fa0232020-10-19 02:51:41 +090026#include <optional>
Steven Moreland5557f1c2018-07-02 13:50:23 -070027#include <sstream>
Adam Lesinskiffa16862014-01-23 18:17:42 -080028
Jooyung Hand2fa0232020-10-19 02:51:41 +090029#include <android-base/format.h>
Christopher Wiley3a9da172016-01-29 11:10:49 -080030#include <android-base/stringprintf.h>
31
Jiyong Park1d2df7d2018-07-23 15:22:50 +090032#include "aidl_to_java.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070033#include "code_writer.h"
Jeongik Chaa2080bf2019-06-18 16:44:29 +090034#include "logging.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070035
Jooyung Han2946afc2020-10-05 20:29:16 +090036using ::android::base::EndsWith;
37using ::android::base::Join;
38using ::android::base::StartsWith;
Christopher Wiley3a9da172016-01-29 11:10:49 -080039using std::string;
Jooyung Han2946afc2020-10-05 20:29:16 +090040using std::unique_ptr;
Jooyung Hand2fa0232020-10-19 02:51:41 +090041using std::vector;
Christopher Wileydb154a52015-09-28 16:32:25 -070042
Jeongik Cha91180252020-07-31 15:43:11 +090043namespace {
Jooyung Han90345002020-10-23 15:28:53 +090044using android::aidl::java::CodeGeneratorContext;
45using android::aidl::java::ConstantValueDecorator;
46
Jooyung Han2946afc2020-10-05 20:29:16 +090047inline string getter_name(const AidlVariableDeclaration& variable) {
Jooyung Hanacae85d2020-10-28 16:39:09 +090048 return "get" + variable.GetCapitalizedName();
Jooyung Han2946afc2020-10-05 20:29:16 +090049}
50inline string setter_name(const AidlVariableDeclaration& variable) {
Jooyung Hanacae85d2020-10-28 16:39:09 +090051 return "set" + variable.GetCapitalizedName();
Jeongik Cha91180252020-07-31 15:43:11 +090052}
Jooyung Hand2fa0232020-10-19 02:51:41 +090053
Jooyung Hanea2147c2020-10-21 18:16:56 +090054// clang-format off
55const map<string, string> contents_describers {
56 {"FileDescriptor", R"(if (_v instanceof java.io.FileDescriptor) {
57 return android.os.Parcelable.CONTENTS_FILE_DESCRIPTOR;
58})"},
59 {"Parcelable", R"(if (_v instanceof android.os.Parcelable) {
60 return ((android.os.Parcelable) _v).describeContents();
61})"},
62 {"Map", R"(if (_v instanceof java.util.Map) {
63 return describeContents(((java.util.Map) _v).values());
64})"},
65 {"List", R"(if (_v instanceof java.util.Collection) {
66 int _mask = 0;
67 for (Object o : (java.util.Collection) _v) {
68 _mask |= describeContents(o);
69 }
70 return _mask;
71})"},
Jooyung Hanea2147c2020-10-21 18:16:56 +090072 {"Array", R"(Class<?> _clazz = _v.getClass();
73if (_clazz.isArray() && _clazz.getComponentType() == Object.class) {
74 int _mask = 0;
75 for (Object o : (Object[]) _v) {
76 _mask |= describeContents(o);
77 }
78 return _mask;
79})"},
80};
81// clang-format on
82
83void GenerateDescribeContentsHelper(CodeWriter& out, const set<string>& describers) {
84 out << "private int describeContents(Object _v) {\n";
85 out.Indent();
86 out << "if (_v == null) return 0;\n";
87 for (const auto& d : describers) {
88 out << contents_describers.at(d) << "\n";
89 }
90 out << "return 0;\n";
91 out.Dedent();
92 out << "}\n";
93}
94
Jooyung Hand2fa0232020-10-19 02:51:41 +090095// Some types contribute to Parcelable.describeContents().
96// e.g. FileDescriptor, Parcelables, List<Parcelables> ...
Jooyung Hanea2147c2020-10-21 18:16:56 +090097bool CanDescribeContents(const AidlTypeSpecifier& type, const AidlTypenames& types,
98 set<string>* describers) {
Jooyung Hanea2147c2020-10-21 18:16:56 +090099 if (type.IsArray()) {
100 if (CanDescribeContents(type.ArrayBase(), types, describers)) {
101 describers->insert("Array");
102 return true;
103 }
104 return false;
105 }
106
107 if (type.GetName() == "List") {
108 if (CanDescribeContents(*type.GetTypeParameters()[0], types, describers)) {
109 describers->insert("List");
110 return true;
111 }
112 return false;
Jooyung Hand2fa0232020-10-19 02:51:41 +0900113 }
114
115 if (type.GetName() == "Map") {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900116 if (CanDescribeContents(*type.GetTypeParameters()[1], types, describers)) {
117 describers->insert("Map"); // Map describer uses List describer
118 describers->insert("List");
119 return true;
Jooyung Hand2fa0232020-10-19 02:51:41 +0900120 }
Jooyung Hanea2147c2020-10-21 18:16:56 +0900121 return false;
Jooyung Hand2fa0232020-10-19 02:51:41 +0900122 }
123
124 if (type.GetName() == "FileDescriptor") {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900125 describers->insert("FileDescriptor");
126 return true;
Jooyung Hand2fa0232020-10-19 02:51:41 +0900127 }
128
129 if (type.GetName() == "ParcelFileDescriptor" || type.GetName() == "ParcelableHolder" ||
130 types.GetParcelable(type) != nullptr) {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900131 describers->insert("Parcelable");
132 return true;
Jooyung Hand2fa0232020-10-19 02:51:41 +0900133 }
134
Jooyung Hanea2147c2020-10-21 18:16:56 +0900135 return false;
Jooyung Hand2fa0232020-10-19 02:51:41 +0900136}
Jooyung Hand2fa0232020-10-19 02:51:41 +0900137void GenerateParcelableDescribeContents(CodeWriter& out, const AidlStructuredParcelable& decl,
138 const AidlTypenames& types) {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900139 set<string> describers;
140
Jooyung Hand2fa0232020-10-19 02:51:41 +0900141 out << "@Override\n";
142 out << "public int describeContents() {\n";
143 out.Indent();
144 out << "int _mask = 0;\n";
145 for (const auto& f : decl.GetFields()) {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900146 if (CanDescribeContents(f->GetType(), types, &describers)) {
147 out << "_mask |= describeContents(" << f->GetName() << ");\n";
Jooyung Hand2fa0232020-10-19 02:51:41 +0900148 }
149 }
150 out << "return _mask;\n";
151 out.Dedent();
152 out << "}\n";
Jooyung Hanea2147c2020-10-21 18:16:56 +0900153 if (!describers.empty()) {
154 GenerateDescribeContentsHelper(out, describers);
155 }
Jooyung Hand2fa0232020-10-19 02:51:41 +0900156}
157
158void GenerateParcelableDescribeContents(CodeWriter& out, const AidlUnionDecl& decl,
159 const AidlTypenames& types) {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900160 set<string> describers;
161
Jooyung Hand2fa0232020-10-19 02:51:41 +0900162 out << "@Override\n";
163 out << "public int describeContents() {\n";
164 out.Indent();
165 out << "int _mask = 0;\n";
166 out << "switch (getTag()) {\n";
167 for (const auto& f : decl.GetFields()) {
Jooyung Hanea2147c2020-10-21 18:16:56 +0900168 if (CanDescribeContents(f->GetType(), types, &describers)) {
169 out << "case " << f->GetName() << ":\n";
Jooyung Hand2fa0232020-10-19 02:51:41 +0900170 out.Indent();
Jooyung Hanea2147c2020-10-21 18:16:56 +0900171 out << "_mask |= describeContents(" << getter_name(*f) << "());\n";
Jooyung Hand2fa0232020-10-19 02:51:41 +0900172 out << "break;\n";
173 out.Dedent();
174 }
175 }
176 out << "}\n";
177 out << "return _mask;\n";
178 out.Dedent();
179 out << "}\n";
Jooyung Hanea2147c2020-10-21 18:16:56 +0900180 if (!describers.empty()) {
181 GenerateDescribeContentsHelper(out, describers);
182 }
Jooyung Hand2fa0232020-10-19 02:51:41 +0900183}
Jooyung Han90345002020-10-23 15:28:53 +0900184
185void GenerateToString(CodeWriter& out, const AidlStructuredParcelable& parcel,
186 const AidlTypenames& typenames) {
187 out << "@Override\n";
188 out << "public String toString() {\n";
189 out.Indent();
190 out << "java.util.StringJoiner _aidl_sj = new java.util.StringJoiner(";
191 out << "\", \", \"{\", \"}\");\n";
192 for (const auto& field : parcel.GetFields()) {
193 CodeGeneratorContext ctx{
194 .writer = out,
195 .typenames = typenames,
196 .type = field->GetType(),
197 .var = field->GetName(),
198 };
199 out << "_aidl_sj.add(\"" << field->GetName() << ": \" + (";
200 ToStringFor(ctx);
201 out << "));\n";
202 }
203 out << "return \"" << parcel.GetCanonicalName() << "\" + _aidl_sj.toString() ;\n";
204 out.Dedent();
205 out << "}\n";
206}
207
Jooyung Han1cbc4962020-10-25 10:07:15 +0900208void GenerateToString(CodeWriter& out, const AidlUnionDecl& parcel,
209 const AidlTypenames& typenames) {
210 out << "@Override\n";
211 out << "public String toString() {\n";
212 out.Indent();
213 out << "switch (_tag) {\n";
214 for (const auto& field : parcel.GetFields()) {
215 CodeGeneratorContext ctx{
216 .writer = out,
217 .typenames = typenames,
218 .type = field->GetType(),
219 .var = getter_name(*field) + "()",
220 };
221 out << "case " << field->GetName() << ": return \"" << parcel.GetCanonicalName() << "."
222 << field->GetName() << "(\" + (";
223 ToStringFor(ctx);
224 out << ") + \")\";\n";
225 }
226 out << "}\n";
227 out << "throw new IllegalStateException(\"unknown field: \" + _tag);\n";
228 out.Dedent();
229 out << "}\n";
230}
231
Jiyong Park9aa3d042020-12-04 23:30:02 +0900232void GenerateEqualsAndHashCode(CodeWriter& out, const AidlStructuredParcelable& parcel,
233 const AidlTypenames&) {
234 out << "@Override\n";
235 out << "public boolean equals(Object other) {\n";
236 out.Indent();
237 out << "if (this == other) return true;\n";
238 out << "if (other == null) return false;\n";
239 out << "if (!(other instanceof " << parcel.GetName() << ")) return false;\n";
240 out << parcel.GetName() << " that = (" << parcel.GetName() << ")other;\n";
241 for (const auto& field : parcel.GetFields()) {
242 out << "if (!java.util.Objects.deepEquals(" << field->GetName() << ", that." << field->GetName()
243 << ")) return false;\n";
244 }
245 out << "return true;\n";
246 out.Dedent();
247 out << "}\n";
248 out << "\n";
249 out << "@Override\n";
250 out << "public int hashCode() {\n";
251 out.Indent();
252 out << "return java.util.Arrays.deepHashCode(java.util.Arrays.asList(";
253 std::vector<std::string> names;
254 for (const auto& field : parcel.GetFields()) {
255 names.push_back(field->GetName());
256 }
257 out << android::base::Join(names, ", ") << ").toArray());\n";
258 out.Dedent();
259 out << "}\n";
260}
261
262void GenerateEqualsAndHashCode(CodeWriter& out, const AidlUnionDecl& decl,
263 const AidlTypenames&) {
264 out << "@Override\n";
265 out << "public boolean equals(Object other) {\n";
266 out.Indent();
267 out << "if (this == other) return true;\n";
268 out << "if (other == null) return false;\n";
269 out << "if (!(other instanceof " << decl.GetName() << ")) return false;\n";
270 out << decl.GetName() << " that = (" << decl.GetName() << ")other;\n";
271 out << "if (_tag != that._tag) return false;\n";
272 out << "if (!java.util.Objects.deepEquals(_value, that._value)) return false;\n";
273 out << "return true;\n";
274 out.Dedent();
275 out << "}\n";
276 out << "\n";
277 out << "@Override\n";
278 out << "public int hashCode() {\n";
279 out.Indent();
280 out << "return java.util.Arrays.deepHashCode(java.util.Arrays.asList(_tag, _value).toArray());\n";
281 out.Dedent();
282 out << "}\n";
283 out << "\n";
284}
285
Jeongik Cha91180252020-07-31 15:43:11 +0900286} // namespace
287
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700288namespace android {
289namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -0700290namespace java {
291
Jooyung Hanbd9db442021-01-14 01:45:55 +0900292std::string GenerateComments(const AidlCommentable& node) {
Jooyung Hanb7a60ec2021-01-21 13:47:59 +0900293 std::string comments = FormatCommentsForJava(node.GetComments());
Jooyung Hanbd9db442021-01-14 01:45:55 +0900294 if (!comments.empty() && comments.back() != '\n') {
295 comments += '\n';
296 }
297 return comments;
298}
299
300std::string GenerateAnnotations(const AidlNode& node) {
301 std::string result;
302 for (const auto& a : JavaAnnotationsFor(node)) {
303 result += a + "\n";
304 }
305 return result;
306}
307
Jiyong Park54fa1e02019-02-08 10:03:20 +0900308bool generate_java_interface(const string& filename, const AidlInterface* iface,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900309 const AidlTypenames& typenames, const IoDelegate& io_delegate,
Jiyong Park54fa1e02019-02-08 10:03:20 +0900310 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -0700311 auto cl = generate_binder_interface_class(iface, typenames, options);
Adam Lesinskiffa16862014-01-23 18:17:42 -0800312
Steven Moreland48548e02019-09-18 15:10:22 -0700313 std::unique_ptr<Document> document =
314 std::make_unique<Document>("" /* no comment */, iface->GetPackage(), std::move(cl));
Adam Lesinskiffa16862014-01-23 18:17:42 -0800315
Christopher Wiley3a9da172016-01-29 11:10:49 -0800316 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
317 document->Write(code_writer.get());
Adam Lesinskiffa16862014-01-23 18:17:42 -0800318
Jiyong Park74595c12018-07-23 15:22:50 +0900319 return true;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800320}
321
Jiyong Park54fa1e02019-02-08 10:03:20 +0900322bool generate_java_parcel(const std::string& filename, const AidlStructuredParcelable* parcel,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900323 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
Steven Moreland48548e02019-09-18 15:10:22 -0700324 auto cl = generate_parcel_class(parcel, typenames);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700325
Steven Moreland48548e02019-09-18 15:10:22 -0700326 std::unique_ptr<Document> document =
327 std::make_unique<Document>("" /* no comment */, parcel->GetPackage(), std::move(cl));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700328
329 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
330 document->Write(code_writer.get());
331
Jiyong Park74595c12018-07-23 15:22:50 +0900332 return true;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700333}
334
Daniel Norman716d3112019-09-10 13:11:56 -0700335bool generate_java_enum_declaration(const std::string& filename,
336 const AidlEnumDeclaration* enum_decl,
337 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
338 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
339 generate_enum(code_writer, enum_decl, typenames);
340 return true;
341}
342
Jooyung Han2946afc2020-10-05 20:29:16 +0900343bool generate_java_union_declaration(const std::string& filename, const AidlUnionDecl* decl,
344 const AidlTypenames& typenames,
345 const IoDelegate& io_delegate) {
346 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
347 generate_union(*code_writer, decl, typenames);
348 return true;
349}
350
Jiyong Park54fa1e02019-02-08 10:03:20 +0900351bool generate_java(const std::string& filename, const AidlDefinedType* defined_type,
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900352 const AidlTypenames& typenames, const IoDelegate& io_delegate,
Jiyong Park54fa1e02019-02-08 10:03:20 +0900353 const Options& options) {
Daniel Norman716d3112019-09-10 13:11:56 -0700354 if (const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
355 parcelable != nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900356 return generate_java_parcel(filename, parcelable, typenames, io_delegate);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700357 }
358
Daniel Norman716d3112019-09-10 13:11:56 -0700359 if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
360 enum_decl != nullptr) {
361 return generate_java_enum_declaration(filename, enum_decl, typenames, io_delegate);
362 }
363
364 if (const AidlInterface* interface = defined_type->AsInterface(); interface != nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900365 return generate_java_interface(filename, interface, typenames, io_delegate, options);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700366 }
367
Jooyung Han2946afc2020-10-05 20:29:16 +0900368 if (const AidlUnionDecl* union_decl = defined_type->AsUnionDeclaration(); union_decl != nullptr) {
369 return generate_java_union_declaration(filename, union_decl, typenames, io_delegate);
370 }
371
Steven Moreland21780812020-09-11 01:29:45 +0000372 AIDL_FATAL(defined_type) << "Unrecognized type sent for Java generation.";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700373 return false;
374}
375
Steven Moreland48548e02019-09-18 15:10:22 -0700376std::unique_ptr<android::aidl::java::Class> generate_parcel_class(
377 const AidlStructuredParcelable* parcel, const AidlTypenames& typenames) {
378 auto parcel_class = std::make_unique<Class>();
Jooyung Hanbd9db442021-01-14 01:45:55 +0900379 parcel_class->comment = GenerateComments(*parcel);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700380 parcel_class->modifiers = PUBLIC;
381 parcel_class->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900382 parcel_class->type = parcel->GetCanonicalName();
383 parcel_class->interfaces.push_back("android.os.Parcelable");
Jooyung Han720253d2021-01-05 19:13:17 +0900384 parcel_class->annotations = JavaAnnotationsFor(*parcel);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700385
Devin Moore53fc99c2020-08-12 08:07:52 -0700386 if (parcel->IsGeneric()) {
387 parcel_class->type += "<" + base::Join(parcel->GetTypeParameters(), ",") + ">";
388 }
389
Steven Moreland5557f1c2018-07-02 13:50:23 -0700390 for (const auto& variable : parcel->GetFields()) {
Steven Moreland9ea10e32018-07-19 15:26:09 -0700391 std::ostringstream out;
Jooyung Hanbd9db442021-01-14 01:45:55 +0900392 out << GenerateComments(*variable);
393 out << GenerateAnnotations(*variable);
Jeongik Cha649e8a72020-03-27 17:47:40 +0900394 out << "public ";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900395
Jeongik Chad0a10272020-08-06 16:33:36 +0900396 if (variable->GetType().GetName() == "ParcelableHolder" || parcel->IsJavaOnlyImmutable()) {
Jeongik Cha649e8a72020-03-27 17:47:40 +0900397 out << "final ";
398 }
399 out << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName();
Jeongik Chad0a10272020-08-06 16:33:36 +0900400 if (!parcel->IsJavaOnlyImmutable() && variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700401 out << " = " << variable->ValueString(ConstantValueDecorator);
Jeongik Cha649e8a72020-03-27 17:47:40 +0900402 } else if (variable->GetType().GetName() == "ParcelableHolder") {
403 out << std::boolalpha;
Steven Moreland4768c962020-07-23 01:21:16 +0000404 out << " = new " << JavaSignatureOf(variable->GetType(), typenames) << "(";
405 if (parcel->IsVintfStability()) {
406 out << "android.os.Parcelable.PARCELABLE_STABILITY_VINTF";
407 } else {
408 out << "android.os.Parcelable.PARCELABLE_STABILITY_LOCAL";
409 }
410 out << ")";
Jeongik Cha649e8a72020-03-27 17:47:40 +0900411 out << std::noboolalpha;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700412 }
413 out << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700414 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700415 }
416
417 std::ostringstream out;
Jeongik Chad0a10272020-08-06 16:33:36 +0900418 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900419 auto builder_class = std::make_shared<Class>();
420 builder_class->modifiers = PUBLIC | FINAL | STATIC;
421 builder_class->what = Class::CLASS;
422 builder_class->type = "Builder";
Jeongik Cha92d33d02020-05-14 00:53:57 +0900423
Jeongik Cha91180252020-07-31 15:43:11 +0900424 out.str("");
425 for (const auto& variable : parcel->GetFields()) {
426 out << "private " << JavaSignatureOf(variable->GetType(), typenames) << " "
427 << variable->GetName();
428 if (variable->GetDefaultValue()) {
429 out << " = " << variable->ValueString(ConstantValueDecorator);
430 }
431 out << ";\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900432 out << "public Builder " << setter_name(*variable) << "("
Jeongik Cha91180252020-07-31 15:43:11 +0900433 << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName()
434 << ") {\n"
435 << " "
436 << "this." << variable->GetName() << " = " << variable->GetName() << ";\n"
437 << " return this;\n"
438 << "}\n";
439 }
440 out << "public " << parcel->GetCanonicalName() << " build() {\n"
441 << " return new " << parcel->GetCanonicalName() << "(";
442 std::vector<std::string> variables;
443 std::transform(parcel->GetFields().begin(), parcel->GetFields().end(),
444 std::back_inserter(variables), [](const auto& f) { return f->GetName(); });
445 out << base::Join(variables, ", ") << ");\n"
446 << "}\n";
447 builder_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
448 parcel_class->elements.push_back(builder_class);
449 }
Jeongik Cha92d33d02020-05-14 00:53:57 +0900450 if (parcel->IsVintfStability()) {
Steven Moreland82466d42020-08-05 18:05:57 +0000451 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(
452 "@Override\n public final int getStability() { return "
453 "android.os.Parcelable.PARCELABLE_STABILITY_VINTF; }\n"));
Jeongik Cha92d33d02020-05-14 00:53:57 +0900454 }
455
456 out.str("");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700457 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
458 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900459 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700460 out << " public " << parcel->GetName()
461 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
Jeongik Chad0a10272020-08-06 16:33:36 +0900462 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900463 out << " return internalCreateFromParcel(_aidl_source);\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900464 } else {
465 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
466 out << " _aidl_out.readFromParcel(_aidl_source);\n";
467 out << " return _aidl_out;\n";
468 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700469 out << " }\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900470 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700471 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
472 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
473 out << " }\n";
474 out << "};\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700475 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700476
Steven Moreland48548e02019-09-18 15:10:22 -0700477 auto flag_variable = std::make_shared<Variable>("int", "_aidl_flag");
478 auto parcel_variable = std::make_shared<Variable>("android.os.Parcel", "_aidl_parcel");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700479
Steven Moreland48548e02019-09-18 15:10:22 -0700480 auto write_method = std::make_shared<Method>();
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900481 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900482 write_method->returnType = "void";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700483 write_method->name = "writeToParcel";
484 write_method->parameters.push_back(parcel_variable);
485 write_method->parameters.push_back(flag_variable);
Steven Moreland48548e02019-09-18 15:10:22 -0700486 write_method->statements = std::make_shared<StatementBlock>();
Jeongik Cha95eba572018-11-22 09:14:52 +0900487
488 out.str("");
489 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
490 << "_aidl_parcel.writeInt(0);\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700491 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900492
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900493 for (const auto& field : parcel->GetFields()) {
494 string code;
495 CodeWriterPtr writer = CodeWriter::ForString(&code);
496 CodeGeneratorContext context{
497 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900498 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900499 .type = field->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900500 .parcel = parcel_variable->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700501 .var = field->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900502 .is_return_value = false,
503 };
504 WriteToParcelFor(context);
505 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700506 write_method->statements->Add(std::make_shared<LiteralStatement>(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700507 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900508
509 out.str("");
510 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
511 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
512 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
513 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
514
Steven Moreland48548e02019-09-18 15:10:22 -0700515 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900516
Steven Moreland5557f1c2018-07-02 13:50:23 -0700517 parcel_class->elements.push_back(write_method);
518
Jeongik Chad0a10272020-08-06 16:33:36 +0900519 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900520 auto constructor = std::make_shared<Method>();
521 constructor->modifiers = PUBLIC;
522 constructor->name = parcel->GetName();
523 constructor->statements = std::make_shared<StatementBlock>();
524 for (const auto& field : parcel->GetFields()) {
525 constructor->parameters.push_back(std::make_shared<Variable>(
526 JavaSignatureOf(field->GetType(), typenames), field->GetName()));
527 out.str("");
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900528
Jeongik Cha36f76c32020-07-28 00:25:52 +0900529 out << "this." << field->GetName() << " = ";
530 if (field->GetType().GetName() == "List") {
Jeongik Cha02c2c1e2020-07-31 15:11:49 +0900531 out << field->GetName() << " == null ? null : java.util.Collections.unmodifiableList("
532 << field->GetName() << ");\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900533 } else if (field->GetType().GetName() == "Map") {
Jeongik Cha02c2c1e2020-07-31 15:11:49 +0900534 out << field->GetName() << " == null ? null : java.util.Collections.unmodifiableMap("
535 << field->GetName() << ");\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900536 } else {
537 out << field->GetName() << ";\n";
538 }
539 constructor->statements->Add(std::make_shared<LiteralStatement>(out.str()));
540 }
541 parcel_class->elements.push_back(constructor);
542 }
543
Jeongik Cha91180252020-07-31 15:43:11 +0900544 // For an immutable parcelable, generate internalCreateFromParcel method.
Jeongik Cha36f76c32020-07-28 00:25:52 +0900545 // Otherwise, generate readFromParcel method.
546 auto read_or_create_method = std::make_shared<Method>();
Jeongik Chad0a10272020-08-06 16:33:36 +0900547 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900548 auto constructor = std::make_shared<Method>();
Jeongik Cha91180252020-07-31 15:43:11 +0900549 read_or_create_method->modifiers = PRIVATE | STATIC;
550 read_or_create_method->returnType = parcel->GetName();
551 read_or_create_method->name = "internalCreateFromParcel";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900552 read_or_create_method->parameters.push_back(parcel_variable);
553 read_or_create_method->statements = std::make_shared<StatementBlock>();
554 } else {
555 read_or_create_method->modifiers = PUBLIC | FINAL;
556 read_or_create_method->returnType = "void";
557 read_or_create_method->name = "readFromParcel";
558 read_or_create_method->parameters.push_back(parcel_variable);
559 read_or_create_method->statements = std::make_shared<StatementBlock>();
560 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900561 out.str("");
Jeongik Cha91180252020-07-31 15:43:11 +0900562 const string builder_variable = "_aidl_parcelable_builder";
Jeongik Chad0a10272020-08-06 16:33:36 +0900563 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900564 out << "Builder " << builder_variable << " = new Builder();\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900565 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900566 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
567 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
Jeongik Cha36f76c32020-07-28 00:25:52 +0900568 << "try {\n"
Jeongik Cha91180252020-07-31 15:43:11 +0900569 << " if (_aidl_parcelable_size < 0) return";
Jeongik Chad0a10272020-08-06 16:33:36 +0900570 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900571 out << " " << builder_variable << ".build()";
572 }
573 out << ";\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900574
Jeongik Cha36f76c32020-07-28 00:25:52 +0900575 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900576
577 out.str("");
Jeongik Cha91180252020-07-31 15:43:11 +0900578 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return";
Jeongik Chad0a10272020-08-06 16:33:36 +0900579 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900580 out << " " << builder_variable << ".build()";
581 }
582 out << ";\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900583
Jooyung Han9e85bce2021-04-29 01:28:19 +0900584 std::shared_ptr<LiteralStatement> sizeCheck = std::make_shared<LiteralStatement>(out.str());
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900585 // keep this across different fields in order to create the classloader
586 // at most once.
587 bool is_classloader_created = false;
588 for (const auto& field : parcel->GetFields()) {
Jooyung Han9e85bce2021-04-29 01:28:19 +0900589 read_or_create_method->statements->Add(sizeCheck);
Jeongik Cha36f76c32020-07-28 00:25:52 +0900590 const auto field_variable_name =
Jeongik Chad0a10272020-08-06 16:33:36 +0900591 (parcel->IsJavaOnlyImmutable() ? "_aidl_temp_" : "") + field->GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900592 string code;
593 CodeWriterPtr writer = CodeWriter::ForString(&code);
594 CodeGeneratorContext context{
595 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900596 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900597 .type = field->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900598 .parcel = parcel_variable->name,
Jeongik Cha36f76c32020-07-28 00:25:52 +0900599 .var = field_variable_name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900600 .is_classloader_created = &is_classloader_created,
601 };
Jeongik Cha95eba572018-11-22 09:14:52 +0900602 context.writer.Indent();
Jeongik Chad0a10272020-08-06 16:33:36 +0900603 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900604 context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType(), typenames).c_str(),
605 field_variable_name.c_str());
606 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900607 CreateFromParcelFor(context);
Jeongik Chad0a10272020-08-06 16:33:36 +0900608 if (parcel->IsJavaOnlyImmutable()) {
Jooyung Han2946afc2020-10-05 20:29:16 +0900609 context.writer.Write("%s.%s(%s);\n", builder_variable.c_str(), setter_name(*field).c_str(),
Steven Moreland21780812020-09-11 01:29:45 +0000610 field_variable_name.c_str());
Jeongik Cha36f76c32020-07-28 00:25:52 +0900611 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900612 writer->Close();
Jeongik Cha36f76c32020-07-28 00:25:52 +0900613 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700614 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900615
616 out.str("");
617 out << "} finally {\n"
Jeongik Cha8b329982020-09-01 20:59:36 +0900618 << " if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {\n"
619 << " throw new android.os.BadParcelableException(\"Overflow in the size of "
620 "parcelable\");\n"
621 << " }\n"
Jeongik Cha36f76c32020-07-28 00:25:52 +0900622 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
Jeongik Chad0a10272020-08-06 16:33:36 +0900623 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900624 out << " return " << builder_variable << ".build();\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900625 }
626 out << "}\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900627
Jeongik Cha36f76c32020-07-28 00:25:52 +0900628 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900629
Jeongik Cha36f76c32020-07-28 00:25:52 +0900630 parcel_class->elements.push_back(read_or_create_method);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700631
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900632 string constants;
633 generate_constant_declarations(*CodeWriter::ForString(&constants), *parcel);
Jooyung Han3f347ca2020-12-01 12:41:50 +0900634 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(constants));
635
Jooyung Han829ec7c2020-12-02 12:07:36 +0900636 if (parcel->JavaDerive("toString")) {
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900637 string to_string;
638 GenerateToString(*CodeWriter::ForString(&to_string), *parcel, typenames);
639 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(to_string));
Jooyung Han829ec7c2020-12-02 12:07:36 +0900640 }
Jiyong Park43113fb2020-07-20 16:26:19 +0900641
Jiyong Park9aa3d042020-12-04 23:30:02 +0900642 if (parcel->JavaDerive("equals")) {
643 string to_string;
644 GenerateEqualsAndHashCode(*CodeWriter::ForString(&to_string), *parcel, typenames);
645 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(to_string));
646 }
647
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900648 string describe_contents;
649 GenerateParcelableDescribeContents(*CodeWriter::ForString(&describe_contents), *parcel,
650 typenames);
651 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(describe_contents));
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900652
Steven Moreland5557f1c2018-07-02 13:50:23 -0700653 return parcel_class;
654}
655
Daniel Norman716d3112019-09-10 13:11:56 -0700656void generate_enum(const CodeWriterPtr& code_writer, const AidlEnumDeclaration* enum_decl,
657 const AidlTypenames& typenames) {
658 code_writer->Write(
659 "/*\n"
660 " * This file is auto-generated. DO NOT MODIFY.\n"
661 " */\n");
662
663 code_writer->Write("package %s;\n", enum_decl->GetPackage().c_str());
Jooyung Hanbd9db442021-01-14 01:45:55 +0900664 (*code_writer) << GenerateComments(*enum_decl);
665 (*code_writer) << GenerateAnnotations(*enum_decl);
Daniel Norman716d3112019-09-10 13:11:56 -0700666 code_writer->Write("public @interface %s {\n", enum_decl->GetName().c_str());
667 code_writer->Indent();
668 for (const auto& enumerator : enum_decl->GetEnumerators()) {
Jooyung Hanbd9db442021-01-14 01:45:55 +0900669 (*code_writer) << GenerateComments(*enumerator);
670 (*code_writer) << GenerateAnnotations(*enumerator);
Daniel Norman716d3112019-09-10 13:11:56 -0700671 code_writer->Write(
672 "public static final %s %s = %s;\n",
673 JavaSignatureOf(enum_decl->GetBackingType(), typenames).c_str(),
674 enumerator->GetName().c_str(),
Daniel Norman37d43dd2019-09-09 17:22:34 -0700675 enumerator->ValueString(enum_decl->GetBackingType(), ConstantValueDecorator).c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700676 }
677 code_writer->Dedent();
678 code_writer->Write("}\n");
679}
680
Jooyung Han2946afc2020-10-05 20:29:16 +0900681void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypenames& typenames) {
682 const string tag_type = "int";
683 const AidlTypeSpecifier tag_type_specifier(AIDL_LOCATION_HERE, tag_type, false /* isArray */,
Jooyung Han8451a202021-01-16 03:07:06 +0900684 nullptr /* type_params */, Comments{});
Jooyung Han2946afc2020-10-05 20:29:16 +0900685 const string clazz = decl->GetName();
686
687 out << "/*\n";
688 out << " * This file is auto-generated. DO NOT MODIFY.\n";
689 out << " */\n";
690
691 out << "package " + decl->GetPackage() + ";\n";
692 out << "\n";
Jooyung Hanbd9db442021-01-14 01:45:55 +0900693 out << GenerateComments(*decl);
694 out << GenerateAnnotations(*decl);
Jooyung Han2946afc2020-10-05 20:29:16 +0900695
696 out << "public final class " + clazz + " implements android.os.Parcelable {\n";
697 out.Indent();
698
699 size_t tag_index = 0;
Jooyung Han97945de2020-10-15 16:41:38 +0900700 out << "// tags for union fields\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900701 for (const auto& variable : decl->GetFields()) {
Jooyung Han97945de2020-10-15 16:41:38 +0900702 auto signature = variable->Signature() + ";";
Jooyung Han2946afc2020-10-05 20:29:16 +0900703 out << "public final static " + tag_type + " " + variable->GetName() + " = " +
Jooyung Han97945de2020-10-15 16:41:38 +0900704 std::to_string(tag_index++) + "; // " + signature + "\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900705 }
706 out << "\n";
707
Jooyung Hance62f932020-10-25 10:21:49 +0900708 const auto final_opt = decl->IsJavaOnlyImmutable() ? "final " : "";
709 out << "private " << final_opt << tag_type + " _tag;\n";
710 out << "private " << final_opt << "Object _value;\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900711 out << "\n";
712
Jooyung Hanfe89f122020-10-14 03:49:18 +0900713 AIDL_FATAL_IF(decl->GetFields().empty(), *decl) << "Union '" << clazz << "' is empty.";
Jooyung Han2946afc2020-10-05 20:29:16 +0900714 const auto& first_field = decl->GetFields()[0];
Jooyung Hanfe89f122020-10-14 03:49:18 +0900715 const auto& first_type = JavaSignatureOf(first_field->GetType(), typenames);
716 const auto& first_value = first_field->ValueString(ConstantValueDecorator);
717
718 // default ctor() inits with first member's default value
Jooyung Han2946afc2020-10-05 20:29:16 +0900719 out << "public " + clazz + "() {\n";
Jooyung Hanfe89f122020-10-14 03:49:18 +0900720 out.Indent();
Jooyung Hance62f932020-10-25 10:21:49 +0900721 out << first_type + " _value = " << (first_value.empty() ? "null" : first_value) << ";\n";
722 out << "this._tag = " << first_field->GetName() << ";\n";
723 out << "this._value = _value;\n";
Jooyung Hanfe89f122020-10-14 03:49:18 +0900724 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900725 out << "}\n\n";
726
Jooyung Hance62f932020-10-25 10:21:49 +0900727 if (!decl->IsJavaOnlyImmutable()) {
728 // private ctor(Parcel)
729 out << "private " + clazz + "(android.os.Parcel _aidl_parcel) {\n";
730 out << " readFromParcel(_aidl_parcel);\n";
731 out << "}\n\n";
732 }
Jooyung Han97945de2020-10-15 16:41:38 +0900733
Jooyung Hance62f932020-10-25 10:21:49 +0900734 // private ctor(tag, value)
735 out << "private " + clazz + "(" + tag_type + " _tag, Object _value) {\n";
736 out.Indent();
737 out << "this._tag = _tag;\n";
738 out << "this._value = _value;\n";
739 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900740 out << "}\n\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900741
742 // getTag()
743 out << "public " + tag_type + " " + "getTag() {\n";
Jooyung Hance62f932020-10-25 10:21:49 +0900744 out.Indent();
745 out << "return _tag;\n";
746 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900747 out << "}\n\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900748
Jooyung Hance62f932020-10-25 10:21:49 +0900749 // value ctor, getter, setter(for mutable) for each field
Jooyung Han2946afc2020-10-05 20:29:16 +0900750 for (const auto& variable : decl->GetFields()) {
Jooyung Hanbd9db442021-01-14 01:45:55 +0900751 out << "// " + variable->Signature() + ";\n\n";
752
Jooyung Han2946afc2020-10-05 20:29:16 +0900753 auto var_name = variable->GetName();
754 auto var_type = JavaSignatureOf(variable->GetType(), typenames);
Jooyung Han2946afc2020-10-05 20:29:16 +0900755
Jooyung Han2946afc2020-10-05 20:29:16 +0900756 // value ctor
Jooyung Hanbd9db442021-01-14 01:45:55 +0900757 out << GenerateComments(*variable);
758 out << GenerateAnnotations(*variable);
Jooyung Hance62f932020-10-25 10:21:49 +0900759 out << "public static " + clazz + " " + var_name + "(" + var_type + " _value) {\n";
760 out.Indent();
761 out << "return new " + clazz + "(" + var_name + ", _value);\n";
762 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900763 out << "}\n\n";
764
Jooyung Han2946afc2020-10-05 20:29:16 +0900765 // getter
766 if (variable->GetType().IsGeneric()) {
767 out << "@SuppressWarnings(\"unchecked\")\n";
768 }
769 out << "public " + var_type + " " + getter_name(*variable) + "() {\n";
Jooyung Hance62f932020-10-25 10:21:49 +0900770 out.Indent();
771 out << "_assertTag(" + var_name + ");\n";
772 out << "return (" + var_type + ") _value;\n";
773 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900774 out << "}\n\n";
775
Jooyung Han2946afc2020-10-05 20:29:16 +0900776 // setter
Jooyung Hance62f932020-10-25 10:21:49 +0900777 if (!decl->IsJavaOnlyImmutable()) {
778 out << "public void " + setter_name(*variable) + "(" + var_type + " _value) {\n";
779 out.Indent();
780 out << "_set(" + var_name + ", _value);\n";
781 out.Dedent();
782 out << "}\n\n";
783 }
Jooyung Han2946afc2020-10-05 20:29:16 +0900784 }
785
786 if (decl->IsVintfStability()) {
787 out << "@Override\n";
788 out << "public final int getStability() {\n";
789 out << " return android.os.Parcelable.PARCELABLE_STABILITY_VINTF;\n";
Jooyung Han97945de2020-10-15 16:41:38 +0900790 out << "}\n\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900791 }
792
793 out << "public static final android.os.Parcelable.Creator<" << clazz << "> CREATOR = "
794 << "new android.os.Parcelable.Creator<" << clazz << ">() {\n";
795 out << " @Override\n";
796 out << " public " << clazz << " createFromParcel(android.os.Parcel _aidl_source) {\n";
Jooyung Hance62f932020-10-25 10:21:49 +0900797 if (decl->IsJavaOnlyImmutable()) {
798 out << " return internalCreateFromParcel(_aidl_source);\n";
799 } else {
800 out << " return new " + clazz + "(_aidl_source);\n";
801 }
Jooyung Han2946afc2020-10-05 20:29:16 +0900802 out << " }\n";
803 out << " @Override\n";
804 out << " public " << clazz << "[] newArray(int _aidl_size) {\n";
805 out << " return new " << clazz << "[_aidl_size];\n";
806 out << " }\n";
Jooyung Han97945de2020-10-15 16:41:38 +0900807 out << "};\n\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900808
809 auto write_to_parcel = [&](const AidlTypeSpecifier& type, std::string name, std::string parcel) {
810 string code;
811 CodeWriterPtr writer = CodeWriter::ForString(&code);
812 CodeGeneratorContext context{
813 .writer = *(writer.get()),
814 .typenames = typenames,
815 .type = type,
816 .parcel = parcel,
817 .var = name,
818 .is_return_value = false,
819 };
820 WriteToParcelFor(context);
821 writer->Close();
822 return code;
823 };
824
825 out << "@Override\n";
826 out << "public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {\n";
Jooyung Hand2fa0232020-10-19 02:51:41 +0900827 out.Indent();
Jooyung Hance62f932020-10-25 10:21:49 +0900828 out << write_to_parcel(tag_type_specifier, "_tag", "_aidl_parcel");
829 out << "switch (_tag) {\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900830 for (const auto& variable : decl->GetFields()) {
Jooyung Hand2fa0232020-10-19 02:51:41 +0900831 out << "case " + variable->GetName() + ":\n";
832 out.Indent();
833 out << write_to_parcel(variable->GetType(), getter_name(*variable) + "()", "_aidl_parcel");
834 out << "break;\n";
835 out.Dedent();
Jooyung Han2946afc2020-10-05 20:29:16 +0900836 }
Jooyung Hand2fa0232020-10-19 02:51:41 +0900837 out << "}\n";
838 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900839 out << "}\n\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900840
841 // keep this across different fields in order to create the classloader
842 // at most once.
843 bool is_classloader_created = false;
844 auto read_from_parcel = [&](const AidlTypeSpecifier& type, std::string name, std::string parcel) {
845 string code;
846 CodeWriterPtr writer = CodeWriter::ForString(&code);
847 CodeGeneratorContext context{
848 .writer = *(writer.get()),
849 .typenames = typenames,
850 .type = type,
851 .parcel = parcel,
852 .var = name,
853 .is_classloader_created = &is_classloader_created,
854 };
855 CreateFromParcelFor(context);
856 writer->Close();
857 return code;
858 };
859
Jooyung Hance62f932020-10-25 10:21:49 +0900860 if (decl->IsJavaOnlyImmutable()) {
861 // When it's immutable we don't need readFromParcel, but we can use it from createFromParcel
862 out << "private static " + clazz +
863 " internalCreateFromParcel(android.os.Parcel _aidl_parcel) {\n";
864 } else {
865 // Not override, but as a user-defined parcelable, this method should be public
866 out << "public void readFromParcel(android.os.Parcel _aidl_parcel) {\n";
867 }
Jooyung Hand2fa0232020-10-19 02:51:41 +0900868 out.Indent();
869 out << tag_type + " _aidl_tag;\n";
870 out << read_from_parcel(tag_type_specifier, "_aidl_tag", "_aidl_parcel");
871 out << "switch (_aidl_tag) {\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900872 for (const auto& variable : decl->GetFields()) {
873 auto var_name = variable->GetName();
874 auto var_type = JavaSignatureOf(variable->GetType(), typenames);
Jooyung Hand2fa0232020-10-19 02:51:41 +0900875 out << "case " + var_name + ": {\n";
876 out.Indent();
877 out << var_type + " _aidl_value;\n";
878 out << read_from_parcel(variable->GetType(), "_aidl_value", "_aidl_parcel");
Jooyung Hance62f932020-10-25 10:21:49 +0900879 if (decl->IsJavaOnlyImmutable()) {
880 out << "return new " << clazz << "(_aidl_tag, _aidl_value); }\n";
881 } else {
882 out << "_set(_aidl_tag, _aidl_value);\n";
883 out << "return; }\n";
884 }
Jooyung Hand2fa0232020-10-19 02:51:41 +0900885 out.Dedent();
Jooyung Han2946afc2020-10-05 20:29:16 +0900886 }
Jooyung Hand2fa0232020-10-19 02:51:41 +0900887 out << "}\n";
Jooyung Hanc453bea2020-11-21 01:00:22 +0900888 out << "throw new IllegalArgumentException(\"union: unknown tag: \" + _aidl_tag);\n";
Jooyung Hand2fa0232020-10-19 02:51:41 +0900889 out.Dedent();
Jooyung Han97945de2020-10-15 16:41:38 +0900890 out << "}\n\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900891
Jooyung Hanb43a61c2020-12-02 14:18:53 +0900892 generate_constant_declarations(out, *decl);
Jooyung Han3f347ca2020-12-01 12:41:50 +0900893
Jooyung Hand2fa0232020-10-19 02:51:41 +0900894 GenerateParcelableDescribeContents(out, *decl, typenames);
895 out << "\n";
Jooyung Han829ec7c2020-12-02 12:07:36 +0900896 if (decl->JavaDerive("toString")) {
897 GenerateToString(out, *decl, typenames);
898 }
Jooyung Han2946afc2020-10-05 20:29:16 +0900899
Jiyong Park9aa3d042020-12-04 23:30:02 +0900900 if (decl->JavaDerive("equals")) {
901 GenerateEqualsAndHashCode(out, *decl, typenames);
902 }
903
Jooyung Han2946afc2020-10-05 20:29:16 +0900904 // helper: _assertTag
905 out << "private void _assertTag(" + tag_type + " tag) {\n";
906 out << " if (getTag() != tag) {\n";
907 out << " throw new IllegalStateException(\"bad access: \" + _tagString(tag) + \", \" + "
Jooyung Hanef9b0f62020-10-14 21:52:55 +0900908 "_tagString(getTag()) + \" is available.\");\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900909 out << " }\n";
Jooyung Han97945de2020-10-15 16:41:38 +0900910 out << "}\n\n";
911
Jooyung Han2946afc2020-10-05 20:29:16 +0900912 // helper: _tagString
Jooyung Hance62f932020-10-25 10:21:49 +0900913 out << "private String _tagString(" + tag_type + " _tag) {\n";
914 out << " switch (_tag) {\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900915 for (const auto& variable : decl->GetFields()) {
916 auto var_name = variable->GetName();
917 out << " case " + var_name + ": return \"" + var_name + "\";\n";
918 }
919 out << " }\n";
Jooyung Hance62f932020-10-25 10:21:49 +0900920 out << " throw new IllegalStateException(\"unknown field: \" + _tag);\n";
Jooyung Han2946afc2020-10-05 20:29:16 +0900921 out << "}\n";
922
Jooyung Hance62f932020-10-25 10:21:49 +0900923 if (!decl->IsJavaOnlyImmutable()) {
924 out << "\n";
925 out << "private void _set(int _tag, Object _value) {\n";
926 out.Indent();
927 out << "this._tag = _tag;\n";
928 out << "this._value = _value;\n";
929 out.Dedent();
930 out << "}\n";
931 }
932
Jooyung Han2946afc2020-10-05 20:29:16 +0900933 out.Dedent();
934 out << "}\n";
935}
936
Mathew Inwoodadb74672019-11-29 14:01:53 +0000937std::string dump_location(const AidlNode& method) {
938 return method.PrintLocation();
939}
940
941std::string generate_java_unsupportedappusage_parameters(const AidlAnnotation& a) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700942 const std::map<std::string, std::string> params = a.AnnotationParams(ConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100943 std::vector<string> parameters_decl;
944 for (const auto& name_and_param : params) {
945 const std::string& param_name = name_and_param.first;
946 const std::string& param_value = name_and_param.second;
947 parameters_decl.push_back(param_name + " = " + param_value);
948 }
Mathew Inwoodadb74672019-11-29 14:01:53 +0000949 parameters_decl.push_back("overrideSourcePosition=\"" + dump_location(a) + "\"");
Jooyung Han2946afc2020-10-05 20:29:16 +0900950 return "(" + Join(parameters_decl, ", ") + ")";
Andrei Onea9445fc62019-06-27 18:11:59 +0100951}
952
Jiyong Parka6605ab2018-11-11 14:30:21 +0900953std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
954 std::vector<std::string> result;
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800955 if (a.IsHide()) {
956 result.emplace_back("@android.annotation.Hide");
957 }
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900958
959 const AidlAnnotation* unsupported_app_usage = a.UnsupportedAppUsage();
Andrei Onea9445fc62019-06-27 18:11:59 +0100960 if (unsupported_app_usage != nullptr) {
Artur Satayev55120a72019-12-09 12:19:11 +0000961 result.emplace_back("@android.compat.annotation.UnsupportedAppUsage" +
Mathew Inwoodadb74672019-11-29 14:01:53 +0000962 generate_java_unsupportedappusage_parameters(*unsupported_app_usage));
Jiyong Parka6605ab2018-11-11 14:30:21 +0900963 }
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900964
Jooyung Hane6bc5e12020-10-13 10:57:10 +0900965 for (const auto& annotation : a.GetAnnotations()) {
966 if (annotation.GetType() == AidlAnnotation::Type::JAVA_PASSTHROUGH) {
Jooyung Hanb3c77ed2020-12-26 02:02:45 +0900967 result.emplace_back(annotation.ParamValue<std::string>("annotation").value());
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900968 }
969 }
970
Jiyong Parka6605ab2018-11-11 14:30:21 +0900971 return result;
972}
973
Jooyung Han720253d2021-01-05 19:13:17 +0900974struct JavaAnnotationsVisitor : AidlVisitor {
975 JavaAnnotationsVisitor(std::vector<std::string>& result) : result(result) {}
976 void Visit(const AidlTypeSpecifier& t) override { result = generate_java_annotations(t); }
977 void Visit(const AidlInterface& t) override { ForDefinedType(t); }
978 void Visit(const AidlParcelable& t) override { ForDefinedType(t); }
979 void Visit(const AidlStructuredParcelable& t) override { ForDefinedType(t); }
980 void Visit(const AidlUnionDecl& t) override { ForDefinedType(t); }
981 void Visit(const AidlEnumDeclaration& t) override { ForDefinedType(t); }
982 void Visit(const AidlMethod& m) override { ForMember(m); }
983 void Visit(const AidlConstantDeclaration& c) override { ForMember(c); }
984 void Visit(const AidlVariableDeclaration& v) override { ForMember(v); }
985 std::vector<std::string>& result;
986
987 void ForDefinedType(const AidlDefinedType& t) {
988 result = generate_java_annotations(t);
989 if (t.IsDeprecated()) {
990 result.push_back("@Deprecated");
991 }
992 }
993 template <typename Member>
994 void ForMember(const Member& t) {
995 result = generate_java_annotations(t.GetType());
996 if (t.IsDeprecated()) {
997 result.push_back("@Deprecated");
998 }
999 }
1000};
1001
1002std::vector<std::string> JavaAnnotationsFor(const AidlNode& a) {
1003 std::vector<std::string> result;
1004 JavaAnnotationsVisitor visitor{result};
1005 a.DispatchVisit(visitor);
1006 return result;
1007}
1008
Christopher Wileydb154a52015-09-28 16:32:25 -07001009} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -07001010} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -07001011} // namespace android