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