blob: 5d572a4bb93c993d88db303250588cc7e21e2a8f [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>
Andrei Onea9445fc62019-06-27 18:11:59 +010022#include <map>
Steven Moreland5557f1c2018-07-02 13:50:23 -070023#include <memory>
24#include <sstream>
Adam Lesinskiffa16862014-01-23 18:17:42 -080025
Christopher Wiley3a9da172016-01-29 11:10:49 -080026#include <android-base/stringprintf.h>
27
Jiyong Park1d2df7d2018-07-23 15:22:50 +090028#include "aidl_to_java.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070029#include "code_writer.h"
Jeongik Chaa2080bf2019-06-18 16:44:29 +090030#include "logging.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070031
Christopher Wileyf76b59a2016-01-29 11:32:11 -080032using std::unique_ptr;
Christopher Wileydb154a52015-09-28 16:32:25 -070033using ::android::aidl::java::Variable;
Christopher Wiley3a9da172016-01-29 11:10:49 -080034using std::string;
Christopher Wileydb154a52015-09-28 16:32:25 -070035
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070036namespace android {
37namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070038namespace java {
39
Jiyong Park54fa1e02019-02-08 10:03:20 +090040bool generate_java_interface(const string& filename, const AidlInterface* iface,
Jeongik Chaa2080bf2019-06-18 16:44:29 +090041 const AidlTypenames& typenames, const IoDelegate& io_delegate,
Jiyong Park54fa1e02019-02-08 10:03:20 +090042 const Options& options) {
Steven Moreland48548e02019-09-18 15:10:22 -070043 auto cl = generate_binder_interface_class(iface, typenames, options);
Adam Lesinskiffa16862014-01-23 18:17:42 -080044
Steven Moreland48548e02019-09-18 15:10:22 -070045 std::unique_ptr<Document> document =
46 std::make_unique<Document>("" /* no comment */, iface->GetPackage(), std::move(cl));
Adam Lesinskiffa16862014-01-23 18:17:42 -080047
Christopher Wiley3a9da172016-01-29 11:10:49 -080048 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
49 document->Write(code_writer.get());
Adam Lesinskiffa16862014-01-23 18:17:42 -080050
Jiyong Park74595c12018-07-23 15:22:50 +090051 return true;
Adam Lesinskiffa16862014-01-23 18:17:42 -080052}
53
Jiyong Park54fa1e02019-02-08 10:03:20 +090054bool generate_java_parcel(const std::string& filename, const AidlStructuredParcelable* parcel,
Jeongik Chaa2080bf2019-06-18 16:44:29 +090055 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
Steven Moreland48548e02019-09-18 15:10:22 -070056 auto cl = generate_parcel_class(parcel, typenames);
Steven Moreland5557f1c2018-07-02 13:50:23 -070057
Steven Moreland48548e02019-09-18 15:10:22 -070058 std::unique_ptr<Document> document =
59 std::make_unique<Document>("" /* no comment */, parcel->GetPackage(), std::move(cl));
Steven Moreland5557f1c2018-07-02 13:50:23 -070060
61 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
62 document->Write(code_writer.get());
63
Jiyong Park74595c12018-07-23 15:22:50 +090064 return true;
Steven Moreland5557f1c2018-07-02 13:50:23 -070065}
66
Daniel Norman716d3112019-09-10 13:11:56 -070067bool generate_java_enum_declaration(const std::string& filename,
68 const AidlEnumDeclaration* enum_decl,
69 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
70 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
71 generate_enum(code_writer, enum_decl, typenames);
72 return true;
73}
74
Jiyong Park54fa1e02019-02-08 10:03:20 +090075bool generate_java(const std::string& filename, const AidlDefinedType* defined_type,
Jeongik Chaa2080bf2019-06-18 16:44:29 +090076 const AidlTypenames& typenames, const IoDelegate& io_delegate,
Jiyong Park54fa1e02019-02-08 10:03:20 +090077 const Options& options) {
Daniel Norman716d3112019-09-10 13:11:56 -070078 if (const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
79 parcelable != nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +090080 return generate_java_parcel(filename, parcelable, typenames, io_delegate);
Steven Moreland5557f1c2018-07-02 13:50:23 -070081 }
82
Daniel Norman716d3112019-09-10 13:11:56 -070083 if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
84 enum_decl != nullptr) {
85 return generate_java_enum_declaration(filename, enum_decl, typenames, io_delegate);
86 }
87
88 if (const AidlInterface* interface = defined_type->AsInterface(); interface != nullptr) {
Jeongik Chaa2080bf2019-06-18 16:44:29 +090089 return generate_java_interface(filename, interface, typenames, io_delegate, options);
Steven Moreland5557f1c2018-07-02 13:50:23 -070090 }
91
Daniel Norman85aed542019-08-21 12:01:14 -070092 CHECK(false) << "Unrecognized type sent for java generation.";
Steven Moreland5557f1c2018-07-02 13:50:23 -070093 return false;
94}
95
Steven Moreland48548e02019-09-18 15:10:22 -070096std::unique_ptr<android::aidl::java::Class> generate_parcel_class(
97 const AidlStructuredParcelable* parcel, const AidlTypenames& typenames) {
98 auto parcel_class = std::make_unique<Class>();
Steven Moreland5557f1c2018-07-02 13:50:23 -070099 parcel_class->comment = parcel->GetComments();
100 parcel_class->modifiers = PUBLIC;
101 parcel_class->what = Class::CLASS;
Jeongik Chaaabc1442019-02-12 17:44:48 +0900102 parcel_class->type = parcel->GetCanonicalName();
103 parcel_class->interfaces.push_back("android.os.Parcelable");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900104 parcel_class->annotations = generate_java_annotations(*parcel);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700105
106 for (const auto& variable : parcel->GetFields()) {
Steven Moreland9ea10e32018-07-19 15:26:09 -0700107 std::ostringstream out;
Jiyong Parka6605ab2018-11-11 14:30:21 +0900108 out << variable->GetType().GetComments() << "\n";
109 for (const auto& a : generate_java_annotations(variable->GetType())) {
110 out << a << "\n";
111 }
Daniel Norman716d3112019-09-10 13:11:56 -0700112 out << "public " << JavaSignatureOf(variable->GetType(), typenames) << " "
113 << variable->GetName();
Steven Moreland25294322018-08-07 18:13:55 -0700114 if (variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700115 out << " = " << variable->ValueString(ConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700116 }
117 out << ";\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700118 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700119 }
120
121 std::ostringstream out;
122 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
123 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900124 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700125 out << " public " << parcel->GetName()
126 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
127 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
128 out << " _aidl_out.readFromParcel(_aidl_source);\n";
129 out << " return _aidl_out;\n";
130 out << " }\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900131 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700132 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
133 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
134 out << " }\n";
135 out << "};\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700136 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700137
Steven Moreland48548e02019-09-18 15:10:22 -0700138 auto flag_variable = std::make_shared<Variable>("int", "_aidl_flag");
139 auto parcel_variable = std::make_shared<Variable>("android.os.Parcel", "_aidl_parcel");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700140
Steven Moreland48548e02019-09-18 15:10:22 -0700141 auto write_method = std::make_shared<Method>();
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900142 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900143 write_method->returnType = "void";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700144 write_method->name = "writeToParcel";
145 write_method->parameters.push_back(parcel_variable);
146 write_method->parameters.push_back(flag_variable);
Steven Moreland48548e02019-09-18 15:10:22 -0700147 write_method->statements = std::make_shared<StatementBlock>();
Jeongik Cha95eba572018-11-22 09:14:52 +0900148
149 out.str("");
150 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
151 << "_aidl_parcel.writeInt(0);\n";
Steven Moreland48548e02019-09-18 15:10:22 -0700152 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900153
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900154 for (const auto& field : parcel->GetFields()) {
155 string code;
156 CodeWriterPtr writer = CodeWriter::ForString(&code);
157 CodeGeneratorContext context{
158 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900159 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900160 .type = field->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900161 .parcel = parcel_variable->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700162 .var = field->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900163 .is_return_value = false,
164 };
165 WriteToParcelFor(context);
166 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700167 write_method->statements->Add(std::make_shared<LiteralStatement>(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700168 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900169
170 out.str("");
171 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
172 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
173 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
174 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
175
Steven Moreland48548e02019-09-18 15:10:22 -0700176 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900177
Steven Moreland5557f1c2018-07-02 13:50:23 -0700178 parcel_class->elements.push_back(write_method);
179
Steven Moreland48548e02019-09-18 15:10:22 -0700180 auto read_method = std::make_shared<Method>();
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900181 read_method->modifiers = PUBLIC | FINAL;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900182 read_method->returnType = "void";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700183 read_method->name = "readFromParcel";
184 read_method->parameters.push_back(parcel_variable);
Steven Moreland48548e02019-09-18 15:10:22 -0700185 read_method->statements = std::make_shared<StatementBlock>();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900186
Jeongik Cha95eba572018-11-22 09:14:52 +0900187 out.str("");
188 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
189 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
190 << "if (_aidl_parcelable_size < 0) return;\n"
191 << "try {\n";
192
Steven Moreland48548e02019-09-18 15:10:22 -0700193 read_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900194
195 out.str("");
196 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;\n";
197
Steven Moreland48548e02019-09-18 15:10:22 -0700198 std::shared_ptr<LiteralStatement> sizeCheck = nullptr;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900199 // keep this across different fields in order to create the classloader
200 // at most once.
201 bool is_classloader_created = false;
202 for (const auto& field : parcel->GetFields()) {
203 string code;
204 CodeWriterPtr writer = CodeWriter::ForString(&code);
205 CodeGeneratorContext context{
206 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900207 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900208 .type = field->GetType(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900209 .parcel = parcel_variable->name,
Nick Desaulniers27e1ff62019-10-07 23:13:10 -0700210 .var = field->GetName(),
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900211 .is_classloader_created = &is_classloader_created,
212 };
Jeongik Cha95eba572018-11-22 09:14:52 +0900213 context.writer.Indent();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900214 CreateFromParcelFor(context);
215 writer->Close();
Steven Moreland48548e02019-09-18 15:10:22 -0700216 read_method->statements->Add(std::make_shared<LiteralStatement>(code));
217 if (!sizeCheck) sizeCheck = std::make_shared<LiteralStatement>(out.str());
Jeongik Cha95eba572018-11-22 09:14:52 +0900218 read_method->statements->Add(sizeCheck);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700219 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900220
221 out.str("");
222 out << "} finally {\n"
223 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
224 << "}\n";
225
Steven Moreland48548e02019-09-18 15:10:22 -0700226 read_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
Jeongik Cha95eba572018-11-22 09:14:52 +0900227
Steven Moreland5557f1c2018-07-02 13:50:23 -0700228 parcel_class->elements.push_back(read_method);
229
Steven Moreland48548e02019-09-18 15:10:22 -0700230 auto describe_contents_method = std::make_shared<Method>();
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900231 describe_contents_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900232 describe_contents_method->returnType = "int";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900233 describe_contents_method->name = "describeContents";
Steven Moreland48548e02019-09-18 15:10:22 -0700234 describe_contents_method->statements = std::make_shared<StatementBlock>();
235 describe_contents_method->statements->Add(std::make_shared<LiteralStatement>("return 0;\n"));
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900236 parcel_class->elements.push_back(describe_contents_method);
237
Steven Moreland5557f1c2018-07-02 13:50:23 -0700238 return parcel_class;
239}
240
Daniel Norman716d3112019-09-10 13:11:56 -0700241void generate_enum(const CodeWriterPtr& code_writer, const AidlEnumDeclaration* enum_decl,
242 const AidlTypenames& typenames) {
243 code_writer->Write(
244 "/*\n"
245 " * This file is auto-generated. DO NOT MODIFY.\n"
246 " */\n");
247
248 code_writer->Write("package %s;\n", enum_decl->GetPackage().c_str());
Daniel Norman2e4112d2019-10-03 10:22:35 -0700249 code_writer->Write("%s\n", enum_decl->GetComments().c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700250 for (const std::string& annotation : generate_java_annotations(*enum_decl)) {
Steven Morelandd3721d62019-12-09 13:04:16 -0800251 code_writer->Write("%s", annotation.c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700252 }
253 code_writer->Write("public @interface %s {\n", enum_decl->GetName().c_str());
254 code_writer->Indent();
255 for (const auto& enumerator : enum_decl->GetEnumerators()) {
Steven Morelandd3721d62019-12-09 13:04:16 -0800256 code_writer->Write("%s", enumerator->GetComments().c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700257 code_writer->Write(
258 "public static final %s %s = %s;\n",
259 JavaSignatureOf(enum_decl->GetBackingType(), typenames).c_str(),
260 enumerator->GetName().c_str(),
Daniel Norman37d43dd2019-09-09 17:22:34 -0700261 enumerator->ValueString(enum_decl->GetBackingType(), ConstantValueDecorator).c_str());
Daniel Norman716d3112019-09-10 13:11:56 -0700262 }
263 code_writer->Dedent();
264 code_writer->Write("}\n");
265}
266
Mathew Inwoodadb74672019-11-29 14:01:53 +0000267std::string dump_location(const AidlNode& method) {
268 return method.PrintLocation();
269}
270
271std::string generate_java_unsupportedappusage_parameters(const AidlAnnotation& a) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700272 const std::map<std::string, std::string> params = a.AnnotationParams(ConstantValueDecorator);
Andrei Onea9445fc62019-06-27 18:11:59 +0100273 std::vector<string> parameters_decl;
274 for (const auto& name_and_param : params) {
275 const std::string& param_name = name_and_param.first;
276 const std::string& param_value = name_and_param.second;
277 parameters_decl.push_back(param_name + " = " + param_value);
278 }
Mathew Inwoodadb74672019-11-29 14:01:53 +0000279 parameters_decl.push_back("overrideSourcePosition=\"" + dump_location(a) + "\"");
Andrei Onea9445fc62019-06-27 18:11:59 +0100280 return "(" + base::Join(parameters_decl, ", ") + ")";
281}
282
Jiyong Parka6605ab2018-11-11 14:30:21 +0900283std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
284 std::vector<std::string> result;
Andrei Onea9445fc62019-06-27 18:11:59 +0100285 const AidlAnnotation* unsupported_app_usage = a.UnsupportedAppUsage();
Makoto Onuki00be5c72020-03-04 16:57:23 -0800286 if (a.IsHide()) {
287 result.emplace_back("@android.annotation.Hide");
288 }
Andrei Onea9445fc62019-06-27 18:11:59 +0100289 if (unsupported_app_usage != nullptr) {
Artur Satayev55120a72019-12-09 12:19:11 +0000290 result.emplace_back("@android.compat.annotation.UnsupportedAppUsage" +
Mathew Inwoodadb74672019-11-29 14:01:53 +0000291 generate_java_unsupportedappusage_parameters(*unsupported_app_usage));
Jiyong Parka6605ab2018-11-11 14:30:21 +0900292 }
293 return result;
294}
295
Christopher Wileydb154a52015-09-28 16:32:25 -0700296} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700297} // namespace aidl
Steven Morelandf4c64df2019-07-29 19:54:04 -0700298} // namespace android