blob: 082b4ba34a3dffd9802b580776d97cbfd84ebaf7 [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>
Steven Moreland5557f1c2018-07-02 13:50:23 -070022#include <memory>
23#include <sstream>
Adam Lesinskiffa16862014-01-23 18:17:42 -080024
Christopher Wiley3a9da172016-01-29 11:10:49 -080025#include <android-base/stringprintf.h>
26
Jiyong Park1d2df7d2018-07-23 15:22:50 +090027#include "aidl_to_java.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070028#include "code_writer.h"
Christopher Wiley775fa1f2015-09-22 15:00:12 -070029#include "type_java.h"
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070030
Christopher Wileyf76b59a2016-01-29 11:32:11 -080031using std::unique_ptr;
Christopher Wileydb154a52015-09-28 16:32:25 -070032using ::android::aidl::java::Variable;
Christopher Wiley3a9da172016-01-29 11:10:49 -080033using std::string;
Christopher Wileydb154a52015-09-28 16:32:25 -070034
Christopher Wileyfdeb0f42015-09-11 15:38:22 -070035namespace android {
36namespace aidl {
Christopher Wileydb154a52015-09-28 16:32:25 -070037namespace java {
38
Jiyong Park54fa1e02019-02-08 10:03:20 +090039bool generate_java_interface(const string& filename, const AidlInterface* iface,
40 JavaTypeNamespace* types, const IoDelegate& io_delegate,
41 const Options& options) {
Andreas Gampee9c816e2018-03-14 09:05:48 -070042 Class* cl = generate_binder_interface_class(iface, types, options);
Adam Lesinskiffa16862014-01-23 18:17:42 -080043
Steven Moreland5557f1c2018-07-02 13:50:23 -070044 Document* document =
Jiyong Park54fa1e02019-02-08 10:03:20 +090045 new Document("" /* no comment */, iface->GetPackage(), unique_ptr<Class>(cl));
Adam Lesinskiffa16862014-01-23 18:17:42 -080046
Christopher Wiley3a9da172016-01-29 11:10:49 -080047 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
48 document->Write(code_writer.get());
Adam Lesinskiffa16862014-01-23 18:17:42 -080049
Jiyong Park74595c12018-07-23 15:22:50 +090050 return true;
Adam Lesinskiffa16862014-01-23 18:17:42 -080051}
52
Jiyong Park54fa1e02019-02-08 10:03:20 +090053bool generate_java_parcel(const std::string& filename, const AidlStructuredParcelable* parcel,
54 AidlTypenames& typenames, const IoDelegate& io_delegate) {
Jeongik Cha6cadc212019-02-12 18:16:03 +090055 Class* cl = generate_parcel_class(parcel, typenames);
Steven Moreland5557f1c2018-07-02 13:50:23 -070056
57 Document* document =
Jiyong Park54fa1e02019-02-08 10:03:20 +090058 new Document("" /* no comment */, parcel->GetPackage(), unique_ptr<Class>(cl));
Steven Moreland5557f1c2018-07-02 13:50:23 -070059
60 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
61 document->Write(code_writer.get());
62
Jiyong Park74595c12018-07-23 15:22:50 +090063 return true;
Steven Moreland5557f1c2018-07-02 13:50:23 -070064}
65
Steven Moreland2a9a7d62019-02-05 16:11:54 -080066bool generate_java_parcel_declaration(const std::string& filename, const IoDelegate& io_delegate) {
67 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
68 *code_writer
69 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
70
71 return true;
72}
73
Jiyong Park54fa1e02019-02-08 10:03:20 +090074bool generate_java(const std::string& filename, const AidlDefinedType* defined_type,
75 JavaTypeNamespace* types, const IoDelegate& io_delegate,
76 const Options& options) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070077 const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
78 if (parcelable != nullptr) {
Jiyong Park54fa1e02019-02-08 10:03:20 +090079 return generate_java_parcel(filename, parcelable, types->typenames_, io_delegate);
Steven Moreland5557f1c2018-07-02 13:50:23 -070080 }
81
Steven Moreland2a9a7d62019-02-05 16:11:54 -080082 const AidlParcelable* parcelable_decl = defined_type->AsParcelable();
83 if (parcelable_decl != nullptr) {
84 return generate_java_parcel_declaration(filename, io_delegate);
85 }
86
Steven Moreland5557f1c2018-07-02 13:50:23 -070087 const AidlInterface* interface = defined_type->AsInterface();
88 if (interface != nullptr) {
Jiyong Park54fa1e02019-02-08 10:03:20 +090089 return generate_java_interface(filename, interface, types, io_delegate, options);
Steven Moreland5557f1c2018-07-02 13:50:23 -070090 }
91
92 CHECK(false) << "Unrecognized type sent for cpp generation.";
93 return false;
94}
95
96android::aidl::java::Class* generate_parcel_class(const AidlStructuredParcelable* parcel,
Jeongik Cha6cadc212019-02-12 18:16:03 +090097 AidlTypenames& typenames) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070098 Class* parcel_class = new Class;
99 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()) {
107 const Type* type = variable->GetType().GetLanguageType<Type>();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700108
109 std::ostringstream out;
Jiyong Parka6605ab2018-11-11 14:30:21 +0900110 out << variable->GetType().GetComments() << "\n";
111 for (const auto& a : generate_java_annotations(variable->GetType())) {
112 out << a << "\n";
113 }
Steven Moreland9ea10e32018-07-19 15:26:09 -0700114 out << "public " << type->JavaType() << (variable->GetType().IsArray() ? "[]" : "") << " "
115 << variable->GetName();
Steven Moreland25294322018-08-07 18:13:55 -0700116 if (variable->GetDefaultValue()) {
Steven Moreland860b1942018-08-16 14:59:28 -0700117 out << " = " << variable->ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700118 }
119 out << ";\n";
120 parcel_class->elements.push_back(new LiteralClassElement(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700121 }
122
123 std::ostringstream out;
124 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
125 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900126 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700127 out << " public " << parcel->GetName()
128 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
129 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
130 out << " _aidl_out.readFromParcel(_aidl_source);\n";
131 out << " return _aidl_out;\n";
132 out << " }\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900133 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700134 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
135 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
136 out << " }\n";
137 out << "};\n";
138 parcel_class->elements.push_back(new LiteralClassElement(out.str()));
139
Jeongik Chadc77c1b2019-02-12 16:13:25 +0900140 Variable* flag_variable = new Variable("int", "_aidl_flag");
141 Variable* parcel_variable = new Variable("android.os.Parcel", "_aidl_parcel");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700142
143 Method* write_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900144 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900145 write_method->returnType = "void";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700146 write_method->name = "writeToParcel";
147 write_method->parameters.push_back(parcel_variable);
148 write_method->parameters.push_back(flag_variable);
149 write_method->statements = new StatementBlock();
Jeongik Cha95eba572018-11-22 09:14:52 +0900150
151 out.str("");
152 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
153 << "_aidl_parcel.writeInt(0);\n";
154 write_method->statements->Add(new LiteralStatement(out.str()));
155
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900156 for (const auto& field : parcel->GetFields()) {
157 string code;
158 CodeWriterPtr writer = CodeWriter::ForString(&code);
159 CodeGeneratorContext context{
160 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900161 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900162 .type = field->GetType(),
163 .var = field->GetName(),
164 .parcel = parcel_variable->name,
165 .is_return_value = false,
166 };
167 WriteToParcelFor(context);
168 writer->Close();
169 write_method->statements->Add(new LiteralStatement(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700170 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900171
172 out.str("");
173 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
174 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
175 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
176 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
177
178 write_method->statements->Add(new LiteralStatement(out.str()));
179
Steven Moreland5557f1c2018-07-02 13:50:23 -0700180 parcel_class->elements.push_back(write_method);
181
182 Method* read_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900183 read_method->modifiers = PUBLIC | FINAL;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900184 read_method->returnType = "void";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700185 read_method->name = "readFromParcel";
186 read_method->parameters.push_back(parcel_variable);
187 read_method->statements = new StatementBlock();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900188
Jeongik Cha95eba572018-11-22 09:14:52 +0900189 out.str("");
190 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
191 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
192 << "if (_aidl_parcelable_size < 0) return;\n"
193 << "try {\n";
194
195 read_method->statements->Add(new LiteralStatement(out.str()));
196
197 out.str("");
198 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;\n";
199
George Burgess IV8efe21a2018-12-05 16:40:40 -0800200 LiteralStatement* sizeCheck = nullptr;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900201 // keep this across different fields in order to create the classloader
202 // at most once.
203 bool is_classloader_created = false;
204 for (const auto& field : parcel->GetFields()) {
205 string code;
206 CodeWriterPtr writer = CodeWriter::ForString(&code);
207 CodeGeneratorContext context{
208 .writer = *(writer.get()),
Jeongik Cha6cadc212019-02-12 18:16:03 +0900209 .typenames = typenames,
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900210 .type = field->GetType(),
211 .var = field->GetName(),
212 .parcel = parcel_variable->name,
213 .is_classloader_created = &is_classloader_created,
214 };
Jeongik Cha95eba572018-11-22 09:14:52 +0900215 context.writer.Indent();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900216 CreateFromParcelFor(context);
217 writer->Close();
218 read_method->statements->Add(new LiteralStatement(code));
George Burgess IV8efe21a2018-12-05 16:40:40 -0800219 if (!sizeCheck) sizeCheck = new LiteralStatement(out.str());
Jeongik Cha95eba572018-11-22 09:14:52 +0900220 read_method->statements->Add(sizeCheck);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700221 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900222
223 out.str("");
224 out << "} finally {\n"
225 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
226 << "}\n";
227
228 read_method->statements->Add(new LiteralStatement(out.str()));
229
Steven Moreland5557f1c2018-07-02 13:50:23 -0700230 parcel_class->elements.push_back(read_method);
231
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900232 Method* describe_contents_method = new Method;
233 describe_contents_method->modifiers = PUBLIC | OVERRIDE;
Jeongik Cha6cadc212019-02-12 18:16:03 +0900234 describe_contents_method->returnType = "int";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900235 describe_contents_method->name = "describeContents";
236 describe_contents_method->statements = new StatementBlock();
Jeongik Cha372a8c82018-12-12 16:31:11 +0900237 describe_contents_method->statements->Add(new LiteralStatement("return 0;\n"));
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900238 parcel_class->elements.push_back(describe_contents_method);
239
Steven Moreland5557f1c2018-07-02 13:50:23 -0700240 return parcel_class;
241}
242
Jiyong Parka6605ab2018-11-11 14:30:21 +0900243std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
244 std::vector<std::string> result;
245 if (a.IsUnsupportedAppUsage()) {
Andrei Onea21dc8a52019-04-17 11:13:31 +0100246 result.emplace_back("@dalvik.annotation.compat.UnsupportedAppUsage");
Jiyong Parka6605ab2018-11-11 14:30:21 +0900247 }
Jeongik Cha698e6af2018-12-12 14:39:55 +0900248 if (a.IsSystemApi()) {
249 result.emplace_back("@android.annotation.SystemApi");
250 }
Jiyong Parka6605ab2018-11-11 14:30:21 +0900251 return result;
252}
253
Christopher Wileydb154a52015-09-28 16:32:25 -0700254} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700255} // namespace android
256} // namespace aidl