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