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