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