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::endl;
37 using std::function;
38 using std::map;
39 using std::string;
40 using std::vector;
41 
ConstantValueDecorator(const AidlTypeSpecifier & type,const std::string & raw_value)42 std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
43   if (type.GetName() == "long" && !type.IsArray()) {
44     return raw_value + "L";
45   }
46 
47   return raw_value;
48 };
49 
JavaNameOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames,bool instantiable=false,bool boxing=false)50 const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
51                          bool instantiable = false, bool boxing = false) {
52   CHECK(aidl.IsResolved()) << aidl.ToString();
53 
54   if (instantiable) {
55     // An instantiable type is used in only out type(not even inout type),
56     // And instantiable type has to be either the type in List, Map, ParcelFileDescriptor or
57     // user-defined type.
58 
59     static map<string, string> instantiable_m = {
60         {"List", "java.util.ArrayList"},
61         {"Map", "java.util.HashMap"},
62         {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
63     };
64     const string& aidl_name = aidl.GetName();
65 
66     if (instantiable_m.find(aidl_name) != instantiable_m.end()) {
67       return instantiable_m[aidl_name];
68     }
69   }
70 
71   // map from AIDL built-in type name to the corresponding Java type name
72   static map<string, string> m = {
73       {"void", "void"},
74       {"boolean", "boolean"},
75       {"byte", "byte"},
76       {"char", "char"},
77       {"int", "int"},
78       {"long", "long"},
79       {"float", "float"},
80       {"double", "double"},
81       {"String", "java.lang.String"},
82       {"List", "java.util.List"},
83       {"Map", "java.util.Map"},
84       {"IBinder", "android.os.IBinder"},
85       {"FileDescriptor", "java.io.FileDescriptor"},
86       {"CharSequence", "java.lang.CharSequence"},
87       {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
88       {"ParcelableHolder", "android.os.ParcelableHolder"},
89   };
90 
91   // map from primitive types to the corresponding boxing types
92   static map<string, string> boxing_types = {
93       {"void", "Void"},   {"boolean", "Boolean"}, {"byte", "Byte"},   {"char", "Character"},
94       {"int", "Integer"}, {"long", "Long"},       {"float", "Float"}, {"double", "Double"},
95   };
96 
97   // Enums in Java are represented by their backing type when
98   // referenced in parcelables, methods, etc.
99   if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
100       enum_decl != nullptr) {
101     const string& backing_type_name = enum_decl->GetBackingType().GetName();
102     CHECK(m.find(backing_type_name) != m.end());
103     CHECK(AidlTypenames::IsBuiltinTypename(backing_type_name));
104     return m[backing_type_name];
105   }
106 
107   const string& aidl_name = aidl.GetName();
108   if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
109     // Every primitive type must have the corresponding boxing type
110     CHECK(boxing_types.find(aidl_name) != m.end());
111     return boxing_types[aidl_name];
112   }
113   if (m.find(aidl_name) != m.end()) {
114     CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
115     return m[aidl_name];
116   } else {
117     // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
118     return aidl_name;
119   }
120 }
121 
122 namespace {
JavaSignatureOfInternal(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames,bool instantiable,bool omit_array,bool boxing=false)123 string JavaSignatureOfInternal(
124     const AidlTypeSpecifier& aidl, const AidlTypenames& typenames, bool instantiable,
125     bool omit_array, bool boxing = false /* boxing can be true only if it is a type parameter */) {
126   string ret = JavaNameOf(aidl, typenames, instantiable, boxing && !aidl.IsArray());
127   if (aidl.IsGeneric()) {
128     vector<string> arg_names;
129     for (const auto& ta : aidl.GetTypeParameters()) {
130       arg_names.emplace_back(
131           JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
132     }
133     ret += "<" + Join(arg_names, ",") + ">";
134   }
135   if (aidl.IsArray() && !omit_array) {
136     ret += "[]";
137   }
138   return ret;
139 }
140 
141 // Returns the name of the backing type for the specified type. Note: this
142 // returns type names as used in AIDL, not a Java signature.
143 // For enums, this is the enum's backing type.
144 // For all other types, this is the type itself.
AidlBackingTypeName(const AidlTypeSpecifier & type,const AidlTypenames & typenames)145 string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
146   string type_name;
147   if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
148       enum_decl != nullptr) {
149     type_name = enum_decl->GetBackingType().GetName();
150   } else {
151     type_name = type.GetName();
152   }
153   if (type.IsArray()) {
154     type_name += "[]";
155   }
156   return type_name;
157 }
158 
159 }  // namespace
160 
JavaSignatureOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)161 string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
162   return JavaSignatureOfInternal(aidl, typenames, false, false);
163 }
164 
InstantiableJavaSignatureOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)165 string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
166   return JavaSignatureOfInternal(aidl, typenames, true, true);
167 }
168 
DefaultJavaValueOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)169 string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
170   static map<string, string> m = {
171       {"boolean", "false"}, {"byte", "0"},     {"char", R"('\u0000')"}, {"int", "0"},
172       {"long", "0L"},       {"float", "0.0f"}, {"double", "0.0d"},
173   };
174 
175   const string name = AidlBackingTypeName(aidl, typenames);
176   CHECK(name != "void");
177 
178   if (!aidl.IsArray() && m.find(name) != m.end()) {
179     CHECK(AidlTypenames::IsBuiltinTypename(name));
180     return m[name];
181   } else {
182     return "null";
183   }
184 }
185 
GetFlagFor(const CodeGeneratorContext & c)186 static string GetFlagFor(const CodeGeneratorContext& c) {
187   if (c.is_return_value) {
188     return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
189   } else {
190     return "0";
191   }
192 }
193 
WriteToParcelFor(const CodeGeneratorContext & c)194 bool WriteToParcelFor(const CodeGeneratorContext& c) {
195   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
196       {"boolean",
197        [](const CodeGeneratorContext& c) {
198          c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
199        }},
200       {"boolean[]",
201        [](const CodeGeneratorContext& c) {
202          c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
203        }},
204       {"byte",
205        [](const CodeGeneratorContext& c) {
206          c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
207        }},
208       {"byte[]",
209        [](const CodeGeneratorContext& c) {
210          c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
211        }},
212       {"char",
213        [](const CodeGeneratorContext& c) {
214          c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
215        }},
216       {"char[]",
217        [](const CodeGeneratorContext& c) {
218          c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
219        }},
220       {"int",
221        [](const CodeGeneratorContext& c) {
222          c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
223        }},
224       {"int[]",
225        [](const CodeGeneratorContext& c) {
226          c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
227        }},
228       {"long",
229        [](const CodeGeneratorContext& c) {
230          c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
231        }},
232       {"long[]",
233        [](const CodeGeneratorContext& c) {
234          c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
235        }},
236       {"float",
237        [](const CodeGeneratorContext& c) {
238          c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
239        }},
240       {"float[]",
241        [](const CodeGeneratorContext& c) {
242          c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
243        }},
244       {"double",
245        [](const CodeGeneratorContext& c) {
246          c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
247        }},
248       {"double[]",
249        [](const CodeGeneratorContext& c) {
250          c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
251        }},
252       {"String",
253        [](const CodeGeneratorContext& c) {
254          c.writer << c.parcel << ".writeString(" << c.var << ");\n";
255        }},
256       {"String[]",
257        [](const CodeGeneratorContext& c) {
258          c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
259        }},
260       {"List",
261        [](const CodeGeneratorContext& c) {
262          if (c.type.IsGeneric()) {
263            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
264            if (AidlTypenames::IsBuiltinTypename(contained_type)) {
265              if (contained_type == "String") {
266                c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
267              } else if (contained_type == "IBinder") {
268                c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
269              }
270            } else {
271              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
272              CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
273              if (t->AsParcelable() != nullptr) {
274                c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
275              }
276            }
277          } else {
278            c.writer << c.parcel << ".writeList(" << c.var << ");\n";
279          }
280        }},
281       {"Map",
282        [](const CodeGeneratorContext& c) {
283          if (c.type.IsGeneric()) {
284            c.writer << "if (" << c.var << " == null) {\n";
285            c.writer.Indent();
286            c.writer << c.parcel << ".writeInt(-1);\n";
287            c.writer.Dedent();
288            c.writer << "} else {\n";
289            c.writer.Indent();
290            c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
291            c.writer << c.var << ".forEach((k, v) -> {\n";
292            c.writer.Indent();
293            c.writer << c.parcel << ".writeString(k);\n";
294 
295            CodeGeneratorContext value_context{
296                c.writer,
297                c.typenames,
298                *c.type.GetTypeParameters()[1].get(),
299                c.parcel,
300                "v",
301                c.is_return_value,
302                c.is_classloader_created,
303                c.filename,
304            };
305            WriteToParcelFor(value_context);
306            c.writer.Dedent();
307            c.writer << "});\n";
308 
309            c.writer.Dedent();
310            c.writer << "}\n";
311          } else {
312            c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
313          }
314        }},
315       {"IBinder",
316        [](const CodeGeneratorContext& c) {
317          c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
318        }},
319       {"IBinder[]",
320        [](const CodeGeneratorContext& c) {
321          c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
322        }},
323       {"FileDescriptor",
324        [](const CodeGeneratorContext& c) {
325          c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
326        }},
327       {"FileDescriptor[]",
328        [](const CodeGeneratorContext& c) {
329          c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
330        }},
331       {"ParcelFileDescriptor",
332        [](const CodeGeneratorContext& c) {
333          // This is same as writeTypedObject which was introduced with SDK 23.
334          // Keeping below code so that the generated code is buildable with older SDK.
335          c.writer << "if ((" << c.var << "!=null)) {\n";
336          c.writer.Indent();
337          c.writer << c.parcel << ".writeInt(1);\n";
338          c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
339          c.writer.Dedent();
340          c.writer << "}\n";
341          c.writer << "else {\n";
342          c.writer.Indent();
343          c.writer << c.parcel << ".writeInt(0);\n";
344          c.writer.Dedent();
345          c.writer << "}\n";
346        }},
347       {"ParcelFileDescriptor[]",
348        [](const CodeGeneratorContext& c) {
349          c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
350        }},
351       {"CharSequence",
352        [](const CodeGeneratorContext& c) {
353          // TextUtils.writeToParcel does not accept null. So, we need to handle
354          // the case here.
355          c.writer << "if (" << c.var << "!=null) {\n";
356          c.writer.Indent();
357          c.writer << c.parcel << ".writeInt(1);\n";
358          c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
359                   << GetFlagFor(c) << ");\n";
360          c.writer.Dedent();
361          c.writer << "}\n";
362          c.writer << "else {\n";
363          c.writer.Indent();
364          c.writer << c.parcel << ".writeInt(0);\n";
365          c.writer.Dedent();
366          c.writer << "}\n";
367        }},
368       {"ParcelableHolder",
369        [](const CodeGeneratorContext& c) {
370          c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
371        }},
372   };
373   const string type_name = AidlBackingTypeName(c.type, c.typenames);
374   const auto found = method_map.find(type_name);
375   if (found != method_map.end()) {
376     found->second(c);
377   } else {
378     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
379     CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
380     if (t->AsInterface() != nullptr) {
381       if (!c.type.IsArray()) {
382         // Why don't we use writeStrongInterface which does the exact same thing?
383         // Keeping below code just not to break unit tests.
384         c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
385                  << "(" << c.var << ".asBinder()):(null)));\n";
386       }
387     } else if (t->AsParcelable() != nullptr) {
388       if (c.type.IsArray()) {
389         c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
390       } else {
391         // This is same as writeTypedObject.
392         // Keeping below code just not to break tests.
393         c.writer << "if ((" << c.var << "!=null)) {\n";
394         c.writer.Indent();
395         c.writer << c.parcel << ".writeInt(1);\n";
396         c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
397         c.writer.Dedent();
398         c.writer << "}\n";
399         c.writer << "else {\n";
400         c.writer.Indent();
401         c.writer << c.parcel << ".writeInt(0);\n";
402         c.writer.Dedent();
403         c.writer << "}\n";
404       }
405     }
406   }
407   return true;
408 }
409 
410 // Ensures that a variable is initialized to refer to the classloader
411 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)412 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
413   CHECK(c.is_classloader_created != nullptr);
414   if (!*(c.is_classloader_created)) {
415     c.writer << "java.lang.ClassLoader cl = "
416              << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
417     *(c.is_classloader_created) = true;
418   }
419   return "cl";
420 }
421 
CreateFromParcelFor(const CodeGeneratorContext & c)422 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
423   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
424       {"boolean",
425        [](const CodeGeneratorContext& c) {
426          c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
427        }},
428       {"boolean[]",
429        [](const CodeGeneratorContext& c) {
430          c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
431        }},
432       {"byte",
433        [](const CodeGeneratorContext& c) {
434          c.writer << c.var << " = " << c.parcel << ".readByte();\n";
435        }},
436       {"byte[]",
437        [](const CodeGeneratorContext& c) {
438          c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
439        }},
440       {"char",
441        [](const CodeGeneratorContext& c) {
442          c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
443        }},
444       {"char[]",
445        [](const CodeGeneratorContext& c) {
446          c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
447        }},
448       {"int",
449        [](const CodeGeneratorContext& c) {
450          c.writer << c.var << " = " << c.parcel << ".readInt();\n";
451        }},
452       {"int[]",
453        [](const CodeGeneratorContext& c) {
454          c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
455        }},
456       {"long",
457        [](const CodeGeneratorContext& c) {
458          c.writer << c.var << " = " << c.parcel << ".readLong();\n";
459        }},
460       {"long[]",
461        [](const CodeGeneratorContext& c) {
462          c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
463        }},
464       {"float",
465        [](const CodeGeneratorContext& c) {
466          c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
467        }},
468       {"float[]",
469        [](const CodeGeneratorContext& c) {
470          c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
471        }},
472       {"double",
473        [](const CodeGeneratorContext& c) {
474          c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
475        }},
476       {"double[]",
477        [](const CodeGeneratorContext& c) {
478          c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
479        }},
480       {"String",
481        [](const CodeGeneratorContext& c) {
482          c.writer << c.var << " = " << c.parcel << ".readString();\n";
483        }},
484       {"String[]",
485        [](const CodeGeneratorContext& c) {
486          c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
487        }},
488       {"List",
489        [](const CodeGeneratorContext& c) {
490          if (c.type.IsGeneric()) {
491            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
492            if (AidlTypenames::IsBuiltinTypename(contained_type)) {
493              if (contained_type == "String") {
494                c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
495              } else if (contained_type == "IBinder") {
496                c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
497              }
498            } else {
499              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
500              CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
501              if (t->AsParcelable() != nullptr) {
502                c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
503                         << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
504                         << ".CREATOR);\n";
505              }
506            }
507          } else {
508            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
509            c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
510          }
511        }},
512       {"Map",
513        [](const CodeGeneratorContext& c) {
514          if (c.type.IsGeneric()) {
515            c.writer << "{\n";
516            c.writer.Indent();
517            c.writer << "int N = " << c.parcel << ".readInt();\n";
518            c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
519 
520            auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) + ".CREATOR";
521            c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
522            c.writer.Indent();
523            c.writer << "String k = " << c.parcel << ".readString();\n";
524            c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
525            CodeGeneratorContext value_context{
526                c.writer,
527                c.typenames,
528                *c.type.GetTypeParameters()[1].get(),
529                c.parcel,
530                "v",
531                c.is_return_value,
532                c.is_classloader_created,
533                c.filename,
534            };
535            CreateFromParcelFor(value_context);
536            c.writer << c.var << ".put(k, v);\n";
537 
538            c.writer.Dedent();
539            c.writer << "});\n";
540 
541            c.writer.Dedent();
542            c.writer << "}\n";
543          } else {
544            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
545            c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
546          }
547        }},
548       {"IBinder",
549        [](const CodeGeneratorContext& c) {
550          c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
551        }},
552       {"IBinder[]",
553        [](const CodeGeneratorContext& c) {
554          c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
555        }},
556       {"FileDescriptor",
557        [](const CodeGeneratorContext& c) {
558          c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
559        }},
560       {"FileDescriptor[]",
561        [](const CodeGeneratorContext& c) {
562          c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
563        }},
564       {"ParcelFileDescriptor",
565        [](const CodeGeneratorContext& c) {
566          // This is same as readTypedObject which was introduced with SDK 23.
567          // Keeping below code so that the generated code is buildable with older SDK.
568          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
569          c.writer.Indent();
570          c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
571                   << ");\n";
572          c.writer.Dedent();
573          c.writer << "}\n";
574          c.writer << "else {\n";
575          c.writer.Indent();
576          c.writer << c.var << " = null;\n";
577          c.writer.Dedent();
578          c.writer << "}\n";
579        }},
580       {"ParcelFileDescriptor[]",
581        [](const CodeGeneratorContext& c) {
582          c.writer << c.var << " = " << c.parcel
583                   << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
584        }},
585       {"CharSequence",
586        [](const CodeGeneratorContext& c) {
587          // We have written 0 for null CharSequence.
588          c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
589          c.writer.Indent();
590          c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
591                   << c.parcel << ");\n";
592          c.writer.Dedent();
593          c.writer << "}\n";
594          c.writer << "else {\n";
595          c.writer.Indent();
596          c.writer << c.var << " = null;\n";
597          c.writer.Dedent();
598          c.writer << "}\n";
599        }},
600       {"ParcelableHolder",
601        [](const CodeGeneratorContext& c) {
602          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
603          c.writer.Indent();
604          c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
605          c.writer.Dedent();
606          c.writer << "}\n";
607        }},
608   };
609   const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
610   if (found != method_map.end()) {
611     found->second(c);
612   } else {
613     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
614     CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
615     if (t->AsInterface() != nullptr) {
616       if (!c.type.IsArray()) {
617         c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
618                  << ".readStrongBinder());\n";
619       }
620     } else if (t->AsParcelable() != nullptr || t->AsStructuredParcelable() != nullptr) {
621       if (c.type.IsArray()) {
622         c.writer << c.var << " = " << c.parcel << ".createTypedArray("
623                  << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
624       } else {
625         // This is same as readTypedObject.
626         // Keeping below code just not to break unit tests.
627         c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
628         c.writer.Indent();
629         c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
630                  << ");\n";
631         c.writer.Dedent();
632         c.writer << "}\n";
633         c.writer << "else {\n";
634         c.writer.Indent();
635         c.writer << c.var << " = null;\n";
636         c.writer.Dedent();
637         c.writer << "}\n";
638       }
639     }
640   }
641   return true;
642 }
643 
ReadFromParcelFor(const CodeGeneratorContext & c)644 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
645   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
646       {"boolean[]",
647        [](const CodeGeneratorContext& c) {
648          c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
649        }},
650       {"byte[]",
651        [](const CodeGeneratorContext& c) {
652          c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
653        }},
654       {"char[]",
655        [](const CodeGeneratorContext& c) {
656          c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
657        }},
658       {"int[]",
659        [](const CodeGeneratorContext& c) {
660          c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
661        }},
662       {"long[]",
663        [](const CodeGeneratorContext& c) {
664          c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
665        }},
666       {"float[]",
667        [](const CodeGeneratorContext& c) {
668          c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
669        }},
670       {"double[]",
671        [](const CodeGeneratorContext& c) {
672          c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
673        }},
674       {"String[]",
675        [](const CodeGeneratorContext& c) {
676          c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
677        }},
678       {"List",
679        [](const CodeGeneratorContext& c) {
680          if (c.type.IsGeneric()) {
681            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
682            if (AidlTypenames::IsBuiltinTypename(contained_type)) {
683              if (contained_type == "String") {
684                c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
685              } else if (contained_type == "IBinder") {
686                c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
687              }
688            } else {
689              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
690              CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
691              if (t->AsParcelable() != nullptr) {
692                c.writer << c.parcel << ".readTypedList(" << c.var << ", "
693                         << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
694                         << ".CREATOR);\n";
695              }
696            }
697          } else {
698            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
699            c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
700          }
701        }},
702       {"Map",
703        [](const CodeGeneratorContext& c) {
704          if (c.type.IsGeneric()) {
705            c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
706            c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
707                     << ".readInt()).forEach(i -> {\n";
708            c.writer.Indent();
709            c.writer << "String k = " << c.parcel << ".readString();\n";
710            c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
711            CodeGeneratorContext value_context{
712                c.writer,
713                c.typenames,
714                *c.type.GetTypeParameters()[1].get(),
715                c.parcel,
716                "v",
717                c.is_return_value,
718                c.is_classloader_created,
719                c.filename,
720            };
721            CreateFromParcelFor(value_context);
722            c.writer << c.var << ".put(k, v);\n";
723 
724            c.writer.Dedent();
725            c.writer << "});\n";
726 
727            c.writer.Dedent();
728            c.writer << "}\n";
729          } else {
730            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
731            c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
732          }
733        }},
734       {"IBinder[]",
735        [](const CodeGeneratorContext& c) {
736          c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
737        }},
738       {"FileDescriptor[]",
739        [](const CodeGeneratorContext& c) {
740          c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
741        }},
742       {"ParcelFileDescriptor",
743        [](const CodeGeneratorContext& c) {
744          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
745          c.writer.Indent();
746          c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
747          c.writer.Dedent();
748          c.writer << "}\n";
749        }},
750       {"ParcelFileDescriptor[]",
751        [](const CodeGeneratorContext& c) {
752          c.writer << c.parcel << ".readTypedArray(" << c.var
753                   << ", android.os.ParcelFileDescriptor.CREATOR);\n";
754        }},
755   };
756   const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
757   if (found != method_map.end()) {
758     found->second(c);
759   } else {
760     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
761     CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
762     if (t->AsParcelable() != nullptr) {
763       if (c.type.IsArray()) {
764         c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
765                  << ".CREATOR);\n";
766       } else {
767         c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
768         c.writer.Indent();
769         c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
770         c.writer.Dedent();
771         c.writer << "}\n";
772       }
773     }
774   }
775   return true;
776 }
777 
ToStringFor(const CodeGeneratorContext & c)778 void ToStringFor(const CodeGeneratorContext& c) {
779   if (c.type.IsArray()) {
780     // Arrays can be null
781     c.writer << c.var << " == null ? \"null\" : ";
782     c.writer << "java.util.Arrays.toString(" << c.var << ")";
783     return;
784   }
785 
786   const std::string name = c.type.GetName();
787 
788   if (AidlTypenames::IsPrimitiveTypename(name)) {
789     c.writer << c.var;
790     return;
791   }
792 
793   const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
794   if (t != nullptr && t->AsEnumDeclaration()) {
795     c.writer << c.var;
796     return;
797   }
798 
799   // FileDescriptor doesn't have a good toString() impl.
800   if (name == "FileDescriptor") {
801     c.writer << c.var << " == null ? \"null\" : ";
802     c.writer << c.var << ".getInt$()";
803     return;
804   }
805 
806   // Rest of the built-in types have reasonable toString() impls.
807   if (AidlTypenames::IsBuiltinTypename(name)) {
808     c.writer << "java.util.Objects.toString(" << c.var << ")";
809     return;
810   }
811 
812   // For user-defined types, we also use toString() that we are generating here, but just make sure
813   // that they are actually user-defined types.
814   AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
815   if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
816     c.writer << c.var << ".toString()";
817     return;
818   }
819   CHECK(true) << "Unhandled typename: " << name << endl;
820 }
821 
822 }  // namespace java
823 }  // namespace aidl
824 }  // namespace android
825