blob: 9fa691a6d872d6219a9c0790c7939b7bb1254b60 [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::function;
37using std::map;
38using std::string;
39using std::vector;
40
Daniel Norman37d43dd2019-09-09 17:22:34 -070041std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
Will McVickerd7d18df2019-09-12 13:40:50 -070042 if (type.GetName() == "long" && !type.IsArray()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -070043 return raw_value + "L";
44 }
45
Steven Moreland860b1942018-08-16 14:59:28 -070046 return raw_value;
47};
48
Daniel Norman716d3112019-09-10 13:11:56 -070049const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
Jeongik Chae74c86d2019-12-12 16:54:03 +090050 bool instantiable = false, bool boxing = false) {
Steven Moreland21780812020-09-11 01:29:45 +000051 AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
Steven Moreland8219c472018-08-17 11:41:13 -070052
Jeongik Chaa2080bf2019-06-18 16:44:29 +090053 if (instantiable) {
54 // An instantiable type is used in only out type(not even inout type),
55 // And instantiable type has to be either the type in List, Map, ParcelFileDescriptor or
56 // user-defined type.
57
58 static map<string, string> instantiable_m = {
59 {"List", "java.util.ArrayList"},
60 {"Map", "java.util.HashMap"},
61 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
62 };
63 const string& aidl_name = aidl.GetName();
64
65 if (instantiable_m.find(aidl_name) != instantiable_m.end()) {
66 return instantiable_m[aidl_name];
67 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +090068 }
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"},
Jeongik Cha649e8a72020-03-27 17:47:40 +090087 {"ParcelableHolder", "android.os.ParcelableHolder"},
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();
Steven Moreland21780812020-09-11 01:29:45 +0000101 AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
102 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
Devin Moore7b68f0b2020-08-28 16:47:40 -0700103 if (boxing) {
104 return boxing_types[backing_type_name];
105 } else {
106 return m[backing_type_name];
107 }
Daniel Norman716d3112019-09-10 13:11:56 -0700108 }
109
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900110 const string& aidl_name = aidl.GetName();
Jeongik Chae74c86d2019-12-12 16:54:03 +0900111 if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
112 // Every primitive type must have the corresponding boxing type
Steven Moreland21780812020-09-11 01:29:45 +0000113 AIDL_FATAL_IF(boxing_types.find(aidl_name) == m.end(), aidl);
Jeongik Chae74c86d2019-12-12 16:54:03 +0900114 return boxing_types[aidl_name];
115 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900116 if (m.find(aidl_name) != m.end()) {
Steven Moreland21780812020-09-11 01:29:45 +0000117 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), aidl);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900118 return m[aidl_name];
119 } else {
120 // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
121 return aidl_name;
122 }
123}
124
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900125namespace {
Jeongik Chae74c86d2019-12-12 16:54:03 +0900126string JavaSignatureOfInternal(
127 const AidlTypeSpecifier& aidl, const AidlTypenames& typenames, bool instantiable,
128 bool omit_array, bool boxing = false /* boxing can be true only if it is a type parameter */) {
129 string ret = JavaNameOf(aidl, typenames, instantiable, boxing && !aidl.IsArray());
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900130 if (aidl.IsGeneric()) {
131 vector<string> arg_names;
132 for (const auto& ta : aidl.GetTypeParameters()) {
Jeongik Chae74c86d2019-12-12 16:54:03 +0900133 arg_names.emplace_back(
134 JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900135 }
136 ret += "<" + Join(arg_names, ",") + ">";
137 }
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900138 if (aidl.IsArray() && !omit_array) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900139 ret += "[]";
140 }
141 return ret;
142}
Daniel Norman716d3112019-09-10 13:11:56 -0700143
144// Returns the name of the backing type for the specified type. Note: this
145// returns type names as used in AIDL, not a Java signature.
146// For enums, this is the enum's backing type.
147// For all other types, this is the type itself.
148string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
149 string type_name;
150 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
151 enum_decl != nullptr) {
152 type_name = enum_decl->GetBackingType().GetName();
153 } else {
154 type_name = type.GetName();
155 }
156 if (type.IsArray()) {
157 type_name += "[]";
158 }
159 return type_name;
160}
161
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900162} // namespace
163
Daniel Norman716d3112019-09-10 13:11:56 -0700164string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
165 return JavaSignatureOfInternal(aidl, typenames, false, false);
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900166}
167
Daniel Norman716d3112019-09-10 13:11:56 -0700168string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
169 return JavaSignatureOfInternal(aidl, typenames, true, true);
Jeongik Chaa2080bf2019-06-18 16:44:29 +0900170}
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900171
Daniel Norman716d3112019-09-10 13:11:56 -0700172string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900173 static map<string, string> m = {
174 {"boolean", "false"}, {"byte", "0"}, {"char", R"('\u0000')"}, {"int", "0"},
175 {"long", "0L"}, {"float", "0.0f"}, {"double", "0.0d"},
176 };
Daniel Norman716d3112019-09-10 13:11:56 -0700177
178 const string name = AidlBackingTypeName(aidl, typenames);
Steven Moreland21780812020-09-11 01:29:45 +0000179 AIDL_FATAL_IF(name == "void", aidl);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900180
181 if (!aidl.IsArray() && m.find(name) != m.end()) {
Steven Moreland21780812020-09-11 01:29:45 +0000182 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(name), aidl);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900183 return m[name];
184 } else {
185 return "null";
186 }
187}
188
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900189static string GetFlagFor(const CodeGeneratorContext& c) {
190 if (c.is_return_value) {
191 return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
192 } else {
193 return "0";
194 }
195}
196
197bool WriteToParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900198 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
199 {"boolean",
200 [](const CodeGeneratorContext& c) {
201 c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
202 }},
203 {"boolean[]",
204 [](const CodeGeneratorContext& c) {
205 c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
206 }},
207 {"byte",
208 [](const CodeGeneratorContext& c) {
209 c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
210 }},
211 {"byte[]",
212 [](const CodeGeneratorContext& c) {
213 c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
214 }},
215 {"char",
216 [](const CodeGeneratorContext& c) {
217 c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
218 }},
219 {"char[]",
220 [](const CodeGeneratorContext& c) {
221 c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
222 }},
223 {"int",
224 [](const CodeGeneratorContext& c) {
225 c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
226 }},
227 {"int[]",
228 [](const CodeGeneratorContext& c) {
229 c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
230 }},
231 {"long",
232 [](const CodeGeneratorContext& c) {
233 c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
234 }},
235 {"long[]",
236 [](const CodeGeneratorContext& c) {
237 c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
238 }},
239 {"float",
240 [](const CodeGeneratorContext& c) {
241 c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
242 }},
243 {"float[]",
244 [](const CodeGeneratorContext& c) {
245 c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
246 }},
247 {"double",
248 [](const CodeGeneratorContext& c) {
249 c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
250 }},
251 {"double[]",
252 [](const CodeGeneratorContext& c) {
253 c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
254 }},
255 {"String",
256 [](const CodeGeneratorContext& c) {
257 c.writer << c.parcel << ".writeString(" << c.var << ");\n";
258 }},
259 {"String[]",
260 [](const CodeGeneratorContext& c) {
261 c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
262 }},
263 {"List",
264 [](const CodeGeneratorContext& c) {
265 if (c.type.IsGeneric()) {
266 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
Jooyung Hana61aa232020-10-20 04:00:08 +0900267 if (contained_type == "String") {
268 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
269 } else if (contained_type == "IBinder") {
270 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
271 } else if (c.typenames.IsParcelable(contained_type)) {
272 c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900273 } else {
Jooyung Hana61aa232020-10-20 04:00:08 +0900274 AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << contained_type;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900275 }
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 }},
Jeongik Cha649e8a72020-03-27 17:47:40 +0900367 {"ParcelableHolder",
368 [](const CodeGeneratorContext& c) {
369 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
370 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900371 };
Daniel Norman716d3112019-09-10 13:11:56 -0700372 const string type_name = AidlBackingTypeName(c.type, c.typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900373 const auto found = method_map.find(type_name);
374 if (found != method_map.end()) {
375 found->second(c);
376 } else {
377 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000378 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900379 if (t->AsInterface() != nullptr) {
380 if (!c.type.IsArray()) {
381 // Why don't we use writeStrongInterface which does the exact same thing?
382 // Keeping below code just not to break unit tests.
383 c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
384 << "(" << c.var << ".asBinder()):(null)));\n";
385 }
386 } else if (t->AsParcelable() != nullptr) {
387 if (c.type.IsArray()) {
388 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
389 } else {
390 // This is same as writeTypedObject.
391 // Keeping below code just not to break tests.
392 c.writer << "if ((" << c.var << "!=null)) {\n";
393 c.writer.Indent();
394 c.writer << c.parcel << ".writeInt(1);\n";
395 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
396 c.writer.Dedent();
397 c.writer << "}\n";
398 c.writer << "else {\n";
399 c.writer.Indent();
400 c.writer << c.parcel << ".writeInt(0);\n";
401 c.writer.Dedent();
402 c.writer << "}\n";
403 }
404 }
405 }
406 return true;
407}
408
409// Ensures that a variable is initialized to refer to the classloader
410// of the current object and returns the name of the variable.
411static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
Steven Moreland21780812020-09-11 01:29:45 +0000412 AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900413 if (!*(c.is_classloader_created)) {
414 c.writer << "java.lang.ClassLoader cl = "
415 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
416 *(c.is_classloader_created) = true;
417 }
418 return "cl";
419}
420
421bool CreateFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900422 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
423 {"boolean",
424 [](const CodeGeneratorContext& c) {
425 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
426 }},
427 {"boolean[]",
428 [](const CodeGeneratorContext& c) {
429 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
430 }},
431 {"byte",
432 [](const CodeGeneratorContext& c) {
433 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
434 }},
435 {"byte[]",
436 [](const CodeGeneratorContext& c) {
437 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
438 }},
439 {"char",
440 [](const CodeGeneratorContext& c) {
441 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
442 }},
443 {"char[]",
444 [](const CodeGeneratorContext& c) {
445 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
446 }},
447 {"int",
448 [](const CodeGeneratorContext& c) {
449 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
450 }},
451 {"int[]",
452 [](const CodeGeneratorContext& c) {
453 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
454 }},
455 {"long",
456 [](const CodeGeneratorContext& c) {
457 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
458 }},
459 {"long[]",
460 [](const CodeGeneratorContext& c) {
461 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
462 }},
463 {"float",
464 [](const CodeGeneratorContext& c) {
465 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
466 }},
467 {"float[]",
468 [](const CodeGeneratorContext& c) {
469 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
470 }},
471 {"double",
472 [](const CodeGeneratorContext& c) {
473 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
474 }},
475 {"double[]",
476 [](const CodeGeneratorContext& c) {
477 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
478 }},
479 {"String",
480 [](const CodeGeneratorContext& c) {
481 c.writer << c.var << " = " << c.parcel << ".readString();\n";
482 }},
483 {"String[]",
484 [](const CodeGeneratorContext& c) {
485 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
486 }},
487 {"List",
488 [](const CodeGeneratorContext& c) {
489 if (c.type.IsGeneric()) {
490 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
Jooyung Hana61aa232020-10-20 04:00:08 +0900491 if (contained_type == "String") {
492 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
493 } else if (contained_type == "IBinder") {
494 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
495 } else if (c.typenames.IsParcelable(contained_type)) {
496 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
497 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
498 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900499 } else {
Jooyung Hana61aa232020-10-20 04:00:08 +0900500 AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << contained_type;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900501 }
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 }},
Jeongik Cha649e8a72020-03-27 17:47:40 +0900595 {"ParcelableHolder",
596 [](const CodeGeneratorContext& c) {
597 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
598 c.writer.Indent();
599 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
600 c.writer.Dedent();
601 c.writer << "}\n";
602 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900603 };
Daniel Norman716d3112019-09-10 13:11:56 -0700604 const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900605 if (found != method_map.end()) {
606 found->second(c);
607 } else {
608 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000609 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900610 if (t->AsInterface() != nullptr) {
611 if (!c.type.IsArray()) {
612 c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
613 << ".readStrongBinder());\n";
614 }
Jooyung Han70df6142020-10-12 19:23:19 +0900615 } else if (t->AsParcelable() != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900616 if (c.type.IsArray()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700617 c.writer << c.var << " = " << c.parcel << ".createTypedArray("
618 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900619 } else {
620 // This is same as readTypedObject.
621 // Keeping below code just not to break unit tests.
622 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
623 c.writer.Indent();
624 c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
625 << ");\n";
626 c.writer.Dedent();
627 c.writer << "}\n";
628 c.writer << "else {\n";
629 c.writer.Indent();
630 c.writer << c.var << " = null;\n";
631 c.writer.Dedent();
632 c.writer << "}\n";
633 }
634 }
635 }
636 return true;
637}
638
639bool ReadFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900640 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
641 {"boolean[]",
642 [](const CodeGeneratorContext& c) {
643 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
644 }},
645 {"byte[]",
646 [](const CodeGeneratorContext& c) {
647 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
648 }},
649 {"char[]",
650 [](const CodeGeneratorContext& c) {
651 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
652 }},
653 {"int[]",
654 [](const CodeGeneratorContext& c) {
655 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
656 }},
657 {"long[]",
658 [](const CodeGeneratorContext& c) {
659 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
660 }},
661 {"float[]",
662 [](const CodeGeneratorContext& c) {
663 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
664 }},
665 {"double[]",
666 [](const CodeGeneratorContext& c) {
667 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
668 }},
669 {"String[]",
670 [](const CodeGeneratorContext& c) {
671 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
672 }},
673 {"List",
674 [](const CodeGeneratorContext& c) {
675 if (c.type.IsGeneric()) {
676 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
Jooyung Hana61aa232020-10-20 04:00:08 +0900677 if (contained_type == "String") {
678 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
679 } else if (contained_type == "IBinder") {
680 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
681 } else if (c.typenames.IsParcelable(contained_type)) {
682 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
683 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
684 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900685 } else {
Jooyung Hana61aa232020-10-20 04:00:08 +0900686 AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << contained_type;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900687 }
688 } else {
689 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
690 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
691 }
692 }},
693 {"Map",
694 [](const CodeGeneratorContext& c) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900695 if (c.type.IsGeneric()) {
696 c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
697 c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
698 << ".readInt()).forEach(i -> {\n";
699 c.writer.Indent();
700 c.writer << "String k = " << c.parcel << ".readString();\n";
701 c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
702 CodeGeneratorContext value_context{
703 c.writer,
704 c.typenames,
705 *c.type.GetTypeParameters()[1].get(),
706 c.parcel,
707 "v",
708 c.is_return_value,
709 c.is_classloader_created,
710 c.filename,
711 };
712 CreateFromParcelFor(value_context);
713 c.writer << c.var << ".put(k, v);\n";
714
715 c.writer.Dedent();
716 c.writer << "});\n";
717
718 c.writer.Dedent();
719 c.writer << "}\n";
720 } else {
721 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
722 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
723 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900724 }},
725 {"IBinder[]",
726 [](const CodeGeneratorContext& c) {
727 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
728 }},
729 {"FileDescriptor[]",
730 [](const CodeGeneratorContext& c) {
731 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
732 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900733 {"ParcelFileDescriptor",
734 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900735 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
736 c.writer.Indent();
737 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
738 c.writer.Dedent();
739 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900740 }},
741 {"ParcelFileDescriptor[]",
742 [](const CodeGeneratorContext& c) {
743 c.writer << c.parcel << ".readTypedArray(" << c.var
744 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
745 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900746 };
Daniel Norman716d3112019-09-10 13:11:56 -0700747 const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900748 if (found != method_map.end()) {
749 found->second(c);
750 } else {
751 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000752 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
Jooyung Han2946afc2020-10-05 20:29:16 +0900753 if (t->AsParcelable() != nullptr || t->AsUnionDeclaration() != nullptr) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900754 if (c.type.IsArray()) {
755 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
756 << ".CREATOR);\n";
757 } else {
758 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
759 c.writer.Indent();
760 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
761 c.writer.Dedent();
762 c.writer << "}\n";
763 }
764 }
765 }
766 return true;
767}
768
Jiyong Park43113fb2020-07-20 16:26:19 +0900769void ToStringFor(const CodeGeneratorContext& c) {
770 if (c.type.IsArray()) {
771 // Arrays can be null
772 c.writer << c.var << " == null ? \"null\" : ";
773 c.writer << "java.util.Arrays.toString(" << c.var << ")";
774 return;
775 }
776
777 const std::string name = c.type.GetName();
778
779 if (AidlTypenames::IsPrimitiveTypename(name)) {
780 c.writer << c.var;
781 return;
782 }
783
784 const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
785 if (t != nullptr && t->AsEnumDeclaration()) {
786 c.writer << c.var;
787 return;
788 }
789
790 // FileDescriptor doesn't have a good toString() impl.
791 if (name == "FileDescriptor") {
792 c.writer << c.var << " == null ? \"null\" : ";
793 c.writer << c.var << ".getInt$()";
794 return;
795 }
796
797 // Rest of the built-in types have reasonable toString() impls.
798 if (AidlTypenames::IsBuiltinTypename(name)) {
799 c.writer << "java.util.Objects.toString(" << c.var << ")";
800 return;
801 }
802
803 // For user-defined types, we also use toString() that we are generating here, but just make sure
804 // that they are actually user-defined types.
805 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
806 if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
807 c.writer << c.var << ".toString()";
808 return;
809 }
Steven Moreland21780812020-09-11 01:29:45 +0000810
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000811 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unhandled typename: " << name;
Jiyong Park43113fb2020-07-20 16:26:19 +0900812}
813
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900814} // namespace java
815} // namespace aidl
816} // namespace android