• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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