1 /*
2  * Copyright (C) 2018, 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 "aidl_to_java.h"
18 #include "aidl_language.h"
19 #include "aidl_typenames.h"
20 #include "logging.h"
21 
22 #include <android-base/strings.h>
23 
24 #include <functional>
25 #include <iostream>
26 #include <map>
27 #include <string>
28 #include <vector>
29 
30 namespace android {
31 namespace aidl {
32 namespace java {
33 
34 using android::base::Join;
35 
36 using std::function;
37 using std::map;
38 using std::string;
39 using std::vector;
40 
ConstantValueDecorator(const AidlTypeSpecifier & type,const std::variant<std::string,std::vector<std::string>> & raw_value)41 std::string ConstantValueDecorator(
42     const AidlTypeSpecifier& type,
43     const std::variant<std::string, std::vector<std::string>>& raw_value) {
44   if (type.IsArray()) {
45     const auto& values = std::get<std::vector<std::string>>(raw_value);
46     return "{" + Join(values, ", ") + "}";
47   }
48   const std::string& value = std::get<std::string>(raw_value);
49   if (type.GetName() == "long") {
50     return value + "L";
51   }
52   if (auto defined_type = type.GetDefinedType(); defined_type) {
53     auto enum_type = defined_type->AsEnumDeclaration();
54     AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
55     return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
56   }
57   return value;
58 };
59 
JavaNameOf(const AidlTypeSpecifier & aidl,bool instantiable=false,bool boxing=false)60 const string& JavaNameOf(const AidlTypeSpecifier& aidl, bool instantiable = false,
61                          bool boxing = false) {
62   AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
63 
64   if (instantiable) {
65     // An instantiable type is used in only out type(not even inout type),
66     // And instantiable type has to be either the type in List, Map, ParcelFileDescriptor or
67     // user-defined type.
68 
69     static map<string, string> instantiable_m = {
70         {"List", "java.util.ArrayList"},
71         {"Map", "java.util.HashMap"},
72         {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
73     };
74     const string& aidl_name = aidl.GetName();
75 
76     if (instantiable_m.find(aidl_name) != instantiable_m.end()) {
77       return instantiable_m[aidl_name];
78     }
79   }
80 
81   // map from AIDL built-in type name to the corresponding Java type name
82   static map<string, string> m = {
83       {"void", "void"},
84       {"boolean", "boolean"},
85       {"byte", "byte"},
86       {"char", "char"},
87       {"int", "int"},
88       {"long", "long"},
89       {"float", "float"},
90       {"double", "double"},
91       {"String", "java.lang.String"},
92       {"List", "java.util.List"},
93       {"Map", "java.util.Map"},
94       {"IBinder", "android.os.IBinder"},
95       {"FileDescriptor", "java.io.FileDescriptor"},
96       {"CharSequence", "java.lang.CharSequence"},
97       {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
98       {"ParcelableHolder", "android.os.ParcelableHolder"},
99   };
100 
101   // map from primitive types to the corresponding boxing types
102   static map<string, string> boxing_types = {
103       {"void", "Void"},   {"boolean", "Boolean"}, {"byte", "Byte"},   {"char", "Character"},
104       {"int", "Integer"}, {"long", "Long"},       {"float", "Float"}, {"double", "Double"},
105   };
106 
107   // Enums in Java are represented by their backing type when
108   // referenced in parcelables, methods, etc.
109   const auto defined_type = aidl.GetDefinedType();
110   if (defined_type && defined_type->AsEnumDeclaration()) {
111     const auto enum_decl = defined_type->AsEnumDeclaration();
112     const string& backing_type_name = enum_decl->GetBackingType().GetName();
113     AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
114     AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
115     if (boxing) {
116       return boxing_types[backing_type_name];
117     } else {
118       return m[backing_type_name];
119     }
120   }
121 
122   const string& aidl_name = aidl.GetName();
123   if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
124     // Every primitive type must have the corresponding boxing type
125     AIDL_FATAL_IF(boxing_types.find(aidl_name) == m.end(), aidl);
126     return boxing_types[aidl_name];
127   }
128   if (m.find(aidl_name) != m.end()) {
129     AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), aidl);
130     return m[aidl_name];
131   } else {
132     // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
133     return aidl_name;
134   }
135 }
136 
137 namespace {
JavaSignatureOfInternal(const AidlTypeSpecifier & aidl,bool instantiable,bool omit_array,bool boxing)138 string JavaSignatureOfInternal(const AidlTypeSpecifier& aidl, bool instantiable, bool omit_array,
139                                bool boxing) {
140   string ret = JavaNameOf(aidl, instantiable, boxing && !aidl.IsArray());
141   if (aidl.IsGeneric()) {
142     vector<string> arg_names;
143     for (const auto& ta : aidl.GetTypeParameters()) {
144       arg_names.emplace_back(JavaSignatureOfInternal(*ta, /*instantiable=*/false,
145                                                      /*omit_array=*/false, /*boxing=*/true));
146     }
147     ret += "<" + Join(arg_names, ",") + ">";
148   }
149   if (aidl.IsArray() && !omit_array) {
150     if (aidl.IsFixedSizeArray()) {
151       ret += Join(std::vector<std::string>(aidl.GetFixedSizeArrayDimensions().size(), "[]"), "");
152     } else {
153       ret += "[]";
154     }
155   }
156   return ret;
157 }
158 
159 // Returns the name of the backing type for the specified type.
160 // Note: Do not use the result in the generated code! It's supposed to be used as a key.
161 // This returns type names as used in AIDL, not a Java signature.
162 // For enums, this is the enum's backing type.
163 // For all other types, this is the type itself.
AidlBackingTypeName(const AidlTypeSpecifier & type)164 string AidlBackingTypeName(const AidlTypeSpecifier& type) {
165   string type_name;
166   const auto defined_type = type.GetDefinedType();
167   if (defined_type && defined_type->AsEnumDeclaration()) {
168     const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
169     type_name = enum_decl->GetBackingType().GetName();
170   } else {
171     type_name = type.GetName();
172   }
173   if (type.IsArray()) {
174     if (type.IsFixedSizeArray()) {
175       for (const auto& dim : type.GetFixedSizeArrayDimensions()) {
176         type_name += "[" + std::to_string(dim) + "]";
177       }
178     } else {
179       type_name += "[]";
180     }
181   }
182   return type_name;
183 }
184 
185 }  // namespace
186 
JavaSignatureOf(const AidlTypeSpecifier & aidl)187 string JavaSignatureOf(const AidlTypeSpecifier& aidl) {
188   return JavaSignatureOfInternal(aidl, /*instantiable=*/false, /*omit_array=*/false,
189                                  /*boxing=*/false);
190 }
191 
192 // Used for "new" expression. Ignore arrays because "new" expression handles it.
InstantiableJavaSignatureOf(const AidlTypeSpecifier & aidl)193 string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl) {
194   return JavaSignatureOfInternal(aidl, /*instantiable=*/true, /*omit_array=*/true,
195                                  /*boxing=*/false);
196 }
197 
JavaBoxingTypeOf(const AidlTypeSpecifier & aidl)198 string JavaBoxingTypeOf(const AidlTypeSpecifier& aidl) {
199   AIDL_FATAL_IF(!AidlTypenames::IsPrimitiveTypename(aidl.GetName()), aidl);
200   return JavaSignatureOfInternal(aidl, /*instantiable=*/false, /*omit_array=*/false,
201                                  /*boxing=*/true);
202 }
203 
DefaultJavaValueOf(const AidlTypeSpecifier & aidl)204 string DefaultJavaValueOf(const AidlTypeSpecifier& aidl) {
205   static map<string, string> m = {
206       {"boolean", "false"}, {"byte", "0"},     {"char", R"('\u0000')"}, {"int", "0"},
207       {"long", "0L"},       {"float", "0.0f"}, {"double", "0.0d"},
208   };
209 
210   const string name = AidlBackingTypeName(aidl);
211   AIDL_FATAL_IF(name == "void", aidl);
212 
213   if (!aidl.IsArray() && m.find(name) != m.end()) {
214     AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(name), aidl);
215     return m[name];
216   } else {
217     return "null";
218   }
219 }
220 
221 typedef void (*ParcelHelperGenerator)(CodeWriter&, const Options&);
222 
GenerateTypedObjectHelper(CodeWriter & out,const Options &)223 static void GenerateTypedObjectHelper(CodeWriter& out, const Options&) {
224   // Note that the name is inconsistent here because Parcel.java defines readTypedObject as if it
225   // "creates" a new value from a parcel. "in-place" read function is not necessary because
226   // user-defined parcelable defines its readFromParcel.
227   out << R"(static private <T> T readTypedObject(
228     android.os.Parcel parcel,
229     android.os.Parcelable.Creator<T> c) {
230   if (parcel.readInt() != 0) {
231       return c.createFromParcel(parcel);
232   } else {
233       return null;
234   }
235 }
236 static private <T extends android.os.Parcelable> void writeTypedObject(
237     android.os.Parcel parcel, T value, int parcelableFlags) {
238   if (value != null) {
239     parcel.writeInt(1);
240     value.writeToParcel(parcel, parcelableFlags);
241   } else {
242     parcel.writeInt(0);
243   }
244 }
245 )";
246 }
247 
GenerateTypedListHelper(CodeWriter & out,const Options & options)248 static void GenerateTypedListHelper(CodeWriter& out, const Options& options) {
249   out << R"(static private <T extends android.os.Parcelable> void writeTypedList(
250     android.os.Parcel parcel, java.util.List<T> value, int parcelableFlags) {
251   if (value == null) {
252     parcel.writeInt(-1);
253   } else {
254     int N = value.size();
255     int i = 0;
256     parcel.writeInt(N);
257     while (i < N) {
258 )";
259 
260   if (options.GetMinSdkVersion() < 23u) {
261     out << "writeTypedObject(parcel, value.get(i), parcelableFlags);";
262   } else {
263     out << "parcel.writeTypedObject(value.get(i), parcelableFlags);";
264   }
265 
266   out << R"(
267       i++;
268     }
269   }
270 }
271 )";
272 }
273 
GenerateParcelHelpers(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)274 void GenerateParcelHelpers(CodeWriter& out, const AidlDefinedType& defined_type,
275                            const AidlTypenames& typenames, const Options& options) {
276   // root-level type contains all necessary helpers
277   if (defined_type.GetParentType()) {
278     return;
279   }
280   // visits method parameters and parcelable fields to collect types which
281   // requires read/write/create helpers.
282   struct Visitor : AidlVisitor {
283     const AidlTypenames& typenames;
284     const Options& options;
285     set<ParcelHelperGenerator> helpers;
286     Visitor(const AidlTypenames& typenames, const Options& options)
287         : typenames(typenames), options(options) {}
288     void Visit(const AidlTypeSpecifier& type) override {
289       auto name = type.GetName();
290       if (auto defined_type = type.GetDefinedType(); defined_type) {
291         if (defined_type->AsParcelable() != nullptr && !type.IsArray()) {
292           // TypedObjects are supported since 23. So we don't need helpers.
293           if (options.GetMinSdkVersion() < 23u) {
294             helpers.insert(&GenerateTypedObjectHelper);
295           }
296         }
297       } else {
298         // There's parcelable-like built-in types as well.
299         if (name == "ParcelFileDescriptor" || name == "CharSequence") {
300           if (!type.IsArray()) {
301             // TypedObjects are supported since 23. So we don't need helpers.
302             if (options.GetMinSdkVersion() < 23u) {
303               helpers.insert(&GenerateTypedObjectHelper);
304             }
305           }
306         }
307 
308         if (name == "List" && type.IsGeneric()) {
309           const auto& element_name = type.GetTypeParameters()[0]->GetName();
310           if (typenames.IsParcelable(element_name) && options.GetMinSdkVersion() <= 33u) {
311             helpers.insert(&GenerateTypedListHelper);
312           }
313         }
314       }
315     }
316   } v{typenames, options};
317 
318   VisitTopDown(v, defined_type);
319   if (!v.helpers.empty()) {
320     // Nested class (_Parcel) is used to contain static helper methods because some targets are
321     // still using Java 7 which doesn't allow interfaces to have static methods.
322     // Helpers shouldn't bother API checks, but in case where AIDL types are not marked `@hide`
323     // explicitly marks the helper class as @hide.
324     out << "/** @hide */\n";
325     out << "static class _Parcel {\n";
326     out.Indent();
327     for (const auto& helper : v.helpers) {
328       helper(out, options);
329     }
330     out.Dedent();
331     out << "}\n";
332   }
333 }
334 
WriteToParcelFor(const CodeGeneratorContext & c)335 void WriteToParcelFor(const CodeGeneratorContext& c) {
336   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
337       {"boolean",
338        [](const CodeGeneratorContext& c) {
339          if (c.min_sdk_version >= 29u) {
340            c.writer << c.parcel << ".writeBoolean(" << c.var << ");\n";
341          } else {
342            c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
343          }
344        }},
345       {"boolean[]",
346        [](const CodeGeneratorContext& c) {
347          c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
348        }},
349       {"byte",
350        [](const CodeGeneratorContext& c) {
351          c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
352        }},
353       {"byte[]",
354        [](const CodeGeneratorContext& c) {
355          c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
356        }},
357       {"char",
358        [](const CodeGeneratorContext& c) {
359          c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
360        }},
361       {"char[]",
362        [](const CodeGeneratorContext& c) {
363          c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
364        }},
365       {"int",
366        [](const CodeGeneratorContext& c) {
367          c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
368        }},
369       {"int[]",
370        [](const CodeGeneratorContext& c) {
371          c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
372        }},
373       {"long",
374        [](const CodeGeneratorContext& c) {
375          c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
376        }},
377       {"long[]",
378        [](const CodeGeneratorContext& c) {
379          c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
380        }},
381       {"float",
382        [](const CodeGeneratorContext& c) {
383          c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
384        }},
385       {"float[]",
386        [](const CodeGeneratorContext& c) {
387          c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
388        }},
389       {"double",
390        [](const CodeGeneratorContext& c) {
391          c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
392        }},
393       {"double[]",
394        [](const CodeGeneratorContext& c) {
395          c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
396        }},
397       {"String",
398        [](const CodeGeneratorContext& c) {
399          c.writer << c.parcel << ".writeString(" << c.var << ");\n";
400        }},
401       {"String[]",
402        [](const CodeGeneratorContext& c) {
403          c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
404        }},
405       {"List",
406        [](const CodeGeneratorContext& c) {
407          if (c.type.IsGeneric()) {
408            AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
409            const auto& element_type = *c.type.GetTypeParameters().at(0);
410            const auto& element_type_name = element_type.GetName();
411            if (element_type_name == "String") {
412              c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
413            } else if (element_type_name == "IBinder") {
414              c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
415            } else if (c.typenames.IsParcelable(element_type_name)) {
416              if (c.min_sdk_version > 33u) {
417                c.writer << c.parcel << ".writeTypedList(" << c.var << ", " << c.write_to_parcel_flag
418                         << ");\n";
419              } else {
420                c.writer << "_Parcel.writeTypedList(" << c.parcel << ", " << c.var << ", "
421                         << c.write_to_parcel_flag << ");\n";
422              }
423            } else if (c.typenames.GetInterface(element_type)) {
424              c.writer << c.parcel << ".writeInterfaceList(" << c.var << ");\n";
425            } else {
426              AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << element_type_name;
427            }
428          } else {
429            c.writer << c.parcel << ".writeList(" << c.var << ");\n";
430          }
431        }},
432       {"Map",
433        [](const CodeGeneratorContext& c) {
434          if (c.type.IsGeneric()) {
435            c.writer << "if (" << c.var << " == null) {\n";
436            c.writer.Indent();
437            c.writer << c.parcel << ".writeInt(-1);\n";
438            c.writer.Dedent();
439            c.writer << "} else {\n";
440            c.writer.Indent();
441            c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
442            c.writer << c.var << ".forEach((k, v) -> {\n";
443            c.writer.Indent();
444            c.writer << c.parcel << ".writeString(k);\n";
445 
446            CodeGeneratorContext value_context{
447                c.writer,
448                c.typenames,
449                *c.type.GetTypeParameters()[1].get(),
450                c.parcel,
451                "v",
452                c.min_sdk_version,
453                c.write_to_parcel_flag,
454                c.is_classloader_created,
455            };
456            WriteToParcelFor(value_context);
457            c.writer.Dedent();
458            c.writer << "});\n";
459 
460            c.writer.Dedent();
461            c.writer << "}\n";
462          } else {
463            c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
464          }
465        }},
466       {"IBinder",
467        [](const CodeGeneratorContext& c) {
468          c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
469        }},
470       {"IBinder[]",
471        [](const CodeGeneratorContext& c) {
472          c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
473        }},
474       {"FileDescriptor",
475        [](const CodeGeneratorContext& c) {
476          c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
477        }},
478       {"FileDescriptor[]",
479        [](const CodeGeneratorContext& c) {
480          c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
481        }},
482       {"ParcelFileDescriptor",
483        [](const CodeGeneratorContext& c) {
484          if (c.min_sdk_version >= 23u) {
485            c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << c.write_to_parcel_flag
486                     << ");\n";
487          } else {
488            c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
489                     << c.write_to_parcel_flag << ");\n";
490          }
491        }},
492       {"ParcelFileDescriptor[]",
493        [](const CodeGeneratorContext& c) {
494          c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << c.write_to_parcel_flag
495                   << ");\n";
496        }},
497       {"CharSequence",
498        [](const CodeGeneratorContext& c) {
499          // TextUtils.writeToParcel does not accept null. So, we need to handle
500          // the case here.
501          c.writer << "if (" << c.var << "!=null) {\n";
502          c.writer.Indent();
503          c.writer << c.parcel << ".writeInt(1);\n";
504          c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
505                   << c.write_to_parcel_flag << ");\n";
506          c.writer.Dedent();
507          c.writer << "}\n";
508          c.writer << "else {\n";
509          c.writer.Indent();
510          c.writer << c.parcel << ".writeInt(0);\n";
511          c.writer.Dedent();
512          c.writer << "}\n";
513        }},
514       {"ParcelableHolder",
515        [](const CodeGeneratorContext& c) {
516          c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
517        }},
518   };
519   const string type_name = AidlBackingTypeName(c.type);
520   const auto found = method_map.find(type_name);
521   if (found != method_map.end()) {
522     found->second(c);
523   } else if (c.type.IsFixedSizeArray()) {
524     std::vector<std::string> args = {c.var, c.write_to_parcel_flag};
525     for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
526       args.push_back(std::to_string(dim));
527     }
528     c.writer << c.parcel << ".writeFixedArray(" << Join(args, ", ") << ");\n";
529   } else {
530     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
531     AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
532     if (t->AsInterface() != nullptr) {
533       if (c.type.IsArray()) {
534         c.writer << c.parcel << ".writeInterfaceArray(" << c.var << ");\n";
535       } else {
536         c.writer << c.parcel << ".writeStrongInterface(" << c.var << ");\n";
537       }
538     } else if (t->AsParcelable() != nullptr) {
539       if (c.type.IsArray()) {
540         c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << c.write_to_parcel_flag
541                  << ");\n";
542       } else {
543         if (c.min_sdk_version >= 23u) {
544           c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << c.write_to_parcel_flag
545                    << ");\n";
546         } else {
547           c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
548                    << c.write_to_parcel_flag << ");\n";
549         }
550       }
551     }
552   }
553 }
554 
555 // Ensures that a variable is initialized to refer to the classloader
556 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)557 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
558   AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
559   if (!*(c.is_classloader_created)) {
560     c.writer << "java.lang.ClassLoader cl = "
561              << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
562     *(c.is_classloader_created) = true;
563   }
564   return "cl";
565 }
566 
CreateFromParcelFor(const CodeGeneratorContext & c)567 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
568   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
569       {"boolean",
570        [](const CodeGeneratorContext& c) {
571          if (c.min_sdk_version >= 29u) {
572            c.writer << c.var << " = " << c.parcel << ".readBoolean();\n";
573          } else {
574            c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
575          }
576        }},
577       {"boolean[]",
578        [](const CodeGeneratorContext& c) {
579          c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
580        }},
581       {"byte",
582        [](const CodeGeneratorContext& c) {
583          c.writer << c.var << " = " << c.parcel << ".readByte();\n";
584        }},
585       {"byte[]",
586        [](const CodeGeneratorContext& c) {
587          c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
588        }},
589       {"char",
590        [](const CodeGeneratorContext& c) {
591          c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
592        }},
593       {"char[]",
594        [](const CodeGeneratorContext& c) {
595          c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
596        }},
597       {"int",
598        [](const CodeGeneratorContext& c) {
599          c.writer << c.var << " = " << c.parcel << ".readInt();\n";
600        }},
601       {"int[]",
602        [](const CodeGeneratorContext& c) {
603          c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
604        }},
605       {"long",
606        [](const CodeGeneratorContext& c) {
607          c.writer << c.var << " = " << c.parcel << ".readLong();\n";
608        }},
609       {"long[]",
610        [](const CodeGeneratorContext& c) {
611          c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
612        }},
613       {"float",
614        [](const CodeGeneratorContext& c) {
615          c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
616        }},
617       {"float[]",
618        [](const CodeGeneratorContext& c) {
619          c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
620        }},
621       {"double",
622        [](const CodeGeneratorContext& c) {
623          c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
624        }},
625       {"double[]",
626        [](const CodeGeneratorContext& c) {
627          c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
628        }},
629       {"String",
630        [](const CodeGeneratorContext& c) {
631          c.writer << c.var << " = " << c.parcel << ".readString();\n";
632        }},
633       {"String[]",
634        [](const CodeGeneratorContext& c) {
635          c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
636        }},
637       {"List",
638        [](const CodeGeneratorContext& c) {
639          if (c.type.IsGeneric()) {
640            AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
641            const auto& element_type = *c.type.GetTypeParameters().at(0);
642            const auto& element_type_name = element_type.GetName();
643            if (element_type_name == "String") {
644              c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
645            } else if (element_type_name == "IBinder") {
646              c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
647            } else if (c.typenames.IsParcelable(element_type_name)) {
648              c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
649                       << JavaNameOf(element_type) << ".CREATOR);\n";
650            } else if (c.typenames.GetInterface(element_type)) {
651              auto as_interface = element_type_name + ".Stub::asInterface";
652              c.writer << c.var << " = " << c.parcel << ".createInterfaceArrayList(" << as_interface
653                       << ");\n";
654            } else {
655              AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << element_type_name;
656            }
657          } else {
658            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
659            c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
660          }
661        }},
662       {"Map",
663        [](const CodeGeneratorContext& c) {
664          if (c.type.IsGeneric()) {
665            c.writer << "{\n";
666            c.writer.Indent();
667            c.writer << "int N = " << c.parcel << ".readInt();\n";
668            c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
669 
670            auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1))) + ".CREATOR";
671            c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
672            c.writer.Indent();
673            c.writer << "String k = " << c.parcel << ".readString();\n";
674            c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
675            CodeGeneratorContext value_context{
676                c.writer,
677                c.typenames,
678                *c.type.GetTypeParameters()[1].get(),
679                c.parcel,
680                "v",
681                c.min_sdk_version,
682                c.write_to_parcel_flag,
683                c.is_classloader_created,
684            };
685            CreateFromParcelFor(value_context);
686            c.writer << c.var << ".put(k, v);\n";
687 
688            c.writer.Dedent();
689            c.writer << "});\n";
690 
691            c.writer.Dedent();
692            c.writer << "}\n";
693          } else {
694            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
695            c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
696          }
697        }},
698       {"IBinder",
699        [](const CodeGeneratorContext& c) {
700          c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
701        }},
702       {"IBinder[]",
703        [](const CodeGeneratorContext& c) {
704          c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
705        }},
706       {"FileDescriptor",
707        [](const CodeGeneratorContext& c) {
708          c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
709        }},
710       {"FileDescriptor[]",
711        [](const CodeGeneratorContext& c) {
712          c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
713        }},
714       {"ParcelFileDescriptor",
715        [](const CodeGeneratorContext& c) {
716          if (c.min_sdk_version >= 23u) {
717            c.writer << c.var << " = " << c.parcel
718                     << ".readTypedObject(android.os.ParcelFileDescriptor.CREATOR);\n";
719          } else {
720            c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
721                     << ", android.os.ParcelFileDescriptor.CREATOR);\n";
722          }
723        }},
724       {"ParcelFileDescriptor[]",
725        [](const CodeGeneratorContext& c) {
726          c.writer << c.var << " = " << c.parcel
727                   << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
728        }},
729       {"CharSequence",
730        [](const CodeGeneratorContext& c) {
731          if (c.min_sdk_version >= 23u) {
732            c.writer << c.var << " = " << c.parcel
733                     << ".readTypedObject(android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
734          } else {
735            c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
736                     << ", android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
737          }
738        }},
739       {"ParcelableHolder",
740        [](const CodeGeneratorContext& c) {
741          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
742          c.writer.Indent();
743          c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
744          c.writer.Dedent();
745          c.writer << "}\n";
746        }},
747   };
748   const auto found = method_map.find(AidlBackingTypeName(c.type));
749   if (found != method_map.end()) {
750     found->second(c);
751   } else if (c.type.IsFixedSizeArray()) {
752     std::vector<std::string> args = {JavaSignatureOf(c.type) + ".class"};
753     if (c.typenames.IsParcelable(c.type.GetName())) {
754       args.push_back(JavaNameOf(c.type) + ".CREATOR");
755     } else if (c.typenames.GetInterface(c.type)) {
756       args.push_back(c.type.GetName() + ".Stub::asInterface");
757     }
758     for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
759       args.push_back(std::to_string(dim));
760     }
761     c.writer << c.var << " = " << c.parcel << ".createFixedArray(" << Join(args, ", ") << ");\n";
762   } else {
763     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
764     AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
765     if (t->AsInterface() != nullptr) {
766       auto name = c.type.GetName();
767       if (c.type.IsArray()) {
768         auto new_array = name + "[]::new";
769         auto as_interface = name + ".Stub::asInterface";
770         c.writer << c.var << " = " << c.parcel << ".createInterfaceArray(" << new_array << ", "
771                  << as_interface << ");\n";
772       } else {
773         c.writer << c.var << " = " << name << ".Stub.asInterface(" << c.parcel
774                  << ".readStrongBinder());\n";
775       }
776     } else if (t->AsParcelable() != nullptr) {
777       if (c.type.IsArray()) {
778         c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
779                  << ".CREATOR);\n";
780       } else {
781         if (c.min_sdk_version >= 23u) {
782           c.writer << c.var << " = " << c.parcel << ".readTypedObject(" << c.type.GetName()
783                    << ".CREATOR);\n";
784         } else {
785           c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel << ", " << c.type.GetName()
786                    << ".CREATOR);\n";
787         }
788       }
789     }
790   }
791   return true;
792 }
793 
ReadFromParcelFor(const CodeGeneratorContext & c)794 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
795   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
796       {"boolean[]",
797        [](const CodeGeneratorContext& c) {
798          c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
799        }},
800       {"byte[]",
801        [](const CodeGeneratorContext& c) {
802          c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
803        }},
804       {"char[]",
805        [](const CodeGeneratorContext& c) {
806          c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
807        }},
808       {"int[]",
809        [](const CodeGeneratorContext& c) {
810          c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
811        }},
812       {"long[]",
813        [](const CodeGeneratorContext& c) {
814          c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
815        }},
816       {"float[]",
817        [](const CodeGeneratorContext& c) {
818          c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
819        }},
820       {"double[]",
821        [](const CodeGeneratorContext& c) {
822          c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
823        }},
824       {"String[]",
825        [](const CodeGeneratorContext& c) {
826          c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
827        }},
828       {"List",
829        [](const CodeGeneratorContext& c) {
830          if (c.type.IsGeneric()) {
831            AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
832            const auto& element_type = *c.type.GetTypeParameters().at(0);
833            const auto& element_type_name = element_type.GetName();
834            if (element_type_name == "String") {
835              c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
836            } else if (element_type_name == "IBinder") {
837              c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
838            } else if (c.typenames.IsParcelable(element_type_name)) {
839              c.writer << c.parcel << ".readTypedList(" << c.var << ", "
840                       << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
841            } else if (c.typenames.GetInterface(element_type)) {
842              auto as_interface = element_type_name + ".Stub::asInterface";
843              c.writer << c.parcel << ".readInterfaceList(" << c.var << ", " << as_interface
844                       << ");\n";
845            } else {
846              AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << element_type_name;
847            }
848          } else {
849            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
850            c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
851          }
852        }},
853       {"Map",
854        [](const CodeGeneratorContext& c) {
855          if (c.type.IsGeneric()) {
856            c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
857            c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
858                     << ".readInt()).forEach(i -> {\n";
859            c.writer.Indent();
860            c.writer << "String k = " << c.parcel << ".readString();\n";
861            c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
862            CodeGeneratorContext value_context{
863                c.writer,
864                c.typenames,
865                *c.type.GetTypeParameters()[1].get(),
866                c.parcel,
867                "v",
868                c.min_sdk_version,
869                c.write_to_parcel_flag,
870                c.is_classloader_created,
871            };
872            CreateFromParcelFor(value_context);
873            c.writer << c.var << ".put(k, v);\n";
874 
875            c.writer.Dedent();
876            c.writer << "});\n";
877          } else {
878            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
879            c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
880          }
881        }},
882       {"IBinder[]",
883        [](const CodeGeneratorContext& c) {
884          c.writer << c.parcel << ".readBinderArray(" << c.var << ");\n";
885        }},
886       {"FileDescriptor[]",
887        [](const CodeGeneratorContext& c) {
888          c.writer << c.parcel << ".readRawFileDescriptorArray(" << c.var << ");\n";
889        }},
890       {"ParcelFileDescriptor",
891        [](const CodeGeneratorContext& c) {
892          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
893          c.writer.Indent();
894          c.writer << c.var << " = "
895                   << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
896                   << ");\n";
897          c.writer.Dedent();
898          c.writer << "}\n";
899        }},
900       {"ParcelFileDescriptor[]",
901        [](const CodeGeneratorContext& c) {
902          c.writer << c.parcel << ".readTypedArray(" << c.var
903                   << ", android.os.ParcelFileDescriptor.CREATOR);\n";
904        }},
905   };
906   const auto& found = method_map.find(AidlBackingTypeName(c.type));
907   if (found != method_map.end()) {
908     found->second(c);
909   } else if (c.type.IsFixedSizeArray()) {
910     std::vector<std::string> args = {c.var};
911     if (c.typenames.IsParcelable(c.type.GetName())) {
912       args.push_back(c.type.GetName() + ".CREATOR");
913     } else if (c.typenames.GetInterface(c.type)) {
914       args.push_back(c.type.GetName() + ".Stub::asInterface");
915     }
916     c.writer << c.parcel << ".readFixedArray(" << Join(args, ", ") << ");\n";
917   } else {
918     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
919     AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
920     if (t->AsParcelable() != nullptr || t->AsUnionDeclaration() != nullptr) {
921       if (c.type.IsArray()) {
922         c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
923                  << ".CREATOR);\n";
924       } else {
925         c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
926         c.writer.Indent();
927         c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
928         c.writer.Dedent();
929         c.writer << "}\n";
930       }
931     } else if (t->AsInterface()) {
932       AIDL_FATAL_IF(!c.type.IsArray(), c.type) << "readFromParcel(interface) doesn't make sense.";
933       auto as_interface = c.type.GetName() + ".Stub::asInterface";
934       c.writer << c.parcel << ".readInterfaceArray(" << c.var << ", " << as_interface << ");\n";
935     }
936   }
937   return true;
938 }
939 
ToStringFor(const CodeGeneratorContext & c)940 void ToStringFor(const CodeGeneratorContext& c) {
941   // Use derived toString() for enum type annotated with @JavaDerive(toString=true)
942   if (auto t = c.type.GetDefinedType();
943       t != nullptr && t->AsEnumDeclaration() && t->JavaDerive("toString")) {
944     if (c.type.IsArray()) {
945       c.writer << c.type.GetName() << ".$.arrayToString(" << c.var << ")";
946     } else {
947       c.writer << c.type.GetName() << ".$.toString(" << c.var << ")";
948     }
949     return;
950   }
951 
952   if (c.type.IsArray()) {
953     if (c.type.IsDynamicArray() || c.type.GetFixedSizeArrayDimensions().size() == 1) {
954       c.writer << "java.util.Arrays.toString(" << c.var << ")";
955     } else {
956       c.writer << "java.util.Arrays.deepToString(" << c.var << ")";
957     }
958     return;
959   }
960 
961   const std::string name = c.type.GetName();
962 
963   if (AidlTypenames::IsPrimitiveTypename(name)) {
964     c.writer << c.var;
965     return;
966   }
967 
968   const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
969   if (t != nullptr && t->AsEnumDeclaration()) {
970     c.writer << c.var;
971     return;
972   }
973 
974   // FileDescriptor doesn't have a good toString() impl.
975   if (name == "FileDescriptor") {
976     c.writer << c.var << " == null ? \"null\" : ";
977     c.writer << c.var << ".getInt$()";
978     return;
979   }
980 
981   // Rest of the built-in types have reasonable toString() impls.
982   if (AidlTypenames::IsBuiltinTypename(name)) {
983     c.writer << "java.util.Objects.toString(" << c.var << ")";
984     return;
985   }
986 
987   // For user-defined types, we also use toString() that we are generating here, but just make sure
988   // that they are actually user-defined types.
989   AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
990   if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
991     c.writer << "java.util.Objects.toString(" << c.var << ")";
992     return;
993   }
994 
995   AIDL_FATAL(AIDL_LOCATION_HERE) << "Unhandled typename: " << name;
996 }
997 
998 }  // namespace java
999 }  // namespace aidl
1000 }  // namespace android
1001