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