blob: 9bb9052d31058247ef1903561c750a18e2b6ac14 [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();
267 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
268 if (contained_type == "String") {
269 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
270 } else if (contained_type == "IBinder") {
271 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
272 }
273 } else {
274 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000275 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900276 if (t->AsParcelable() != nullptr) {
277 c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
278 }
279 }
280 } else {
281 c.writer << c.parcel << ".writeList(" << c.var << ");\n";
282 }
283 }},
284 {"Map",
285 [](const CodeGeneratorContext& c) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900286 if (c.type.IsGeneric()) {
287 c.writer << "if (" << c.var << " == null) {\n";
288 c.writer.Indent();
289 c.writer << c.parcel << ".writeInt(-1);\n";
290 c.writer.Dedent();
291 c.writer << "} else {\n";
292 c.writer.Indent();
293 c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
294 c.writer << c.var << ".forEach((k, v) -> {\n";
295 c.writer.Indent();
296 c.writer << c.parcel << ".writeString(k);\n";
297
298 CodeGeneratorContext value_context{
299 c.writer,
300 c.typenames,
301 *c.type.GetTypeParameters()[1].get(),
302 c.parcel,
303 "v",
304 c.is_return_value,
305 c.is_classloader_created,
306 c.filename,
307 };
308 WriteToParcelFor(value_context);
309 c.writer.Dedent();
310 c.writer << "});\n";
311
312 c.writer.Dedent();
313 c.writer << "}\n";
314 } else {
315 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
316 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900317 }},
318 {"IBinder",
319 [](const CodeGeneratorContext& c) {
320 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
321 }},
322 {"IBinder[]",
323 [](const CodeGeneratorContext& c) {
324 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
325 }},
326 {"FileDescriptor",
327 [](const CodeGeneratorContext& c) {
328 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
329 }},
330 {"FileDescriptor[]",
331 [](const CodeGeneratorContext& c) {
332 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
333 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900334 {"ParcelFileDescriptor",
335 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900336 // This is same as writeTypedObject which was introduced with SDK 23.
337 // Keeping below code so that the generated code is buildable with older SDK.
338 c.writer << "if ((" << c.var << "!=null)) {\n";
339 c.writer.Indent();
340 c.writer << c.parcel << ".writeInt(1);\n";
341 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
342 c.writer.Dedent();
343 c.writer << "}\n";
344 c.writer << "else {\n";
345 c.writer.Indent();
346 c.writer << c.parcel << ".writeInt(0);\n";
347 c.writer.Dedent();
348 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900349 }},
350 {"ParcelFileDescriptor[]",
351 [](const CodeGeneratorContext& c) {
352 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
353 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900354 {"CharSequence",
355 [](const CodeGeneratorContext& c) {
356 // TextUtils.writeToParcel does not accept null. So, we need to handle
357 // the case here.
358 c.writer << "if (" << c.var << "!=null) {\n";
359 c.writer.Indent();
360 c.writer << c.parcel << ".writeInt(1);\n";
361 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
362 << GetFlagFor(c) << ");\n";
363 c.writer.Dedent();
364 c.writer << "}\n";
365 c.writer << "else {\n";
366 c.writer.Indent();
367 c.writer << c.parcel << ".writeInt(0);\n";
368 c.writer.Dedent();
369 c.writer << "}\n";
370 }},
Jeongik Cha649e8a72020-03-27 17:47:40 +0900371 {"ParcelableHolder",
372 [](const CodeGeneratorContext& c) {
373 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
374 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900375 };
Daniel Norman716d3112019-09-10 13:11:56 -0700376 const string type_name = AidlBackingTypeName(c.type, c.typenames);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900377 const auto found = method_map.find(type_name);
378 if (found != method_map.end()) {
379 found->second(c);
380 } else {
381 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000382 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900383 if (t->AsInterface() != nullptr) {
384 if (!c.type.IsArray()) {
385 // Why don't we use writeStrongInterface which does the exact same thing?
386 // Keeping below code just not to break unit tests.
387 c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
388 << "(" << c.var << ".asBinder()):(null)));\n";
389 }
390 } else if (t->AsParcelable() != nullptr) {
391 if (c.type.IsArray()) {
392 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
393 } else {
394 // This is same as writeTypedObject.
395 // Keeping below code just not to break tests.
396 c.writer << "if ((" << c.var << "!=null)) {\n";
397 c.writer.Indent();
398 c.writer << c.parcel << ".writeInt(1);\n";
399 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
400 c.writer.Dedent();
401 c.writer << "}\n";
402 c.writer << "else {\n";
403 c.writer.Indent();
404 c.writer << c.parcel << ".writeInt(0);\n";
405 c.writer.Dedent();
406 c.writer << "}\n";
407 }
408 }
409 }
410 return true;
411}
412
413// Ensures that a variable is initialized to refer to the classloader
414// of the current object and returns the name of the variable.
415static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
Steven Moreland21780812020-09-11 01:29:45 +0000416 AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900417 if (!*(c.is_classloader_created)) {
418 c.writer << "java.lang.ClassLoader cl = "
419 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
420 *(c.is_classloader_created) = true;
421 }
422 return "cl";
423}
424
425bool CreateFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900426 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
427 {"boolean",
428 [](const CodeGeneratorContext& c) {
429 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
430 }},
431 {"boolean[]",
432 [](const CodeGeneratorContext& c) {
433 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
434 }},
435 {"byte",
436 [](const CodeGeneratorContext& c) {
437 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
438 }},
439 {"byte[]",
440 [](const CodeGeneratorContext& c) {
441 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
442 }},
443 {"char",
444 [](const CodeGeneratorContext& c) {
445 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
446 }},
447 {"char[]",
448 [](const CodeGeneratorContext& c) {
449 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
450 }},
451 {"int",
452 [](const CodeGeneratorContext& c) {
453 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
454 }},
455 {"int[]",
456 [](const CodeGeneratorContext& c) {
457 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
458 }},
459 {"long",
460 [](const CodeGeneratorContext& c) {
461 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
462 }},
463 {"long[]",
464 [](const CodeGeneratorContext& c) {
465 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
466 }},
467 {"float",
468 [](const CodeGeneratorContext& c) {
469 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
470 }},
471 {"float[]",
472 [](const CodeGeneratorContext& c) {
473 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
474 }},
475 {"double",
476 [](const CodeGeneratorContext& c) {
477 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
478 }},
479 {"double[]",
480 [](const CodeGeneratorContext& c) {
481 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
482 }},
483 {"String",
484 [](const CodeGeneratorContext& c) {
485 c.writer << c.var << " = " << c.parcel << ".readString();\n";
486 }},
487 {"String[]",
488 [](const CodeGeneratorContext& c) {
489 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
490 }},
491 {"List",
492 [](const CodeGeneratorContext& c) {
493 if (c.type.IsGeneric()) {
494 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
495 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
496 if (contained_type == "String") {
497 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
498 } else if (contained_type == "IBinder") {
499 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
500 }
501 } else {
502 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000503 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900504 if (t->AsParcelable() != nullptr) {
505 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
Daniel Norman716d3112019-09-10 13:11:56 -0700506 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
507 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900508 }
509 }
510 } else {
511 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
512 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
513 }
514 }},
515 {"Map",
516 [](const CodeGeneratorContext& c) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900517 if (c.type.IsGeneric()) {
518 c.writer << "{\n";
519 c.writer.Indent();
520 c.writer << "int N = " << c.parcel << ".readInt();\n";
521 c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
522
523 auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) + ".CREATOR";
524 c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
525 c.writer.Indent();
526 c.writer << "String k = " << c.parcel << ".readString();\n";
527 c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
528 CodeGeneratorContext value_context{
529 c.writer,
530 c.typenames,
531 *c.type.GetTypeParameters()[1].get(),
532 c.parcel,
533 "v",
534 c.is_return_value,
535 c.is_classloader_created,
536 c.filename,
537 };
538 CreateFromParcelFor(value_context);
539 c.writer << c.var << ".put(k, v);\n";
540
541 c.writer.Dedent();
542 c.writer << "});\n";
543
544 c.writer.Dedent();
545 c.writer << "}\n";
546 } else {
547 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
548 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
549 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900550 }},
551 {"IBinder",
552 [](const CodeGeneratorContext& c) {
553 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
554 }},
555 {"IBinder[]",
556 [](const CodeGeneratorContext& c) {
557 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
558 }},
559 {"FileDescriptor",
560 [](const CodeGeneratorContext& c) {
561 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
562 }},
563 {"FileDescriptor[]",
564 [](const CodeGeneratorContext& c) {
565 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
566 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900567 {"ParcelFileDescriptor",
568 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900569 // This is same as readTypedObject which was introduced with SDK 23.
570 // Keeping below code so that the generated code is buildable with older SDK.
571 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
572 c.writer.Indent();
573 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
574 << ");\n";
575 c.writer.Dedent();
576 c.writer << "}\n";
577 c.writer << "else {\n";
578 c.writer.Indent();
579 c.writer << c.var << " = null;\n";
580 c.writer.Dedent();
581 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900582 }},
583 {"ParcelFileDescriptor[]",
584 [](const CodeGeneratorContext& c) {
585 c.writer << c.var << " = " << c.parcel
586 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
587 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900588 {"CharSequence",
589 [](const CodeGeneratorContext& c) {
590 // We have written 0 for null CharSequence.
591 c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
592 c.writer.Indent();
593 c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
594 << c.parcel << ");\n";
595 c.writer.Dedent();
596 c.writer << "}\n";
597 c.writer << "else {\n";
598 c.writer.Indent();
599 c.writer << c.var << " = null;\n";
600 c.writer.Dedent();
601 c.writer << "}\n";
602 }},
Jeongik Cha649e8a72020-03-27 17:47:40 +0900603 {"ParcelableHolder",
604 [](const CodeGeneratorContext& c) {
605 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
606 c.writer.Indent();
607 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
608 c.writer.Dedent();
609 c.writer << "}\n";
610 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900611 };
Daniel Norman716d3112019-09-10 13:11:56 -0700612 const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900613 if (found != method_map.end()) {
614 found->second(c);
615 } else {
616 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000617 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900618 if (t->AsInterface() != nullptr) {
619 if (!c.type.IsArray()) {
620 c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
621 << ".readStrongBinder());\n";
622 }
623 } else if (t->AsParcelable() != nullptr || t->AsStructuredParcelable() != nullptr) {
624 if (c.type.IsArray()) {
Daniel Norman716d3112019-09-10 13:11:56 -0700625 c.writer << c.var << " = " << c.parcel << ".createTypedArray("
626 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900627 } else {
628 // This is same as readTypedObject.
629 // Keeping below code just not to break unit tests.
630 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
631 c.writer.Indent();
632 c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
633 << ");\n";
634 c.writer.Dedent();
635 c.writer << "}\n";
636 c.writer << "else {\n";
637 c.writer.Indent();
638 c.writer << c.var << " = null;\n";
639 c.writer.Dedent();
640 c.writer << "}\n";
641 }
642 }
643 }
644 return true;
645}
646
647bool ReadFromParcelFor(const CodeGeneratorContext& c) {
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900648 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
649 {"boolean[]",
650 [](const CodeGeneratorContext& c) {
651 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
652 }},
653 {"byte[]",
654 [](const CodeGeneratorContext& c) {
655 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
656 }},
657 {"char[]",
658 [](const CodeGeneratorContext& c) {
659 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
660 }},
661 {"int[]",
662 [](const CodeGeneratorContext& c) {
663 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
664 }},
665 {"long[]",
666 [](const CodeGeneratorContext& c) {
667 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
668 }},
669 {"float[]",
670 [](const CodeGeneratorContext& c) {
671 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
672 }},
673 {"double[]",
674 [](const CodeGeneratorContext& c) {
675 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
676 }},
677 {"String[]",
678 [](const CodeGeneratorContext& c) {
679 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
680 }},
681 {"List",
682 [](const CodeGeneratorContext& c) {
683 if (c.type.IsGeneric()) {
684 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
685 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
686 if (contained_type == "String") {
687 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
688 } else if (contained_type == "IBinder") {
689 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
690 }
691 } else {
692 const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000693 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type;
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900694 if (t->AsParcelable() != nullptr) {
695 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
Daniel Norman716d3112019-09-10 13:11:56 -0700696 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
697 << ".CREATOR);\n";
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900698 }
699 }
700 } else {
701 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
702 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
703 }
704 }},
705 {"Map",
706 [](const CodeGeneratorContext& c) {
Jeongik Chae48d9942020-01-02 17:39:00 +0900707 if (c.type.IsGeneric()) {
708 c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
709 c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
710 << ".readInt()).forEach(i -> {\n";
711 c.writer.Indent();
712 c.writer << "String k = " << c.parcel << ".readString();\n";
713 c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
714 CodeGeneratorContext value_context{
715 c.writer,
716 c.typenames,
717 *c.type.GetTypeParameters()[1].get(),
718 c.parcel,
719 "v",
720 c.is_return_value,
721 c.is_classloader_created,
722 c.filename,
723 };
724 CreateFromParcelFor(value_context);
725 c.writer << c.var << ".put(k, v);\n";
726
727 c.writer.Dedent();
728 c.writer << "});\n";
729
730 c.writer.Dedent();
731 c.writer << "}\n";
732 } else {
733 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
734 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
735 }
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900736 }},
737 {"IBinder[]",
738 [](const CodeGeneratorContext& c) {
739 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
740 }},
741 {"FileDescriptor[]",
742 [](const CodeGeneratorContext& c) {
743 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
744 }},
Jiyong Parke05195e2018-10-08 18:24:23 +0900745 {"ParcelFileDescriptor",
746 [](const CodeGeneratorContext& c) {
Jiyong Parkd53fdbe2018-11-14 15:53:32 +0900747 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
748 c.writer.Indent();
749 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
750 c.writer.Dedent();
751 c.writer << "}\n";
Jiyong Parke05195e2018-10-08 18:24:23 +0900752 }},
753 {"ParcelFileDescriptor[]",
754 [](const CodeGeneratorContext& c) {
755 c.writer << c.parcel << ".readTypedArray(" << c.var
756 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
757 }},
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900758 };
Daniel Norman716d3112019-09-10 13:11:56 -0700759 const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900760 if (found != method_map.end()) {
761 found->second(c);
762 } else {
763 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000764 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900765 if (t->AsParcelable() != nullptr) {
766 if (c.type.IsArray()) {
767 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
768 << ".CREATOR);\n";
769 } else {
770 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
771 c.writer.Indent();
772 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
773 c.writer.Dedent();
774 c.writer << "}\n";
775 }
776 }
777 }
778 return true;
779}
780
Jiyong Park43113fb2020-07-20 16:26:19 +0900781void ToStringFor(const CodeGeneratorContext& c) {
782 if (c.type.IsArray()) {
783 // Arrays can be null
784 c.writer << c.var << " == null ? \"null\" : ";
785 c.writer << "java.util.Arrays.toString(" << c.var << ")";
786 return;
787 }
788
789 const std::string name = c.type.GetName();
790
791 if (AidlTypenames::IsPrimitiveTypename(name)) {
792 c.writer << c.var;
793 return;
794 }
795
796 const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
797 if (t != nullptr && t->AsEnumDeclaration()) {
798 c.writer << c.var;
799 return;
800 }
801
802 // FileDescriptor doesn't have a good toString() impl.
803 if (name == "FileDescriptor") {
804 c.writer << c.var << " == null ? \"null\" : ";
805 c.writer << c.var << ".getInt$()";
806 return;
807 }
808
809 // Rest of the built-in types have reasonable toString() impls.
810 if (AidlTypenames::IsBuiltinTypename(name)) {
811 c.writer << "java.util.Objects.toString(" << c.var << ")";
812 return;
813 }
814
815 // For user-defined types, we also use toString() that we are generating here, but just make sure
816 // that they are actually user-defined types.
817 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
818 if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
819 c.writer << c.var << ".toString()";
820 return;
821 }
Steven Moreland21780812020-09-11 01:29:45 +0000822
Steven Morelandf01ff3a2020-09-17 23:37:45 +0000823 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unhandled typename: " << name;
Jiyong Park43113fb2020-07-20 16:26:19 +0900824}
825
Jiyong Park1d2df7d2018-07-23 15:22:50 +0900826} // namespace java
827} // namespace aidl
828} // namespace android