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