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