blob: 4fcfe9ab8b45293793b23cbc8fe2d6a2a737c888 [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
Daniel Norman37d43dd2019-09-09 17:22:34 -070042std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
Will McVickerd7d18df2019-09-12 13:40:50 -070043 if (type.GetName() == "long" && !type.IsArray()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -070044 return raw_value + "L";
45 }
46
Steven Moreland860b1942018-08-16 14:59:28 -070047 return raw_value;
48};
49
Daniel Norman716d3112019-09-10 13:11:56 -070050const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
51 bool instantiable = false) {
Steven Moreland8219c472018-08-17 11:41:13 -070052 CHECK(aidl.IsResolved()) << aidl.ToString();
53
Jeongik Chaa2080bf2019-06-18 16:44:29 +090054 if (instantiable) {
55 // An instantiable type is used in only out type(not even inout type),
56 // And instantiable type has to be either the type in List, Map, ParcelFileDescriptor or
57 // user-defined type.
58
59 static map<string, string> instantiable_m = {
60 {"List", "java.util.ArrayList"},
61 {"Map", "java.util.HashMap"},
62 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
63 };
64 const string& aidl_name = aidl.GetName();
65
66 if (instantiable_m.find(aidl_name) != instantiable_m.end()) {
67 return instantiable_m[aidl_name];
68 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +090069 }
70
Jiyong Park1d2df7d2018-07-23 15:22:50 +090071 // map from AIDL built-in type name to the corresponding Java type name
72 static map<string, string> m = {
73 {"void", "void"},
74 {"boolean", "boolean"},
75 {"byte", "byte"},
76 {"char", "char"},
77 {"int", "int"},
78 {"long", "long"},
79 {"float", "float"},
80 {"double", "double"},
81 {"String", "java.lang.String"},
82 {"List", "java.util.List"},
83 {"Map", "java.util.Map"},
84 {"IBinder", "android.os.IBinder"},
85 {"FileDescriptor", "java.io.FileDescriptor"},
86 {"CharSequence", "java.lang.CharSequence"},
Jiyong Parke05195e2018-10-08 18:24:23 +090087 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
Jiyong Park1d2df7d2018-07-23 15:22:50 +090088 };
Daniel Norman716d3112019-09-10 13:11:56 -070089
90 // Enums in Java are represented by their backing type when
91 // referenced in parcelables, methods, etc.
92 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
93 enum_decl != nullptr) {
94 const string& backing_type_name = enum_decl->GetBackingType().GetName();
95 CHECK(m.find(backing_type_name) != m.end());
96 CHECK(AidlTypenames::IsBuiltinTypename(backing_type_name));
97 return m[backing_type_name];
98 }
99
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900100 const string& aidl_name = aidl.GetName();
101 if (m.find(aidl_name) != m.end()) {
102 CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
103 return m[aidl_name];
104 } else {
105 // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
106 return aidl_name;
107 }
108}
109
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900110namespace {
Daniel Norman716d3112019-09-10 13:11:56 -0700111string JavaSignatureOfInternal(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
112 bool instantiable, bool omit_array) {
113 string ret = JavaNameOf(aidl, typenames, instantiable);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900114 if (aidl.IsGeneric()) {
115 vector<string> arg_names;
116 for (const auto& ta : aidl.GetTypeParameters()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700117 arg_names.emplace_back(JavaSignatureOfInternal(*ta, typenames, false, false));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900118 }
119 ret += "<" + Join(arg_names, ",") + ">";
120 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900121 if (aidl.IsArray() && !omit_array) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900122 ret += "[]";
123 }
124 return ret;
125}
Daniel Norman716d3112019-09-10 13:11:56 -0700126
127// Returns the name of the backing type for the specified type. Note: this
128// returns type names as used in AIDL, not a Java signature.
129// For enums, this is the enum's backing type.
130// For all other types, this is the type itself.
131string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
132 string type_name;
133 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
134 enum_decl != nullptr) {
135 type_name = enum_decl->GetBackingType().GetName();
136 } else {
137 type_name = type.GetName();
138 }
139 if (type.IsArray()) {
140 type_name += "[]";
141 }
142 return type_name;
143}
144
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900145} // namespace
146
Daniel Norman716d3112019-09-10 13:11:56 -0700147string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
148 return JavaSignatureOfInternal(aidl, typenames, false, false);
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900149}
150
Daniel Norman716d3112019-09-10 13:11:56 -0700151string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
152 return JavaSignatureOfInternal(aidl, typenames, true, true);
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900153}
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900154
Daniel Norman716d3112019-09-10 13:11:56 -0700155string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900156 static map<string, string> m = {
157 {"boolean", "false"}, {"byte", "0"}, {"char", R"('\u0000')"}, {"int", "0"},
158 {"long", "0L"}, {"float", "0.0f"}, {"double", "0.0d"},
159 };
Daniel Norman716d3112019-09-10 13:11:56 -0700160
161 const string name = AidlBackingTypeName(aidl, typenames);
Steven Moreland9731c632019-08-13 10:21:08 -0700162 CHECK(name != "void");
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900163
164 if (!aidl.IsArray() && m.find(name) != m.end()) {
165 CHECK(AidlTypenames::IsBuiltinTypename(name));
166 return m[name];
167 } else {
168 return "null";
169 }
170}
171
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900172static string GetFlagFor(const CodeGeneratorContext& c) {
173 if (c.is_return_value) {
174 return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
175 } else {
176 return "0";
177 }
178}
179
180bool WriteToParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900181 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
182 {"boolean",
183 [](const CodeGeneratorContext& c) {
184 c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
185 }},
186 {"boolean[]",
187 [](const CodeGeneratorContext& c) {
188 c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
189 }},
190 {"byte",
191 [](const CodeGeneratorContext& c) {
192 c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
193 }},
194 {"byte[]",
195 [](const CodeGeneratorContext& c) {
196 c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
197 }},
198 {"char",
199 [](const CodeGeneratorContext& c) {
200 c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
201 }},
202 {"char[]",
203 [](const CodeGeneratorContext& c) {
204 c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
205 }},
206 {"int",
207 [](const CodeGeneratorContext& c) {
208 c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
209 }},
210 {"int[]",
211 [](const CodeGeneratorContext& c) {
212 c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
213 }},
214 {"long",
215 [](const CodeGeneratorContext& c) {
216 c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
217 }},
218 {"long[]",
219 [](const CodeGeneratorContext& c) {
220 c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
221 }},
222 {"float",
223 [](const CodeGeneratorContext& c) {
224 c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
225 }},
226 {"float[]",
227 [](const CodeGeneratorContext& c) {
228 c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
229 }},
230 {"double",
231 [](const CodeGeneratorContext& c) {
232 c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
233 }},
234 {"double[]",
235 [](const CodeGeneratorContext& c) {
236 c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
237 }},
238 {"String",
239 [](const CodeGeneratorContext& c) {
240 c.writer << c.parcel << ".writeString(" << c.var << ");\n";
241 }},
242 {"String[]",
243 [](const CodeGeneratorContext& c) {
244 c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
245 }},
246 {"List",
247 [](const CodeGeneratorContext& c) {
248 if (c.type.IsGeneric()) {
249 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
250 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
251 if (contained_type == "String") {
252 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
253 } else if (contained_type == "IBinder") {
254 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
255 }
256 } else {
257 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
258 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
259 if (t->AsParcelable() != nullptr) {
260 c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
261 }
262 }
263 } else {
264 c.writer << c.parcel << ".writeList(" << c.var << ");\n";
265 }
266 }},
267 {"Map",
268 [](const CodeGeneratorContext& c) {
269 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
270 }},
271 {"IBinder",
272 [](const CodeGeneratorContext& c) {
273 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
274 }},
275 {"IBinder[]",
276 [](const CodeGeneratorContext& c) {
277 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
278 }},
279 {"FileDescriptor",
280 [](const CodeGeneratorContext& c) {
281 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
282 }},
283 {"FileDescriptor[]",
284 [](const CodeGeneratorContext& c) {
285 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
286 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900287 {"ParcelFileDescriptor",
288 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900289 // This is same as writeTypedObject which was introduced with SDK 23.
290 // Keeping below code so that the generated code is buildable with older SDK.
291 c.writer << "if ((" << c.var << "!=null)) {\n";
292 c.writer.Indent();
293 c.writer << c.parcel << ".writeInt(1);\n";
294 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
295 c.writer.Dedent();
296 c.writer << "}\n";
297 c.writer << "else {\n";
298 c.writer.Indent();
299 c.writer << c.parcel << ".writeInt(0);\n";
300 c.writer.Dedent();
301 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900302 }},
303 {"ParcelFileDescriptor[]",
304 [](const CodeGeneratorContext& c) {
305 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
306 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900307 {"CharSequence",
308 [](const CodeGeneratorContext& c) {
309 // TextUtils.writeToParcel does not accept null. So, we need to handle
310 // the case here.
311 c.writer << "if (" << c.var << "!=null) {\n";
312 c.writer.Indent();
313 c.writer << c.parcel << ".writeInt(1);\n";
314 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
315 << GetFlagFor(c) << ");\n";
316 c.writer.Dedent();
317 c.writer << "}\n";
318 c.writer << "else {\n";
319 c.writer.Indent();
320 c.writer << c.parcel << ".writeInt(0);\n";
321 c.writer.Dedent();
322 c.writer << "}\n";
323 }},
324 };
Daniel Norman716d3112019-09-10 13:11:56 -0700325 const string type_name = AidlBackingTypeName(c.type, c.typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900326 const auto found = method_map.find(type_name);
327 if (found != method_map.end()) {
328 found->second(c);
329 } else {
330 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
331 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
332 if (t->AsInterface() != nullptr) {
333 if (!c.type.IsArray()) {
334 // Why don't we use writeStrongInterface which does the exact same thing?
335 // Keeping below code just not to break unit tests.
336 c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
337 << "(" << c.var << ".asBinder()):(null)));\n";
338 }
339 } else if (t->AsParcelable() != nullptr) {
340 if (c.type.IsArray()) {
341 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
342 } else {
343 // This is same as writeTypedObject.
344 // Keeping below code just not to break tests.
345 c.writer << "if ((" << c.var << "!=null)) {\n";
346 c.writer.Indent();
347 c.writer << c.parcel << ".writeInt(1);\n";
348 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
349 c.writer.Dedent();
350 c.writer << "}\n";
351 c.writer << "else {\n";
352 c.writer.Indent();
353 c.writer << c.parcel << ".writeInt(0);\n";
354 c.writer.Dedent();
355 c.writer << "}\n";
356 }
357 }
358 }
359 return true;
360}
361
362// Ensures that a variable is initialized to refer to the classloader
363// of the current object and returns the name of the variable.
364static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
365 CHECK(c.is_classloader_created != nullptr);
366 if (!*(c.is_classloader_created)) {
367 c.writer << "java.lang.ClassLoader cl = "
368 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
369 *(c.is_classloader_created) = true;
370 }
371 return "cl";
372}
373
374bool CreateFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900375 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
376 {"boolean",
377 [](const CodeGeneratorContext& c) {
378 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
379 }},
380 {"boolean[]",
381 [](const CodeGeneratorContext& c) {
382 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
383 }},
384 {"byte",
385 [](const CodeGeneratorContext& c) {
386 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
387 }},
388 {"byte[]",
389 [](const CodeGeneratorContext& c) {
390 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
391 }},
392 {"char",
393 [](const CodeGeneratorContext& c) {
394 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
395 }},
396 {"char[]",
397 [](const CodeGeneratorContext& c) {
398 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
399 }},
400 {"int",
401 [](const CodeGeneratorContext& c) {
402 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
403 }},
404 {"int[]",
405 [](const CodeGeneratorContext& c) {
406 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
407 }},
408 {"long",
409 [](const CodeGeneratorContext& c) {
410 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
411 }},
412 {"long[]",
413 [](const CodeGeneratorContext& c) {
414 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
415 }},
416 {"float",
417 [](const CodeGeneratorContext& c) {
418 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
419 }},
420 {"float[]",
421 [](const CodeGeneratorContext& c) {
422 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
423 }},
424 {"double",
425 [](const CodeGeneratorContext& c) {
426 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
427 }},
428 {"double[]",
429 [](const CodeGeneratorContext& c) {
430 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
431 }},
432 {"String",
433 [](const CodeGeneratorContext& c) {
434 c.writer << c.var << " = " << c.parcel << ".readString();\n";
435 }},
436 {"String[]",
437 [](const CodeGeneratorContext& c) {
438 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
439 }},
440 {"List",
441 [](const CodeGeneratorContext& c) {
442 if (c.type.IsGeneric()) {
443 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
444 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
445 if (contained_type == "String") {
446 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
447 } else if (contained_type == "IBinder") {
448 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
449 }
450 } else {
451 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
452 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
453 if (t->AsParcelable() != nullptr) {
454 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
Daniel Norman716d3112019-09-10 13:11:56 -0700455 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
456 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900457 }
458 }
459 } else {
460 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
461 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
462 }
463 }},
464 {"Map",
465 [](const CodeGeneratorContext& c) {
466 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
467 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
468 }},
469 {"IBinder",
470 [](const CodeGeneratorContext& c) {
471 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
472 }},
473 {"IBinder[]",
474 [](const CodeGeneratorContext& c) {
475 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
476 }},
477 {"FileDescriptor",
478 [](const CodeGeneratorContext& c) {
479 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
480 }},
481 {"FileDescriptor[]",
482 [](const CodeGeneratorContext& c) {
483 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
484 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900485 {"ParcelFileDescriptor",
486 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900487 // This is same as readTypedObject which was introduced with SDK 23.
488 // Keeping below code so that the generated code is buildable with older SDK.
489 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
490 c.writer.Indent();
491 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
492 << ");\n";
493 c.writer.Dedent();
494 c.writer << "}\n";
495 c.writer << "else {\n";
496 c.writer.Indent();
497 c.writer << c.var << " = null;\n";
498 c.writer.Dedent();
499 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900500 }},
501 {"ParcelFileDescriptor[]",
502 [](const CodeGeneratorContext& c) {
503 c.writer << c.var << " = " << c.parcel
504 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
505 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900506 {"CharSequence",
507 [](const CodeGeneratorContext& c) {
508 // We have written 0 for null CharSequence.
509 c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
510 c.writer.Indent();
511 c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
512 << c.parcel << ");\n";
513 c.writer.Dedent();
514 c.writer << "}\n";
515 c.writer << "else {\n";
516 c.writer.Indent();
517 c.writer << c.var << " = null;\n";
518 c.writer.Dedent();
519 c.writer << "}\n";
520 }},
521 };
Daniel Norman716d3112019-09-10 13:11:56 -0700522 const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900523 if (found != method_map.end()) {
524 found->second(c);
525 } else {
526 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
527 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
528 if (t->AsInterface() != nullptr) {
529 if (!c.type.IsArray()) {
530 c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
531 << ".readStrongBinder());\n";
532 }
533 } else if (t->AsParcelable() != nullptr || t->AsStructuredParcelable() != nullptr) {
534 if (c.type.IsArray()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700535 c.writer << c.var << " = " << c.parcel << ".createTypedArray("
536 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900537 } else {
538 // This is same as readTypedObject.
539 // Keeping below code just not to break unit tests.
540 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
541 c.writer.Indent();
542 c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
543 << ");\n";
544 c.writer.Dedent();
545 c.writer << "}\n";
546 c.writer << "else {\n";
547 c.writer.Indent();
548 c.writer << c.var << " = null;\n";
549 c.writer.Dedent();
550 c.writer << "}\n";
551 }
552 }
553 }
554 return true;
555}
556
557bool ReadFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900558 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
559 {"boolean[]",
560 [](const CodeGeneratorContext& c) {
561 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
562 }},
563 {"byte[]",
564 [](const CodeGeneratorContext& c) {
565 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
566 }},
567 {"char[]",
568 [](const CodeGeneratorContext& c) {
569 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
570 }},
571 {"int[]",
572 [](const CodeGeneratorContext& c) {
573 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
574 }},
575 {"long[]",
576 [](const CodeGeneratorContext& c) {
577 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
578 }},
579 {"float[]",
580 [](const CodeGeneratorContext& c) {
581 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
582 }},
583 {"double[]",
584 [](const CodeGeneratorContext& c) {
585 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
586 }},
587 {"String[]",
588 [](const CodeGeneratorContext& c) {
589 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
590 }},
591 {"List",
592 [](const CodeGeneratorContext& c) {
593 if (c.type.IsGeneric()) {
594 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
595 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
596 if (contained_type == "String") {
597 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
598 } else if (contained_type == "IBinder") {
599 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
600 }
601 } else {
602 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
603 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
604 if (t->AsParcelable() != nullptr) {
605 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
Daniel Norman716d3112019-09-10 13:11:56 -0700606 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
607 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900608 }
609 }
610 } else {
611 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
612 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
613 }
614 }},
615 {"Map",
616 [](const CodeGeneratorContext& c) {
617 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
618 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
619 }},
620 {"IBinder[]",
621 [](const CodeGeneratorContext& c) {
622 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
623 }},
624 {"FileDescriptor[]",
625 [](const CodeGeneratorContext& c) {
626 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
627 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900628 {"ParcelFileDescriptor",
629 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900630 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
631 c.writer.Indent();
632 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
633 c.writer.Dedent();
634 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900635 }},
636 {"ParcelFileDescriptor[]",
637 [](const CodeGeneratorContext& c) {
638 c.writer << c.parcel << ".readTypedArray(" << c.var
639 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
640 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900641 };
Daniel Norman716d3112019-09-10 13:11:56 -0700642 const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900643 if (found != method_map.end()) {
644 found->second(c);
645 } else {
646 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
647 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
648 if (t->AsParcelable() != nullptr) {
649 if (c.type.IsArray()) {
650 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
651 << ".CREATOR);\n";
652 } else {
653 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
654 c.writer.Indent();
655 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
656 c.writer.Dedent();
657 c.writer << "}\n";
658 }
659 }
660 }
661 return true;
662}
663
664} // namespace java
665} // namespace aidl
666} // namespace android