blob: 01c24329bc6f481b3724b092a8373b60e213727f [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 Park74595c12018-07-23 15:22:50 +090039bool generate_java_interface(const string& filename, const string& original_src,
40 const AidlInterface* iface, JavaTypeNamespace* types,
41 const IoDelegate& io_delegate, 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 =
45 new Document("" /* no comment */, iface->GetPackage(), original_src, 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 Park74595c12018-07-23 15:22:50 +090053bool generate_java_parcel(const std::string& filename, const std::string& original_src,
54 const AidlStructuredParcelable* parcel, JavaTypeNamespace* types,
55 const IoDelegate& io_delegate, const Options& options) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070056 Class* cl = generate_parcel_class(parcel, types, options);
57
58 Document* document =
59 new Document("" /* no comment */, parcel->GetPackage(), original_src, unique_ptr<Class>(cl));
60
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
Steven Moreland2a9a7d62019-02-05 16:11:54 -080067bool generate_java_parcel_declaration(const std::string& filename, const IoDelegate& io_delegate) {
68 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
69 *code_writer
70 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
71
72 return true;
73}
74
Jiyong Park74595c12018-07-23 15:22:50 +090075bool generate_java(const std::string& filename, const std::string& original_src,
76 const AidlDefinedType* defined_type, JavaTypeNamespace* types,
77 const IoDelegate& io_delegate, const Options& options) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070078 const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
79 if (parcelable != nullptr) {
80 return generate_java_parcel(filename, original_src, parcelable, types, io_delegate, options);
81 }
82
Steven Moreland2a9a7d62019-02-05 16:11:54 -080083 const AidlParcelable* parcelable_decl = defined_type->AsParcelable();
84 if (parcelable_decl != nullptr) {
85 return generate_java_parcel_declaration(filename, io_delegate);
86 }
87
Steven Moreland5557f1c2018-07-02 13:50:23 -070088 const AidlInterface* interface = defined_type->AsInterface();
89 if (interface != nullptr) {
90 return generate_java_interface(filename, original_src, interface, types, io_delegate, options);
91 }
92
93 CHECK(false) << "Unrecognized type sent for cpp generation.";
94 return false;
95}
96
97android::aidl::java::Class* generate_parcel_class(const AidlStructuredParcelable* parcel,
98 java::JavaTypeNamespace* types,
Jiyong Park74595c12018-07-23 15:22:50 +090099 const Options& /*options*/) {
Steven Moreland5557f1c2018-07-02 13:50:23 -0700100 const ParcelType* parcelType = parcel->GetLanguageType<ParcelType>();
101
102 Class* parcel_class = new Class;
103 parcel_class->comment = parcel->GetComments();
104 parcel_class->modifiers = PUBLIC;
105 parcel_class->what = Class::CLASS;
106 parcel_class->type = parcelType;
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900107 parcel_class->interfaces.push_back(types->ParcelableInterfaceType());
Jiyong Parka6605ab2018-11-11 14:30:21 +0900108 parcel_class->annotations = generate_java_annotations(*parcel);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700109
110 for (const auto& variable : parcel->GetFields()) {
111 const Type* type = variable->GetType().GetLanguageType<Type>();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700112
113 std::ostringstream out;
Jiyong Parka6605ab2018-11-11 14:30:21 +0900114 out << variable->GetType().GetComments() << "\n";
115 for (const auto& a : generate_java_annotations(variable->GetType())) {
116 out << a << "\n";
117 }
Steven Moreland9ea10e32018-07-19 15:26:09 -0700118 out << "public " << type->JavaType() << (variable->GetType().IsArray() ? "[]" : "") << " "
119 << variable->GetName();
Steven Moreland25294322018-08-07 18:13:55 -0700120 if (variable->GetDefaultValue()) {
Steven Moreland860b1942018-08-16 14:59:28 -0700121 out << " = " << variable->ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700122 }
123 out << ";\n";
124 parcel_class->elements.push_back(new LiteralClassElement(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700125 }
126
127 std::ostringstream out;
128 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
129 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900130 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700131 out << " public " << parcel->GetName()
132 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
133 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
134 out << " _aidl_out.readFromParcel(_aidl_source);\n";
135 out << " return _aidl_out;\n";
136 out << " }\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900137 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700138 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
139 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
140 out << " }\n";
141 out << "};\n";
142 parcel_class->elements.push_back(new LiteralClassElement(out.str()));
143
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900144 Variable* flag_variable = new Variable(new Type(types, "int", 0, false), "_aidl_flag");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700145 Variable* parcel_variable =
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900146 new Variable(new Type(types, "android.os.Parcel", 0, false), "_aidl_parcel");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700147
148 Method* write_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900149 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900150 write_method->returnType = new Type(types, "void", 0, false);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700151 write_method->name = "writeToParcel";
152 write_method->parameters.push_back(parcel_variable);
153 write_method->parameters.push_back(flag_variable);
154 write_method->statements = new StatementBlock();
Jeongik Cha95eba572018-11-22 09:14:52 +0900155
156 out.str("");
157 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
158 << "_aidl_parcel.writeInt(0);\n";
159 write_method->statements->Add(new LiteralStatement(out.str()));
160
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900161 for (const auto& field : parcel->GetFields()) {
162 string code;
163 CodeWriterPtr writer = CodeWriter::ForString(&code);
164 CodeGeneratorContext context{
165 .writer = *(writer.get()),
166 .typenames = types->typenames_,
167 .type = field->GetType(),
168 .var = field->GetName(),
169 .parcel = parcel_variable->name,
170 .is_return_value = false,
171 };
172 WriteToParcelFor(context);
173 writer->Close();
174 write_method->statements->Add(new LiteralStatement(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700175 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900176
177 out.str("");
178 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
179 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
180 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
181 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
182
183 write_method->statements->Add(new LiteralStatement(out.str()));
184
Steven Moreland5557f1c2018-07-02 13:50:23 -0700185 parcel_class->elements.push_back(write_method);
186
187 Method* read_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900188 read_method->modifiers = PUBLIC | FINAL;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900189 read_method->returnType = new Type(types, "void", 0, false);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700190 read_method->name = "readFromParcel";
191 read_method->parameters.push_back(parcel_variable);
192 read_method->statements = new StatementBlock();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900193
Jeongik Cha95eba572018-11-22 09:14:52 +0900194 out.str("");
195 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
196 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
197 << "if (_aidl_parcelable_size < 0) return;\n"
198 << "try {\n";
199
200 read_method->statements->Add(new LiteralStatement(out.str()));
201
202 out.str("");
203 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;\n";
204
George Burgess IV8efe21a2018-12-05 16:40:40 -0800205 LiteralStatement* sizeCheck = nullptr;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900206 // keep this across different fields in order to create the classloader
207 // at most once.
208 bool is_classloader_created = false;
209 for (const auto& field : parcel->GetFields()) {
210 string code;
211 CodeWriterPtr writer = CodeWriter::ForString(&code);
212 CodeGeneratorContext context{
213 .writer = *(writer.get()),
214 .typenames = types->typenames_,
215 .type = field->GetType(),
216 .var = field->GetName(),
217 .parcel = parcel_variable->name,
218 .is_classloader_created = &is_classloader_created,
219 };
Jeongik Cha95eba572018-11-22 09:14:52 +0900220 context.writer.Indent();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900221 CreateFromParcelFor(context);
222 writer->Close();
223 read_method->statements->Add(new LiteralStatement(code));
George Burgess IV8efe21a2018-12-05 16:40:40 -0800224 if (!sizeCheck) sizeCheck = new LiteralStatement(out.str());
Jeongik Cha95eba572018-11-22 09:14:52 +0900225 read_method->statements->Add(sizeCheck);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700226 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900227
228 out.str("");
229 out << "} finally {\n"
230 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
231 << "}\n";
232
233 read_method->statements->Add(new LiteralStatement(out.str()));
234
Steven Moreland5557f1c2018-07-02 13:50:23 -0700235 parcel_class->elements.push_back(read_method);
236
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900237 Method* describe_contents_method = new Method;
238 describe_contents_method->modifiers = PUBLIC | OVERRIDE;
239 describe_contents_method->returnType = types->IntType();
240 describe_contents_method->name = "describeContents";
241 describe_contents_method->statements = new StatementBlock();
Jeongik Cha372a8c82018-12-12 16:31:11 +0900242 describe_contents_method->statements->Add(new LiteralStatement("return 0;\n"));
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900243 parcel_class->elements.push_back(describe_contents_method);
244
Steven Moreland5557f1c2018-07-02 13:50:23 -0700245 return parcel_class;
246}
247
Jiyong Parka6605ab2018-11-11 14:30:21 +0900248std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
249 std::vector<std::string> result;
250 if (a.IsUnsupportedAppUsage()) {
251 result.emplace_back("@android.annotation.UnsupportedAppUsage");
252 }
Jeongik Cha698e6af2018-12-12 14:39:55 +0900253 if (a.IsSystemApi()) {
254 result.emplace_back("@android.annotation.SystemApi");
255 }
Jiyong Parka6605ab2018-11-11 14:30:21 +0900256 return result;
257}
258
Christopher Wileydb154a52015-09-28 16:32:25 -0700259} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700260} // namespace android
261} // namespace aidl