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 <cassert>
25 #include <functional>
26 #include <iostream>
27 #include <map>
28 #include <string>
29 #include <vector>
30
31 namespace android {
32 namespace aidl {
33 namespace java {
34
35 using android::base::Join;
36
37 using std::endl;
38 using std::function;
39 using std::map;
40 using std::string;
41 using std::vector;
42
ConstantValueDecorator(const AidlTypeSpecifier &,const std::string & raw_value)43 std::string ConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
44 const std::string& raw_value) {
45 // no difference
46 return raw_value;
47 };
48
JavaNameOf(const AidlTypeSpecifier & aidl)49 const string& JavaNameOf(const AidlTypeSpecifier& aidl) {
50 CHECK(aidl.IsResolved()) << aidl.ToString();
51
52 // map from AIDL built-in type name to the corresponding Java type name
53 static map<string, string> m = {
54 {"void", "void"},
55 {"boolean", "boolean"},
56 {"byte", "byte"},
57 {"char", "char"},
58 {"int", "int"},
59 {"long", "long"},
60 {"float", "float"},
61 {"double", "double"},
62 {"String", "java.lang.String"},
63 {"List", "java.util.List"},
64 {"Map", "java.util.Map"},
65 {"IBinder", "android.os.IBinder"},
66 {"FileDescriptor", "java.io.FileDescriptor"},
67 {"CharSequence", "java.lang.CharSequence"},
68 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
69 };
70 const string& aidl_name = aidl.GetName();
71 if (m.find(aidl_name) != m.end()) {
72 CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
73 return m[aidl_name];
74 } else {
75 // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
76 return aidl_name;
77 }
78 }
79
JavaSignatureOf(const AidlTypeSpecifier & aidl)80 string JavaSignatureOf(const AidlTypeSpecifier& aidl) {
81 string ret = JavaNameOf(aidl);
82 if (aidl.IsGeneric()) {
83 vector<string> arg_names;
84 for (const auto& ta : aidl.GetTypeParameters()) {
85 arg_names.emplace_back(JavaSignatureOf(*ta));
86 }
87 ret += "<" + Join(arg_names, ",") + ">";
88 }
89 if (aidl.IsArray()) {
90 ret += "[]";
91 }
92 return ret;
93 }
94
DefaultJavaValueOf(const AidlTypeSpecifier & aidl)95 string DefaultJavaValueOf(const AidlTypeSpecifier& aidl) {
96 static map<string, string> m = {
97 {"boolean", "false"}, {"byte", "0"}, {"char", R"('\u0000')"}, {"int", "0"},
98 {"long", "0L"}, {"float", "0.0f"}, {"double", "0.0d"},
99 };
100 const string& name = aidl.GetName();
101 assert(name != "void");
102
103 if (!aidl.IsArray() && m.find(name) != m.end()) {
104 CHECK(AidlTypenames::IsBuiltinTypename(name));
105 return m[name];
106 } else {
107 return "null";
108 }
109 }
110
111 // These are supported by AIDL syntax, but are unsupported by the AIDL compiler
IsMarshallingUnsupportedFor(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)112 static bool IsMarshallingUnsupportedFor(const AidlTypeSpecifier& aidl,
113 const AidlTypenames& typenames) {
114 const string name = aidl.GetName();
115
116 // List<T> is support only for String, Binder, ParcelFileDescriptor and Parcelable.
117 if (name == "List" && aidl.IsGeneric()) {
118 const string& contained_type = aidl.GetTypeParameters().at(0)->GetName();
119 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
120 if (contained_type != "String" && contained_type != "IBinder" &&
121 contained_type != "ParcelFileDescriptor") {
122 return true;
123 }
124 } else {
125 const AidlDefinedType* t = typenames.TryGetDefinedType(contained_type);
126 if (t != nullptr && t->AsInterface() != nullptr) {
127 return true;
128 }
129 }
130 }
131
132 // List[], Map[], CharSequence[] are not supported.
133 if (AidlTypenames::IsBuiltinTypename(name) && aidl.IsArray()) {
134 if (name == "List" || name == "Map" || name == "CharSequence") {
135 return true;
136 }
137 }
138
139 // T[] is not supported for interfaces
140 const AidlDefinedType* t = typenames.TryGetDefinedType(name);
141 if (aidl.IsArray() && t != nullptr && t->AsInterface() != nullptr) {
142 return true;
143 }
144
145 return false;
146 }
147
EnsureCodegenIsSupported(const CodeGeneratorContext & c)148 static bool EnsureCodegenIsSupported(const CodeGeneratorContext& c) {
149 if (IsMarshallingUnsupportedFor(c.type, c.typenames)) {
150 AIDL_ERROR(c.type) << c.type.ToString() << "' is not yet supported.";
151 return false;
152 }
153 return true;
154 }
155
GetFlagFor(const CodeGeneratorContext & c)156 static string GetFlagFor(const CodeGeneratorContext& c) {
157 if (c.is_return_value) {
158 return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
159 } else {
160 return "0";
161 }
162 }
163
WriteToParcelFor(const CodeGeneratorContext & c)164 bool WriteToParcelFor(const CodeGeneratorContext& c) {
165 if (!EnsureCodegenIsSupported(c)) {
166 return false;
167 }
168 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
169 {"boolean",
170 [](const CodeGeneratorContext& c) {
171 c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
172 }},
173 {"boolean[]",
174 [](const CodeGeneratorContext& c) {
175 c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
176 }},
177 {"byte",
178 [](const CodeGeneratorContext& c) {
179 c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
180 }},
181 {"byte[]",
182 [](const CodeGeneratorContext& c) {
183 c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
184 }},
185 {"char",
186 [](const CodeGeneratorContext& c) {
187 c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
188 }},
189 {"char[]",
190 [](const CodeGeneratorContext& c) {
191 c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
192 }},
193 {"int",
194 [](const CodeGeneratorContext& c) {
195 c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
196 }},
197 {"int[]",
198 [](const CodeGeneratorContext& c) {
199 c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
200 }},
201 {"long",
202 [](const CodeGeneratorContext& c) {
203 c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
204 }},
205 {"long[]",
206 [](const CodeGeneratorContext& c) {
207 c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
208 }},
209 {"float",
210 [](const CodeGeneratorContext& c) {
211 c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
212 }},
213 {"float[]",
214 [](const CodeGeneratorContext& c) {
215 c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
216 }},
217 {"double",
218 [](const CodeGeneratorContext& c) {
219 c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
220 }},
221 {"double[]",
222 [](const CodeGeneratorContext& c) {
223 c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
224 }},
225 {"String",
226 [](const CodeGeneratorContext& c) {
227 c.writer << c.parcel << ".writeString(" << c.var << ");\n";
228 }},
229 {"String[]",
230 [](const CodeGeneratorContext& c) {
231 c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
232 }},
233 {"List",
234 [](const CodeGeneratorContext& c) {
235 if (c.type.IsGeneric()) {
236 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
237 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
238 if (contained_type == "String") {
239 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
240 } else if (contained_type == "IBinder") {
241 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
242 }
243 } else {
244 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
245 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
246 if (t->AsParcelable() != nullptr) {
247 c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
248 }
249 }
250 } else {
251 c.writer << c.parcel << ".writeList(" << c.var << ");\n";
252 }
253 }},
254 {"Map",
255 [](const CodeGeneratorContext& c) {
256 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
257 }},
258 {"IBinder",
259 [](const CodeGeneratorContext& c) {
260 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
261 }},
262 {"IBinder[]",
263 [](const CodeGeneratorContext& c) {
264 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
265 }},
266 {"FileDescriptor",
267 [](const CodeGeneratorContext& c) {
268 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
269 }},
270 {"FileDescriptor[]",
271 [](const CodeGeneratorContext& c) {
272 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
273 }},
274 {"ParcelFileDescriptor",
275 [](const CodeGeneratorContext& c) {
276 // This is same as writeTypedObject which was introduced with SDK 23.
277 // Keeping below code so that the generated code is buildable with older SDK.
278 c.writer << "if ((" << c.var << "!=null)) {\n";
279 c.writer.Indent();
280 c.writer << c.parcel << ".writeInt(1);\n";
281 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
282 c.writer.Dedent();
283 c.writer << "}\n";
284 c.writer << "else {\n";
285 c.writer.Indent();
286 c.writer << c.parcel << ".writeInt(0);\n";
287 c.writer.Dedent();
288 c.writer << "}\n";
289 }},
290 {"ParcelFileDescriptor[]",
291 [](const CodeGeneratorContext& c) {
292 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
293 }},
294 {"CharSequence",
295 [](const CodeGeneratorContext& c) {
296 // TextUtils.writeToParcel does not accept null. So, we need to handle
297 // the case here.
298 c.writer << "if (" << c.var << "!=null) {\n";
299 c.writer.Indent();
300 c.writer << c.parcel << ".writeInt(1);\n";
301 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
302 << GetFlagFor(c) << ");\n";
303 c.writer.Dedent();
304 c.writer << "}\n";
305 c.writer << "else {\n";
306 c.writer.Indent();
307 c.writer << c.parcel << ".writeInt(0);\n";
308 c.writer.Dedent();
309 c.writer << "}\n";
310 }},
311 };
312 const string type_name = c.type.GetName() + (c.type.IsArray() ? "[]" : "");
313 const auto found = method_map.find(type_name);
314 if (found != method_map.end()) {
315 found->second(c);
316 } else {
317 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
318 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
319 if (t->AsInterface() != nullptr) {
320 if (!c.type.IsArray()) {
321 // Why don't we use writeStrongInterface which does the exact same thing?
322 // Keeping below code just not to break unit tests.
323 c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
324 << "(" << c.var << ".asBinder()):(null)));\n";
325 }
326 } else if (t->AsParcelable() != nullptr) {
327 if (c.type.IsArray()) {
328 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
329 } else {
330 // This is same as writeTypedObject.
331 // Keeping below code just not to break tests.
332 c.writer << "if ((" << c.var << "!=null)) {\n";
333 c.writer.Indent();
334 c.writer << c.parcel << ".writeInt(1);\n";
335 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
336 c.writer.Dedent();
337 c.writer << "}\n";
338 c.writer << "else {\n";
339 c.writer.Indent();
340 c.writer << c.parcel << ".writeInt(0);\n";
341 c.writer.Dedent();
342 c.writer << "}\n";
343 }
344 }
345 }
346 return true;
347 }
348
349 // Ensures that a variable is initialized to refer to the classloader
350 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)351 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
352 CHECK(c.is_classloader_created != nullptr);
353 if (!*(c.is_classloader_created)) {
354 c.writer << "java.lang.ClassLoader cl = "
355 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
356 *(c.is_classloader_created) = true;
357 }
358 return "cl";
359 }
360
CreateFromParcelFor(const CodeGeneratorContext & c)361 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
362 if (!EnsureCodegenIsSupported(c)) {
363 return false;
364 }
365 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
366 {"boolean",
367 [](const CodeGeneratorContext& c) {
368 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
369 }},
370 {"boolean[]",
371 [](const CodeGeneratorContext& c) {
372 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
373 }},
374 {"byte",
375 [](const CodeGeneratorContext& c) {
376 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
377 }},
378 {"byte[]",
379 [](const CodeGeneratorContext& c) {
380 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
381 }},
382 {"char",
383 [](const CodeGeneratorContext& c) {
384 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
385 }},
386 {"char[]",
387 [](const CodeGeneratorContext& c) {
388 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
389 }},
390 {"int",
391 [](const CodeGeneratorContext& c) {
392 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
393 }},
394 {"int[]",
395 [](const CodeGeneratorContext& c) {
396 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
397 }},
398 {"long",
399 [](const CodeGeneratorContext& c) {
400 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
401 }},
402 {"long[]",
403 [](const CodeGeneratorContext& c) {
404 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
405 }},
406 {"float",
407 [](const CodeGeneratorContext& c) {
408 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
409 }},
410 {"float[]",
411 [](const CodeGeneratorContext& c) {
412 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
413 }},
414 {"double",
415 [](const CodeGeneratorContext& c) {
416 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
417 }},
418 {"double[]",
419 [](const CodeGeneratorContext& c) {
420 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
421 }},
422 {"String",
423 [](const CodeGeneratorContext& c) {
424 c.writer << c.var << " = " << c.parcel << ".readString();\n";
425 }},
426 {"String[]",
427 [](const CodeGeneratorContext& c) {
428 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
429 }},
430 {"List",
431 [](const CodeGeneratorContext& c) {
432 if (c.type.IsGeneric()) {
433 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
434 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
435 if (contained_type == "String") {
436 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
437 } else if (contained_type == "IBinder") {
438 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
439 }
440 } else {
441 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
442 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
443 if (t->AsParcelable() != nullptr) {
444 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
445 << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
446 }
447 }
448 } else {
449 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
450 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
451 }
452 }},
453 {"Map",
454 [](const CodeGeneratorContext& c) {
455 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
456 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
457 }},
458 {"IBinder",
459 [](const CodeGeneratorContext& c) {
460 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
461 }},
462 {"IBinder[]",
463 [](const CodeGeneratorContext& c) {
464 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
465 }},
466 {"FileDescriptor",
467 [](const CodeGeneratorContext& c) {
468 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
469 }},
470 {"FileDescriptor[]",
471 [](const CodeGeneratorContext& c) {
472 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
473 }},
474 {"ParcelFileDescriptor",
475 [](const CodeGeneratorContext& c) {
476 // This is same as readTypedObject which was introduced with SDK 23.
477 // Keeping below code so that the generated code is buildable with older SDK.
478 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
479 c.writer.Indent();
480 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
481 << ");\n";
482 c.writer.Dedent();
483 c.writer << "}\n";
484 c.writer << "else {\n";
485 c.writer.Indent();
486 c.writer << c.var << " = null;\n";
487 c.writer.Dedent();
488 c.writer << "}\n";
489 }},
490 {"ParcelFileDescriptor[]",
491 [](const CodeGeneratorContext& c) {
492 c.writer << c.var << " = " << c.parcel
493 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
494 }},
495 {"CharSequence",
496 [](const CodeGeneratorContext& c) {
497 // We have written 0 for null CharSequence.
498 c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
499 c.writer.Indent();
500 c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
501 << c.parcel << ");\n";
502 c.writer.Dedent();
503 c.writer << "}\n";
504 c.writer << "else {\n";
505 c.writer.Indent();
506 c.writer << c.var << " = null;\n";
507 c.writer.Dedent();
508 c.writer << "}\n";
509 }},
510 };
511 const string type_name = c.type.GetName() + (c.type.IsArray() ? "[]" : "");
512 const auto found = method_map.find(type_name);
513 if (found != method_map.end()) {
514 found->second(c);
515 } else {
516 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
517 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
518 if (t->AsInterface() != nullptr) {
519 if (!c.type.IsArray()) {
520 c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
521 << ".readStrongBinder());\n";
522 }
523 } else if (t->AsParcelable() != nullptr || t->AsStructuredParcelable() != nullptr) {
524 if (c.type.IsArray()) {
525 c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
526 << ".CREATOR);\n";
527 } else {
528 // This is same as readTypedObject.
529 // Keeping below code just not to break unit tests.
530 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
531 c.writer.Indent();
532 c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
533 << ");\n";
534 c.writer.Dedent();
535 c.writer << "}\n";
536 c.writer << "else {\n";
537 c.writer.Indent();
538 c.writer << c.var << " = null;\n";
539 c.writer.Dedent();
540 c.writer << "}\n";
541 }
542 }
543 }
544 return true;
545 }
546
ReadFromParcelFor(const CodeGeneratorContext & c)547 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
548 if (!EnsureCodegenIsSupported(c)) {
549 return false;
550 }
551 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
552 {"boolean[]",
553 [](const CodeGeneratorContext& c) {
554 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
555 }},
556 {"byte[]",
557 [](const CodeGeneratorContext& c) {
558 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
559 }},
560 {"char[]",
561 [](const CodeGeneratorContext& c) {
562 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
563 }},
564 {"int[]",
565 [](const CodeGeneratorContext& c) {
566 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
567 }},
568 {"long[]",
569 [](const CodeGeneratorContext& c) {
570 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
571 }},
572 {"float[]",
573 [](const CodeGeneratorContext& c) {
574 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
575 }},
576 {"double[]",
577 [](const CodeGeneratorContext& c) {
578 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
579 }},
580 {"String[]",
581 [](const CodeGeneratorContext& c) {
582 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
583 }},
584 {"List",
585 [](const CodeGeneratorContext& c) {
586 if (c.type.IsGeneric()) {
587 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
588 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
589 if (contained_type == "String") {
590 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
591 } else if (contained_type == "IBinder") {
592 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
593 }
594 } else {
595 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
596 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
597 if (t->AsParcelable() != nullptr) {
598 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
599 << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
600 }
601 }
602 } else {
603 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
604 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
605 }
606 }},
607 {"Map",
608 [](const CodeGeneratorContext& c) {
609 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
610 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
611 }},
612 {"IBinder[]",
613 [](const CodeGeneratorContext& c) {
614 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
615 }},
616 {"FileDescriptor[]",
617 [](const CodeGeneratorContext& c) {
618 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
619 }},
620 {"ParcelFileDescriptor",
621 [](const CodeGeneratorContext& c) {
622 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
623 c.writer.Indent();
624 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
625 c.writer.Dedent();
626 c.writer << "}\n";
627 }},
628 {"ParcelFileDescriptor[]",
629 [](const CodeGeneratorContext& c) {
630 c.writer << c.parcel << ".readTypedArray(" << c.var
631 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
632 }},
633 };
634 const string type_name = c.type.GetName() + (c.type.IsArray() ? "[]" : "");
635 const auto& found = method_map.find(type_name);
636 if (found != method_map.end()) {
637 found->second(c);
638 } else {
639 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
640 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
641 if (t->AsParcelable() != nullptr) {
642 if (c.type.IsArray()) {
643 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
644 << ".CREATOR);\n";
645 } else {
646 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
647 c.writer.Indent();
648 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
649 c.writer.Dedent();
650 c.writer << "}\n";
651 }
652 }
653 }
654 return true;
655 }
656
657 } // namespace java
658 } // namespace aidl
659 } // namespace android
660