1 /*
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
17 #include "generate_java.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <algorithm>
24 #include <map>
25 #include <memory>
26 #include <optional>
27 #include <sstream>
28
29 #include <android-base/format.h>
30 #include <android-base/stringprintf.h>
31
32 #include "aidl_to_java.h"
33 #include "code_writer.h"
34 #include "logging.h"
35
36 using ::android::base::EndsWith;
37 using ::android::base::Join;
38 using ::android::base::StartsWith;
39 using std::string;
40 using std::unique_ptr;
41 using std::vector;
42
43 namespace {
44 using android::aidl::java::CodeGeneratorContext;
45 using android::aidl::java::ConstantValueDecorator;
46
getter_name(const AidlVariableDeclaration & variable)47 inline string getter_name(const AidlVariableDeclaration& variable) {
48 return "get" + variable.GetCapitalizedName();
49 }
setter_name(const AidlVariableDeclaration & variable)50 inline string setter_name(const AidlVariableDeclaration& variable) {
51 return "set" + variable.GetCapitalizedName();
52 }
53
54 // clang-format off
55 const map<string, string> contents_describers {
56 {"FileDescriptor", R"(if (_v instanceof java.io.FileDescriptor) {
57 return android.os.Parcelable.CONTENTS_FILE_DESCRIPTOR;
58 })"},
59 {"Parcelable", R"(if (_v instanceof android.os.Parcelable) {
60 return ((android.os.Parcelable) _v).describeContents();
61 })"},
62 {"Map", R"(if (_v instanceof java.util.Map) {
63 return describeContents(((java.util.Map) _v).values());
64 })"},
65 {"List", R"(if (_v instanceof java.util.Collection) {
66 int _mask = 0;
67 for (Object o : (java.util.Collection) _v) {
68 _mask |= describeContents(o);
69 }
70 return _mask;
71 })"},
72 {"Array", R"(Class<?> _clazz = _v.getClass();
73 if (_clazz.isArray() && _clazz.getComponentType() == Object.class) {
74 int _mask = 0;
75 for (Object o : (Object[]) _v) {
76 _mask |= describeContents(o);
77 }
78 return _mask;
79 })"},
80 };
81 // clang-format on
82
GenerateDescribeContentsHelper(CodeWriter & out,const set<string> & describers)83 void GenerateDescribeContentsHelper(CodeWriter& out, const set<string>& describers) {
84 out << "private int describeContents(Object _v) {\n";
85 out.Indent();
86 out << "if (_v == null) return 0;\n";
87 for (const auto& d : describers) {
88 out << contents_describers.at(d) << "\n";
89 }
90 out << "return 0;\n";
91 out.Dedent();
92 out << "}\n";
93 }
94
95 // Some types contribute to Parcelable.describeContents().
96 // e.g. FileDescriptor, Parcelables, List<Parcelables> ...
CanDescribeContents(const AidlTypeSpecifier & type,const AidlTypenames & types,set<string> * describers)97 bool CanDescribeContents(const AidlTypeSpecifier& type, const AidlTypenames& types,
98 set<string>* describers) {
99 if (type.IsArray()) {
100 if (CanDescribeContents(type.ArrayBase(), types, describers)) {
101 describers->insert("Array");
102 return true;
103 }
104 return false;
105 }
106
107 if (type.GetName() == "List") {
108 if (CanDescribeContents(*type.GetTypeParameters()[0], types, describers)) {
109 describers->insert("List");
110 return true;
111 }
112 return false;
113 }
114
115 if (type.GetName() == "Map") {
116 if (CanDescribeContents(*type.GetTypeParameters()[1], types, describers)) {
117 describers->insert("Map"); // Map describer uses List describer
118 describers->insert("List");
119 return true;
120 }
121 return false;
122 }
123
124 if (type.GetName() == "FileDescriptor") {
125 describers->insert("FileDescriptor");
126 return true;
127 }
128
129 if (type.GetName() == "ParcelFileDescriptor" || type.GetName() == "ParcelableHolder" ||
130 types.GetParcelable(type) != nullptr) {
131 describers->insert("Parcelable");
132 return true;
133 }
134
135 return false;
136 }
GenerateParcelableDescribeContents(CodeWriter & out,const AidlStructuredParcelable & decl,const AidlTypenames & types)137 void GenerateParcelableDescribeContents(CodeWriter& out, const AidlStructuredParcelable& decl,
138 const AidlTypenames& types) {
139 set<string> describers;
140
141 out << "@Override\n";
142 out << "public int describeContents() {\n";
143 out.Indent();
144 out << "int _mask = 0;\n";
145 for (const auto& f : decl.GetFields()) {
146 if (CanDescribeContents(f->GetType(), types, &describers)) {
147 out << "_mask |= describeContents(" << f->GetName() << ");\n";
148 }
149 }
150 out << "return _mask;\n";
151 out.Dedent();
152 out << "}\n";
153 if (!describers.empty()) {
154 GenerateDescribeContentsHelper(out, describers);
155 }
156 }
157
GenerateParcelableDescribeContents(CodeWriter & out,const AidlUnionDecl & decl,const AidlTypenames & types)158 void GenerateParcelableDescribeContents(CodeWriter& out, const AidlUnionDecl& decl,
159 const AidlTypenames& types) {
160 set<string> describers;
161
162 out << "@Override\n";
163 out << "public int describeContents() {\n";
164 out.Indent();
165 out << "int _mask = 0;\n";
166 out << "switch (getTag()) {\n";
167 for (const auto& f : decl.GetFields()) {
168 if (CanDescribeContents(f->GetType(), types, &describers)) {
169 out << "case " << f->GetName() << ":\n";
170 out.Indent();
171 out << "_mask |= describeContents(" << getter_name(*f) << "());\n";
172 out << "break;\n";
173 out.Dedent();
174 }
175 }
176 out << "}\n";
177 out << "return _mask;\n";
178 out.Dedent();
179 out << "}\n";
180 if (!describers.empty()) {
181 GenerateDescribeContentsHelper(out, describers);
182 }
183 }
184
GenerateToString(CodeWriter & out,const AidlStructuredParcelable & parcel,const AidlTypenames & typenames)185 void GenerateToString(CodeWriter& out, const AidlStructuredParcelable& parcel,
186 const AidlTypenames& typenames) {
187 out << "@Override\n";
188 out << "public String toString() {\n";
189 out.Indent();
190 out << "java.util.StringJoiner _aidl_sj = new java.util.StringJoiner(";
191 out << "\", \", \"{\", \"}\");\n";
192 for (const auto& field : parcel.GetFields()) {
193 CodeGeneratorContext ctx{
194 .writer = out,
195 .typenames = typenames,
196 .type = field->GetType(),
197 .var = field->GetName(),
198 };
199 out << "_aidl_sj.add(\"" << field->GetName() << ": \" + (";
200 ToStringFor(ctx);
201 out << "));\n";
202 }
203 out << "return \"" << parcel.GetCanonicalName() << "\" + _aidl_sj.toString() ;\n";
204 out.Dedent();
205 out << "}\n";
206 }
207
GenerateToString(CodeWriter & out,const AidlUnionDecl & parcel,const AidlTypenames & typenames)208 void GenerateToString(CodeWriter& out, const AidlUnionDecl& parcel,
209 const AidlTypenames& typenames) {
210 out << "@Override\n";
211 out << "public String toString() {\n";
212 out.Indent();
213 out << "switch (_tag) {\n";
214 for (const auto& field : parcel.GetFields()) {
215 CodeGeneratorContext ctx{
216 .writer = out,
217 .typenames = typenames,
218 .type = field->GetType(),
219 .var = getter_name(*field) + "()",
220 };
221 out << "case " << field->GetName() << ": return \"" << parcel.GetCanonicalName() << "."
222 << field->GetName() << "(\" + (";
223 ToStringFor(ctx);
224 out << ") + \")\";\n";
225 }
226 out << "}\n";
227 out << "throw new IllegalStateException(\"unknown field: \" + _tag);\n";
228 out.Dedent();
229 out << "}\n";
230 }
231
GenerateEqualsAndHashCode(CodeWriter & out,const AidlStructuredParcelable & parcel,const AidlTypenames &)232 void GenerateEqualsAndHashCode(CodeWriter& out, const AidlStructuredParcelable& parcel,
233 const AidlTypenames&) {
234 out << "@Override\n";
235 out << "public boolean equals(Object other) {\n";
236 out.Indent();
237 out << "if (this == other) return true;\n";
238 out << "if (other == null) return false;\n";
239 out << "if (!(other instanceof " << parcel.GetName() << ")) return false;\n";
240 out << parcel.GetName() << " that = (" << parcel.GetName() << ")other;\n";
241 for (const auto& field : parcel.GetFields()) {
242 out << "if (!java.util.Objects.deepEquals(" << field->GetName() << ", that." << field->GetName()
243 << ")) return false;\n";
244 }
245 out << "return true;\n";
246 out.Dedent();
247 out << "}\n";
248 out << "\n";
249 out << "@Override\n";
250 out << "public int hashCode() {\n";
251 out.Indent();
252 out << "return java.util.Arrays.deepHashCode(java.util.Arrays.asList(";
253 std::vector<std::string> names;
254 for (const auto& field : parcel.GetFields()) {
255 names.push_back(field->GetName());
256 }
257 out << android::base::Join(names, ", ") << ").toArray());\n";
258 out.Dedent();
259 out << "}\n";
260 }
261
GenerateEqualsAndHashCode(CodeWriter & out,const AidlUnionDecl & decl,const AidlTypenames &)262 void GenerateEqualsAndHashCode(CodeWriter& out, const AidlUnionDecl& decl,
263 const AidlTypenames&) {
264 out << "@Override\n";
265 out << "public boolean equals(Object other) {\n";
266 out.Indent();
267 out << "if (this == other) return true;\n";
268 out << "if (other == null) return false;\n";
269 out << "if (!(other instanceof " << decl.GetName() << ")) return false;\n";
270 out << decl.GetName() << " that = (" << decl.GetName() << ")other;\n";
271 out << "if (_tag != that._tag) return false;\n";
272 out << "if (!java.util.Objects.deepEquals(_value, that._value)) return false;\n";
273 out << "return true;\n";
274 out.Dedent();
275 out << "}\n";
276 out << "\n";
277 out << "@Override\n";
278 out << "public int hashCode() {\n";
279 out.Indent();
280 out << "return java.util.Arrays.deepHashCode(java.util.Arrays.asList(_tag, _value).toArray());\n";
281 out.Dedent();
282 out << "}\n";
283 out << "\n";
284 }
285
286 } // namespace
287
288 namespace android {
289 namespace aidl {
290 namespace java {
291
GenerateComments(const AidlCommentable & node)292 std::string GenerateComments(const AidlCommentable& node) {
293 std::string comments = FormatCommentsForJava(node.GetComments());
294 if (!comments.empty() && comments.back() != '\n') {
295 comments += '\n';
296 }
297 return comments;
298 }
299
GenerateAnnotations(const AidlNode & node)300 std::string GenerateAnnotations(const AidlNode& node) {
301 std::string result;
302 for (const auto& a : JavaAnnotationsFor(node)) {
303 result += a + "\n";
304 }
305 return result;
306 }
307
generate_java_interface(const string & filename,const AidlInterface * iface,const AidlTypenames & typenames,const IoDelegate & io_delegate,const Options & options)308 bool generate_java_interface(const string& filename, const AidlInterface* iface,
309 const AidlTypenames& typenames, const IoDelegate& io_delegate,
310 const Options& options) {
311 auto cl = generate_binder_interface_class(iface, typenames, options);
312
313 std::unique_ptr<Document> document =
314 std::make_unique<Document>("" /* no comment */, iface->GetPackage(), std::move(cl));
315
316 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
317 document->Write(code_writer.get());
318
319 return true;
320 }
321
generate_java_parcel(const std::string & filename,const AidlStructuredParcelable * parcel,const AidlTypenames & typenames,const IoDelegate & io_delegate)322 bool generate_java_parcel(const std::string& filename, const AidlStructuredParcelable* parcel,
323 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
324 auto cl = generate_parcel_class(parcel, typenames);
325
326 std::unique_ptr<Document> document =
327 std::make_unique<Document>("" /* no comment */, parcel->GetPackage(), std::move(cl));
328
329 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
330 document->Write(code_writer.get());
331
332 return true;
333 }
334
generate_java_enum_declaration(const std::string & filename,const AidlEnumDeclaration * enum_decl,const AidlTypenames & typenames,const IoDelegate & io_delegate)335 bool generate_java_enum_declaration(const std::string& filename,
336 const AidlEnumDeclaration* enum_decl,
337 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
338 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
339 generate_enum(code_writer, enum_decl, typenames);
340 return true;
341 }
342
generate_java_union_declaration(const std::string & filename,const AidlUnionDecl * decl,const AidlTypenames & typenames,const IoDelegate & io_delegate)343 bool generate_java_union_declaration(const std::string& filename, const AidlUnionDecl* decl,
344 const AidlTypenames& typenames,
345 const IoDelegate& io_delegate) {
346 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
347 generate_union(*code_writer, decl, typenames);
348 return true;
349 }
350
generate_java(const std::string & filename,const AidlDefinedType * defined_type,const AidlTypenames & typenames,const IoDelegate & io_delegate,const Options & options)351 bool generate_java(const std::string& filename, const AidlDefinedType* defined_type,
352 const AidlTypenames& typenames, const IoDelegate& io_delegate,
353 const Options& options) {
354 if (const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
355 parcelable != nullptr) {
356 return generate_java_parcel(filename, parcelable, typenames, io_delegate);
357 }
358
359 if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
360 enum_decl != nullptr) {
361 return generate_java_enum_declaration(filename, enum_decl, typenames, io_delegate);
362 }
363
364 if (const AidlInterface* interface = defined_type->AsInterface(); interface != nullptr) {
365 return generate_java_interface(filename, interface, typenames, io_delegate, options);
366 }
367
368 if (const AidlUnionDecl* union_decl = defined_type->AsUnionDeclaration(); union_decl != nullptr) {
369 return generate_java_union_declaration(filename, union_decl, typenames, io_delegate);
370 }
371
372 AIDL_FATAL(defined_type) << "Unrecognized type sent for Java generation.";
373 return false;
374 }
375
generate_parcel_class(const AidlStructuredParcelable * parcel,const AidlTypenames & typenames)376 std::unique_ptr<android::aidl::java::Class> generate_parcel_class(
377 const AidlStructuredParcelable* parcel, const AidlTypenames& typenames) {
378 auto parcel_class = std::make_unique<Class>();
379 parcel_class->comment = GenerateComments(*parcel);
380 parcel_class->modifiers = PUBLIC;
381 parcel_class->what = Class::CLASS;
382 parcel_class->type = parcel->GetCanonicalName();
383 parcel_class->interfaces.push_back("android.os.Parcelable");
384 parcel_class->annotations = JavaAnnotationsFor(*parcel);
385
386 if (parcel->IsGeneric()) {
387 parcel_class->type += "<" + base::Join(parcel->GetTypeParameters(), ",") + ">";
388 }
389
390 for (const auto& variable : parcel->GetFields()) {
391 std::ostringstream out;
392 out << GenerateComments(*variable);
393 out << GenerateAnnotations(*variable);
394 out << "public ";
395
396 if (variable->GetType().GetName() == "ParcelableHolder" || parcel->IsJavaOnlyImmutable()) {
397 out << "final ";
398 }
399 out << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName();
400 if (!parcel->IsJavaOnlyImmutable() && variable->GetDefaultValue()) {
401 out << " = " << variable->ValueString(ConstantValueDecorator);
402 } else if (variable->GetType().GetName() == "ParcelableHolder") {
403 out << std::boolalpha;
404 out << " = new " << JavaSignatureOf(variable->GetType(), typenames) << "(";
405 if (parcel->IsVintfStability()) {
406 out << "android.os.Parcelable.PARCELABLE_STABILITY_VINTF";
407 } else {
408 out << "android.os.Parcelable.PARCELABLE_STABILITY_LOCAL";
409 }
410 out << ")";
411 out << std::noboolalpha;
412 }
413 out << ";\n";
414 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
415 }
416
417 std::ostringstream out;
418 if (parcel->IsJavaOnlyImmutable()) {
419 auto builder_class = std::make_shared<Class>();
420 builder_class->modifiers = PUBLIC | FINAL | STATIC;
421 builder_class->what = Class::CLASS;
422 builder_class->type = "Builder";
423
424 out.str("");
425 for (const auto& variable : parcel->GetFields()) {
426 out << "private " << JavaSignatureOf(variable->GetType(), typenames) << " "
427 << variable->GetName();
428 if (variable->GetDefaultValue()) {
429 out << " = " << variable->ValueString(ConstantValueDecorator);
430 }
431 out << ";\n";
432 out << "public Builder " << setter_name(*variable) << "("
433 << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName()
434 << ") {\n"
435 << " "
436 << "this." << variable->GetName() << " = " << variable->GetName() << ";\n"
437 << " return this;\n"
438 << "}\n";
439 }
440 out << "public " << parcel->GetCanonicalName() << " build() {\n"
441 << " return new " << parcel->GetCanonicalName() << "(";
442 std::vector<std::string> variables;
443 std::transform(parcel->GetFields().begin(), parcel->GetFields().end(),
444 std::back_inserter(variables), [](const auto& f) { return f->GetName(); });
445 out << base::Join(variables, ", ") << ");\n"
446 << "}\n";
447 builder_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
448 parcel_class->elements.push_back(builder_class);
449 }
450 if (parcel->IsVintfStability()) {
451 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(
452 "@Override\n public final int getStability() { return "
453 "android.os.Parcelable.PARCELABLE_STABILITY_VINTF; }\n"));
454 }
455
456 out.str("");
457 out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
458 << "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
459 out << " @Override\n";
460 out << " public " << parcel->GetName()
461 << " createFromParcel(android.os.Parcel _aidl_source) {\n";
462 if (parcel->IsJavaOnlyImmutable()) {
463 out << " return internalCreateFromParcel(_aidl_source);\n";
464 } else {
465 out << " " << parcel->GetName() << " _aidl_out = new " << parcel->GetName() << "();\n";
466 out << " _aidl_out.readFromParcel(_aidl_source);\n";
467 out << " return _aidl_out;\n";
468 }
469 out << " }\n";
470 out << " @Override\n";
471 out << " public " << parcel->GetName() << "[] newArray(int _aidl_size) {\n";
472 out << " return new " << parcel->GetName() << "[_aidl_size];\n";
473 out << " }\n";
474 out << "};\n";
475 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
476
477 auto flag_variable = std::make_shared<Variable>("int", "_aidl_flag");
478 auto parcel_variable = std::make_shared<Variable>("android.os.Parcel", "_aidl_parcel");
479
480 auto write_method = std::make_shared<Method>();
481 write_method->modifiers = PUBLIC | OVERRIDE | FINAL;
482 write_method->returnType = "void";
483 write_method->name = "writeToParcel";
484 write_method->parameters.push_back(parcel_variable);
485 write_method->parameters.push_back(flag_variable);
486 write_method->statements = std::make_shared<StatementBlock>();
487
488 out.str("");
489 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
490 << "_aidl_parcel.writeInt(0);\n";
491 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
492
493 for (const auto& field : parcel->GetFields()) {
494 string code;
495 CodeWriterPtr writer = CodeWriter::ForString(&code);
496 CodeGeneratorContext context{
497 .writer = *(writer.get()),
498 .typenames = typenames,
499 .type = field->GetType(),
500 .parcel = parcel_variable->name,
501 .var = field->GetName(),
502 .is_return_value = false,
503 };
504 WriteToParcelFor(context);
505 writer->Close();
506 write_method->statements->Add(std::make_shared<LiteralStatement>(code));
507 }
508
509 out.str("");
510 out << "int _aidl_end_pos = _aidl_parcel.dataPosition();\n"
511 << "_aidl_parcel.setDataPosition(_aidl_start_pos);\n"
512 << "_aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);\n"
513 << "_aidl_parcel.setDataPosition(_aidl_end_pos);\n";
514
515 write_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
516
517 parcel_class->elements.push_back(write_method);
518
519 if (parcel->IsJavaOnlyImmutable()) {
520 auto constructor = std::make_shared<Method>();
521 constructor->modifiers = PUBLIC;
522 constructor->name = parcel->GetName();
523 constructor->statements = std::make_shared<StatementBlock>();
524 for (const auto& field : parcel->GetFields()) {
525 constructor->parameters.push_back(std::make_shared<Variable>(
526 JavaSignatureOf(field->GetType(), typenames), field->GetName()));
527 out.str("");
528
529 out << "this." << field->GetName() << " = ";
530 if (field->GetType().GetName() == "List") {
531 out << field->GetName() << " == null ? null : java.util.Collections.unmodifiableList("
532 << field->GetName() << ");\n";
533 } else if (field->GetType().GetName() == "Map") {
534 out << field->GetName() << " == null ? null : java.util.Collections.unmodifiableMap("
535 << field->GetName() << ");\n";
536 } else {
537 out << field->GetName() << ";\n";
538 }
539 constructor->statements->Add(std::make_shared<LiteralStatement>(out.str()));
540 }
541 parcel_class->elements.push_back(constructor);
542 }
543
544 // For an immutable parcelable, generate internalCreateFromParcel method.
545 // Otherwise, generate readFromParcel method.
546 auto read_or_create_method = std::make_shared<Method>();
547 if (parcel->IsJavaOnlyImmutable()) {
548 auto constructor = std::make_shared<Method>();
549 read_or_create_method->modifiers = PRIVATE | STATIC;
550 read_or_create_method->returnType = parcel->GetName();
551 read_or_create_method->name = "internalCreateFromParcel";
552 read_or_create_method->parameters.push_back(parcel_variable);
553 read_or_create_method->statements = std::make_shared<StatementBlock>();
554 } else {
555 read_or_create_method->modifiers = PUBLIC | FINAL;
556 read_or_create_method->returnType = "void";
557 read_or_create_method->name = "readFromParcel";
558 read_or_create_method->parameters.push_back(parcel_variable);
559 read_or_create_method->statements = std::make_shared<StatementBlock>();
560 }
561 out.str("");
562 const string builder_variable = "_aidl_parcelable_builder";
563 if (parcel->IsJavaOnlyImmutable()) {
564 out << "Builder " << builder_variable << " = new Builder();\n";
565 }
566 out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
567 << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
568 << "try {\n"
569 << " if (_aidl_parcelable_size < 0) return";
570 if (parcel->IsJavaOnlyImmutable()) {
571 out << " " << builder_variable << ".build()";
572 }
573 out << ";\n";
574
575 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
576
577 out.str("");
578 out << " if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return";
579 if (parcel->IsJavaOnlyImmutable()) {
580 out << " " << builder_variable << ".build()";
581 }
582 out << ";\n";
583
584 std::shared_ptr<LiteralStatement> sizeCheck = std::make_shared<LiteralStatement>(out.str());
585 // keep this across different fields in order to create the classloader
586 // at most once.
587 bool is_classloader_created = false;
588 for (const auto& field : parcel->GetFields()) {
589 read_or_create_method->statements->Add(sizeCheck);
590 const auto field_variable_name =
591 (parcel->IsJavaOnlyImmutable() ? "_aidl_temp_" : "") + field->GetName();
592 string code;
593 CodeWriterPtr writer = CodeWriter::ForString(&code);
594 CodeGeneratorContext context{
595 .writer = *(writer.get()),
596 .typenames = typenames,
597 .type = field->GetType(),
598 .parcel = parcel_variable->name,
599 .var = field_variable_name,
600 .is_classloader_created = &is_classloader_created,
601 };
602 context.writer.Indent();
603 if (parcel->IsJavaOnlyImmutable()) {
604 context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType(), typenames).c_str(),
605 field_variable_name.c_str());
606 }
607 CreateFromParcelFor(context);
608 if (parcel->IsJavaOnlyImmutable()) {
609 context.writer.Write("%s.%s(%s);\n", builder_variable.c_str(), setter_name(*field).c_str(),
610 field_variable_name.c_str());
611 }
612 writer->Close();
613 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(code));
614 }
615
616 out.str("");
617 out << "} finally {\n"
618 << " if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {\n"
619 << " throw new android.os.BadParcelableException(\"Overflow in the size of "
620 "parcelable\");\n"
621 << " }\n"
622 << " _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
623 if (parcel->IsJavaOnlyImmutable()) {
624 out << " return " << builder_variable << ".build();\n";
625 }
626 out << "}\n";
627
628 read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(out.str()));
629
630 parcel_class->elements.push_back(read_or_create_method);
631
632 string constants;
633 generate_constant_declarations(*CodeWriter::ForString(&constants), *parcel);
634 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(constants));
635
636 if (parcel->JavaDerive("toString")) {
637 string to_string;
638 GenerateToString(*CodeWriter::ForString(&to_string), *parcel, typenames);
639 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(to_string));
640 }
641
642 if (parcel->JavaDerive("equals")) {
643 string to_string;
644 GenerateEqualsAndHashCode(*CodeWriter::ForString(&to_string), *parcel, typenames);
645 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(to_string));
646 }
647
648 string describe_contents;
649 GenerateParcelableDescribeContents(*CodeWriter::ForString(&describe_contents), *parcel,
650 typenames);
651 parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(describe_contents));
652
653 return parcel_class;
654 }
655
generate_enum(const CodeWriterPtr & code_writer,const AidlEnumDeclaration * enum_decl,const AidlTypenames & typenames)656 void generate_enum(const CodeWriterPtr& code_writer, const AidlEnumDeclaration* enum_decl,
657 const AidlTypenames& typenames) {
658 code_writer->Write(
659 "/*\n"
660 " * This file is auto-generated. DO NOT MODIFY.\n"
661 " */\n");
662
663 code_writer->Write("package %s;\n", enum_decl->GetPackage().c_str());
664 (*code_writer) << GenerateComments(*enum_decl);
665 (*code_writer) << GenerateAnnotations(*enum_decl);
666 code_writer->Write("public @interface %s {\n", enum_decl->GetName().c_str());
667 code_writer->Indent();
668 for (const auto& enumerator : enum_decl->GetEnumerators()) {
669 (*code_writer) << GenerateComments(*enumerator);
670 (*code_writer) << GenerateAnnotations(*enumerator);
671 code_writer->Write(
672 "public static final %s %s = %s;\n",
673 JavaSignatureOf(enum_decl->GetBackingType(), typenames).c_str(),
674 enumerator->GetName().c_str(),
675 enumerator->ValueString(enum_decl->GetBackingType(), ConstantValueDecorator).c_str());
676 }
677 code_writer->Dedent();
678 code_writer->Write("}\n");
679 }
680
generate_union(CodeWriter & out,const AidlUnionDecl * decl,const AidlTypenames & typenames)681 void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypenames& typenames) {
682 const string tag_type = "int";
683 const AidlTypeSpecifier tag_type_specifier(AIDL_LOCATION_HERE, tag_type, false /* isArray */,
684 nullptr /* type_params */, Comments{});
685 const string clazz = decl->GetName();
686
687 out << "/*\n";
688 out << " * This file is auto-generated. DO NOT MODIFY.\n";
689 out << " */\n";
690
691 out << "package " + decl->GetPackage() + ";\n";
692 out << "\n";
693 out << GenerateComments(*decl);
694 out << GenerateAnnotations(*decl);
695
696 out << "public final class " + clazz + " implements android.os.Parcelable {\n";
697 out.Indent();
698
699 size_t tag_index = 0;
700 out << "// tags for union fields\n";
701 for (const auto& variable : decl->GetFields()) {
702 auto signature = variable->Signature() + ";";
703 out << "public final static " + tag_type + " " + variable->GetName() + " = " +
704 std::to_string(tag_index++) + "; // " + signature + "\n";
705 }
706 out << "\n";
707
708 const auto final_opt = decl->IsJavaOnlyImmutable() ? "final " : "";
709 out << "private " << final_opt << tag_type + " _tag;\n";
710 out << "private " << final_opt << "Object _value;\n";
711 out << "\n";
712
713 AIDL_FATAL_IF(decl->GetFields().empty(), *decl) << "Union '" << clazz << "' is empty.";
714 const auto& first_field = decl->GetFields()[0];
715 const auto& first_type = JavaSignatureOf(first_field->GetType(), typenames);
716 const auto& first_value = first_field->ValueString(ConstantValueDecorator);
717
718 // default ctor() inits with first member's default value
719 out << "public " + clazz + "() {\n";
720 out.Indent();
721 out << first_type + " _value = " << (first_value.empty() ? "null" : first_value) << ";\n";
722 out << "this._tag = " << first_field->GetName() << ";\n";
723 out << "this._value = _value;\n";
724 out.Dedent();
725 out << "}\n\n";
726
727 if (!decl->IsJavaOnlyImmutable()) {
728 // private ctor(Parcel)
729 out << "private " + clazz + "(android.os.Parcel _aidl_parcel) {\n";
730 out << " readFromParcel(_aidl_parcel);\n";
731 out << "}\n\n";
732 }
733
734 // private ctor(tag, value)
735 out << "private " + clazz + "(" + tag_type + " _tag, Object _value) {\n";
736 out.Indent();
737 out << "this._tag = _tag;\n";
738 out << "this._value = _value;\n";
739 out.Dedent();
740 out << "}\n\n";
741
742 // getTag()
743 out << "public " + tag_type + " " + "getTag() {\n";
744 out.Indent();
745 out << "return _tag;\n";
746 out.Dedent();
747 out << "}\n\n";
748
749 // value ctor, getter, setter(for mutable) for each field
750 for (const auto& variable : decl->GetFields()) {
751 out << "// " + variable->Signature() + ";\n\n";
752
753 auto var_name = variable->GetName();
754 auto var_type = JavaSignatureOf(variable->GetType(), typenames);
755
756 // value ctor
757 out << GenerateComments(*variable);
758 out << GenerateAnnotations(*variable);
759 out << "public static " + clazz + " " + var_name + "(" + var_type + " _value) {\n";
760 out.Indent();
761 out << "return new " + clazz + "(" + var_name + ", _value);\n";
762 out.Dedent();
763 out << "}\n\n";
764
765 // getter
766 if (variable->GetType().IsGeneric()) {
767 out << "@SuppressWarnings(\"unchecked\")\n";
768 }
769 out << "public " + var_type + " " + getter_name(*variable) + "() {\n";
770 out.Indent();
771 out << "_assertTag(" + var_name + ");\n";
772 out << "return (" + var_type + ") _value;\n";
773 out.Dedent();
774 out << "}\n\n";
775
776 // setter
777 if (!decl->IsJavaOnlyImmutable()) {
778 out << "public void " + setter_name(*variable) + "(" + var_type + " _value) {\n";
779 out.Indent();
780 out << "_set(" + var_name + ", _value);\n";
781 out.Dedent();
782 out << "}\n\n";
783 }
784 }
785
786 if (decl->IsVintfStability()) {
787 out << "@Override\n";
788 out << "public final int getStability() {\n";
789 out << " return android.os.Parcelable.PARCELABLE_STABILITY_VINTF;\n";
790 out << "}\n\n";
791 }
792
793 out << "public static final android.os.Parcelable.Creator<" << clazz << "> CREATOR = "
794 << "new android.os.Parcelable.Creator<" << clazz << ">() {\n";
795 out << " @Override\n";
796 out << " public " << clazz << " createFromParcel(android.os.Parcel _aidl_source) {\n";
797 if (decl->IsJavaOnlyImmutable()) {
798 out << " return internalCreateFromParcel(_aidl_source);\n";
799 } else {
800 out << " return new " + clazz + "(_aidl_source);\n";
801 }
802 out << " }\n";
803 out << " @Override\n";
804 out << " public " << clazz << "[] newArray(int _aidl_size) {\n";
805 out << " return new " << clazz << "[_aidl_size];\n";
806 out << " }\n";
807 out << "};\n\n";
808
809 auto write_to_parcel = [&](const AidlTypeSpecifier& type, std::string name, std::string parcel) {
810 string code;
811 CodeWriterPtr writer = CodeWriter::ForString(&code);
812 CodeGeneratorContext context{
813 .writer = *(writer.get()),
814 .typenames = typenames,
815 .type = type,
816 .parcel = parcel,
817 .var = name,
818 .is_return_value = false,
819 };
820 WriteToParcelFor(context);
821 writer->Close();
822 return code;
823 };
824
825 out << "@Override\n";
826 out << "public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {\n";
827 out.Indent();
828 out << write_to_parcel(tag_type_specifier, "_tag", "_aidl_parcel");
829 out << "switch (_tag) {\n";
830 for (const auto& variable : decl->GetFields()) {
831 out << "case " + variable->GetName() + ":\n";
832 out.Indent();
833 out << write_to_parcel(variable->GetType(), getter_name(*variable) + "()", "_aidl_parcel");
834 out << "break;\n";
835 out.Dedent();
836 }
837 out << "}\n";
838 out.Dedent();
839 out << "}\n\n";
840
841 // keep this across different fields in order to create the classloader
842 // at most once.
843 bool is_classloader_created = false;
844 auto read_from_parcel = [&](const AidlTypeSpecifier& type, std::string name, std::string parcel) {
845 string code;
846 CodeWriterPtr writer = CodeWriter::ForString(&code);
847 CodeGeneratorContext context{
848 .writer = *(writer.get()),
849 .typenames = typenames,
850 .type = type,
851 .parcel = parcel,
852 .var = name,
853 .is_classloader_created = &is_classloader_created,
854 };
855 CreateFromParcelFor(context);
856 writer->Close();
857 return code;
858 };
859
860 if (decl->IsJavaOnlyImmutable()) {
861 // When it's immutable we don't need readFromParcel, but we can use it from createFromParcel
862 out << "private static " + clazz +
863 " internalCreateFromParcel(android.os.Parcel _aidl_parcel) {\n";
864 } else {
865 // Not override, but as a user-defined parcelable, this method should be public
866 out << "public void readFromParcel(android.os.Parcel _aidl_parcel) {\n";
867 }
868 out.Indent();
869 out << tag_type + " _aidl_tag;\n";
870 out << read_from_parcel(tag_type_specifier, "_aidl_tag", "_aidl_parcel");
871 out << "switch (_aidl_tag) {\n";
872 for (const auto& variable : decl->GetFields()) {
873 auto var_name = variable->GetName();
874 auto var_type = JavaSignatureOf(variable->GetType(), typenames);
875 out << "case " + var_name + ": {\n";
876 out.Indent();
877 out << var_type + " _aidl_value;\n";
878 out << read_from_parcel(variable->GetType(), "_aidl_value", "_aidl_parcel");
879 if (decl->IsJavaOnlyImmutable()) {
880 out << "return new " << clazz << "(_aidl_tag, _aidl_value); }\n";
881 } else {
882 out << "_set(_aidl_tag, _aidl_value);\n";
883 out << "return; }\n";
884 }
885 out.Dedent();
886 }
887 out << "}\n";
888 out << "throw new IllegalArgumentException(\"union: unknown tag: \" + _aidl_tag);\n";
889 out.Dedent();
890 out << "}\n\n";
891
892 generate_constant_declarations(out, *decl);
893
894 GenerateParcelableDescribeContents(out, *decl, typenames);
895 out << "\n";
896 if (decl->JavaDerive("toString")) {
897 GenerateToString(out, *decl, typenames);
898 }
899
900 if (decl->JavaDerive("equals")) {
901 GenerateEqualsAndHashCode(out, *decl, typenames);
902 }
903
904 // helper: _assertTag
905 out << "private void _assertTag(" + tag_type + " tag) {\n";
906 out << " if (getTag() != tag) {\n";
907 out << " throw new IllegalStateException(\"bad access: \" + _tagString(tag) + \", \" + "
908 "_tagString(getTag()) + \" is available.\");\n";
909 out << " }\n";
910 out << "}\n\n";
911
912 // helper: _tagString
913 out << "private String _tagString(" + tag_type + " _tag) {\n";
914 out << " switch (_tag) {\n";
915 for (const auto& variable : decl->GetFields()) {
916 auto var_name = variable->GetName();
917 out << " case " + var_name + ": return \"" + var_name + "\";\n";
918 }
919 out << " }\n";
920 out << " throw new IllegalStateException(\"unknown field: \" + _tag);\n";
921 out << "}\n";
922
923 if (!decl->IsJavaOnlyImmutable()) {
924 out << "\n";
925 out << "private void _set(int _tag, Object _value) {\n";
926 out.Indent();
927 out << "this._tag = _tag;\n";
928 out << "this._value = _value;\n";
929 out.Dedent();
930 out << "}\n";
931 }
932
933 out.Dedent();
934 out << "}\n";
935 }
936
dump_location(const AidlNode & method)937 std::string dump_location(const AidlNode& method) {
938 return method.PrintLocation();
939 }
940
generate_java_unsupportedappusage_parameters(const AidlAnnotation & a)941 std::string generate_java_unsupportedappusage_parameters(const AidlAnnotation& a) {
942 const std::map<std::string, std::string> params = a.AnnotationParams(ConstantValueDecorator);
943 std::vector<string> parameters_decl;
944 for (const auto& name_and_param : params) {
945 const std::string& param_name = name_and_param.first;
946 const std::string& param_value = name_and_param.second;
947 parameters_decl.push_back(param_name + " = " + param_value);
948 }
949 parameters_decl.push_back("overrideSourcePosition=\"" + dump_location(a) + "\"");
950 return "(" + Join(parameters_decl, ", ") + ")";
951 }
952
generate_java_annotations(const AidlAnnotatable & a)953 std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
954 std::vector<std::string> result;
955 if (a.IsHide()) {
956 result.emplace_back("@android.annotation.Hide");
957 }
958
959 const AidlAnnotation* unsupported_app_usage = a.UnsupportedAppUsage();
960 if (unsupported_app_usage != nullptr) {
961 result.emplace_back("@android.compat.annotation.UnsupportedAppUsage" +
962 generate_java_unsupportedappusage_parameters(*unsupported_app_usage));
963 }
964
965 for (const auto& annotation : a.GetAnnotations()) {
966 if (annotation.GetType() == AidlAnnotation::Type::JAVA_PASSTHROUGH) {
967 result.emplace_back(annotation.ParamValue<std::string>("annotation").value());
968 }
969 }
970
971 return result;
972 }
973
974 struct JavaAnnotationsVisitor : AidlVisitor {
JavaAnnotationsVisitorandroid::aidl::java::JavaAnnotationsVisitor975 JavaAnnotationsVisitor(std::vector<std::string>& result) : result(result) {}
Visitandroid::aidl::java::JavaAnnotationsVisitor976 void Visit(const AidlTypeSpecifier& t) override { result = generate_java_annotations(t); }
Visitandroid::aidl::java::JavaAnnotationsVisitor977 void Visit(const AidlInterface& t) override { ForDefinedType(t); }
Visitandroid::aidl::java::JavaAnnotationsVisitor978 void Visit(const AidlParcelable& t) override { ForDefinedType(t); }
Visitandroid::aidl::java::JavaAnnotationsVisitor979 void Visit(const AidlStructuredParcelable& t) override { ForDefinedType(t); }
Visitandroid::aidl::java::JavaAnnotationsVisitor980 void Visit(const AidlUnionDecl& t) override { ForDefinedType(t); }
Visitandroid::aidl::java::JavaAnnotationsVisitor981 void Visit(const AidlEnumDeclaration& t) override { ForDefinedType(t); }
Visitandroid::aidl::java::JavaAnnotationsVisitor982 void Visit(const AidlMethod& m) override { ForMember(m); }
Visitandroid::aidl::java::JavaAnnotationsVisitor983 void Visit(const AidlConstantDeclaration& c) override { ForMember(c); }
Visitandroid::aidl::java::JavaAnnotationsVisitor984 void Visit(const AidlVariableDeclaration& v) override { ForMember(v); }
985 std::vector<std::string>& result;
986
ForDefinedTypeandroid::aidl::java::JavaAnnotationsVisitor987 void ForDefinedType(const AidlDefinedType& t) {
988 result = generate_java_annotations(t);
989 if (t.IsDeprecated()) {
990 result.push_back("@Deprecated");
991 }
992 }
993 template <typename Member>
ForMemberandroid::aidl::java::JavaAnnotationsVisitor994 void ForMember(const Member& t) {
995 result = generate_java_annotations(t.GetType());
996 if (t.IsDeprecated()) {
997 result.push_back("@Deprecated");
998 }
999 }
1000 };
1001
JavaAnnotationsFor(const AidlNode & a)1002 std::vector<std::string> JavaAnnotationsFor(const AidlNode& a) {
1003 std::vector<std::string> result;
1004 JavaAnnotationsVisitor visitor{result};
1005 a.DispatchVisit(visitor);
1006 return result;
1007 }
1008
1009 } // namespace java
1010 } // namespace aidl
1011 } // namespace android
1012