blob: f09ac06c2bd1cbabc4c16c3da0f055d200c72acb [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();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900143 for (const auto& field : parcel->GetFields()) {
144 string code;
145 CodeWriterPtr writer = CodeWriter::ForString(&code);
146 CodeGeneratorContext context{
147 .writer = *(writer.get()),
148 .typenames = types->typenames_,
149 .type = field->GetType(),
150 .var = field->GetName(),
151 .parcel = parcel_variable->name,
152 .is_return_value = false,
153 };
154 WriteToParcelFor(context);
155 writer->Close();
156 write_method->statements->Add(new LiteralStatement(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700157 }
158 parcel_class->elements.push_back(write_method);
159
160 Method* read_method = new Method;
Jeongik Chaa2ada0c2018-11-17 15:11:45 +0900161 read_method->modifiers = PUBLIC | FINAL;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900162 read_method->returnType = new Type(types, "void", 0, false);
Steven Moreland5557f1c2018-07-02 13:50:23 -0700163 read_method->name = "readFromParcel";
164 read_method->parameters.push_back(parcel_variable);
165 read_method->statements = new StatementBlock();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900166
167 // keep this across different fields in order to create the classloader
168 // at most once.
169 bool is_classloader_created = false;
170 for (const auto& field : parcel->GetFields()) {
171 string code;
172 CodeWriterPtr writer = CodeWriter::ForString(&code);
173 CodeGeneratorContext context{
174 .writer = *(writer.get()),
175 .typenames = types->typenames_,
176 .type = field->GetType(),
177 .var = field->GetName(),
178 .parcel = parcel_variable->name,
179 .is_classloader_created = &is_classloader_created,
180 };
181 CreateFromParcelFor(context);
182 writer->Close();
183 read_method->statements->Add(new LiteralStatement(code));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700184 }
185 parcel_class->elements.push_back(read_method);
186
Jiyong Parkb77f7a52018-09-13 21:32:38 +0900187 Method* describe_contents_method = new Method;
188 describe_contents_method->modifiers = PUBLIC | OVERRIDE;
189 describe_contents_method->returnType = types->IntType();
190 describe_contents_method->name = "describeContents";
191 describe_contents_method->statements = new StatementBlock();
192 describe_contents_method->statements->Add(new LiteralStatement("return 0;"));
193 parcel_class->elements.push_back(describe_contents_method);
194
Steven Moreland5557f1c2018-07-02 13:50:23 -0700195 return parcel_class;
196}
197
Jiyong Parka6605ab2018-11-11 14:30:21 +0900198std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
199 std::vector<std::string> result;
200 if (a.IsUnsupportedAppUsage()) {
201 result.emplace_back("@android.annotation.UnsupportedAppUsage");
202 }
203 return result;
204}
205
Christopher Wileydb154a52015-09-28 16:32:25 -0700206} // namespace java
Christopher Wileyfdeb0f42015-09-11 15:38:22 -0700207} // namespace android
208} // namespace aidl