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
GenerateTypedListHelper(CodeWriter & out,const Options & options)248 static void GenerateTypedListHelper(CodeWriter& out, const Options& options) {
249 out << R"(static private <T extends android.os.Parcelable> void writeTypedList(
250 android.os.Parcel parcel, java.util.List<T> value, int parcelableFlags) {
251 if (value == null) {
252 parcel.writeInt(-1);
253 } else {
254 int N = value.size();
255 int i = 0;
256 parcel.writeInt(N);
257 while (i < N) {
258 )";
259
260 if (options.GetMinSdkVersion() < 23u) {
261 out << "writeTypedObject(parcel, value.get(i), parcelableFlags);";
262 } else {
263 out << "parcel.writeTypedObject(value.get(i), parcelableFlags);";
264 }
265
266 out << R"(
267 i++;
268 }
269 }
270 }
271 )";
272 }
273
GenerateParcelHelpers(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)274 void GenerateParcelHelpers(CodeWriter& out, const AidlDefinedType& defined_type,
275 const AidlTypenames& typenames, const Options& options) {
276 // root-level type contains all necessary helpers
277 if (defined_type.GetParentType()) {
278 return;
279 }
280 // visits method parameters and parcelable fields to collect types which
281 // requires read/write/create helpers.
282 struct Visitor : AidlVisitor {
283 const AidlTypenames& typenames;
284 const Options& options;
285 set<ParcelHelperGenerator> helpers;
286 Visitor(const AidlTypenames& typenames, const Options& options)
287 : typenames(typenames), options(options) {}
288 void Visit(const AidlTypeSpecifier& type) override {
289 auto name = type.GetName();
290 if (auto defined_type = type.GetDefinedType(); defined_type) {
291 if (defined_type->AsParcelable() != nullptr && !type.IsArray()) {
292 // TypedObjects are supported since 23. So we don't need helpers.
293 if (options.GetMinSdkVersion() < 23u) {
294 helpers.insert(&GenerateTypedObjectHelper);
295 }
296 }
297 } else {
298 // There's parcelable-like built-in types as well.
299 if (name == "ParcelFileDescriptor" || name == "CharSequence") {
300 if (!type.IsArray()) {
301 // TypedObjects are supported since 23. So we don't need helpers.
302 if (options.GetMinSdkVersion() < 23u) {
303 helpers.insert(&GenerateTypedObjectHelper);
304 }
305 }
306 }
307
308 if (name == "List" && type.IsGeneric()) {
309 const auto& element_name = type.GetTypeParameters()[0]->GetName();
310 if (typenames.IsParcelable(element_name) && options.GetMinSdkVersion() <= 33u) {
311 helpers.insert(&GenerateTypedListHelper);
312 }
313 }
314 }
315 }
316 } v{typenames, options};
317
318 VisitTopDown(v, defined_type);
319 if (!v.helpers.empty()) {
320 // Nested class (_Parcel) is used to contain static helper methods because some targets are
321 // still using Java 7 which doesn't allow interfaces to have static methods.
322 // Helpers shouldn't bother API checks, but in case where AIDL types are not marked `@hide`
323 // explicitly marks the helper class as @hide.
324 out << "/** @hide */\n";
325 out << "static class _Parcel {\n";
326 out.Indent();
327 for (const auto& helper : v.helpers) {
328 helper(out, options);
329 }
330 out.Dedent();
331 out << "}\n";
332 }
333 }
334
WriteToParcelFor(const CodeGeneratorContext & c)335 void WriteToParcelFor(const CodeGeneratorContext& c) {
336 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
337 {"boolean",
338 [](const CodeGeneratorContext& c) {
339 if (c.min_sdk_version >= 29u) {
340 c.writer << c.parcel << ".writeBoolean(" << c.var << ");\n";
341 } else {
342 c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
343 }
344 }},
345 {"boolean[]",
346 [](const CodeGeneratorContext& c) {
347 c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
348 }},
349 {"byte",
350 [](const CodeGeneratorContext& c) {
351 c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
352 }},
353 {"byte[]",
354 [](const CodeGeneratorContext& c) {
355 c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
356 }},
357 {"char",
358 [](const CodeGeneratorContext& c) {
359 c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
360 }},
361 {"char[]",
362 [](const CodeGeneratorContext& c) {
363 c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
364 }},
365 {"int",
366 [](const CodeGeneratorContext& c) {
367 c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
368 }},
369 {"int[]",
370 [](const CodeGeneratorContext& c) {
371 c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
372 }},
373 {"long",
374 [](const CodeGeneratorContext& c) {
375 c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
376 }},
377 {"long[]",
378 [](const CodeGeneratorContext& c) {
379 c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
380 }},
381 {"float",
382 [](const CodeGeneratorContext& c) {
383 c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
384 }},
385 {"float[]",
386 [](const CodeGeneratorContext& c) {
387 c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
388 }},
389 {"double",
390 [](const CodeGeneratorContext& c) {
391 c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
392 }},
393 {"double[]",
394 [](const CodeGeneratorContext& c) {
395 c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
396 }},
397 {"String",
398 [](const CodeGeneratorContext& c) {
399 c.writer << c.parcel << ".writeString(" << c.var << ");\n";
400 }},
401 {"String[]",
402 [](const CodeGeneratorContext& c) {
403 c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
404 }},
405 {"List",
406 [](const CodeGeneratorContext& c) {
407 if (c.type.IsGeneric()) {
408 AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
409 const auto& element_type = *c.type.GetTypeParameters().at(0);
410 const auto& element_type_name = element_type.GetName();
411 if (element_type_name == "String") {
412 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
413 } else if (element_type_name == "IBinder") {
414 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
415 } else if (c.typenames.IsParcelable(element_type_name)) {
416 if (c.min_sdk_version > 33u) {
417 c.writer << c.parcel << ".writeTypedList(" << c.var << ", " << c.write_to_parcel_flag
418 << ");\n";
419 } else {
420 c.writer << "_Parcel.writeTypedList(" << c.parcel << ", " << c.var << ", "
421 << c.write_to_parcel_flag << ");\n";
422 }
423 } else if (c.typenames.GetInterface(element_type)) {
424 c.writer << c.parcel << ".writeInterfaceList(" << c.var << ");\n";
425 } else {
426 AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << element_type_name;
427 }
428 } else {
429 c.writer << c.parcel << ".writeList(" << c.var << ");\n";
430 }
431 }},
432 {"Map",
433 [](const CodeGeneratorContext& c) {
434 if (c.type.IsGeneric()) {
435 c.writer << "if (" << c.var << " == null) {\n";
436 c.writer.Indent();
437 c.writer << c.parcel << ".writeInt(-1);\n";
438 c.writer.Dedent();
439 c.writer << "} else {\n";
440 c.writer.Indent();
441 c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
442 c.writer << c.var << ".forEach((k, v) -> {\n";
443 c.writer.Indent();
444 c.writer << c.parcel << ".writeString(k);\n";
445
446 CodeGeneratorContext value_context{
447 c.writer,
448 c.typenames,
449 *c.type.GetTypeParameters()[1].get(),
450 c.parcel,
451 "v",
452 c.min_sdk_version,
453 c.write_to_parcel_flag,
454 c.is_classloader_created,
455 };
456 WriteToParcelFor(value_context);
457 c.writer.Dedent();
458 c.writer << "});\n";
459
460 c.writer.Dedent();
461 c.writer << "}\n";
462 } else {
463 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
464 }
465 }},
466 {"IBinder",
467 [](const CodeGeneratorContext& c) {
468 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
469 }},
470 {"IBinder[]",
471 [](const CodeGeneratorContext& c) {
472 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
473 }},
474 {"FileDescriptor",
475 [](const CodeGeneratorContext& c) {
476 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
477 }},
478 {"FileDescriptor[]",
479 [](const CodeGeneratorContext& c) {
480 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
481 }},
482 {"ParcelFileDescriptor",
483 [](const CodeGeneratorContext& c) {
484 if (c.min_sdk_version >= 23u) {
485 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << c.write_to_parcel_flag
486 << ");\n";
487 } else {
488 c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
489 << c.write_to_parcel_flag << ");\n";
490 }
491 }},
492 {"ParcelFileDescriptor[]",
493 [](const CodeGeneratorContext& c) {
494 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << c.write_to_parcel_flag
495 << ");\n";
496 }},
497 {"CharSequence",
498 [](const CodeGeneratorContext& c) {
499 // TextUtils.writeToParcel does not accept null. So, we need to handle
500 // the case here.
501 c.writer << "if (" << c.var << "!=null) {\n";
502 c.writer.Indent();
503 c.writer << c.parcel << ".writeInt(1);\n";
504 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
505 << c.write_to_parcel_flag << ");\n";
506 c.writer.Dedent();
507 c.writer << "}\n";
508 c.writer << "else {\n";
509 c.writer.Indent();
510 c.writer << c.parcel << ".writeInt(0);\n";
511 c.writer.Dedent();
512 c.writer << "}\n";
513 }},
514 {"ParcelableHolder",
515 [](const CodeGeneratorContext& c) {
516 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
517 }},
518 };
519 const string type_name = AidlBackingTypeName(c.type);
520 const auto found = method_map.find(type_name);
521 if (found != method_map.end()) {
522 found->second(c);
523 } else if (c.type.IsFixedSizeArray()) {
524 std::vector<std::string> args = {c.var, c.write_to_parcel_flag};
525 for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
526 args.push_back(std::to_string(dim));
527 }
528 c.writer << c.parcel << ".writeFixedArray(" << Join(args, ", ") << ");\n";
529 } else {
530 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
531 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
532 if (t->AsInterface() != nullptr) {
533 if (c.type.IsArray()) {
534 c.writer << c.parcel << ".writeInterfaceArray(" << c.var << ");\n";
535 } else {
536 c.writer << c.parcel << ".writeStrongInterface(" << c.var << ");\n";
537 }
538 } else if (t->AsParcelable() != nullptr) {
539 if (c.type.IsArray()) {
540 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << c.write_to_parcel_flag
541 << ");\n";
542 } else {
543 if (c.min_sdk_version >= 23u) {
544 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << c.write_to_parcel_flag
545 << ");\n";
546 } else {
547 c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
548 << c.write_to_parcel_flag << ");\n";
549 }
550 }
551 }
552 }
553 }
554
555 // Ensures that a variable is initialized to refer to the classloader
556 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)557 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
558 AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
559 if (!*(c.is_classloader_created)) {
560 c.writer << "java.lang.ClassLoader cl = "
561 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
562 *(c.is_classloader_created) = true;
563 }
564 return "cl";
565 }
566
CreateFromParcelFor(const CodeGeneratorContext & c)567 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
568 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
569 {"boolean",
570 [](const CodeGeneratorContext& c) {
571 if (c.min_sdk_version >= 29u) {
572 c.writer << c.var << " = " << c.parcel << ".readBoolean();\n";
573 } else {
574 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
575 }
576 }},
577 {"boolean[]",
578 [](const CodeGeneratorContext& c) {
579 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
580 }},
581 {"byte",
582 [](const CodeGeneratorContext& c) {
583 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
584 }},
585 {"byte[]",
586 [](const CodeGeneratorContext& c) {
587 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
588 }},
589 {"char",
590 [](const CodeGeneratorContext& c) {
591 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
592 }},
593 {"char[]",
594 [](const CodeGeneratorContext& c) {
595 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
596 }},
597 {"int",
598 [](const CodeGeneratorContext& c) {
599 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
600 }},
601 {"int[]",
602 [](const CodeGeneratorContext& c) {
603 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
604 }},
605 {"long",
606 [](const CodeGeneratorContext& c) {
607 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
608 }},
609 {"long[]",
610 [](const CodeGeneratorContext& c) {
611 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
612 }},
613 {"float",
614 [](const CodeGeneratorContext& c) {
615 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
616 }},
617 {"float[]",
618 [](const CodeGeneratorContext& c) {
619 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
620 }},
621 {"double",
622 [](const CodeGeneratorContext& c) {
623 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
624 }},
625 {"double[]",
626 [](const CodeGeneratorContext& c) {
627 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
628 }},
629 {"String",
630 [](const CodeGeneratorContext& c) {
631 c.writer << c.var << " = " << c.parcel << ".readString();\n";
632 }},
633 {"String[]",
634 [](const CodeGeneratorContext& c) {
635 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
636 }},
637 {"List",
638 [](const CodeGeneratorContext& c) {
639 if (c.type.IsGeneric()) {
640 AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
641 const auto& element_type = *c.type.GetTypeParameters().at(0);
642 const auto& element_type_name = element_type.GetName();
643 if (element_type_name == "String") {
644 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
645 } else if (element_type_name == "IBinder") {
646 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
647 } else if (c.typenames.IsParcelable(element_type_name)) {
648 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
649 << JavaNameOf(element_type) << ".CREATOR);\n";
650 } else if (c.typenames.GetInterface(element_type)) {
651 auto as_interface = element_type_name + ".Stub::asInterface";
652 c.writer << c.var << " = " << c.parcel << ".createInterfaceArrayList(" << as_interface
653 << ");\n";
654 } else {
655 AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << element_type_name;
656 }
657 } else {
658 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
659 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
660 }
661 }},
662 {"Map",
663 [](const CodeGeneratorContext& c) {
664 if (c.type.IsGeneric()) {
665 c.writer << "{\n";
666 c.writer.Indent();
667 c.writer << "int N = " << c.parcel << ".readInt();\n";
668 c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
669
670 auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1))) + ".CREATOR";
671 c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
672 c.writer.Indent();
673 c.writer << "String k = " << c.parcel << ".readString();\n";
674 c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
675 CodeGeneratorContext value_context{
676 c.writer,
677 c.typenames,
678 *c.type.GetTypeParameters()[1].get(),
679 c.parcel,
680 "v",
681 c.min_sdk_version,
682 c.write_to_parcel_flag,
683 c.is_classloader_created,
684 };
685 CreateFromParcelFor(value_context);
686 c.writer << c.var << ".put(k, v);\n";
687
688 c.writer.Dedent();
689 c.writer << "});\n";
690
691 c.writer.Dedent();
692 c.writer << "}\n";
693 } else {
694 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
695 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
696 }
697 }},
698 {"IBinder",
699 [](const CodeGeneratorContext& c) {
700 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
701 }},
702 {"IBinder[]",
703 [](const CodeGeneratorContext& c) {
704 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
705 }},
706 {"FileDescriptor",
707 [](const CodeGeneratorContext& c) {
708 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
709 }},
710 {"FileDescriptor[]",
711 [](const CodeGeneratorContext& c) {
712 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
713 }},
714 {"ParcelFileDescriptor",
715 [](const CodeGeneratorContext& c) {
716 if (c.min_sdk_version >= 23u) {
717 c.writer << c.var << " = " << c.parcel
718 << ".readTypedObject(android.os.ParcelFileDescriptor.CREATOR);\n";
719 } else {
720 c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
721 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
722 }
723 }},
724 {"ParcelFileDescriptor[]",
725 [](const CodeGeneratorContext& c) {
726 c.writer << c.var << " = " << c.parcel
727 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
728 }},
729 {"CharSequence",
730 [](const CodeGeneratorContext& c) {
731 if (c.min_sdk_version >= 23u) {
732 c.writer << c.var << " = " << c.parcel
733 << ".readTypedObject(android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
734 } else {
735 c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
736 << ", android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
737 }
738 }},
739 {"ParcelableHolder",
740 [](const CodeGeneratorContext& c) {
741 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
742 c.writer.Indent();
743 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
744 c.writer.Dedent();
745 c.writer << "}\n";
746 }},
747 };
748 const auto found = method_map.find(AidlBackingTypeName(c.type));
749 if (found != method_map.end()) {
750 found->second(c);
751 } else if (c.type.IsFixedSizeArray()) {
752 std::vector<std::string> args = {JavaSignatureOf(c.type) + ".class"};
753 if (c.typenames.IsParcelable(c.type.GetName())) {
754 args.push_back(JavaNameOf(c.type) + ".CREATOR");
755 } else if (c.typenames.GetInterface(c.type)) {
756 args.push_back(c.type.GetName() + ".Stub::asInterface");
757 }
758 for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
759 args.push_back(std::to_string(dim));
760 }
761 c.writer << c.var << " = " << c.parcel << ".createFixedArray(" << Join(args, ", ") << ");\n";
762 } else {
763 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
764 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
765 if (t->AsInterface() != nullptr) {
766 auto name = c.type.GetName();
767 if (c.type.IsArray()) {
768 auto new_array = name + "[]::new";
769 auto as_interface = name + ".Stub::asInterface";
770 c.writer << c.var << " = " << c.parcel << ".createInterfaceArray(" << new_array << ", "
771 << as_interface << ");\n";
772 } else {
773 c.writer << c.var << " = " << name << ".Stub.asInterface(" << c.parcel
774 << ".readStrongBinder());\n";
775 }
776 } else if (t->AsParcelable() != nullptr) {
777 if (c.type.IsArray()) {
778 c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
779 << ".CREATOR);\n";
780 } else {
781 if (c.min_sdk_version >= 23u) {
782 c.writer << c.var << " = " << c.parcel << ".readTypedObject(" << c.type.GetName()
783 << ".CREATOR);\n";
784 } else {
785 c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel << ", " << c.type.GetName()
786 << ".CREATOR);\n";
787 }
788 }
789 }
790 }
791 return true;
792 }
793
ReadFromParcelFor(const CodeGeneratorContext & c)794 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
795 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
796 {"boolean[]",
797 [](const CodeGeneratorContext& c) {
798 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
799 }},
800 {"byte[]",
801 [](const CodeGeneratorContext& c) {
802 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
803 }},
804 {"char[]",
805 [](const CodeGeneratorContext& c) {
806 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
807 }},
808 {"int[]",
809 [](const CodeGeneratorContext& c) {
810 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
811 }},
812 {"long[]",
813 [](const CodeGeneratorContext& c) {
814 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
815 }},
816 {"float[]",
817 [](const CodeGeneratorContext& c) {
818 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
819 }},
820 {"double[]",
821 [](const CodeGeneratorContext& c) {
822 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
823 }},
824 {"String[]",
825 [](const CodeGeneratorContext& c) {
826 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
827 }},
828 {"List",
829 [](const CodeGeneratorContext& c) {
830 if (c.type.IsGeneric()) {
831 AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
832 const auto& element_type = *c.type.GetTypeParameters().at(0);
833 const auto& element_type_name = element_type.GetName();
834 if (element_type_name == "String") {
835 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
836 } else if (element_type_name == "IBinder") {
837 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
838 } else if (c.typenames.IsParcelable(element_type_name)) {
839 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
840 << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
841 } else if (c.typenames.GetInterface(element_type)) {
842 auto as_interface = element_type_name + ".Stub::asInterface";
843 c.writer << c.parcel << ".readInterfaceList(" << c.var << ", " << as_interface
844 << ");\n";
845 } else {
846 AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << element_type_name;
847 }
848 } else {
849 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
850 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
851 }
852 }},
853 {"Map",
854 [](const CodeGeneratorContext& c) {
855 if (c.type.IsGeneric()) {
856 c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
857 c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
858 << ".readInt()).forEach(i -> {\n";
859 c.writer.Indent();
860 c.writer << "String k = " << c.parcel << ".readString();\n";
861 c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
862 CodeGeneratorContext value_context{
863 c.writer,
864 c.typenames,
865 *c.type.GetTypeParameters()[1].get(),
866 c.parcel,
867 "v",
868 c.min_sdk_version,
869 c.write_to_parcel_flag,
870 c.is_classloader_created,
871 };
872 CreateFromParcelFor(value_context);
873 c.writer << c.var << ".put(k, v);\n";
874
875 c.writer.Dedent();
876 c.writer << "});\n";
877 } else {
878 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
879 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
880 }
881 }},
882 {"IBinder[]",
883 [](const CodeGeneratorContext& c) {
884 c.writer << c.parcel << ".readBinderArray(" << c.var << ");\n";
885 }},
886 {"FileDescriptor[]",
887 [](const CodeGeneratorContext& c) {
888 c.writer << c.parcel << ".readRawFileDescriptorArray(" << c.var << ");\n";
889 }},
890 {"ParcelFileDescriptor",
891 [](const CodeGeneratorContext& c) {
892 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
893 c.writer.Indent();
894 c.writer << c.var << " = "
895 << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
896 << ");\n";
897 c.writer.Dedent();
898 c.writer << "}\n";
899 }},
900 {"ParcelFileDescriptor[]",
901 [](const CodeGeneratorContext& c) {
902 c.writer << c.parcel << ".readTypedArray(" << c.var
903 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
904 }},
905 };
906 const auto& found = method_map.find(AidlBackingTypeName(c.type));
907 if (found != method_map.end()) {
908 found->second(c);
909 } else if (c.type.IsFixedSizeArray()) {
910 std::vector<std::string> args = {c.var};
911 if (c.typenames.IsParcelable(c.type.GetName())) {
912 args.push_back(c.type.GetName() + ".CREATOR");
913 } else if (c.typenames.GetInterface(c.type)) {
914 args.push_back(c.type.GetName() + ".Stub::asInterface");
915 }
916 c.writer << c.parcel << ".readFixedArray(" << Join(args, ", ") << ");\n";
917 } else {
918 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
919 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
920 if (t->AsParcelable() != nullptr || t->AsUnionDeclaration() != nullptr) {
921 if (c.type.IsArray()) {
922 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
923 << ".CREATOR);\n";
924 } else {
925 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
926 c.writer.Indent();
927 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
928 c.writer.Dedent();
929 c.writer << "}\n";
930 }
931 } else if (t->AsInterface()) {
932 AIDL_FATAL_IF(!c.type.IsArray(), c.type) << "readFromParcel(interface) doesn't make sense.";
933 auto as_interface = c.type.GetName() + ".Stub::asInterface";
934 c.writer << c.parcel << ".readInterfaceArray(" << c.var << ", " << as_interface << ");\n";
935 }
936 }
937 return true;
938 }
939
ToStringFor(const CodeGeneratorContext & c)940 void ToStringFor(const CodeGeneratorContext& c) {
941 // Use derived toString() for enum type annotated with @JavaDerive(toString=true)
942 if (auto t = c.type.GetDefinedType();
943 t != nullptr && t->AsEnumDeclaration() && t->JavaDerive("toString")) {
944 if (c.type.IsArray()) {
945 c.writer << c.type.GetName() << ".$.arrayToString(" << c.var << ")";
946 } else {
947 c.writer << c.type.GetName() << ".$.toString(" << c.var << ")";
948 }
949 return;
950 }
951
952 if (c.type.IsArray()) {
953 if (c.type.IsDynamicArray() || c.type.GetFixedSizeArrayDimensions().size() == 1) {
954 c.writer << "java.util.Arrays.toString(" << c.var << ")";
955 } else {
956 c.writer << "java.util.Arrays.deepToString(" << c.var << ")";
957 }
958 return;
959 }
960
961 const std::string name = c.type.GetName();
962
963 if (AidlTypenames::IsPrimitiveTypename(name)) {
964 c.writer << c.var;
965 return;
966 }
967
968 const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
969 if (t != nullptr && t->AsEnumDeclaration()) {
970 c.writer << c.var;
971 return;
972 }
973
974 // FileDescriptor doesn't have a good toString() impl.
975 if (name == "FileDescriptor") {
976 c.writer << c.var << " == null ? \"null\" : ";
977 c.writer << c.var << ".getInt$()";
978 return;
979 }
980
981 // Rest of the built-in types have reasonable toString() impls.
982 if (AidlTypenames::IsBuiltinTypename(name)) {
983 c.writer << "java.util.Objects.toString(" << c.var << ")";
984 return;
985 }
986
987 // For user-defined types, we also use toString() that we are generating here, but just make sure
988 // that they are actually user-defined types.
989 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
990 if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
991 c.writer << "java.util.Objects.toString(" << c.var << ")";
992 return;
993 }
994
995 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unhandled typename: " << name;
996 }
997
998 } // namespace java
999 } // namespace aidl
1000 } // namespace android
1001