• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cassert>
25 #include <functional>
26 #include <iostream>
27 #include <map>
28 #include <string>
29 #include <vector>
30 
31 namespace android {
32 namespace aidl {
33 namespace java {
34 
35 using android::base::Join;
36 
37 using std::endl;
38 using std::function;
39 using std::map;
40 using std::string;
41 using std::vector;
42 
ConstantValueDecorator(const AidlTypeSpecifier &,const std::string & raw_value)43 std::string ConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
44                                    const std::string& raw_value) {
45   // no difference
46   return raw_value;
47 };
48 
JavaNameOf(const AidlTypeSpecifier & aidl)49 const string& JavaNameOf(const AidlTypeSpecifier& aidl) {
50   CHECK(aidl.IsResolved()) << aidl.ToString();
51 
52   // map from AIDL built-in type name to the corresponding Java type name
53   static map<string, string> m = {
54       {"void", "void"},
55       {"boolean", "boolean"},
56       {"byte", "byte"},
57       {"char", "char"},
58       {"int", "int"},
59       {"long", "long"},
60       {"float", "float"},
61       {"double", "double"},
62       {"String", "java.lang.String"},
63       {"List", "java.util.List"},
64       {"Map", "java.util.Map"},
65       {"IBinder", "android.os.IBinder"},
66       {"FileDescriptor", "java.io.FileDescriptor"},
67       {"CharSequence", "java.lang.CharSequence"},
68       {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
69   };
70   const string& aidl_name = aidl.GetName();
71   if (m.find(aidl_name) != m.end()) {
72     CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
73     return m[aidl_name];
74   } else {
75     // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
76     return aidl_name;
77   }
78 }
79 
JavaSignatureOf(const AidlTypeSpecifier & aidl)80 string JavaSignatureOf(const AidlTypeSpecifier& aidl) {
81   string ret = JavaNameOf(aidl);
82   if (aidl.IsGeneric()) {
83     vector<string> arg_names;
84     for (const auto& ta : aidl.GetTypeParameters()) {
85       arg_names.emplace_back(JavaSignatureOf(*ta));
86     }
87     ret += "<" + Join(arg_names, ",") + ">";
88   }
89   if (aidl.IsArray()) {
90     ret += "[]";
91   }
92   return ret;
93 }
94 
DefaultJavaValueOf(const AidlTypeSpecifier & aidl)95 string DefaultJavaValueOf(const AidlTypeSpecifier& aidl) {
96   static map<string, string> m = {
97       {"boolean", "false"}, {"byte", "0"},     {"char", R"('\u0000')"}, {"int", "0"},
98       {"long", "0L"},       {"float", "0.0f"}, {"double", "0.0d"},
99   };
100   const string& name = aidl.GetName();
101   assert(name != "void");
102 
103   if (!aidl.IsArray() && m.find(name) != m.end()) {
104     CHECK(AidlTypenames::IsBuiltinTypename(name));
105     return m[name];
106   } else {
107     return "null";
108   }
109 }
110 
111 // These are supported by AIDL syntax, but are unsupported by the AIDL compiler
IsMarshallingUnsupportedFor(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)112 static bool IsMarshallingUnsupportedFor(const AidlTypeSpecifier& aidl,
113                                         const AidlTypenames& typenames) {
114   const string name = aidl.GetName();
115 
116   // List<T> is support only for String, Binder, ParcelFileDescriptor and Parcelable.
117   if (name == "List" && aidl.IsGeneric()) {
118     const string& contained_type = aidl.GetTypeParameters().at(0)->GetName();
119     if (AidlTypenames::IsBuiltinTypename(contained_type)) {
120       if (contained_type != "String" && contained_type != "IBinder" &&
121           contained_type != "ParcelFileDescriptor") {
122         return true;
123       }
124     } else {
125       const AidlDefinedType* t = typenames.TryGetDefinedType(contained_type);
126       if (t != nullptr && t->AsInterface() != nullptr) {
127         return true;
128       }
129     }
130   }
131 
132   // List[], Map[], CharSequence[] are not supported.
133   if (AidlTypenames::IsBuiltinTypename(name) && aidl.IsArray()) {
134     if (name == "List" || name == "Map" || name == "CharSequence") {
135       return true;
136     }
137   }
138 
139   // T[] is not supported for interfaces
140   const AidlDefinedType* t = typenames.TryGetDefinedType(name);
141   if (aidl.IsArray() && t != nullptr && t->AsInterface() != nullptr) {
142     return true;
143   }
144 
145   return false;
146 }
147 
EnsureCodegenIsSupported(const CodeGeneratorContext & c)148 static bool EnsureCodegenIsSupported(const CodeGeneratorContext& c) {
149   if (IsMarshallingUnsupportedFor(c.type, c.typenames)) {
150     AIDL_ERROR(c.type) << c.type.ToString() << "' is not yet supported.";
151     return false;
152   }
153   return true;
154 }
155 
GetFlagFor(const CodeGeneratorContext & c)156 static string GetFlagFor(const CodeGeneratorContext& c) {
157   if (c.is_return_value) {
158     return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
159   } else {
160     return "0";
161   }
162 }
163 
WriteToParcelFor(const CodeGeneratorContext & c)164 bool WriteToParcelFor(const CodeGeneratorContext& c) {
165   if (!EnsureCodegenIsSupported(c)) {
166     return false;
167   }
168   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
169       {"boolean",
170        [](const CodeGeneratorContext& c) {
171          c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
172        }},
173       {"boolean[]",
174        [](const CodeGeneratorContext& c) {
175          c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
176        }},
177       {"byte",
178        [](const CodeGeneratorContext& c) {
179          c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
180        }},
181       {"byte[]",
182        [](const CodeGeneratorContext& c) {
183          c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
184        }},
185       {"char",
186        [](const CodeGeneratorContext& c) {
187          c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
188        }},
189       {"char[]",
190        [](const CodeGeneratorContext& c) {
191          c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
192        }},
193       {"int",
194        [](const CodeGeneratorContext& c) {
195          c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
196        }},
197       {"int[]",
198        [](const CodeGeneratorContext& c) {
199          c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
200        }},
201       {"long",
202        [](const CodeGeneratorContext& c) {
203          c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
204        }},
205       {"long[]",
206        [](const CodeGeneratorContext& c) {
207          c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
208        }},
209       {"float",
210        [](const CodeGeneratorContext& c) {
211          c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
212        }},
213       {"float[]",
214        [](const CodeGeneratorContext& c) {
215          c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
216        }},
217       {"double",
218        [](const CodeGeneratorContext& c) {
219          c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
220        }},
221       {"double[]",
222        [](const CodeGeneratorContext& c) {
223          c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
224        }},
225       {"String",
226        [](const CodeGeneratorContext& c) {
227          c.writer << c.parcel << ".writeString(" << c.var << ");\n";
228        }},
229       {"String[]",
230        [](const CodeGeneratorContext& c) {
231          c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
232        }},
233       {"List",
234        [](const CodeGeneratorContext& c) {
235          if (c.type.IsGeneric()) {
236            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
237            if (AidlTypenames::IsBuiltinTypename(contained_type)) {
238              if (contained_type == "String") {
239                c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
240              } else if (contained_type == "IBinder") {
241                c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
242              }
243            } else {
244              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
245              CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
246              if (t->AsParcelable() != nullptr) {
247                c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
248              }
249            }
250          } else {
251            c.writer << c.parcel << ".writeList(" << c.var << ");\n";
252          }
253        }},
254       {"Map",
255        [](const CodeGeneratorContext& c) {
256          c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
257        }},
258       {"IBinder",
259        [](const CodeGeneratorContext& c) {
260          c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
261        }},
262       {"IBinder[]",
263        [](const CodeGeneratorContext& c) {
264          c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
265        }},
266       {"FileDescriptor",
267        [](const CodeGeneratorContext& c) {
268          c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
269        }},
270       {"FileDescriptor[]",
271        [](const CodeGeneratorContext& c) {
272          c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
273        }},
274       {"ParcelFileDescriptor",
275        [](const CodeGeneratorContext& c) {
276          // This is same as writeTypedObject which was introduced with SDK 23.
277          // Keeping below code so that the generated code is buildable with older SDK.
278          c.writer << "if ((" << c.var << "!=null)) {\n";
279          c.writer.Indent();
280          c.writer << c.parcel << ".writeInt(1);\n";
281          c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
282          c.writer.Dedent();
283          c.writer << "}\n";
284          c.writer << "else {\n";
285          c.writer.Indent();
286          c.writer << c.parcel << ".writeInt(0);\n";
287          c.writer.Dedent();
288          c.writer << "}\n";
289        }},
290       {"ParcelFileDescriptor[]",
291        [](const CodeGeneratorContext& c) {
292          c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
293        }},
294       {"CharSequence",
295        [](const CodeGeneratorContext& c) {
296          // TextUtils.writeToParcel does not accept null. So, we need to handle
297          // the case here.
298          c.writer << "if (" << c.var << "!=null) {\n";
299          c.writer.Indent();
300          c.writer << c.parcel << ".writeInt(1);\n";
301          c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
302                   << GetFlagFor(c) << ");\n";
303          c.writer.Dedent();
304          c.writer << "}\n";
305          c.writer << "else {\n";
306          c.writer.Indent();
307          c.writer << c.parcel << ".writeInt(0);\n";
308          c.writer.Dedent();
309          c.writer << "}\n";
310        }},
311   };
312   const string type_name = c.type.GetName() + (c.type.IsArray() ? "[]" : "");
313   const auto found = method_map.find(type_name);
314   if (found != method_map.end()) {
315     found->second(c);
316   } else {
317     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
318     CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
319     if (t->AsInterface() != nullptr) {
320       if (!c.type.IsArray()) {
321         // Why don't we use writeStrongInterface which does the exact same thing?
322         // Keeping below code just not to break unit tests.
323         c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
324                  << "(" << c.var << ".asBinder()):(null)));\n";
325       }
326     } else if (t->AsParcelable() != nullptr) {
327       if (c.type.IsArray()) {
328         c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
329       } else {
330         // This is same as writeTypedObject.
331         // Keeping below code just not to break tests.
332         c.writer << "if ((" << c.var << "!=null)) {\n";
333         c.writer.Indent();
334         c.writer << c.parcel << ".writeInt(1);\n";
335         c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
336         c.writer.Dedent();
337         c.writer << "}\n";
338         c.writer << "else {\n";
339         c.writer.Indent();
340         c.writer << c.parcel << ".writeInt(0);\n";
341         c.writer.Dedent();
342         c.writer << "}\n";
343       }
344     }
345   }
346   return true;
347 }
348 
349 // Ensures that a variable is initialized to refer to the classloader
350 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)351 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
352   CHECK(c.is_classloader_created != nullptr);
353   if (!*(c.is_classloader_created)) {
354     c.writer << "java.lang.ClassLoader cl = "
355              << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
356     *(c.is_classloader_created) = true;
357   }
358   return "cl";
359 }
360 
CreateFromParcelFor(const CodeGeneratorContext & c)361 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
362   if (!EnsureCodegenIsSupported(c)) {
363     return false;
364   }
365   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
366       {"boolean",
367        [](const CodeGeneratorContext& c) {
368          c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
369        }},
370       {"boolean[]",
371        [](const CodeGeneratorContext& c) {
372          c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
373        }},
374       {"byte",
375        [](const CodeGeneratorContext& c) {
376          c.writer << c.var << " = " << c.parcel << ".readByte();\n";
377        }},
378       {"byte[]",
379        [](const CodeGeneratorContext& c) {
380          c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
381        }},
382       {"char",
383        [](const CodeGeneratorContext& c) {
384          c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
385        }},
386       {"char[]",
387        [](const CodeGeneratorContext& c) {
388          c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
389        }},
390       {"int",
391        [](const CodeGeneratorContext& c) {
392          c.writer << c.var << " = " << c.parcel << ".readInt();\n";
393        }},
394       {"int[]",
395        [](const CodeGeneratorContext& c) {
396          c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
397        }},
398       {"long",
399        [](const CodeGeneratorContext& c) {
400          c.writer << c.var << " = " << c.parcel << ".readLong();\n";
401        }},
402       {"long[]",
403        [](const CodeGeneratorContext& c) {
404          c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
405        }},
406       {"float",
407        [](const CodeGeneratorContext& c) {
408          c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
409        }},
410       {"float[]",
411        [](const CodeGeneratorContext& c) {
412          c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
413        }},
414       {"double",
415        [](const CodeGeneratorContext& c) {
416          c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
417        }},
418       {"double[]",
419        [](const CodeGeneratorContext& c) {
420          c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
421        }},
422       {"String",
423        [](const CodeGeneratorContext& c) {
424          c.writer << c.var << " = " << c.parcel << ".readString();\n";
425        }},
426       {"String[]",
427        [](const CodeGeneratorContext& c) {
428          c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
429        }},
430       {"List",
431        [](const CodeGeneratorContext& c) {
432          if (c.type.IsGeneric()) {
433            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
434            if (AidlTypenames::IsBuiltinTypename(contained_type)) {
435              if (contained_type == "String") {
436                c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
437              } else if (contained_type == "IBinder") {
438                c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
439              }
440            } else {
441              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
442              CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
443              if (t->AsParcelable() != nullptr) {
444                c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
445                         << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
446              }
447            }
448          } else {
449            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
450            c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
451          }
452        }},
453       {"Map",
454        [](const CodeGeneratorContext& c) {
455          const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
456          c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
457        }},
458       {"IBinder",
459        [](const CodeGeneratorContext& c) {
460          c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
461        }},
462       {"IBinder[]",
463        [](const CodeGeneratorContext& c) {
464          c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
465        }},
466       {"FileDescriptor",
467        [](const CodeGeneratorContext& c) {
468          c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
469        }},
470       {"FileDescriptor[]",
471        [](const CodeGeneratorContext& c) {
472          c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
473        }},
474       {"ParcelFileDescriptor",
475        [](const CodeGeneratorContext& c) {
476          // This is same as readTypedObject which was introduced with SDK 23.
477          // Keeping below code so that the generated code is buildable with older SDK.
478          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
479          c.writer.Indent();
480          c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
481                   << ");\n";
482          c.writer.Dedent();
483          c.writer << "}\n";
484          c.writer << "else {\n";
485          c.writer.Indent();
486          c.writer << c.var << " = null;\n";
487          c.writer.Dedent();
488          c.writer << "}\n";
489        }},
490       {"ParcelFileDescriptor[]",
491        [](const CodeGeneratorContext& c) {
492          c.writer << c.var << " = " << c.parcel
493                   << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
494        }},
495       {"CharSequence",
496        [](const CodeGeneratorContext& c) {
497          // We have written 0 for null CharSequence.
498          c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
499          c.writer.Indent();
500          c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
501                   << c.parcel << ");\n";
502          c.writer.Dedent();
503          c.writer << "}\n";
504          c.writer << "else {\n";
505          c.writer.Indent();
506          c.writer << c.var << " = null;\n";
507          c.writer.Dedent();
508          c.writer << "}\n";
509        }},
510   };
511   const string type_name = c.type.GetName() + (c.type.IsArray() ? "[]" : "");
512   const auto found = method_map.find(type_name);
513   if (found != method_map.end()) {
514     found->second(c);
515   } else {
516     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
517     CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
518     if (t->AsInterface() != nullptr) {
519       if (!c.type.IsArray()) {
520         c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
521                  << ".readStrongBinder());\n";
522       }
523     } else if (t->AsParcelable() != nullptr || t->AsStructuredParcelable() != nullptr) {
524       if (c.type.IsArray()) {
525         c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
526                  << ".CREATOR);\n";
527       } else {
528         // This is same as readTypedObject.
529         // Keeping below code just not to break unit tests.
530         c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
531         c.writer.Indent();
532         c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
533                  << ");\n";
534         c.writer.Dedent();
535         c.writer << "}\n";
536         c.writer << "else {\n";
537         c.writer.Indent();
538         c.writer << c.var << " = null;\n";
539         c.writer.Dedent();
540         c.writer << "}\n";
541       }
542     }
543   }
544   return true;
545 }
546 
ReadFromParcelFor(const CodeGeneratorContext & c)547 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
548   if (!EnsureCodegenIsSupported(c)) {
549     return false;
550   }
551   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
552       {"boolean[]",
553        [](const CodeGeneratorContext& c) {
554          c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
555        }},
556       {"byte[]",
557        [](const CodeGeneratorContext& c) {
558          c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
559        }},
560       {"char[]",
561        [](const CodeGeneratorContext& c) {
562          c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
563        }},
564       {"int[]",
565        [](const CodeGeneratorContext& c) {
566          c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
567        }},
568       {"long[]",
569        [](const CodeGeneratorContext& c) {
570          c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
571        }},
572       {"float[]",
573        [](const CodeGeneratorContext& c) {
574          c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
575        }},
576       {"double[]",
577        [](const CodeGeneratorContext& c) {
578          c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
579        }},
580       {"String[]",
581        [](const CodeGeneratorContext& c) {
582          c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
583        }},
584       {"List",
585        [](const CodeGeneratorContext& c) {
586          if (c.type.IsGeneric()) {
587            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
588            if (AidlTypenames::IsBuiltinTypename(contained_type)) {
589              if (contained_type == "String") {
590                c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
591              } else if (contained_type == "IBinder") {
592                c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
593              }
594            } else {
595              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
596              CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
597              if (t->AsParcelable() != nullptr) {
598                c.writer << c.parcel << ".readTypedList(" << c.var << ", "
599                         << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
600              }
601            }
602          } else {
603            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
604            c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
605          }
606        }},
607       {"Map",
608        [](const CodeGeneratorContext& c) {
609          const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
610          c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
611        }},
612       {"IBinder[]",
613        [](const CodeGeneratorContext& c) {
614          c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
615        }},
616       {"FileDescriptor[]",
617        [](const CodeGeneratorContext& c) {
618          c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
619        }},
620       {"ParcelFileDescriptor",
621        [](const CodeGeneratorContext& c) {
622          c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
623          c.writer.Indent();
624          c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
625          c.writer.Dedent();
626          c.writer << "}\n";
627        }},
628       {"ParcelFileDescriptor[]",
629        [](const CodeGeneratorContext& c) {
630          c.writer << c.parcel << ".readTypedArray(" << c.var
631                   << ", android.os.ParcelFileDescriptor.CREATOR);\n";
632        }},
633   };
634   const string type_name = c.type.GetName() + (c.type.IsArray() ? "[]" : "");
635   const auto& found = method_map.find(type_name);
636   if (found != method_map.end()) {
637     found->second(c);
638   } else {
639     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
640     CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
641     if (t->AsParcelable() != nullptr) {
642       if (c.type.IsArray()) {
643         c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
644                  << ".CREATOR);\n";
645       } else {
646         c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
647         c.writer.Indent();
648         c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
649         c.writer.Dedent();
650         c.writer << "}\n";
651       }
652     }
653   }
654   return true;
655 }
656 
657 }  // namespace java
658 }  // namespace aidl
659 }  // namespace android
660