1 /*
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
24 #include <functional>
25 #include <iostream>
26 #include <map>
27 #include <string>
28 #include <vector>
29
30 namespace android {
31 namespace aidl {
32 namespace java {
33
34 using android::base::Join;
35
36 using std::function;
37 using std::map;
38 using std::string;
39 using std::vector;
40
ConstantValueDecorator(const AidlTypeSpecifier & type,const std::string & raw_value)41 std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
42 if (type.IsArray()) {
43 return raw_value;
44 }
45 if (type.GetName() == "long") {
46 return raw_value + "L";
47 }
48 if (auto defined_type = type.GetDefinedType(); defined_type) {
49 auto enum_type = defined_type->AsEnumDeclaration();
50 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
51 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
52 }
53 return raw_value;
54 };
55
JavaNameOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames,bool instantiable=false,bool boxing=false)56 const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
57 bool instantiable = false, bool boxing = false) {
58 AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
59
60 if (instantiable) {
61 // An instantiable type is used in only out type(not even inout type),
62 // And instantiable type has to be either the type in List, Map, ParcelFileDescriptor or
63 // user-defined type.
64
65 static map<string, string> instantiable_m = {
66 {"List", "java.util.ArrayList"},
67 {"Map", "java.util.HashMap"},
68 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
69 };
70 const string& aidl_name = aidl.GetName();
71
72 if (instantiable_m.find(aidl_name) != instantiable_m.end()) {
73 return instantiable_m[aidl_name];
74 }
75 }
76
77 // map from AIDL built-in type name to the corresponding Java type name
78 static map<string, string> m = {
79 {"void", "void"},
80 {"boolean", "boolean"},
81 {"byte", "byte"},
82 {"char", "char"},
83 {"int", "int"},
84 {"long", "long"},
85 {"float", "float"},
86 {"double", "double"},
87 {"String", "java.lang.String"},
88 {"List", "java.util.List"},
89 {"Map", "java.util.Map"},
90 {"IBinder", "android.os.IBinder"},
91 {"FileDescriptor", "java.io.FileDescriptor"},
92 {"CharSequence", "java.lang.CharSequence"},
93 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
94 {"ParcelableHolder", "android.os.ParcelableHolder"},
95 };
96
97 // map from primitive types to the corresponding boxing types
98 static map<string, string> boxing_types = {
99 {"void", "Void"}, {"boolean", "Boolean"}, {"byte", "Byte"}, {"char", "Character"},
100 {"int", "Integer"}, {"long", "Long"}, {"float", "Float"}, {"double", "Double"},
101 };
102
103 // Enums in Java are represented by their backing type when
104 // referenced in parcelables, methods, etc.
105 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
106 enum_decl != nullptr) {
107 const string& backing_type_name = enum_decl->GetBackingType().GetName();
108 AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
109 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
110 if (boxing) {
111 return boxing_types[backing_type_name];
112 } else {
113 return m[backing_type_name];
114 }
115 }
116
117 const string& aidl_name = aidl.GetName();
118 if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
119 // Every primitive type must have the corresponding boxing type
120 AIDL_FATAL_IF(boxing_types.find(aidl_name) == m.end(), aidl);
121 return boxing_types[aidl_name];
122 }
123 if (m.find(aidl_name) != m.end()) {
124 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), aidl);
125 return m[aidl_name];
126 } else {
127 // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
128 return aidl_name;
129 }
130 }
131
132 namespace {
JavaSignatureOfInternal(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames,bool instantiable,bool omit_array,bool boxing=false)133 string JavaSignatureOfInternal(
134 const AidlTypeSpecifier& aidl, const AidlTypenames& typenames, bool instantiable,
135 bool omit_array, bool boxing = false /* boxing can be true only if it is a type parameter */) {
136 string ret = JavaNameOf(aidl, typenames, instantiable, boxing && !aidl.IsArray());
137 if (aidl.IsGeneric()) {
138 vector<string> arg_names;
139 for (const auto& ta : aidl.GetTypeParameters()) {
140 arg_names.emplace_back(
141 JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
142 }
143 ret += "<" + Join(arg_names, ",") + ">";
144 }
145 if (aidl.IsArray() && !omit_array) {
146 ret += "[]";
147 }
148 return ret;
149 }
150
151 // Returns the name of the backing type for the specified type. Note: this
152 // returns type names as used in AIDL, not a Java signature.
153 // For enums, this is the enum's backing type.
154 // For all other types, this is the type itself.
AidlBackingTypeName(const AidlTypeSpecifier & type,const AidlTypenames & typenames)155 string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
156 string type_name;
157 if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
158 enum_decl != nullptr) {
159 type_name = enum_decl->GetBackingType().GetName();
160 } else {
161 type_name = type.GetName();
162 }
163 if (type.IsArray()) {
164 type_name += "[]";
165 }
166 return type_name;
167 }
168
169 } // namespace
170
JavaSignatureOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)171 string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
172 return JavaSignatureOfInternal(aidl, typenames, false, false);
173 }
174
InstantiableJavaSignatureOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)175 string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
176 return JavaSignatureOfInternal(aidl, typenames, true, true);
177 }
178
DefaultJavaValueOf(const AidlTypeSpecifier & aidl,const AidlTypenames & typenames)179 string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
180 static map<string, string> m = {
181 {"boolean", "false"}, {"byte", "0"}, {"char", R"('\u0000')"}, {"int", "0"},
182 {"long", "0L"}, {"float", "0.0f"}, {"double", "0.0d"},
183 };
184
185 const string name = AidlBackingTypeName(aidl, typenames);
186 AIDL_FATAL_IF(name == "void", aidl);
187
188 if (!aidl.IsArray() && m.find(name) != m.end()) {
189 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(name), aidl);
190 return m[name];
191 } else {
192 return "null";
193 }
194 }
195
GetFlagFor(const CodeGeneratorContext & c)196 static string GetFlagFor(const CodeGeneratorContext& c) {
197 if (c.is_return_value) {
198 return "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE";
199 } else {
200 return "0";
201 }
202 }
203
WriteToParcelFor(const CodeGeneratorContext & c)204 bool WriteToParcelFor(const CodeGeneratorContext& c) {
205 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
206 {"boolean",
207 [](const CodeGeneratorContext& c) {
208 c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
209 }},
210 {"boolean[]",
211 [](const CodeGeneratorContext& c) {
212 c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
213 }},
214 {"byte",
215 [](const CodeGeneratorContext& c) {
216 c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
217 }},
218 {"byte[]",
219 [](const CodeGeneratorContext& c) {
220 c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
221 }},
222 {"char",
223 [](const CodeGeneratorContext& c) {
224 c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
225 }},
226 {"char[]",
227 [](const CodeGeneratorContext& c) {
228 c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
229 }},
230 {"int",
231 [](const CodeGeneratorContext& c) {
232 c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
233 }},
234 {"int[]",
235 [](const CodeGeneratorContext& c) {
236 c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
237 }},
238 {"long",
239 [](const CodeGeneratorContext& c) {
240 c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
241 }},
242 {"long[]",
243 [](const CodeGeneratorContext& c) {
244 c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
245 }},
246 {"float",
247 [](const CodeGeneratorContext& c) {
248 c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
249 }},
250 {"float[]",
251 [](const CodeGeneratorContext& c) {
252 c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
253 }},
254 {"double",
255 [](const CodeGeneratorContext& c) {
256 c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
257 }},
258 {"double[]",
259 [](const CodeGeneratorContext& c) {
260 c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
261 }},
262 {"String",
263 [](const CodeGeneratorContext& c) {
264 c.writer << c.parcel << ".writeString(" << c.var << ");\n";
265 }},
266 {"String[]",
267 [](const CodeGeneratorContext& c) {
268 c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
269 }},
270 {"List",
271 [](const CodeGeneratorContext& c) {
272 if (c.type.IsGeneric()) {
273 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
274 if (contained_type == "String") {
275 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
276 } else if (contained_type == "IBinder") {
277 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
278 } else if (c.typenames.IsParcelable(contained_type)) {
279 c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
280 } else {
281 AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << contained_type;
282 }
283 } else {
284 c.writer << c.parcel << ".writeList(" << c.var << ");\n";
285 }
286 }},
287 {"Map",
288 [](const CodeGeneratorContext& c) {
289 if (c.type.IsGeneric()) {
290 c.writer << "if (" << c.var << " == null) {\n";
291 c.writer.Indent();
292 c.writer << c.parcel << ".writeInt(-1);\n";
293 c.writer.Dedent();
294 c.writer << "} else {\n";
295 c.writer.Indent();
296 c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
297 c.writer << c.var << ".forEach((k, v) -> {\n";
298 c.writer.Indent();
299 c.writer << c.parcel << ".writeString(k);\n";
300
301 CodeGeneratorContext value_context{
302 c.writer,
303 c.typenames,
304 *c.type.GetTypeParameters()[1].get(),
305 c.parcel,
306 "v",
307 c.is_return_value,
308 c.is_classloader_created,
309 c.filename,
310 };
311 WriteToParcelFor(value_context);
312 c.writer.Dedent();
313 c.writer << "});\n";
314
315 c.writer.Dedent();
316 c.writer << "}\n";
317 } else {
318 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
319 }
320 }},
321 {"IBinder",
322 [](const CodeGeneratorContext& c) {
323 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
324 }},
325 {"IBinder[]",
326 [](const CodeGeneratorContext& c) {
327 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
328 }},
329 {"FileDescriptor",
330 [](const CodeGeneratorContext& c) {
331 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
332 }},
333 {"FileDescriptor[]",
334 [](const CodeGeneratorContext& c) {
335 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
336 }},
337 {"ParcelFileDescriptor",
338 [](const CodeGeneratorContext& c) {
339 // This is same as writeTypedObject which was introduced with SDK 23.
340 // Keeping below code so that the generated code is buildable with older SDK.
341 c.writer << "if ((" << c.var << "!=null)) {\n";
342 c.writer.Indent();
343 c.writer << c.parcel << ".writeInt(1);\n";
344 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
345 c.writer.Dedent();
346 c.writer << "}\n";
347 c.writer << "else {\n";
348 c.writer.Indent();
349 c.writer << c.parcel << ".writeInt(0);\n";
350 c.writer.Dedent();
351 c.writer << "}\n";
352 }},
353 {"ParcelFileDescriptor[]",
354 [](const CodeGeneratorContext& c) {
355 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
356 }},
357 {"CharSequence",
358 [](const CodeGeneratorContext& c) {
359 // TextUtils.writeToParcel does not accept null. So, we need to handle
360 // the case here.
361 c.writer << "if (" << c.var << "!=null) {\n";
362 c.writer.Indent();
363 c.writer << c.parcel << ".writeInt(1);\n";
364 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
365 << GetFlagFor(c) << ");\n";
366 c.writer.Dedent();
367 c.writer << "}\n";
368 c.writer << "else {\n";
369 c.writer.Indent();
370 c.writer << c.parcel << ".writeInt(0);\n";
371 c.writer.Dedent();
372 c.writer << "}\n";
373 }},
374 {"ParcelableHolder",
375 [](const CodeGeneratorContext& c) {
376 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
377 }},
378 };
379 const string type_name = AidlBackingTypeName(c.type, c.typenames);
380 const auto found = method_map.find(type_name);
381 if (found != method_map.end()) {
382 found->second(c);
383 } else {
384 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
385 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
386 if (t->AsInterface() != nullptr) {
387 if (!c.type.IsArray()) {
388 // Why don't we use writeStrongInterface which does the exact same thing?
389 // Keeping below code just not to break unit tests.
390 c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
391 << "(" << c.var << ".asBinder()):(null)));\n";
392 }
393 } else if (t->AsParcelable() != nullptr) {
394 if (c.type.IsArray()) {
395 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
396 } else {
397 // This is same as writeTypedObject.
398 // Keeping below code just not to break tests.
399 c.writer << "if ((" << c.var << "!=null)) {\n";
400 c.writer.Indent();
401 c.writer << c.parcel << ".writeInt(1);\n";
402 c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
403 c.writer.Dedent();
404 c.writer << "}\n";
405 c.writer << "else {\n";
406 c.writer.Indent();
407 c.writer << c.parcel << ".writeInt(0);\n";
408 c.writer.Dedent();
409 c.writer << "}\n";
410 }
411 }
412 }
413 return true;
414 }
415
416 // Ensures that a variable is initialized to refer to the classloader
417 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)418 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
419 AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
420 if (!*(c.is_classloader_created)) {
421 c.writer << "java.lang.ClassLoader cl = "
422 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
423 *(c.is_classloader_created) = true;
424 }
425 return "cl";
426 }
427
CreateFromParcelFor(const CodeGeneratorContext & c)428 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
429 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
430 {"boolean",
431 [](const CodeGeneratorContext& c) {
432 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
433 }},
434 {"boolean[]",
435 [](const CodeGeneratorContext& c) {
436 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
437 }},
438 {"byte",
439 [](const CodeGeneratorContext& c) {
440 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
441 }},
442 {"byte[]",
443 [](const CodeGeneratorContext& c) {
444 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
445 }},
446 {"char",
447 [](const CodeGeneratorContext& c) {
448 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
449 }},
450 {"char[]",
451 [](const CodeGeneratorContext& c) {
452 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
453 }},
454 {"int",
455 [](const CodeGeneratorContext& c) {
456 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
457 }},
458 {"int[]",
459 [](const CodeGeneratorContext& c) {
460 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
461 }},
462 {"long",
463 [](const CodeGeneratorContext& c) {
464 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
465 }},
466 {"long[]",
467 [](const CodeGeneratorContext& c) {
468 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
469 }},
470 {"float",
471 [](const CodeGeneratorContext& c) {
472 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
473 }},
474 {"float[]",
475 [](const CodeGeneratorContext& c) {
476 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
477 }},
478 {"double",
479 [](const CodeGeneratorContext& c) {
480 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
481 }},
482 {"double[]",
483 [](const CodeGeneratorContext& c) {
484 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
485 }},
486 {"String",
487 [](const CodeGeneratorContext& c) {
488 c.writer << c.var << " = " << c.parcel << ".readString();\n";
489 }},
490 {"String[]",
491 [](const CodeGeneratorContext& c) {
492 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
493 }},
494 {"List",
495 [](const CodeGeneratorContext& c) {
496 if (c.type.IsGeneric()) {
497 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
498 if (contained_type == "String") {
499 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
500 } else if (contained_type == "IBinder") {
501 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
502 } else if (c.typenames.IsParcelable(contained_type)) {
503 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
504 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
505 << ".CREATOR);\n";
506 } else {
507 AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << contained_type;
508 }
509 } else {
510 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
511 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
512 }
513 }},
514 {"Map",
515 [](const CodeGeneratorContext& c) {
516 if (c.type.IsGeneric()) {
517 c.writer << "{\n";
518 c.writer.Indent();
519 c.writer << "int N = " << c.parcel << ".readInt();\n";
520 c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
521
522 auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) + ".CREATOR";
523 c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
524 c.writer.Indent();
525 c.writer << "String k = " << c.parcel << ".readString();\n";
526 c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
527 CodeGeneratorContext value_context{
528 c.writer,
529 c.typenames,
530 *c.type.GetTypeParameters()[1].get(),
531 c.parcel,
532 "v",
533 c.is_return_value,
534 c.is_classloader_created,
535 c.filename,
536 };
537 CreateFromParcelFor(value_context);
538 c.writer << c.var << ".put(k, v);\n";
539
540 c.writer.Dedent();
541 c.writer << "});\n";
542
543 c.writer.Dedent();
544 c.writer << "}\n";
545 } else {
546 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
547 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
548 }
549 }},
550 {"IBinder",
551 [](const CodeGeneratorContext& c) {
552 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
553 }},
554 {"IBinder[]",
555 [](const CodeGeneratorContext& c) {
556 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
557 }},
558 {"FileDescriptor",
559 [](const CodeGeneratorContext& c) {
560 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
561 }},
562 {"FileDescriptor[]",
563 [](const CodeGeneratorContext& c) {
564 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
565 }},
566 {"ParcelFileDescriptor",
567 [](const CodeGeneratorContext& c) {
568 // This is same as readTypedObject which was introduced with SDK 23.
569 // Keeping below code so that the generated code is buildable with older SDK.
570 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
571 c.writer.Indent();
572 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
573 << ");\n";
574 c.writer.Dedent();
575 c.writer << "}\n";
576 c.writer << "else {\n";
577 c.writer.Indent();
578 c.writer << c.var << " = null;\n";
579 c.writer.Dedent();
580 c.writer << "}\n";
581 }},
582 {"ParcelFileDescriptor[]",
583 [](const CodeGeneratorContext& c) {
584 c.writer << c.var << " = " << c.parcel
585 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
586 }},
587 {"CharSequence",
588 [](const CodeGeneratorContext& c) {
589 // We have written 0 for null CharSequence.
590 c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
591 c.writer.Indent();
592 c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
593 << c.parcel << ");\n";
594 c.writer.Dedent();
595 c.writer << "}\n";
596 c.writer << "else {\n";
597 c.writer.Indent();
598 c.writer << c.var << " = null;\n";
599 c.writer.Dedent();
600 c.writer << "}\n";
601 }},
602 {"ParcelableHolder",
603 [](const CodeGeneratorContext& c) {
604 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
605 c.writer.Indent();
606 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
607 c.writer.Dedent();
608 c.writer << "}\n";
609 }},
610 };
611 const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
612 if (found != method_map.end()) {
613 found->second(c);
614 } else {
615 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
616 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
617 if (t->AsInterface() != nullptr) {
618 if (!c.type.IsArray()) {
619 c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
620 << ".readStrongBinder());\n";
621 }
622 } else if (t->AsParcelable() != nullptr) {
623 if (c.type.IsArray()) {
624 c.writer << c.var << " = " << c.parcel << ".createTypedArray("
625 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
626 } else {
627 // This is same as readTypedObject.
628 // Keeping below code just not to break unit tests.
629 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
630 c.writer.Indent();
631 c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
632 << ");\n";
633 c.writer.Dedent();
634 c.writer << "}\n";
635 c.writer << "else {\n";
636 c.writer.Indent();
637 c.writer << c.var << " = null;\n";
638 c.writer.Dedent();
639 c.writer << "}\n";
640 }
641 }
642 }
643 return true;
644 }
645
ReadFromParcelFor(const CodeGeneratorContext & c)646 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
647 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
648 {"boolean[]",
649 [](const CodeGeneratorContext& c) {
650 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
651 }},
652 {"byte[]",
653 [](const CodeGeneratorContext& c) {
654 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
655 }},
656 {"char[]",
657 [](const CodeGeneratorContext& c) {
658 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
659 }},
660 {"int[]",
661 [](const CodeGeneratorContext& c) {
662 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
663 }},
664 {"long[]",
665 [](const CodeGeneratorContext& c) {
666 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
667 }},
668 {"float[]",
669 [](const CodeGeneratorContext& c) {
670 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
671 }},
672 {"double[]",
673 [](const CodeGeneratorContext& c) {
674 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
675 }},
676 {"String[]",
677 [](const CodeGeneratorContext& c) {
678 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
679 }},
680 {"List",
681 [](const CodeGeneratorContext& c) {
682 if (c.type.IsGeneric()) {
683 const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
684 if (contained_type == "String") {
685 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
686 } else if (contained_type == "IBinder") {
687 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
688 } else if (c.typenames.IsParcelable(contained_type)) {
689 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
690 << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
691 << ".CREATOR);\n";
692 } else {
693 AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << contained_type;
694 }
695 } else {
696 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
697 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
698 }
699 }},
700 {"Map",
701 [](const CodeGeneratorContext& c) {
702 if (c.type.IsGeneric()) {
703 c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
704 c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
705 << ".readInt()).forEach(i -> {\n";
706 c.writer.Indent();
707 c.writer << "String k = " << c.parcel << ".readString();\n";
708 c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
709 CodeGeneratorContext value_context{
710 c.writer,
711 c.typenames,
712 *c.type.GetTypeParameters()[1].get(),
713 c.parcel,
714 "v",
715 c.is_return_value,
716 c.is_classloader_created,
717 c.filename,
718 };
719 CreateFromParcelFor(value_context);
720 c.writer << c.var << ".put(k, v);\n";
721
722 c.writer.Dedent();
723 c.writer << "});\n";
724
725 c.writer.Dedent();
726 c.writer << "}\n";
727 } else {
728 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
729 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
730 }
731 }},
732 {"IBinder[]",
733 [](const CodeGeneratorContext& c) {
734 c.writer << c.parcel << ".readBinderArray(" << c.var << ");\n";
735 }},
736 {"FileDescriptor[]",
737 [](const CodeGeneratorContext& c) {
738 c.writer << c.parcel << ".readRawFileDescriptorArray(" << c.var << ");\n";
739 }},
740 {"ParcelFileDescriptor",
741 [](const CodeGeneratorContext& c) {
742 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
743 c.writer.Indent();
744 c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel << ");\n";
745 c.writer.Dedent();
746 c.writer << "}\n";
747 }},
748 {"ParcelFileDescriptor[]",
749 [](const CodeGeneratorContext& c) {
750 c.writer << c.parcel << ".readTypedArray(" << c.var
751 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
752 }},
753 };
754 const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
755 if (found != method_map.end()) {
756 found->second(c);
757 } else {
758 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
759 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
760 if (t->AsParcelable() != nullptr || t->AsUnionDeclaration() != nullptr) {
761 if (c.type.IsArray()) {
762 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
763 << ".CREATOR);\n";
764 } else {
765 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
766 c.writer.Indent();
767 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
768 c.writer.Dedent();
769 c.writer << "}\n";
770 }
771 }
772 }
773 return true;
774 }
775
ToStringFor(const CodeGeneratorContext & c)776 void ToStringFor(const CodeGeneratorContext& c) {
777 if (c.type.IsArray()) {
778 c.writer << "java.util.Arrays.toString(" << c.var << ")";
779 return;
780 }
781
782 const std::string name = c.type.GetName();
783
784 if (AidlTypenames::IsPrimitiveTypename(name)) {
785 c.writer << c.var;
786 return;
787 }
788
789 const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
790 if (t != nullptr && t->AsEnumDeclaration()) {
791 c.writer << c.var;
792 return;
793 }
794
795 // FileDescriptor doesn't have a good toString() impl.
796 if (name == "FileDescriptor") {
797 c.writer << c.var << " == null ? \"null\" : ";
798 c.writer << c.var << ".getInt$()";
799 return;
800 }
801
802 // Rest of the built-in types have reasonable toString() impls.
803 if (AidlTypenames::IsBuiltinTypename(name)) {
804 c.writer << "java.util.Objects.toString(" << c.var << ")";
805 return;
806 }
807
808 // For user-defined types, we also use toString() that we are generating here, but just make sure
809 // that they are actually user-defined types.
810 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
811 if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
812 c.writer << "java.util.Objects.toString(" << c.var << ")";
813 return;
814 }
815
816 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unhandled typename: " << name;
817 }
818
819 } // namespace java
820 } // namespace aidl
821 } // namespace android
822