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::variant<std::string,std::vector<std::string>> & raw_value)41 std::string ConstantValueDecorator(
42 const AidlTypeSpecifier& type,
43 const std::variant<std::string, std::vector<std::string>>& raw_value) {
44 if (type.IsArray()) {
45 const auto& values = std::get<std::vector<std::string>>(raw_value);
46 return "{" + Join(values, ", ") + "}";
47 }
48 const std::string& value = std::get<std::string>(raw_value);
49 if (type.GetName() == "long") {
50 return value + "L";
51 }
52 if (auto defined_type = type.GetDefinedType(); defined_type) {
53 auto enum_type = defined_type->AsEnumDeclaration();
54 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
55 return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
56 }
57 return value;
58 };
59
JavaNameOf(const AidlTypeSpecifier & aidl,bool instantiable=false,bool boxing=false)60 const string& JavaNameOf(const AidlTypeSpecifier& aidl, bool instantiable = false,
61 bool boxing = false) {
62 AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
63
64 if (instantiable) {
65 // An instantiable type is used in only out type(not even inout type),
66 // And instantiable type has to be either the type in List, Map, ParcelFileDescriptor or
67 // user-defined type.
68
69 static map<string, string> instantiable_m = {
70 {"List", "java.util.ArrayList"},
71 {"Map", "java.util.HashMap"},
72 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
73 };
74 const string& aidl_name = aidl.GetName();
75
76 if (instantiable_m.find(aidl_name) != instantiable_m.end()) {
77 return instantiable_m[aidl_name];
78 }
79 }
80
81 // map from AIDL built-in type name to the corresponding Java type name
82 static map<string, string> m = {
83 {"void", "void"},
84 {"boolean", "boolean"},
85 {"byte", "byte"},
86 {"char", "char"},
87 {"int", "int"},
88 {"long", "long"},
89 {"float", "float"},
90 {"double", "double"},
91 {"String", "java.lang.String"},
92 {"List", "java.util.List"},
93 {"Map", "java.util.Map"},
94 {"IBinder", "android.os.IBinder"},
95 {"FileDescriptor", "java.io.FileDescriptor"},
96 {"CharSequence", "java.lang.CharSequence"},
97 {"ParcelFileDescriptor", "android.os.ParcelFileDescriptor"},
98 {"ParcelableHolder", "android.os.ParcelableHolder"},
99 };
100
101 // map from primitive types to the corresponding boxing types
102 static map<string, string> boxing_types = {
103 {"void", "Void"}, {"boolean", "Boolean"}, {"byte", "Byte"}, {"char", "Character"},
104 {"int", "Integer"}, {"long", "Long"}, {"float", "Float"}, {"double", "Double"},
105 };
106
107 // Enums in Java are represented by their backing type when
108 // referenced in parcelables, methods, etc.
109 const auto defined_type = aidl.GetDefinedType();
110 if (defined_type && defined_type->AsEnumDeclaration()) {
111 const auto enum_decl = defined_type->AsEnumDeclaration();
112 const string& backing_type_name = enum_decl->GetBackingType().GetName();
113 AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
114 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
115 if (boxing) {
116 return boxing_types[backing_type_name];
117 } else {
118 return m[backing_type_name];
119 }
120 }
121
122 const string& aidl_name = aidl.GetName();
123 if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
124 // Every primitive type must have the corresponding boxing type
125 AIDL_FATAL_IF(boxing_types.find(aidl_name) == m.end(), aidl);
126 return boxing_types[aidl_name];
127 }
128 if (m.find(aidl_name) != m.end()) {
129 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), aidl);
130 return m[aidl_name];
131 } else {
132 // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
133 return aidl_name;
134 }
135 }
136
137 namespace {
JavaSignatureOfInternal(const AidlTypeSpecifier & aidl,bool instantiable,bool omit_array,bool boxing)138 string JavaSignatureOfInternal(const AidlTypeSpecifier& aidl, bool instantiable, bool omit_array,
139 bool boxing) {
140 string ret = JavaNameOf(aidl, instantiable, boxing && !aidl.IsArray());
141 if (aidl.IsGeneric()) {
142 vector<string> arg_names;
143 for (const auto& ta : aidl.GetTypeParameters()) {
144 arg_names.emplace_back(JavaSignatureOfInternal(*ta, /*instantiable=*/false,
145 /*omit_array=*/false, /*boxing=*/true));
146 }
147 ret += "<" + Join(arg_names, ",") + ">";
148 }
149 if (aidl.IsArray() && !omit_array) {
150 if (aidl.IsFixedSizeArray()) {
151 ret += Join(std::vector<std::string>(aidl.GetFixedSizeArrayDimensions().size(), "[]"), "");
152 } else {
153 ret += "[]";
154 }
155 }
156 return ret;
157 }
158
159 // Returns the name of the backing type for the specified type.
160 // Note: Do not use the result in the generated code! It's supposed to be used as a key.
161 // This returns type names as used in AIDL, not a Java signature.
162 // For enums, this is the enum's backing type.
163 // For all other types, this is the type itself.
AidlBackingTypeName(const AidlTypeSpecifier & type)164 string AidlBackingTypeName(const AidlTypeSpecifier& type) {
165 string type_name;
166 const auto defined_type = type.GetDefinedType();
167 if (defined_type && defined_type->AsEnumDeclaration()) {
168 const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
169 type_name = enum_decl->GetBackingType().GetName();
170 } else {
171 type_name = type.GetName();
172 }
173 if (type.IsArray()) {
174 if (type.IsFixedSizeArray()) {
175 for (const auto& dim : type.GetFixedSizeArrayDimensions()) {
176 type_name += "[" + std::to_string(dim) + "]";
177 }
178 } else {
179 type_name += "[]";
180 }
181 }
182 return type_name;
183 }
184
185 } // namespace
186
JavaSignatureOf(const AidlTypeSpecifier & aidl)187 string JavaSignatureOf(const AidlTypeSpecifier& aidl) {
188 return JavaSignatureOfInternal(aidl, /*instantiable=*/false, /*omit_array=*/false,
189 /*boxing=*/false);
190 }
191
192 // Used for "new" expression. Ignore arrays because "new" expression handles it.
InstantiableJavaSignatureOf(const AidlTypeSpecifier & aidl)193 string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl) {
194 return JavaSignatureOfInternal(aidl, /*instantiable=*/true, /*omit_array=*/true,
195 /*boxing=*/false);
196 }
197
JavaBoxingTypeOf(const AidlTypeSpecifier & aidl)198 string JavaBoxingTypeOf(const AidlTypeSpecifier& aidl) {
199 AIDL_FATAL_IF(!AidlTypenames::IsPrimitiveTypename(aidl.GetName()), aidl);
200 return JavaSignatureOfInternal(aidl, /*instantiable=*/false, /*omit_array=*/false,
201 /*boxing=*/true);
202 }
203
DefaultJavaValueOf(const AidlTypeSpecifier & aidl)204 string DefaultJavaValueOf(const AidlTypeSpecifier& aidl) {
205 static map<string, string> m = {
206 {"boolean", "false"}, {"byte", "0"}, {"char", R"('\u0000')"}, {"int", "0"},
207 {"long", "0L"}, {"float", "0.0f"}, {"double", "0.0d"},
208 };
209
210 const string name = AidlBackingTypeName(aidl);
211 AIDL_FATAL_IF(name == "void", aidl);
212
213 if (!aidl.IsArray() && m.find(name) != m.end()) {
214 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(name), aidl);
215 return m[name];
216 } else {
217 return "null";
218 }
219 }
220
221 typedef void (*ParcelHelperGenerator)(CodeWriter&, const Options&);
222
GenerateTypedObjectHelper(CodeWriter & out,const Options &)223 static void GenerateTypedObjectHelper(CodeWriter& out, const Options&) {
224 // Note that the name is inconsistent here because Parcel.java defines readTypedObject as if it
225 // "creates" a new value from a parcel. "in-place" read function is not necessary because
226 // user-defined parcelable defines its readFromParcel.
227 out << R"(static private <T> T readTypedObject(
228 android.os.Parcel parcel,
229 android.os.Parcelable.Creator<T> c) {
230 if (parcel.readInt() != 0) {
231 return c.createFromParcel(parcel);
232 } else {
233 return null;
234 }
235 }
236 static private <T extends android.os.Parcelable> void writeTypedObject(
237 android.os.Parcel parcel, T value, int parcelableFlags) {
238 if (value != null) {
239 parcel.writeInt(1);
240 value.writeToParcel(parcel, parcelableFlags);
241 } else {
242 parcel.writeInt(0);
243 }
244 }
245 )";
246 }
247
GenerateParcelHelpers(CodeWriter & out,const AidlDefinedType & defined_type,const Options & options)248 void GenerateParcelHelpers(CodeWriter& out, const AidlDefinedType& defined_type,
249 const Options& options) {
250 // root-level type contains all necessary helpers
251 if (defined_type.GetParentType()) {
252 return;
253 }
254 // visits method parameters and parcelable fields to collect types which
255 // requires read/write/create helpers.
256 struct Visitor : AidlVisitor {
257 const Options& options;
258 set<ParcelHelperGenerator> helpers;
259 Visitor(const Options& options) : options(options) {}
260 void Visit(const AidlTypeSpecifier& type) override {
261 auto name = type.GetName();
262 if (auto defined_type = type.GetDefinedType(); defined_type) {
263 if (defined_type->AsParcelable() != nullptr && !type.IsArray()) {
264 // TypedObjects are supported since 23. So we don't need helpers.
265 if (options.GetMinSdkVersion() < 23u) {
266 helpers.insert(&GenerateTypedObjectHelper);
267 }
268 }
269 } else {
270 // There's parcelable-like built-in types as well.
271 if (name == "ParcelFileDescriptor" || name == "CharSequence") {
272 if (!type.IsArray()) {
273 // TypedObjects are supported since 23. So we don't need helpers.
274 if (options.GetMinSdkVersion() < 23u) {
275 helpers.insert(&GenerateTypedObjectHelper);
276 }
277 }
278 }
279 }
280 }
281 } v{options};
282
283 VisitTopDown(v, defined_type);
284 if (!v.helpers.empty()) {
285 // Nested class (_Parcel) is used to contain static helper methods because some targets are
286 // still using Java 7 which doesn't allow interfaces to have static methods.
287 // Helpers shouldn't bother API checks, but in case where AIDL types are not marked `@hide`
288 // explicitly marks the helper class as @hide.
289 out << "/** @hide */\n";
290 out << "static class _Parcel {\n";
291 out.Indent();
292 for (const auto& helper : v.helpers) {
293 helper(out, options);
294 }
295 out.Dedent();
296 out << "}\n";
297 }
298 }
299
WriteToParcelFor(const CodeGeneratorContext & c)300 void WriteToParcelFor(const CodeGeneratorContext& c) {
301 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
302 {"boolean",
303 [](const CodeGeneratorContext& c) {
304 if (c.min_sdk_version >= 29u) {
305 c.writer << c.parcel << ".writeBoolean(" << c.var << ");\n";
306 } else {
307 c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
308 }
309 }},
310 {"boolean[]",
311 [](const CodeGeneratorContext& c) {
312 c.writer << c.parcel << ".writeBooleanArray(" << c.var << ");\n";
313 }},
314 {"byte",
315 [](const CodeGeneratorContext& c) {
316 c.writer << c.parcel << ".writeByte(" << c.var << ");\n";
317 }},
318 {"byte[]",
319 [](const CodeGeneratorContext& c) {
320 c.writer << c.parcel << ".writeByteArray(" << c.var << ");\n";
321 }},
322 {"char",
323 [](const CodeGeneratorContext& c) {
324 c.writer << c.parcel << ".writeInt(((int)" << c.var << "));\n";
325 }},
326 {"char[]",
327 [](const CodeGeneratorContext& c) {
328 c.writer << c.parcel << ".writeCharArray(" << c.var << ");\n";
329 }},
330 {"int",
331 [](const CodeGeneratorContext& c) {
332 c.writer << c.parcel << ".writeInt(" << c.var << ");\n";
333 }},
334 {"int[]",
335 [](const CodeGeneratorContext& c) {
336 c.writer << c.parcel << ".writeIntArray(" << c.var << ");\n";
337 }},
338 {"long",
339 [](const CodeGeneratorContext& c) {
340 c.writer << c.parcel << ".writeLong(" << c.var << ");\n";
341 }},
342 {"long[]",
343 [](const CodeGeneratorContext& c) {
344 c.writer << c.parcel << ".writeLongArray(" << c.var << ");\n";
345 }},
346 {"float",
347 [](const CodeGeneratorContext& c) {
348 c.writer << c.parcel << ".writeFloat(" << c.var << ");\n";
349 }},
350 {"float[]",
351 [](const CodeGeneratorContext& c) {
352 c.writer << c.parcel << ".writeFloatArray(" << c.var << ");\n";
353 }},
354 {"double",
355 [](const CodeGeneratorContext& c) {
356 c.writer << c.parcel << ".writeDouble(" << c.var << ");\n";
357 }},
358 {"double[]",
359 [](const CodeGeneratorContext& c) {
360 c.writer << c.parcel << ".writeDoubleArray(" << c.var << ");\n";
361 }},
362 {"String",
363 [](const CodeGeneratorContext& c) {
364 c.writer << c.parcel << ".writeString(" << c.var << ");\n";
365 }},
366 {"String[]",
367 [](const CodeGeneratorContext& c) {
368 c.writer << c.parcel << ".writeStringArray(" << c.var << ");\n";
369 }},
370 {"List",
371 [](const CodeGeneratorContext& c) {
372 if (c.type.IsGeneric()) {
373 AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
374 const auto& element_type = *c.type.GetTypeParameters().at(0);
375 const auto& element_type_name = element_type.GetName();
376 if (element_type_name == "String") {
377 c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
378 } else if (element_type_name == "IBinder") {
379 c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
380 } else if (c.typenames.IsParcelable(element_type_name)) {
381 c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
382 } else if (c.typenames.GetInterface(element_type)) {
383 c.writer << c.parcel << ".writeInterfaceList(" << c.var << ");\n";
384 } else {
385 AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << element_type_name;
386 }
387 } else {
388 c.writer << c.parcel << ".writeList(" << c.var << ");\n";
389 }
390 }},
391 {"Map",
392 [](const CodeGeneratorContext& c) {
393 if (c.type.IsGeneric()) {
394 c.writer << "if (" << c.var << " == null) {\n";
395 c.writer.Indent();
396 c.writer << c.parcel << ".writeInt(-1);\n";
397 c.writer.Dedent();
398 c.writer << "} else {\n";
399 c.writer.Indent();
400 c.writer << c.parcel << ".writeInt(" << c.var << ".size());\n";
401 c.writer << c.var << ".forEach((k, v) -> {\n";
402 c.writer.Indent();
403 c.writer << c.parcel << ".writeString(k);\n";
404
405 CodeGeneratorContext value_context{
406 c.writer,
407 c.typenames,
408 *c.type.GetTypeParameters()[1].get(),
409 c.parcel,
410 "v",
411 c.min_sdk_version,
412 c.write_to_parcel_flag,
413 c.is_classloader_created,
414 };
415 WriteToParcelFor(value_context);
416 c.writer.Dedent();
417 c.writer << "});\n";
418
419 c.writer.Dedent();
420 c.writer << "}\n";
421 } else {
422 c.writer << c.parcel << ".writeMap(" << c.var << ");\n";
423 }
424 }},
425 {"IBinder",
426 [](const CodeGeneratorContext& c) {
427 c.writer << c.parcel << ".writeStrongBinder(" << c.var << ");\n";
428 }},
429 {"IBinder[]",
430 [](const CodeGeneratorContext& c) {
431 c.writer << c.parcel << ".writeBinderArray(" << c.var << ");\n";
432 }},
433 {"FileDescriptor",
434 [](const CodeGeneratorContext& c) {
435 c.writer << c.parcel << ".writeRawFileDescriptor(" << c.var << ");\n";
436 }},
437 {"FileDescriptor[]",
438 [](const CodeGeneratorContext& c) {
439 c.writer << c.parcel << ".writeRawFileDescriptorArray(" << c.var << ");\n";
440 }},
441 {"ParcelFileDescriptor",
442 [](const CodeGeneratorContext& c) {
443 if (c.min_sdk_version >= 23u) {
444 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << c.write_to_parcel_flag
445 << ");\n";
446 } else {
447 c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
448 << c.write_to_parcel_flag << ");\n";
449 }
450 }},
451 {"ParcelFileDescriptor[]",
452 [](const CodeGeneratorContext& c) {
453 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << c.write_to_parcel_flag
454 << ");\n";
455 }},
456 {"CharSequence",
457 [](const CodeGeneratorContext& c) {
458 // TextUtils.writeToParcel does not accept null. So, we need to handle
459 // the case here.
460 c.writer << "if (" << c.var << "!=null) {\n";
461 c.writer.Indent();
462 c.writer << c.parcel << ".writeInt(1);\n";
463 c.writer << "android.text.TextUtils.writeToParcel(" << c.var << ", " << c.parcel << ", "
464 << c.write_to_parcel_flag << ");\n";
465 c.writer.Dedent();
466 c.writer << "}\n";
467 c.writer << "else {\n";
468 c.writer.Indent();
469 c.writer << c.parcel << ".writeInt(0);\n";
470 c.writer.Dedent();
471 c.writer << "}\n";
472 }},
473 {"ParcelableHolder",
474 [](const CodeGeneratorContext& c) {
475 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
476 }},
477 };
478 const string type_name = AidlBackingTypeName(c.type);
479 const auto found = method_map.find(type_name);
480 if (found != method_map.end()) {
481 found->second(c);
482 } else if (c.type.IsFixedSizeArray()) {
483 std::vector<std::string> args = {c.var, c.write_to_parcel_flag};
484 for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
485 args.push_back(std::to_string(dim));
486 }
487 c.writer << c.parcel << ".writeFixedArray(" << Join(args, ", ") << ");\n";
488 } else {
489 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
490 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
491 if (t->AsInterface() != nullptr) {
492 if (c.type.IsArray()) {
493 c.writer << c.parcel << ".writeInterfaceArray(" << c.var << ");\n";
494 } else {
495 c.writer << c.parcel << ".writeStrongInterface(" << c.var << ");\n";
496 }
497 } else if (t->AsParcelable() != nullptr) {
498 if (c.type.IsArray()) {
499 c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << c.write_to_parcel_flag
500 << ");\n";
501 } else {
502 if (c.min_sdk_version >= 23u) {
503 c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << c.write_to_parcel_flag
504 << ");\n";
505 } else {
506 c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
507 << c.write_to_parcel_flag << ");\n";
508 }
509 }
510 }
511 }
512 }
513
514 // Ensures that a variable is initialized to refer to the classloader
515 // of the current object and returns the name of the variable.
EnsureAndGetClassloader(CodeGeneratorContext & c)516 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
517 AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
518 if (!*(c.is_classloader_created)) {
519 c.writer << "java.lang.ClassLoader cl = "
520 << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
521 *(c.is_classloader_created) = true;
522 }
523 return "cl";
524 }
525
CreateFromParcelFor(const CodeGeneratorContext & c)526 bool CreateFromParcelFor(const CodeGeneratorContext& c) {
527 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
528 {"boolean",
529 [](const CodeGeneratorContext& c) {
530 if (c.min_sdk_version >= 29u) {
531 c.writer << c.var << " = " << c.parcel << ".readBoolean();\n";
532 } else {
533 c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
534 }
535 }},
536 {"boolean[]",
537 [](const CodeGeneratorContext& c) {
538 c.writer << c.var << " = " << c.parcel << ".createBooleanArray();\n";
539 }},
540 {"byte",
541 [](const CodeGeneratorContext& c) {
542 c.writer << c.var << " = " << c.parcel << ".readByte();\n";
543 }},
544 {"byte[]",
545 [](const CodeGeneratorContext& c) {
546 c.writer << c.var << " = " << c.parcel << ".createByteArray();\n";
547 }},
548 {"char",
549 [](const CodeGeneratorContext& c) {
550 c.writer << c.var << " = (char)" << c.parcel << ".readInt();\n";
551 }},
552 {"char[]",
553 [](const CodeGeneratorContext& c) {
554 c.writer << c.var << " = " << c.parcel << ".createCharArray();\n";
555 }},
556 {"int",
557 [](const CodeGeneratorContext& c) {
558 c.writer << c.var << " = " << c.parcel << ".readInt();\n";
559 }},
560 {"int[]",
561 [](const CodeGeneratorContext& c) {
562 c.writer << c.var << " = " << c.parcel << ".createIntArray();\n";
563 }},
564 {"long",
565 [](const CodeGeneratorContext& c) {
566 c.writer << c.var << " = " << c.parcel << ".readLong();\n";
567 }},
568 {"long[]",
569 [](const CodeGeneratorContext& c) {
570 c.writer << c.var << " = " << c.parcel << ".createLongArray();\n";
571 }},
572 {"float",
573 [](const CodeGeneratorContext& c) {
574 c.writer << c.var << " = " << c.parcel << ".readFloat();\n";
575 }},
576 {"float[]",
577 [](const CodeGeneratorContext& c) {
578 c.writer << c.var << " = " << c.parcel << ".createFloatArray();\n";
579 }},
580 {"double",
581 [](const CodeGeneratorContext& c) {
582 c.writer << c.var << " = " << c.parcel << ".readDouble();\n";
583 }},
584 {"double[]",
585 [](const CodeGeneratorContext& c) {
586 c.writer << c.var << " = " << c.parcel << ".createDoubleArray();\n";
587 }},
588 {"String",
589 [](const CodeGeneratorContext& c) {
590 c.writer << c.var << " = " << c.parcel << ".readString();\n";
591 }},
592 {"String[]",
593 [](const CodeGeneratorContext& c) {
594 c.writer << c.var << " = " << c.parcel << ".createStringArray();\n";
595 }},
596 {"List",
597 [](const CodeGeneratorContext& c) {
598 if (c.type.IsGeneric()) {
599 AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
600 const auto& element_type = *c.type.GetTypeParameters().at(0);
601 const auto& element_type_name = element_type.GetName();
602 if (element_type_name == "String") {
603 c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
604 } else if (element_type_name == "IBinder") {
605 c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
606 } else if (c.typenames.IsParcelable(element_type_name)) {
607 c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
608 << JavaNameOf(element_type) << ".CREATOR);\n";
609 } else if (c.typenames.GetInterface(element_type)) {
610 auto as_interface = element_type_name + ".Stub::asInterface";
611 c.writer << c.var << " = " << c.parcel << ".createInterfaceArrayList(" << as_interface
612 << ");\n";
613 } else {
614 AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << element_type_name;
615 }
616 } else {
617 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
618 c.writer << c.var << " = " << c.parcel << ".readArrayList(" << classloader << ");\n";
619 }
620 }},
621 {"Map",
622 [](const CodeGeneratorContext& c) {
623 if (c.type.IsGeneric()) {
624 c.writer << "{\n";
625 c.writer.Indent();
626 c.writer << "int N = " << c.parcel << ".readInt();\n";
627 c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
628
629 auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1))) + ".CREATOR";
630 c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
631 c.writer.Indent();
632 c.writer << "String k = " << c.parcel << ".readString();\n";
633 c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
634 CodeGeneratorContext value_context{
635 c.writer,
636 c.typenames,
637 *c.type.GetTypeParameters()[1].get(),
638 c.parcel,
639 "v",
640 c.min_sdk_version,
641 c.write_to_parcel_flag,
642 c.is_classloader_created,
643 };
644 CreateFromParcelFor(value_context);
645 c.writer << c.var << ".put(k, v);\n";
646
647 c.writer.Dedent();
648 c.writer << "});\n";
649
650 c.writer.Dedent();
651 c.writer << "}\n";
652 } else {
653 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
654 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
655 }
656 }},
657 {"IBinder",
658 [](const CodeGeneratorContext& c) {
659 c.writer << c.var << " = " << c.parcel << ".readStrongBinder();\n";
660 }},
661 {"IBinder[]",
662 [](const CodeGeneratorContext& c) {
663 c.writer << c.var << " = " << c.parcel << ".createBinderArray();\n";
664 }},
665 {"FileDescriptor",
666 [](const CodeGeneratorContext& c) {
667 c.writer << c.var << " = " << c.parcel << ".readRawFileDescriptor();\n";
668 }},
669 {"FileDescriptor[]",
670 [](const CodeGeneratorContext& c) {
671 c.writer << c.var << " = " << c.parcel << ".createRawFileDescriptorArray();\n";
672 }},
673 {"ParcelFileDescriptor",
674 [](const CodeGeneratorContext& c) {
675 if (c.min_sdk_version >= 23u) {
676 c.writer << c.var << " = " << c.parcel
677 << ".readTypedObject(android.os.ParcelFileDescriptor.CREATOR);\n";
678 } else {
679 c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
680 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
681 }
682 }},
683 {"ParcelFileDescriptor[]",
684 [](const CodeGeneratorContext& c) {
685 c.writer << c.var << " = " << c.parcel
686 << ".createTypedArray(android.os.ParcelFileDescriptor.CREATOR);\n";
687 }},
688 {"CharSequence",
689 [](const CodeGeneratorContext& c) {
690 if (c.min_sdk_version >= 23u) {
691 c.writer << c.var << " = " << c.parcel
692 << ".readTypedObject(android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
693 } else {
694 c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
695 << ", android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
696 }
697 }},
698 {"ParcelableHolder",
699 [](const CodeGeneratorContext& c) {
700 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
701 c.writer.Indent();
702 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
703 c.writer.Dedent();
704 c.writer << "}\n";
705 }},
706 };
707 const auto found = method_map.find(AidlBackingTypeName(c.type));
708 if (found != method_map.end()) {
709 found->second(c);
710 } else if (c.type.IsFixedSizeArray()) {
711 std::vector<std::string> args = {JavaSignatureOf(c.type) + ".class"};
712 if (c.typenames.IsParcelable(c.type.GetName())) {
713 args.push_back(JavaNameOf(c.type) + ".CREATOR");
714 } else if (c.typenames.GetInterface(c.type)) {
715 args.push_back(c.type.GetName() + ".Stub::asInterface");
716 }
717 for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
718 args.push_back(std::to_string(dim));
719 }
720 c.writer << c.var << " = " << c.parcel << ".createFixedArray(" << Join(args, ", ") << ");\n";
721 } else {
722 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
723 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
724 if (t->AsInterface() != nullptr) {
725 auto name = c.type.GetName();
726 if (c.type.IsArray()) {
727 auto new_array = name + "[]::new";
728 auto as_interface = name + ".Stub::asInterface";
729 c.writer << c.var << " = " << c.parcel << ".createInterfaceArray(" << new_array << ", "
730 << as_interface << ");\n";
731 } else {
732 c.writer << c.var << " = " << name << ".Stub.asInterface(" << c.parcel
733 << ".readStrongBinder());\n";
734 }
735 } else if (t->AsParcelable() != nullptr) {
736 if (c.type.IsArray()) {
737 c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
738 << ".CREATOR);\n";
739 } else {
740 if (c.min_sdk_version >= 23u) {
741 c.writer << c.var << " = " << c.parcel << ".readTypedObject(" << c.type.GetName()
742 << ".CREATOR);\n";
743 } else {
744 c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel << ", " << c.type.GetName()
745 << ".CREATOR);\n";
746 }
747 }
748 }
749 }
750 return true;
751 }
752
ReadFromParcelFor(const CodeGeneratorContext & c)753 bool ReadFromParcelFor(const CodeGeneratorContext& c) {
754 static map<string, function<void(const CodeGeneratorContext&)>> method_map{
755 {"boolean[]",
756 [](const CodeGeneratorContext& c) {
757 c.writer << c.parcel << ".readBooleanArray(" << c.var << ");\n";
758 }},
759 {"byte[]",
760 [](const CodeGeneratorContext& c) {
761 c.writer << c.parcel << ".readByteArray(" << c.var << ");\n";
762 }},
763 {"char[]",
764 [](const CodeGeneratorContext& c) {
765 c.writer << c.parcel << ".readCharArray(" << c.var << ");\n";
766 }},
767 {"int[]",
768 [](const CodeGeneratorContext& c) {
769 c.writer << c.parcel << ".readIntArray(" << c.var << ");\n";
770 }},
771 {"long[]",
772 [](const CodeGeneratorContext& c) {
773 c.writer << c.parcel << ".readLongArray(" << c.var << ");\n";
774 }},
775 {"float[]",
776 [](const CodeGeneratorContext& c) {
777 c.writer << c.parcel << ".readFloatArray(" << c.var << ");\n";
778 }},
779 {"double[]",
780 [](const CodeGeneratorContext& c) {
781 c.writer << c.parcel << ".readDoubleArray(" << c.var << ");\n";
782 }},
783 {"String[]",
784 [](const CodeGeneratorContext& c) {
785 c.writer << c.parcel << ".readStringArray(" << c.var << ");\n";
786 }},
787 {"List",
788 [](const CodeGeneratorContext& c) {
789 if (c.type.IsGeneric()) {
790 AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
791 const auto& element_type = *c.type.GetTypeParameters().at(0);
792 const auto& element_type_name = element_type.GetName();
793 if (element_type_name == "String") {
794 c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
795 } else if (element_type_name == "IBinder") {
796 c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
797 } else if (c.typenames.IsParcelable(element_type_name)) {
798 c.writer << c.parcel << ".readTypedList(" << c.var << ", "
799 << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
800 } else if (c.typenames.GetInterface(element_type)) {
801 auto as_interface = element_type_name + ".Stub::asInterface";
802 c.writer << c.parcel << ".readInterfaceList(" << c.var << ", " << as_interface
803 << ");\n";
804 } else {
805 AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << element_type_name;
806 }
807 } else {
808 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
809 c.writer << c.parcel << ".readList(" << c.var << ", " << classloader << ");\n";
810 }
811 }},
812 {"Map",
813 [](const CodeGeneratorContext& c) {
814 if (c.type.IsGeneric()) {
815 c.writer << "if (" << c.var << " != null) " << c.var << ".clear();\n";
816 c.writer << "java.util.stream.IntStream.range(0, " << c.parcel
817 << ".readInt()).forEach(i -> {\n";
818 c.writer.Indent();
819 c.writer << "String k = " << c.parcel << ".readString();\n";
820 c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
821 CodeGeneratorContext value_context{
822 c.writer,
823 c.typenames,
824 *c.type.GetTypeParameters()[1].get(),
825 c.parcel,
826 "v",
827 c.min_sdk_version,
828 c.write_to_parcel_flag,
829 c.is_classloader_created,
830 };
831 CreateFromParcelFor(value_context);
832 c.writer << c.var << ".put(k, v);\n";
833
834 c.writer.Dedent();
835 c.writer << "});\n";
836 } else {
837 const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
838 c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
839 }
840 }},
841 {"IBinder[]",
842 [](const CodeGeneratorContext& c) {
843 c.writer << c.parcel << ".readBinderArray(" << c.var << ");\n";
844 }},
845 {"FileDescriptor[]",
846 [](const CodeGeneratorContext& c) {
847 c.writer << c.parcel << ".readRawFileDescriptorArray(" << c.var << ");\n";
848 }},
849 {"ParcelFileDescriptor",
850 [](const CodeGeneratorContext& c) {
851 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
852 c.writer.Indent();
853 c.writer << c.var << " = "
854 << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
855 << ");\n";
856 c.writer.Dedent();
857 c.writer << "}\n";
858 }},
859 {"ParcelFileDescriptor[]",
860 [](const CodeGeneratorContext& c) {
861 c.writer << c.parcel << ".readTypedArray(" << c.var
862 << ", android.os.ParcelFileDescriptor.CREATOR);\n";
863 }},
864 };
865 const auto& found = method_map.find(AidlBackingTypeName(c.type));
866 if (found != method_map.end()) {
867 found->second(c);
868 } else if (c.type.IsFixedSizeArray()) {
869 std::vector<std::string> args = {c.var};
870 if (c.typenames.IsParcelable(c.type.GetName())) {
871 args.push_back(c.type.GetName() + ".CREATOR");
872 } else if (c.typenames.GetInterface(c.type)) {
873 args.push_back(c.type.GetName() + ".Stub::asInterface");
874 }
875 c.writer << c.parcel << ".readFixedArray(" << Join(args, ", ") << ");\n";
876 } else {
877 const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
878 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
879 if (t->AsParcelable() != nullptr || t->AsUnionDeclaration() != nullptr) {
880 if (c.type.IsArray()) {
881 c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
882 << ".CREATOR);\n";
883 } else {
884 c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
885 c.writer.Indent();
886 c.writer << c.var << ".readFromParcel(" << c.parcel << ");\n";
887 c.writer.Dedent();
888 c.writer << "}\n";
889 }
890 } else if (t->AsInterface()) {
891 AIDL_FATAL_IF(!c.type.IsArray(), c.type) << "readFromParcel(interface) doesn't make sense.";
892 auto as_interface = c.type.GetName() + ".Stub::asInterface";
893 c.writer << c.parcel << ".readInterfaceArray(" << c.var << ", " << as_interface << ");\n";
894 }
895 }
896 return true;
897 }
898
ToStringFor(const CodeGeneratorContext & c)899 void ToStringFor(const CodeGeneratorContext& c) {
900 // Use derived toString() for enum type annotated with @JavaDerive(toString=true)
901 if (auto t = c.type.GetDefinedType();
902 t != nullptr && t->AsEnumDeclaration() && t->JavaDerive("toString")) {
903 if (c.type.IsArray()) {
904 c.writer << c.type.GetName() << ".$.arrayToString(" << c.var << ")";
905 } else {
906 c.writer << c.type.GetName() << ".$.toString(" << c.var << ")";
907 }
908 return;
909 }
910
911 if (c.type.IsArray()) {
912 if (c.type.IsDynamicArray() || c.type.GetFixedSizeArrayDimensions().size() == 1) {
913 c.writer << "java.util.Arrays.toString(" << c.var << ")";
914 } else {
915 c.writer << "java.util.Arrays.deepToString(" << c.var << ")";
916 }
917 return;
918 }
919
920 const std::string name = c.type.GetName();
921
922 if (AidlTypenames::IsPrimitiveTypename(name)) {
923 c.writer << c.var;
924 return;
925 }
926
927 const AidlDefinedType* t = c.typenames.TryGetDefinedType(name);
928 if (t != nullptr && t->AsEnumDeclaration()) {
929 c.writer << c.var;
930 return;
931 }
932
933 // FileDescriptor doesn't have a good toString() impl.
934 if (name == "FileDescriptor") {
935 c.writer << c.var << " == null ? \"null\" : ";
936 c.writer << c.var << ".getInt$()";
937 return;
938 }
939
940 // Rest of the built-in types have reasonable toString() impls.
941 if (AidlTypenames::IsBuiltinTypename(name)) {
942 c.writer << "java.util.Objects.toString(" << c.var << ")";
943 return;
944 }
945
946 // For user-defined types, we also use toString() that we are generating here, but just make sure
947 // that they are actually user-defined types.
948 AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type";
949 if (t->AsInterface() != nullptr || t->AsParcelable() != nullptr) {
950 c.writer << "java.util.Objects.toString(" << c.var << ")";
951 return;
952 }
953
954 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unhandled typename: " << name;
955 }
956
957 } // namespace java
958 } // namespace aidl
959 } // namespace android
960