blob: 89103656e3350ff32781d32ceeb3be80edf052b2 [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,
Jeongik Chae74c86d2019-12-12 16:54:03 +090051 bool instantiable = false, bool boxing = 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
Jeongik Chae74c86d2019-12-12 16:54:03 +090090 // map from primitive types to the corresponding boxing types
91 static map<string, string> boxing_types = {
92 {"void", "Void"}, {"boolean", "Boolean"}, {"byte", "Byte"}, {"char", "Character"},
93 {"int", "Integer"}, {"long", "Long"}, {"float", "Float"}, {"double", "Double"},
94 };
95
Daniel Norman716d3112019-09-10 13:11:56 -070096 // Enums in Java are represented by their backing type when
97 // referenced in parcelables, methods, etc.
98 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
99 enum_decl != nullptr) {
100 const string& backing_type_name = enum_decl->GetBackingType().GetName();
101 CHECK(m.find(backing_type_name) != m.end());
102 CHECK(AidlTypenames::IsBuiltinTypename(backing_type_name));
103 return m[backing_type_name];
104 }
105
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900106 const string& aidl_name = aidl.GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900107 if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
108 // Every primitive type must have the corresponding boxing type
109 CHECK(boxing_types.find(aidl_name) != m.end());
110 return boxing_types[aidl_name];
111 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900112 if (m.find(aidl_name) != m.end()) {
113 CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
114 return m[aidl_name];
115 } else {
116 // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
117 return aidl_name;
118 }
119}
120
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900121namespace {
Jeongik Chae74c86d2019-12-12 16:54:03 +0900122string JavaSignatureOfInternal(
123 const AidlTypeSpecifier& aidl, const AidlTypenames& typenames, bool instantiable,
124 bool omit_array, bool boxing = false /* boxing can be true only if it is a type parameter */) {
125 string ret = JavaNameOf(aidl, typenames, instantiable, boxing && !aidl.IsArray());
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900126 if (aidl.IsGeneric()) {
127 vector<string> arg_names;
128 for (const auto& ta : aidl.GetTypeParameters()) {
Jeongik Chae74c86d2019-12-12 16:54:03 +0900129 arg_names.emplace_back(
130 JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900131 }
132 ret += "<" + Join(arg_names, ",") + ">";
133 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900134 if (aidl.IsArray() && !omit_array) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900135 ret += "[]";
136 }
137 return ret;
138}
Daniel Norman716d3112019-09-10 13:11:56 -0700139
140// Returns the name of the backing type for the specified type. Note: this
141// returns type names as used in AIDL, not a Java signature.
142// For enums, this is the enum's backing type.
143// For all other types, this is the type itself.
144string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
145 string type_name;
146 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
147 enum_decl != nullptr) {
148 type_name = enum_decl->GetBackingType().GetName();
149 } else {
150 type_name = type.GetName();
151 }
152 if (type.IsArray()) {
153 type_name += "[]";
154 }
155 return type_name;
156}
157
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900158} // namespace
159
Daniel Norman716d3112019-09-10 13:11:56 -0700160string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
161 return JavaSignatureOfInternal(aidl, typenames, false, false);
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900162}
163
Daniel Norman716d3112019-09-10 13:11:56 -0700164string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
165 return JavaSignatureOfInternal(aidl, typenames, true, true);
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900166}
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900167
Daniel Norman716d3112019-09-10 13:11:56 -0700168string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900169 static map<string, string> m = {
170 {"boolean", "false"}, {"byte", "0"}, {"char", R"('\u0000')"}, {"int", "0"},
171 {"long", "0L"}, {"float", "0.0f"}, {"double", "0.0d"},
172 };
Daniel Norman716d3112019-09-10 13:11:56 -0700173
174 const string name = AidlBackingTypeName(aidl, typenames);
Steven Moreland9731c632019-08-13 10:21:08 -0700175 CHECK(name != "void");
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900176
177 if (!aidl.IsArray() && m.find(name) != m.end()) {
178 CHECK(AidlTypenames::IsBuiltinTypename(name));
179 return m[name];
180 } else {
181 return "null";
182 }
183}
184
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900185static string GetFlagFor(const CodeGeneratorContext& c) {
186 if (c.is_return_value) {
187 return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
188 } else {
189 return "0";
190 }
191}
192
193bool WriteToParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900194 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) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900282 if (c.type.IsGeneric()) {
283 c.writer << "if (" << c.var << " == null) {\n";
284 c.writer.Indent();
285 c.writer << c.parcel << ".writeInt(-1);\n";
286 c.writer.Dedent();
287 c.writer << "} else {\n";
288 c.writer.Indent();
289 c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
290 c.writer << c.var << ".forEach((k, v) -> {\n";
291 c.writer.Indent();
292 c.writer << c.parcel << ".writeString(k);\n";
293
294 CodeGeneratorContext value_context{
295 c.writer,
296 c.typenames,
297 *c.type.GetTypeParameters()[1].get(),
298 c.parcel,
299 "v",
300 c.is_return_value,
301 c.is_classloader_created,
302 c.filename,
303 };
304 WriteToParcelFor(value_context);
305 c.writer.Dedent();
306 c.writer << "});\n";
307
308 c.writer.Dedent();
309 c.writer << "}\n";
310 } else {
311 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
312 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900313 }},
314 {"IBinder",
315 [](const CodeGeneratorContext& c) {
316 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
317 }},
318 {"IBinder[]",
319 [](const CodeGeneratorContext& c) {
320 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
321 }},
322 {"FileDescriptor",
323 [](const CodeGeneratorContext& c) {
324 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
325 }},
326 {"FileDescriptor[]",
327 [](const CodeGeneratorContext& c) {
328 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
329 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900330 {"ParcelFileDescriptor",
331 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900332 // This is same as writeTypedObject which was introduced with SDK 23.
333 // Keeping below code so that the generated code is buildable with older SDK.
334 c.writer << "if ((" << c.var << "!=null)) {\n";
335 c.writer.Indent();
336 c.writer << c.parcel << ".writeInt(1);\n";
337 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
338 c.writer.Dedent();
339 c.writer << "}\n";
340 c.writer << "else {\n";
341 c.writer.Indent();
342 c.writer << c.parcel << ".writeInt(0);\n";
343 c.writer.Dedent();
344 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900345 }},
346 {"ParcelFileDescriptor[]",
347 [](const CodeGeneratorContext& c) {
348 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
349 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900350 {"CharSequence",
351 [](const CodeGeneratorContext& c) {
352 // TextUtils.writeToParcel does not accept null. So, we need to handle
353 // the case here.
354 c.writer << "if (" << c.var << "!=null) {\n";
355 c.writer.Indent();
356 c.writer << c.parcel << ".writeInt(1);\n";
357 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
358 << GetFlagFor(c) << ");\n";
359 c.writer.Dedent();
360 c.writer << "}\n";
361 c.writer << "else {\n";
362 c.writer.Indent();
363 c.writer << c.parcel << ".writeInt(0);\n";
364 c.writer.Dedent();
365 c.writer << "}\n";
366 }},
367 };
Daniel Norman716d3112019-09-10 13:11:56 -0700368 const string type_name = AidlBackingTypeName(c.type, c.typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900369 const auto found = method_map.find(type_name);
370 if (found != method_map.end()) {
371 found->second(c);
372 } else {
373 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
374 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
375 if (t->AsInterface() != nullptr) {
376 if (!c.type.IsArray()) {
377 // Why don't we use writeStrongInterface which does the exact same thing?
378 // Keeping below code just not to break unit tests.
379 c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
380 << "(" << c.var << ".asBinder()):(null)));\n";
381 }
382 } else if (t->AsParcelable() != nullptr) {
383 if (c.type.IsArray()) {
384 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
385 } else {
386 // This is same as writeTypedObject.
387 // Keeping below code just not to break tests.
388 c.writer << "if ((" << c.var << "!=null)) {\n";
389 c.writer.Indent();
390 c.writer << c.parcel << ".writeInt(1);\n";
391 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
392 c.writer.Dedent();
393 c.writer << "}\n";
394 c.writer << "else {\n";
395 c.writer.Indent();
396 c.writer << c.parcel << ".writeInt(0);\n";
397 c.writer.Dedent();
398 c.writer << "}\n";
399 }
400 }
401 }
402 return true;
403}
404
405// Ensures that a variable is initialized to refer to the classloader
406// of the current object and returns the name of the variable.
407static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
408 CHECK(c.is_classloader_created != nullptr);
409 if (!*(c.is_classloader_created)) {
410 c.writer << "java.lang.ClassLoader cl = "
411 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
412 *(c.is_classloader_created) = true;
413 }
414 return "cl";
415}
416
417bool CreateFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900418 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
419 {"boolean",
420 [](const CodeGeneratorContext& c) {
421 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
422 }},
423 {"boolean[]",
424 [](const CodeGeneratorContext& c) {
425 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
426 }},
427 {"byte",
428 [](const CodeGeneratorContext& c) {
429 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
430 }},
431 {"byte[]",
432 [](const CodeGeneratorContext& c) {
433 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
434 }},
435 {"char",
436 [](const CodeGeneratorContext& c) {
437 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
438 }},
439 {"char[]",
440 [](const CodeGeneratorContext& c) {
441 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
442 }},
443 {"int",
444 [](const CodeGeneratorContext& c) {
445 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
446 }},
447 {"int[]",
448 [](const CodeGeneratorContext& c) {
449 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
450 }},
451 {"long",
452 [](const CodeGeneratorContext& c) {
453 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
454 }},
455 {"long[]",
456 [](const CodeGeneratorContext& c) {
457 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
458 }},
459 {"float",
460 [](const CodeGeneratorContext& c) {
461 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
462 }},
463 {"float[]",
464 [](const CodeGeneratorContext& c) {
465 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
466 }},
467 {"double",
468 [](const CodeGeneratorContext& c) {
469 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
470 }},
471 {"double[]",
472 [](const CodeGeneratorContext& c) {
473 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
474 }},
475 {"String",
476 [](const CodeGeneratorContext& c) {
477 c.writer << c.var << " = " << c.parcel << ".readString();\n";
478 }},
479 {"String[]",
480 [](const CodeGeneratorContext& c) {
481 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
482 }},
483 {"List",
484 [](const CodeGeneratorContext& c) {
485 if (c.type.IsGeneric()) {
486 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
487 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
488 if (contained_type == "String") {
489 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
490 } else if (contained_type == "IBinder") {
491 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
492 }
493 } else {
494 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
495 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
496 if (t->AsParcelable() != nullptr) {
497 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
Daniel Norman716d3112019-09-10 13:11:56 -0700498 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
499 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900500 }
501 }
502 } else {
503 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
504 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
505 }
506 }},
507 {"Map",
508 [](const CodeGeneratorContext& c) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900509 if (c.type.IsGeneric()) {
510 c.writer << "{\n";
511 c.writer.Indent();
512 c.writer << "int N = " << c.parcel << ".readInt();\n";
513 c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
514
515 auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) + ".CREATOR";
516 c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
517 c.writer.Indent();
518 c.writer << "String k = " << c.parcel << ".readString();\n";
519 c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
520 CodeGeneratorContext value_context{
521 c.writer,
522 c.typenames,
523 *c.type.GetTypeParameters()[1].get(),
524 c.parcel,
525 "v",
526 c.is_return_value,
527 c.is_classloader_created,
528 c.filename,
529 };
530 CreateFromParcelFor(value_context);
531 c.writer << c.var << ".put(k, v);\n";
532
533 c.writer.Dedent();
534 c.writer << "});\n";
535
536 c.writer.Dedent();
537 c.writer << "}\n";
538 } else {
539 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
540 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
541 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900542 }},
543 {"IBinder",
544 [](const CodeGeneratorContext& c) {
545 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
546 }},
547 {"IBinder[]",
548 [](const CodeGeneratorContext& c) {
549 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
550 }},
551 {"FileDescriptor",
552 [](const CodeGeneratorContext& c) {
553 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
554 }},
555 {"FileDescriptor[]",
556 [](const CodeGeneratorContext& c) {
557 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
558 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900559 {"ParcelFileDescriptor",
560 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900561 // This is same as readTypedObject which was introduced with SDK 23.
562 // Keeping below code so that the generated code is buildable with older SDK.
563 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
564 c.writer.Indent();
565 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
566 << ");\n";
567 c.writer.Dedent();
568 c.writer << "}\n";
569 c.writer << "else {\n";
570 c.writer.Indent();
571 c.writer << c.var << " = null;\n";
572 c.writer.Dedent();
573 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900574 }},
575 {"ParcelFileDescriptor[]",
576 [](const CodeGeneratorContext& c) {
577 c.writer << c.var << " = " << c.parcel
578 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
579 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900580 {"CharSequence",
581 [](const CodeGeneratorContext& c) {
582 // We have written 0 for null CharSequence.
583 c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
584 c.writer.Indent();
585 c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
586 << c.parcel << ");\n";
587 c.writer.Dedent();
588 c.writer << "}\n";
589 c.writer << "else {\n";
590 c.writer.Indent();
591 c.writer << c.var << " = null;\n";
592 c.writer.Dedent();
593 c.writer << "}\n";
594 }},
595 };
Daniel Norman716d3112019-09-10 13:11:56 -0700596 const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900597 if (found != method_map.end()) {
598 found->second(c);
599 } else {
600 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
601 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
602 if (t->AsInterface() != nullptr) {
603 if (!c.type.IsArray()) {
604 c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
605 << ".readStrongBinder());\n";
606 }
607 } else if (t->AsParcelable() != nullptr || t->AsStructuredParcelable() != nullptr) {
608 if (c.type.IsArray()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700609 c.writer << c.var << " = " << c.parcel << ".createTypedArray("
610 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900611 } else {
612 // This is same as readTypedObject.
613 // Keeping below code just not to break unit tests.
614 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
615 c.writer.Indent();
616 c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
617 << ");\n";
618 c.writer.Dedent();
619 c.writer << "}\n";
620 c.writer << "else {\n";
621 c.writer.Indent();
622 c.writer << c.var << " = null;\n";
623 c.writer.Dedent();
624 c.writer << "}\n";
625 }
626 }
627 }
628 return true;
629}
630
631bool ReadFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900632 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
633 {"boolean[]",
634 [](const CodeGeneratorContext& c) {
635 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
636 }},
637 {"byte[]",
638 [](const CodeGeneratorContext& c) {
639 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
640 }},
641 {"char[]",
642 [](const CodeGeneratorContext& c) {
643 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
644 }},
645 {"int[]",
646 [](const CodeGeneratorContext& c) {
647 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
648 }},
649 {"long[]",
650 [](const CodeGeneratorContext& c) {
651 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
652 }},
653 {"float[]",
654 [](const CodeGeneratorContext& c) {
655 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
656 }},
657 {"double[]",
658 [](const CodeGeneratorContext& c) {
659 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
660 }},
661 {"String[]",
662 [](const CodeGeneratorContext& c) {
663 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
664 }},
665 {"List",
666 [](const CodeGeneratorContext& c) {
667 if (c.type.IsGeneric()) {
668 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
669 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
670 if (contained_type == "String") {
671 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
672 } else if (contained_type == "IBinder") {
673 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
674 }
675 } else {
676 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
677 CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
678 if (t->AsParcelable() != nullptr) {
679 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
Daniel Norman716d3112019-09-10 13:11:56 -0700680 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
681 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900682 }
683 }
684 } else {
685 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
686 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
687 }
688 }},
689 {"Map",
690 [](const CodeGeneratorContext& c) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900691 if (c.type.IsGeneric()) {
692 c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
693 c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
694 << ".readInt()).forEach(i -> {\n";
695 c.writer.Indent();
696 c.writer << "String k = " << c.parcel << ".readString();\n";
697 c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
698 CodeGeneratorContext value_context{
699 c.writer,
700 c.typenames,
701 *c.type.GetTypeParameters()[1].get(),
702 c.parcel,
703 "v",
704 c.is_return_value,
705 c.is_classloader_created,
706 c.filename,
707 };
708 CreateFromParcelFor(value_context);
709 c.writer << c.var << ".put(k, v);\n";
710
711 c.writer.Dedent();
712 c.writer << "});\n";
713
714 c.writer.Dedent();
715 c.writer << "}\n";
716 } else {
717 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
718 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
719 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900720 }},
721 {"IBinder[]",
722 [](const CodeGeneratorContext& c) {
723 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
724 }},
725 {"FileDescriptor[]",
726 [](const CodeGeneratorContext& c) {
727 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
728 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900729 {"ParcelFileDescriptor",
730 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900731 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
732 c.writer.Indent();
733 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
734 c.writer.Dedent();
735 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900736 }},
737 {"ParcelFileDescriptor[]",
738 [](const CodeGeneratorContext& c) {
739 c.writer << c.parcel << ".readTypedArray(" << c.var
740 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
741 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900742 };
Daniel Norman716d3112019-09-10 13:11:56 -0700743 const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900744 if (found != method_map.end()) {
745 found->second(c);
746 } else {
747 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
748 CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
749 if (t->AsParcelable() != nullptr) {
750 if (c.type.IsArray()) {
751 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
752 << ".CREATOR);\n";
753 } else {
754 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
755 c.writer.Indent();
756 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
757 c.writer.Dedent();
758 c.writer << "}\n";
759 }
760 }
761 }
762 return true;
763}
764
765} // namespace java
766} // namespace aidl
767} // namespace android