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