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