blob: 09211a640a408e169bd4020cb2fa6a4aacfa8b03 [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;
34using android::base::StringPrintf;
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 Park74595c12018-07-23 15:22:50 +090040bool generate_java_interface(const string& filename, const string& original_src,
41 const AidlInterface* iface, JavaTypeNamespace* types,
42 const IoDelegate& io_delegate, const Options& options) {
Andreas Gampee9c816e2018-03-14 09:05:48 -070043 Class* cl = generate_binder_interface_class(iface, types, options);
Adam Lesinskiffa16862014-01-23 18:17:42 -080044
Steven Moreland5557f1c2018-07-02 13:50:23 -070045 Document* document =
46 new Document("" /* no comment */, iface->GetPackage(), original_src, unique_ptr<Class>(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 Park74595c12018-07-23 15:22:50 +090054bool generate_java_parcel(const std::string& filename, const std::string& original_src,
55 const AidlStructuredParcelable* parcel, JavaTypeNamespace* types,
56 const IoDelegate& io_delegate, const Options& options) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070057 Class* cl = generate_parcel_class(parcel, types, options);
58
59 Document* document =
60 new Document("" /* no comment */, parcel->GetPackage(), original_src, unique_ptr<Class>(cl));
61
62 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
63 document->Write(code_writer.get());
64
Jiyong Park74595c12018-07-23 15:22:50 +090065 return true;
Steven Moreland5557f1c2018-07-02 13:50:23 -070066}
67
Jiyong Park74595c12018-07-23 15:22:50 +090068bool generate_java(const std::string& filename, const std::string& original_src,
69 const AidlDefinedType* defined_type, JavaTypeNamespace* types,
70 const IoDelegate& io_delegate, const Options& options) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070071 const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
72 if (parcelable != nullptr) {
73 return generate_java_parcel(filename, original_src, parcelable, types, io_delegate, options);
74 }
75
76 const AidlInterface* interface = defined_type->AsInterface();
77 if (interface != nullptr) {
78 return generate_java_interface(filename, original_src, interface, types, io_delegate, options);
79 }
80
81 CHECK(false) << "Unrecognized type sent for cpp generation.";
82 return false;
83}
84
85android::aidl::java::Class* generate_parcel_class(const AidlStructuredParcelable* parcel,
86 java::JavaTypeNamespace* types,
Jiyong Park74595c12018-07-23 15:22:50 +090087 const Options& /*options*/) {
Steven Moreland5557f1c2018-07-02 13:50:23 -070088 const ParcelType* parcelType = parcel->GetLanguageType<ParcelType>();
89
90 Class* parcel_class = new Class;
91 parcel_class->comment = parcel->GetComments();
92 parcel_class->modifiers = PUBLIC;
93 parcel_class->what = Class::CLASS;
94 parcel_class->type = parcelType;
Jiyong Parkb77f7a52018-09-13 21:32:38 +090095 parcel_class->interfaces.push_back(types->ParcelableInterfaceType());
Jiyong Parka6605ab2018-11-11 14:30:21 +090096 parcel_class->annotations = generate_java_annotations(*parcel);
Steven Moreland5557f1c2018-07-02 13:50:23 -070097
98 for (const auto& variable : parcel->GetFields()) {
99 const Type* type = variable->GetType().GetLanguageType<Type>();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700100
101 std::ostringstream out;
Jiyong Parka6605ab2018-11-11 14:30:21 +0900102 out << variable->GetType().GetComments() << "\n";
103 for (const auto& a : generate_java_annotations(variable->GetType())) {
104 out << a << "\n";
105 }
Steven Moreland9ea10e32018-07-19 15:26:09 -0700106 out << "public " << type->JavaType() << (variable->GetType().IsArray() ? "[]" : "") << " "
107 << variable->GetName();
Steven Moreland25294322018-08-07 18:13:55 -0700108 if (variable->GetDefaultValue()) {
Steven Moreland860b1942018-08-16 14:59:28 -0700109 out << " = " << variable->ValueString(AidlConstantValueDecorator);
Steven Moreland9ea10e32018-07-19 15:26:09 -0700110 }
111 out << ";\n";
112 parcel_class->elements.push_back(new LiteralClassElement(out.str()));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700113 }
114
115 std::ostringstream out;
116 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
117 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900118 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700119 out << " public " << parcel->GetName()
120 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
121 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
122 out << " _aidl_out.readFromParcel(_aidl_source);\n";
123 out << " return _aidl_out;\n";
124 out << " }\n";
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900125 out << " @Override\n";
Steven Moreland5557f1c2018-07-02 13:50:23 -0700126 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
127 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
128 out << " }\n";
129 out << "};\n";
130 parcel_class->elements.push_back(new LiteralClassElement(out.str()));
131
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900132 Variable* flag_variable = new Variable(new Type(types, "int", 0, false), "_aidl_flag");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700133 Variable* parcel_variable =
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900134 new Variable(new Type(types, "android.os.Parcel", 0, false), "_aidl_parcel");
Steven Moreland5557f1c2018-07-02 13:50:23 -0700135
136 Method* write_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900137 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900138 write_method->returnType = new Type(types, "void", 0, false);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700139 write_method->name = "writeToParcel";
140 write_method->parameters.push_back(parcel_variable);
141 write_method->parameters.push_back(flag_variable);
142 write_method->statements = new StatementBlock();
Jeongik Cha95eba572018-11-22 09:14:52 +0900143
144 out.str("");
145 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
146 << "_aidl_parcel.writeInt(0);\n";
147 write_method->statements->Add(new LiteralStatement(out.str()));
148
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900149 for (const auto& field : parcel->GetFields()) {
150 string code;
151 CodeWriterPtr writer = CodeWriter::ForString(&code);
152 CodeGeneratorContext context{
153 .writer = *(writer.get()),
154 .typenames = types->typenames_,
155 .type = field->GetType(),
156 .var = field->GetName(),
157 .parcel = parcel_variable->name,
158 .is_return_value = false,
159 };
160 WriteToParcelFor(context);
161 writer->Close();
162 write_method->statements->Add(new LiteralStatement(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700163 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900164
165 out.str("");
166 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
167 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
168 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
169 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
170
171 write_method->statements->Add(new LiteralStatement(out.str()));
172
Steven Moreland5557f1c2018-07-02 13:50:23 -0700173 parcel_class->elements.push_back(write_method);
174
175 Method* read_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900176 read_method->modifiers = PUBLIC | FINAL;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900177 read_method->returnType = new Type(types, "void", 0, false);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700178 read_method->name = "readFromParcel";
179 read_method->parameters.push_back(parcel_variable);
180 read_method->statements = new StatementBlock();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900181
Jeongik Cha95eba572018-11-22 09:14:52 +0900182 out.str("");
183 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
184 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
185 << "if (_aidl_parcelable_size < 0) return;\n"
186 << "try {\n";
187
188 read_method->statements->Add(new LiteralStatement(out.str()));
189
190 out.str("");
191 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;\n";
192
193 auto sizeCheck = new LiteralStatement(out.str());
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900194 // keep this across different fields in order to create the classloader
195 // at most once.
196 bool is_classloader_created = false;
197 for (const auto& field : parcel->GetFields()) {
198 string code;
199 CodeWriterPtr writer = CodeWriter::ForString(&code);
200 CodeGeneratorContext context{
201 .writer = *(writer.get()),
202 .typenames = types->typenames_,
203 .type = field->GetType(),
204 .var = field->GetName(),
205 .parcel = parcel_variable->name,
206 .is_classloader_created = &is_classloader_created,
207 };
Jeongik Cha95eba572018-11-22 09:14:52 +0900208 context.writer.Indent();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900209 CreateFromParcelFor(context);
210 writer->Close();
211 read_method->statements->Add(new LiteralStatement(code));
Jeongik Cha95eba572018-11-22 09:14:52 +0900212 read_method->statements->Add(sizeCheck);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700213 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900214
215 out.str("");
216 out << "} finally {\n"
217 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
218 << "}\n";
219
220 read_method->statements->Add(new LiteralStatement(out.str()));
221
Steven Moreland5557f1c2018-07-02 13:50:23 -0700222 parcel_class->elements.push_back(read_method);
223
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900224 Method* describe_contents_method = new Method;
225 describe_contents_method->modifiers = PUBLIC | OVERRIDE;
226 describe_contents_method->returnType = types->IntType();
227 describe_contents_method->name = "describeContents";
228 describe_contents_method->statements = new StatementBlock();
229 describe_contents_method->statements->Add(new LiteralStatement("return 0;"));
230 parcel_class->elements.push_back(describe_contents_method);
231
Steven Moreland5557f1c2018-07-02 13:50:23 -0700232 return parcel_class;
233}
234
Jiyong Parka6605ab2018-11-11 14:30:21 +0900235std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
236 std::vector<std::string> result;
237 if (a.IsUnsupportedAppUsage()) {
238 result.emplace_back("@android.annotation.UnsupportedAppUsage");
239 }
240 return result;
241}
242
Christopher Wileydb154a52015-09-28 16:32:25 -0700243} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700244} // namespace android
245} // namespace aidl