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