blob: 9c918d169c205539ecdddb56742be4560d5615bc [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>
26#include <sstream>
Adam Lesinskiffa16862014-01-23 18:17:42 -080027
Christopher Wiley3a9da172016-01-29 11:10:49 -080028#include <android-base/stringprintf.h>
29
Jiyong Park1d2df7d2018-07-23 15:22:50 +090030#include "aidl_to_java.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070031#include "code_writer.h"
Jeongik Chaa2080bf2019-06-18 16:44:29 +090032#include "logging.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070033
Christopher Wileyf76b59a2016-01-29 11:32:11 -080034using std::unique_ptr;
Christopher Wileydb154a52015-09-28 16:32:25 -070035using ::android::aidl::java::Variable;
Christopher Wiley3a9da172016-01-29 11:10:49 -080036using std::string;
Christopher Wileydb154a52015-09-28 16:32:25 -070037
Jeongik Cha91180252020-07-31 15:43:11 +090038namespace {
39inline string get_setter_name(const string& variablename) {
40 CHECK(variablename.size() > 0) << "A field name cannot be empty.";
41 std::ostringstream out;
42 out << "set" << static_cast<char>(toupper(variablename[0])) << variablename.substr(1);
43 return out.str();
44}
45} // namespace
46
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070047namespace android {
48namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070049namespace java {
50
Jiyong Park54fa1e02019-02-08 10:03:20 +090051bool generate_java_interface(const string& filename, const AidlInterface* iface,
Jeongik Chaa2080bf2019-06-18 16:44:29 +090052 const AidlTypenames& typenames, const IoDelegate& io_delegate,
Jiyong Park54fa1e02019-02-08 10:03:20 +090053 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -070054 auto cl = generate_binder_interface_class(iface, typenames, options);
Adam Lesinskiffa16862014-01-23 18:17:42 -080055
Steven Moreland48548e02019-09-18 15:10:22 -070056 std::unique_ptr<Document> document =
57 std::make_unique<Document>("" /* no comment */, iface->GetPackage(), std::move(cl));
Adam Lesinskiffa16862014-01-23 18:17:42 -080058
Christopher Wiley3a9da172016-01-29 11:10:49 -080059 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
60 document->Write(code_writer.get());
Adam Lesinskiffa16862014-01-23 18:17:42 -080061
Jiyong Park74595c12018-07-23 15:22:50 +090062 return true;
Adam Lesinskiffa16862014-01-23 18:17:42 -080063}
64
Jiyong Park54fa1e02019-02-08 10:03:20 +090065bool generate_java_parcel(const std::string& filename, const AidlStructuredParcelable* parcel,
Jeongik Chaa2080bf2019-06-18 16:44:29 +090066 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
Steven Moreland48548e02019-09-18 15:10:22 -070067 auto cl = generate_parcel_class(parcel, typenames);
Steven Moreland5557f1c2018-07-02 13:50:23 -070068
Steven Moreland48548e02019-09-18 15:10:22 -070069 std::unique_ptr<Document> document =
70 std::make_unique<Document>("" /* no comment */, parcel->GetPackage(), std::move(cl));
Steven Moreland5557f1c2018-07-02 13:50:23 -070071
72 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
73 document->Write(code_writer.get());
74
Jiyong Park74595c12018-07-23 15:22:50 +090075 return true;
Steven Moreland5557f1c2018-07-02 13:50:23 -070076}
77
Daniel Norman716d3112019-09-10 13:11:56 -070078bool generate_java_enum_declaration(const std::string& filename,
79 const AidlEnumDeclaration* enum_decl,
80 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
81 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
82 generate_enum(code_writer, enum_decl, typenames);
83 return true;
84}
85
Jiyong Park54fa1e02019-02-08 10:03:20 +090086bool generate_java(const std::string& filename, const AidlDefinedType* defined_type,
Jeongik Chaa2080bf2019-06-18 16:44:29 +090087 const AidlTypenames& typenames, const IoDelegate& io_delegate,
Jiyong Park54fa1e02019-02-08 10:03:20 +090088 const Options& options) {
Daniel Norman716d3112019-09-10 13:11:56 -070089 if (const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
90 parcelable != nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +090091 return generate_java_parcel(filename, parcelable, typenames, io_delegate);
Steven Moreland5557f1c2018-07-02 13:50:23 -070092 }
93
Daniel Norman716d3112019-09-10 13:11:56 -070094 if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
95 enum_decl != nullptr) {
96 return generate_java_enum_declaration(filename, enum_decl, typenames, io_delegate);
97 }
98
99 if (const AidlInterface* interface = defined_type->AsInterface(); interface != nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900100 return generate_java_interface(filename, interface, typenames, io_delegate, options);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700101 }
102
Daniel Norman85aed542019-08-21 12:01:14 -0700103 CHECK(false) << "Unrecognized type sent for java generation.";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700104 return false;
105}
106
Steven Moreland48548e02019-09-18 15:10:22 -0700107std::unique_ptr<android::aidl::java::Class> generate_parcel_class(
108 const AidlStructuredParcelable* parcel, const AidlTypenames& typenames) {
109 auto parcel_class = std::make_unique<Class>();
Steven Moreland5557f1c2018-07-02 13:50:23 -0700110 parcel_class->comment = parcel->GetComments();
111 parcel_class->modifiers = PUBLIC;
112 parcel_class->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900113 parcel_class->type = parcel->GetCanonicalName();
114 parcel_class->interfaces.push_back("android.os.Parcelable");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900115 parcel_class->annotations = generate_java_annotations(*parcel);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700116
Devin Moore53fc99c2020-08-12 08:07:52 -0700117 if (parcel->IsGeneric()) {
118 parcel_class->type += "<" + base::Join(parcel->GetTypeParameters(), ",") + ">";
119 }
120
Steven Moreland5557f1c2018-07-02 13:50:23 -0700121 for (const auto& variable : parcel->GetFields()) {
Steven Moreland9ea10e32018-07-19 15:26:09 -0700122 std::ostringstream out;
Jiyong Parka6605ab2018-11-11 14:30:21 +0900123 out << variable->GetType().GetComments() << "\n";
124 for (const auto& a : generate_java_annotations(variable->GetType())) {
125 out << a << "\n";
126 }
Jeongik Cha649e8a72020-03-27 17:47:40 +0900127 out << "public ";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900128
Jeongik Chad0a10272020-08-06 16:33:36 +0900129 if (variable->GetType().GetName() == "ParcelableHolder" || parcel->IsJavaOnlyImmutable()) {
Jeongik Cha649e8a72020-03-27 17:47:40 +0900130 out << "final ";
131 }
132 out << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName();
Jeongik Chad0a10272020-08-06 16:33:36 +0900133 if (!parcel->IsJavaOnlyImmutable() && variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700134 out << " = " << variable->ValueString(ConstantValueDecorator);
Jeongik Cha649e8a72020-03-27 17:47:40 +0900135 } else if (variable->GetType().GetName() == "ParcelableHolder") {
136 out << std::boolalpha;
Steven Moreland4768c962020-07-23 01:21:16 +0000137 out << " = new " << JavaSignatureOf(variable->GetType(), typenames) << "(";
138 if (parcel->IsVintfStability()) {
139 out << "android.os.Parcelable.PARCELABLE_STABILITY_VINTF";
140 } else {
141 out << "android.os.Parcelable.PARCELABLE_STABILITY_LOCAL";
142 }
143 out << ")";
Jeongik Cha649e8a72020-03-27 17:47:40 +0900144 out << std::noboolalpha;
Steven Moreland9ea10e32018-07-19 15:26:09 -0700145 }
146 out << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700147 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700148 }
149
150 std::ostringstream out;
Jeongik Chad0a10272020-08-06 16:33:36 +0900151 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900152 auto builder_class = std::make_shared<Class>();
153 builder_class->modifiers = PUBLIC | FINAL | STATIC;
154 builder_class->what = Class::CLASS;
155 builder_class->type = "Builder";
Jeongik Cha92d33d02020-05-14 00:53:57 +0900156
Jeongik Cha91180252020-07-31 15:43:11 +0900157 out.str("");
158 for (const auto& variable : parcel->GetFields()) {
159 out << "private " << JavaSignatureOf(variable->GetType(), typenames) << " "
160 << variable->GetName();
161 if (variable->GetDefaultValue()) {
162 out << " = " << variable->ValueString(ConstantValueDecorator);
163 }
164 out << ";\n";
165 out << "public Builder " << get_setter_name(variable->GetName()) << "("
166 << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName()
167 << ") {\n"
168 << " "
169 << "this." << variable->GetName() << " = " << variable->GetName() << ";\n"
170 << " return this;\n"
171 << "}\n";
172 }
173 out << "public " << parcel->GetCanonicalName() << " build() {\n"
174 << " return new " << parcel->GetCanonicalName() << "(";
175 std::vector<std::string> variables;
176 std::transform(parcel->GetFields().begin(), parcel->GetFields().end(),
177 std::back_inserter(variables), [](const auto& f) { return f->GetName(); });
178 out << base::Join(variables, ", ") << ");\n"
179 << "}\n";
180 builder_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
181 parcel_class->elements.push_back(builder_class);
182 }
Jeongik Cha92d33d02020-05-14 00:53:57 +0900183 if (parcel->IsVintfStability()) {
Steven Moreland82466d42020-08-05 18:05:57 +0000184 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(
185 "@Override\n public final int getStability() { return "
186 "android.os.Parcelable.PARCELABLE_STABILITY_VINTF; }\n"));
Jeongik Cha92d33d02020-05-14 00:53:57 +0900187 }
188
189 out.str("");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700190 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
191 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900192 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700193 out << " public " << parcel->GetName()
194 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
Jeongik Chad0a10272020-08-06 16:33:36 +0900195 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900196 out << " return internalCreateFromParcel(_aidl_source);\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900197 } else {
198 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
199 out << " _aidl_out.readFromParcel(_aidl_source);\n";
200 out << " return _aidl_out;\n";
201 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700202 out << " }\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900203 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700204 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
205 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
206 out << " }\n";
207 out << "};\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700208 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700209
Steven Moreland48548e02019-09-18 15:10:22 -0700210 auto flag_variable = std::make_shared<Variable>("int", "_aidl_flag");
211 auto parcel_variable = std::make_shared<Variable>("android.os.Parcel", "_aidl_parcel");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700212
Steven Moreland48548e02019-09-18 15:10:22 -0700213 auto write_method = std::make_shared<Method>();
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900214 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900215 write_method->returnType = "void";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700216 write_method->name = "writeToParcel";
217 write_method->parameters.push_back(parcel_variable);
218 write_method->parameters.push_back(flag_variable);
Steven Moreland48548e02019-09-18 15:10:22 -0700219 write_method->statements = std::make_shared<StatementBlock>();
Jeongik Cha95eba572018-11-22 09:14:52 +0900220
221 out.str("");
222 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
223 << "_aidl_parcel.writeInt(0);\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700224 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900225
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900226 for (const auto& field : parcel->GetFields()) {
227 string code;
228 CodeWriterPtr writer = CodeWriter::ForString(&code);
229 CodeGeneratorContext context{
230 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900231 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900232 .type = field->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900233 .parcel = parcel_variable->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700234 .var = field->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900235 .is_return_value = false,
236 };
237 WriteToParcelFor(context);
238 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700239 write_method->statements->Add(std::make_shared<LiteralStatement>(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700240 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900241
242 out.str("");
243 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
244 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
245 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
246 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
247
Steven Moreland48548e02019-09-18 15:10:22 -0700248 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900249
Steven Moreland5557f1c2018-07-02 13:50:23 -0700250 parcel_class->elements.push_back(write_method);
251
Jeongik Chad0a10272020-08-06 16:33:36 +0900252 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900253 auto constructor = std::make_shared<Method>();
254 constructor->modifiers = PUBLIC;
255 constructor->name = parcel->GetName();
256 constructor->statements = std::make_shared<StatementBlock>();
257 for (const auto& field : parcel->GetFields()) {
258 constructor->parameters.push_back(std::make_shared<Variable>(
259 JavaSignatureOf(field->GetType(), typenames), field->GetName()));
260 out.str("");
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900261
Jeongik Cha36f76c32020-07-28 00:25:52 +0900262 out << "this." << field->GetName() << " = ";
263 if (field->GetType().GetName() == "List") {
Jeongik Cha02c2c1e2020-07-31 15:11:49 +0900264 out << field->GetName() << " == null ? null : java.util.Collections.unmodifiableList("
265 << field->GetName() << ");\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900266 } else if (field->GetType().GetName() == "Map") {
Jeongik Cha02c2c1e2020-07-31 15:11:49 +0900267 out << field->GetName() << " == null ? null : java.util.Collections.unmodifiableMap("
268 << field->GetName() << ");\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900269 } else {
270 out << field->GetName() << ";\n";
271 }
272 constructor->statements->Add(std::make_shared<LiteralStatement>(out.str()));
273 }
274 parcel_class->elements.push_back(constructor);
275 }
276
Jeongik Cha91180252020-07-31 15:43:11 +0900277 // For an immutable parcelable, generate internalCreateFromParcel method.
Jeongik Cha36f76c32020-07-28 00:25:52 +0900278 // Otherwise, generate readFromParcel method.
279 auto read_or_create_method = std::make_shared<Method>();
Jeongik Chad0a10272020-08-06 16:33:36 +0900280 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900281 auto constructor = std::make_shared<Method>();
Jeongik Cha91180252020-07-31 15:43:11 +0900282 read_or_create_method->modifiers = PRIVATE | STATIC;
283 read_or_create_method->returnType = parcel->GetName();
284 read_or_create_method->name = "internalCreateFromParcel";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900285 read_or_create_method->parameters.push_back(parcel_variable);
286 read_or_create_method->statements = std::make_shared<StatementBlock>();
287 } else {
288 read_or_create_method->modifiers = PUBLIC | FINAL;
289 read_or_create_method->returnType = "void";
290 read_or_create_method->name = "readFromParcel";
291 read_or_create_method->parameters.push_back(parcel_variable);
292 read_or_create_method->statements = std::make_shared<StatementBlock>();
293 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900294 out.str("");
Jeongik Cha91180252020-07-31 15:43:11 +0900295 const string builder_variable = "_aidl_parcelable_builder";
Jeongik Chad0a10272020-08-06 16:33:36 +0900296 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900297 out << "Builder " << builder_variable << " = new Builder();\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900298 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900299 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
300 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
Jeongik Cha36f76c32020-07-28 00:25:52 +0900301 << "try {\n"
Jeongik Cha91180252020-07-31 15:43:11 +0900302 << " if (_aidl_parcelable_size < 0) return";
Jeongik Chad0a10272020-08-06 16:33:36 +0900303 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900304 out << " " << builder_variable << ".build()";
305 }
306 out << ";\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900307
Jeongik Cha36f76c32020-07-28 00:25:52 +0900308 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900309
310 out.str("");
Jeongik Cha91180252020-07-31 15:43:11 +0900311 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return";
Jeongik Chad0a10272020-08-06 16:33:36 +0900312 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900313 out << " " << builder_variable << ".build()";
314 }
315 out << ";\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900316
Steven Moreland48548e02019-09-18 15:10:22 -0700317 std::shared_ptr<LiteralStatement> sizeCheck = nullptr;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900318 // keep this across different fields in order to create the classloader
319 // at most once.
320 bool is_classloader_created = false;
321 for (const auto& field : parcel->GetFields()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900322 const auto field_variable_name =
Jeongik Chad0a10272020-08-06 16:33:36 +0900323 (parcel->IsJavaOnlyImmutable() ? "_aidl_temp_" : "") + field->GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900324 string code;
325 CodeWriterPtr writer = CodeWriter::ForString(&code);
326 CodeGeneratorContext context{
327 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900328 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900329 .type = field->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900330 .parcel = parcel_variable->name,
Jeongik Cha36f76c32020-07-28 00:25:52 +0900331 .var = field_variable_name,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900332 .is_classloader_created = &is_classloader_created,
333 };
Jeongik Cha95eba572018-11-22 09:14:52 +0900334 context.writer.Indent();
Jeongik Chad0a10272020-08-06 16:33:36 +0900335 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha36f76c32020-07-28 00:25:52 +0900336 context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType(), typenames).c_str(),
337 field_variable_name.c_str());
338 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900339 CreateFromParcelFor(context);
Jeongik Chad0a10272020-08-06 16:33:36 +0900340 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900341 context.writer.Write("%s.%s(%s);\n", builder_variable.c_str(),
342 get_setter_name(field->GetName()).c_str(), field_variable_name.c_str());
Jeongik Cha36f76c32020-07-28 00:25:52 +0900343 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900344 writer->Close();
Jeongik Cha36f76c32020-07-28 00:25:52 +0900345 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(code));
Steven Moreland48548e02019-09-18 15:10:22 -0700346 if (!sizeCheck) sizeCheck = std::make_shared<LiteralStatement>(out.str());
Jeongik Cha36f76c32020-07-28 00:25:52 +0900347 read_or_create_method->statements->Add(sizeCheck);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700348 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900349
350 out.str("");
351 out << "} finally {\n"
Jeongik Cha8b329982020-09-01 20:59:36 +0900352 << " if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {\n"
353 << " throw new android.os.BadParcelableException(\"Overflow in the size of "
354 "parcelable\");\n"
355 << " }\n"
Jeongik Cha36f76c32020-07-28 00:25:52 +0900356 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
Jeongik Chad0a10272020-08-06 16:33:36 +0900357 if (parcel->IsJavaOnlyImmutable()) {
Jeongik Cha91180252020-07-31 15:43:11 +0900358 out << " return " << builder_variable << ".build();\n";
Jeongik Cha36f76c32020-07-28 00:25:52 +0900359 }
360 out << "}\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900361
Jeongik Cha36f76c32020-07-28 00:25:52 +0900362 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900363
Jeongik Cha36f76c32020-07-28 00:25:52 +0900364 parcel_class->elements.push_back(read_or_create_method);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700365
Jiyong Park43113fb2020-07-20 16:26:19 +0900366 if (parcel->IsJavaDebug()) {
367 out.str("");
368 out << "@Override\n";
369 out << "public String toString() {\n";
370 out << " java.util.StringJoiner _aidl_sj = new java.util.StringJoiner(";
371 out << "\", \", \"{\", \"}\");\n";
372 for (const auto& field : parcel->GetFields()) {
373 std::string code;
374 CodeWriterPtr writer = CodeWriter::ForString(&code);
375 CodeGeneratorContext context{
376 .writer = *(writer.get()),
377 .typenames = typenames,
378 .type = field->GetType(),
379 .parcel = parcel_variable->name,
380 .var = field->GetName(),
381 .is_classloader_created = &is_classloader_created,
382 };
383 ToStringFor(context);
384 writer->Close();
385 out << " _aidl_sj.add(\"" << field->GetName() << ": \" + (" << code << "));\n";
386 }
387 out << " return \"" << parcel->GetCanonicalName() << "\" + _aidl_sj.toString() ;\n";
388 out << "}\n";
389 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
390 }
391
Steven Moreland48548e02019-09-18 15:10:22 -0700392 auto describe_contents_method = std::make_shared<Method>();
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900393 describe_contents_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900394 describe_contents_method->returnType = "int";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900395 describe_contents_method->name = "describeContents";
Steven Moreland48548e02019-09-18 15:10:22 -0700396 describe_contents_method->statements = std::make_shared<StatementBlock>();
397 describe_contents_method->statements->Add(std::make_shared<LiteralStatement>("return 0;\n"));
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900398 parcel_class->elements.push_back(describe_contents_method);
399
Steven Moreland5557f1c2018-07-02 13:50:23 -0700400 return parcel_class;
401}
402
Daniel Norman716d3112019-09-10 13:11:56 -0700403void generate_enum(const CodeWriterPtr& code_writer, const AidlEnumDeclaration* enum_decl,
404 const AidlTypenames& typenames) {
405 code_writer->Write(
406 "/*\n"
407 " * This file is auto-generated. DO NOT MODIFY.\n"
408 " */\n");
409
410 code_writer->Write("package %s;\n", enum_decl->GetPackage().c_str());
Daniel Norman2e4112d2019-10-03 10:22:35 -0700411 code_writer->Write("%s\n", enum_decl->GetComments().c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700412 for (const std::string& annotation : generate_java_annotations(*enum_decl)) {
Steven Morelandd3721d62019-12-09 13:04:16 -0800413 code_writer->Write("%s", annotation.c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700414 }
415 code_writer->Write("public @interface %s {\n", enum_decl->GetName().c_str());
416 code_writer->Indent();
417 for (const auto& enumerator : enum_decl->GetEnumerators()) {
Steven Morelandd3721d62019-12-09 13:04:16 -0800418 code_writer->Write("%s", enumerator->GetComments().c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700419 code_writer->Write(
420 "public static final %s %s = %s;\n",
421 JavaSignatureOf(enum_decl->GetBackingType(), typenames).c_str(),
422 enumerator->GetName().c_str(),
Daniel Norman37d43dd2019-09-09 17:22:34 -0700423 enumerator->ValueString(enum_decl->GetBackingType(), ConstantValueDecorator).c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700424 }
425 code_writer->Dedent();
426 code_writer->Write("}\n");
427}
428
Mathew Inwoodadb74672019-11-29 14:01:53 +0000429std::string dump_location(const AidlNode& method) {
430 return method.PrintLocation();
431}
432
433std::string generate_java_unsupportedappusage_parameters(const AidlAnnotation& a) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700434 const std::map<std::string, std::string> params = a.AnnotationParams(ConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100435 std::vector<string> parameters_decl;
436 for (const auto& name_and_param : params) {
437 const std::string& param_name = name_and_param.first;
438 const std::string& param_value = name_and_param.second;
439 parameters_decl.push_back(param_name + " = " + param_value);
440 }
Mathew Inwoodadb74672019-11-29 14:01:53 +0000441 parameters_decl.push_back("overrideSourcePosition=\"" + dump_location(a) + "\"");
Andrei Onea9445fc62019-06-27 18:11:59 +0100442 return "(" + base::Join(parameters_decl, ", ") + ")";
443}
444
Jiyong Parka6605ab2018-11-11 14:30:21 +0900445std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
446 std::vector<std::string> result;
Makoto Onuki78a1c1c2020-03-04 16:57:23 -0800447 if (a.IsHide()) {
448 result.emplace_back("@android.annotation.Hide");
449 }
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900450
451 const AidlAnnotation* unsupported_app_usage = a.UnsupportedAppUsage();
Andrei Onea9445fc62019-06-27 18:11:59 +0100452 if (unsupported_app_usage != nullptr) {
Artur Satayev55120a72019-12-09 12:19:11 +0000453 result.emplace_back("@android.compat.annotation.UnsupportedAppUsage" +
Mathew Inwoodadb74672019-11-29 14:01:53 +0000454 generate_java_unsupportedappusage_parameters(*unsupported_app_usage));
Jiyong Parka6605ab2018-11-11 14:30:21 +0900455 }
Jiyong Parkbf5fd5c2020-06-05 19:48:05 +0900456
457 auto strip_double_quote = [](const AidlTypeSpecifier& type, const std::string& raw_value) -> std::string {
458 if (!android::base::StartsWith(raw_value, "\"") ||
459 !android::base::EndsWith(raw_value, "\"")) {
460 AIDL_FATAL(type) << "Java passthrough annotation " << raw_value << " is not properly quoted";
461 return "";
462 }
463 return raw_value.substr(1, raw_value.size() - 2);
464 };
465
466 const AidlAnnotation* java_passthrough = a.JavaPassthrough();
467 if (java_passthrough != nullptr) {
468 for (const auto& name_and_param : java_passthrough->AnnotationParams(strip_double_quote)) {
469 if (name_and_param.first == "annotation") {
470 result.emplace_back(name_and_param.second);
471 break;
472 }
473 }
474 }
475
Jiyong Parka6605ab2018-11-11 14:30:21 +0900476 return result;
477}
478
Christopher Wileydb154a52015-09-28 16:32:25 -0700479} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700480} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -0700481} // namespace android