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 "generate_ndk.h"
18
19 #include "aidl.h"
20 #include "aidl_language.h"
21 #include "aidl_to_cpp_common.h"
22 #include "aidl_to_ndk.h"
23 #include "logging.h"
24
25 #include <android-base/stringprintf.h>
26
27 namespace android {
28 namespace aidl {
29 namespace ndk {
30
31 static constexpr const char* kClazz = "_g_aidl_clazz";
32 static constexpr const char* kDescriptor = "descriptor";
33 static constexpr const char* kVersion = "version";
34 static constexpr const char* kHash = "hash";
35 static constexpr const char* kCachedVersion = "_aidl_cached_version";
36 static constexpr const char* kCachedHash = "_aidl_cached_hash";
37 static constexpr const char* kCachedHashMutex = "_aidl_cached_hash_mutex";
38
39 using namespace internals;
40 namespace internals {
41 void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
42 const AidlStructuredParcelable& defined_type, const Options& options);
43 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
44 const AidlStructuredParcelable& defined_type, const Options& options);
45 void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
46 const AidlUnionDecl& defined_type, const Options& options);
47 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
48 const AidlUnionDecl& defined_type, const Options& options);
49 } // namespace internals
50
51 using cpp::ClassNames;
52
GenerateNdkInterface(const string & output_file,const Options & options,const AidlTypenames & types,const AidlInterface & defined_type,const IoDelegate & io_delegate)53 void GenerateNdkInterface(const string& output_file, const Options& options,
54 const AidlTypenames& types, const AidlInterface& defined_type,
55 const IoDelegate& io_delegate) {
56 const string i_header = options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
57 unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
58 GenerateInterfaceHeader(*i_writer, types, defined_type, options);
59 AIDL_FATAL_IF(!i_writer->Close(), i_header);
60
61 const string bp_header =
62 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
63 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
64 GenerateClientHeader(*bp_writer, types, defined_type, options);
65 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
66
67 const string bn_header =
68 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
69 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
70 GenerateServerHeader(*bn_writer, types, defined_type, options);
71 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
72
73 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
74 GenerateSource(*source_writer, types, defined_type, options);
75 AIDL_FATAL_IF(!source_writer->Close(), output_file);
76 }
77
78 template <typename ParcelableType>
GenerateNdkParcel(const string & output_file,const Options & options,const AidlTypenames & types,const ParcelableType & defined_type,const IoDelegate & io_delegate)79 void GenerateNdkParcel(const string& output_file, const Options& options,
80 const AidlTypenames& types, const ParcelableType& defined_type,
81 const IoDelegate& io_delegate) {
82 const string header_path =
83 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
84 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
85 GenerateParcelHeader(*header_writer, types, defined_type, options);
86
87 unique_ptr<CodeWriter> source_writer(io_delegate.GetCodeWriter(output_file));
88 if (defined_type.IsGeneric()) {
89 // Need to write source to header if this is a template
90 GenerateParcelSource(*header_writer, types, defined_type, options);
91 } else {
92 GenerateParcelSource(*source_writer, types, defined_type, options);
93 }
94 (source_writer->Close());
95 AIDL_FATAL_IF(!header_writer->Close(), header_path);
96
97 const string bp_header =
98 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
99 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
100 *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
101 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
102
103 const string bn_header =
104 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
105 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
106 *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
107 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
108 }
109
GenerateNdkParcelDeclaration(const std::string & filename,const IoDelegate & io_delegate)110 void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
111 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
112 *code_writer
113 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
114 AIDL_FATAL_IF(!code_writer->Close(), filename);
115 }
116
GenerateNdkEnumDeclaration(const string & output_file,const Options & options,const AidlTypenames & types,const AidlEnumDeclaration & defined_type,const IoDelegate & io_delegate)117 void GenerateNdkEnumDeclaration(const string& output_file, const Options& options,
118 const AidlTypenames& types, const AidlEnumDeclaration& defined_type,
119 const IoDelegate& io_delegate) {
120 const string header_path =
121 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
122 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
123 GenerateEnumHeader(*header_writer, types, defined_type, options);
124 AIDL_FATAL_IF(!header_writer->Close(), header_path);
125
126 const string bp_header =
127 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
128 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
129 *bp_writer << "#error TODO(b/111362593) enums do not have bp classes\n";
130 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
131
132 const string bn_header =
133 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
134 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
135 *bn_writer << "#error TODO(b/111362593) enums do not have bn classes\n";
136 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
137
138 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
139 *source_writer
140 << "// This file is intentionally left blank as placeholder for enum declaration.\n";
141 AIDL_FATAL_IF(!source_writer->Close(), output_file);
142 }
143
GenerateNdk(const string & output_file,const Options & options,const AidlTypenames & types,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)144 void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
145 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
146 if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
147 parcelable != nullptr) {
148 GenerateNdkParcel<AidlStructuredParcelable>(output_file, options, types, *parcelable,
149 io_delegate);
150 return;
151 }
152
153 if (const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration(); union_decl != nullptr) {
154 GenerateNdkParcel<AidlUnionDecl>(output_file, options, types, *union_decl, io_delegate);
155 return;
156 }
157
158 if (const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
159 parcelable_decl != nullptr) {
160 GenerateNdkParcelDeclaration(output_file, io_delegate);
161 return;
162 }
163
164 if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
165 enum_decl != nullptr) {
166 GenerateNdkEnumDeclaration(output_file, options, types, *enum_decl, io_delegate);
167 return;
168 }
169
170 if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
171 GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
172 return;
173 }
174
175 AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK cpp generation.";
176 }
177 namespace internals {
178
EnterNdkNamespace(CodeWriter & out,const AidlDefinedType & defined_type)179 void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
180 out << "namespace aidl {\n";
181 cpp::EnterNamespace(out, defined_type);
182 }
LeaveNdkNamespace(CodeWriter & out,const AidlDefinedType & defined_type)183 void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
184 cpp::LeaveNamespace(out, defined_type);
185 out << "} // namespace aidl\n";
186 }
187
StatusCheckGoto(CodeWriter & out)188 static void StatusCheckGoto(CodeWriter& out) {
189 out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
190 }
StatusCheckBreak(CodeWriter & out)191 static void StatusCheckBreak(CodeWriter& out) {
192 out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
193 }
StatusCheckReturn(CodeWriter & out)194 static void StatusCheckReturn(CodeWriter& out) {
195 out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
196 }
197
GenerateHeaderIncludes(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type)198 static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
199 const AidlDefinedType& defined_type) {
200 out << "#include <cstdint>\n";
201 out << "#include <memory>\n";
202 out << "#include <optional>\n";
203 out << "#include <string>\n";
204 out << "#include <vector>\n";
205 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
206 out << "#include <android/binder_stability.h>\n";
207 out << "#endif // BINDER_STABILITY_SUPPORT\n";
208
209 if (defined_type.IsSensitiveData()) {
210 out << "#include <android/binder_parcel_platform.h>\n";
211 out << "#include <android/binder_ibinder_platform.h>\n";
212 }
213
214 auto headerFilePath = [&types](const AidlTypeSpecifier& typespec) -> std::string {
215 const AidlDefinedType* type = types.TryGetDefinedType(typespec.GetName());
216 if (type == nullptr) {
217 // could be a primitive type.
218 return "";
219 }
220
221 if (type->AsInterface() != nullptr) {
222 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
223 } else if (type->AsStructuredParcelable() != nullptr) {
224 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
225 } else if (type->AsUnionDeclaration() != nullptr) {
226 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
227 } else if (type->AsParcelable() != nullptr) {
228 return type->AsParcelable()->GetCppHeader();
229 } else if (type->AsEnumDeclaration() != nullptr) {
230 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
231 } else {
232 AIDL_FATAL(*type) << "Unrecognized type.";
233 return "";
234 }
235 };
236
237 std::set<std::string> includes;
238
239 // visit a type and collect all reference types' headers
240 std::function<void(const AidlTypeSpecifier& type)> visit = [&](const AidlTypeSpecifier& type) {
241 includes.insert(headerFilePath(type));
242 if (type.IsGeneric()) {
243 for (const auto& param : type.GetTypeParameters()) {
244 visit(*param);
245 }
246 }
247 };
248
249 const AidlInterface* interface = defined_type.AsInterface();
250 if (interface != nullptr) {
251 for (const auto& method : interface->GetMethods()) {
252 visit(method->GetType());
253 for (const auto& argument : method->GetArguments()) {
254 visit(argument->GetType());
255 }
256 }
257 }
258
259 auto visit_parcelable = [&](const auto& parcelable) {
260 for (const auto& field : parcelable.GetFields()) {
261 visit(field->GetType());
262 // Check the fields for generic type arguments
263 if (field->GetType().IsGeneric()) {
264 for (const auto& type_argument : field->GetType().GetTypeParameters()) {
265 visit(*type_argument);
266 }
267 }
268 }
269 };
270
271 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
272 if (parcelable != nullptr) {
273 visit_parcelable(*parcelable);
274 }
275
276 const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
277 if (union_decl != nullptr) {
278 visit_parcelable(*union_decl);
279 }
280
281 const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
282 if (enum_decl != nullptr) {
283 visit(enum_decl->GetBackingType());
284 }
285
286 for (const auto& path : includes) {
287 if (path == "") {
288 continue;
289 }
290 out << "#include <" << path << ">\n";
291 }
292 }
293
GenerateSourceIncludes(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType &)294 static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
295 const AidlDefinedType& /*defined_type*/) {
296 out << "#include <android/binder_parcel_utils.h>\n";
297
298 types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
299 if (a_defined_type.AsInterface() != nullptr) {
300 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
301 << ">\n";
302 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
303 << ">\n";
304 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/)
305 << ">\n";
306 }
307 });
308 }
309
310 template <typename TypeWithConstants>
GenerateConstantDeclarations(CodeWriter & out,const AidlTypenames & types,const TypeWithConstants & type)311 static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types,
312 const TypeWithConstants& type) {
313 for (const auto& constant : type.GetConstantDeclarations()) {
314 const AidlTypeSpecifier& type = constant->GetType();
315
316 if (type.Signature() == "String") {
317 out << "static const char*";
318 cpp::GenerateDeprecated(out, *constant);
319 out << " " << constant->GetName() << ";\n";
320 } else {
321 out << "enum : " << NdkNameOf(types, type, StorageMode::STACK) << " { ";
322 out << constant->GetName();
323 cpp::GenerateDeprecated(out, *constant);
324 out << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
325 }
326 }
327 }
328
329 template <typename TypeWithConstants>
GenerateConstantDefinitions(CodeWriter & out,const TypeWithConstants & interface,const std::string & clazz,const std::string & tmpl_decl="")330 static void GenerateConstantDefinitions(CodeWriter& out, const TypeWithConstants& interface,
331 const std::string& clazz,
332 const std::string& tmpl_decl = "") {
333 for (const auto& constant : interface.GetConstantDeclarations()) {
334 const AidlConstantValue& value = constant->GetValue();
335 AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
336 value.GetType() == AidlConstantValue::Type::BINARY,
337 value);
338 if (value.GetType() == AidlConstantValue::Type::STRING) {
339 out << tmpl_decl;
340 out << "const char* " << clazz << "::" << constant->GetName() << " = "
341 << constant->ValueString(ConstantValueDecorator) << ";\n";
342 }
343 }
344 }
345
GenerateSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)346 void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
347 const Options& options) {
348 GenerateSourceIncludes(out, types, defined_type);
349 if (options.GenLog()) {
350 out << "#include <android/binder_to_string.h>\n";
351 }
352 out << "\n";
353
354 EnterNdkNamespace(out, defined_type);
355 GenerateClassSource(out, types, defined_type, options);
356 GenerateClientSource(out, types, defined_type, options);
357 GenerateServerSource(out, types, defined_type, options);
358 GenerateInterfaceSource(out, types, defined_type, options);
359 LeaveNdkNamespace(out, defined_type);
360 }
361
MethodId(const AidlMethod & m)362 static std::string MethodId(const AidlMethod& m) {
363 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
364 }
365
GenerateClientMethodDefinition(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const AidlMethod & method,const Options & options)366 static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
367 const AidlInterface& defined_type,
368 const AidlMethod& method,
369 const Options& options) {
370 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
371
372 out << NdkMethodDecl(types, method, clazz) << " {\n";
373 out.Indent();
374 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
375 out << "::ndk::ScopedAStatus _aidl_status;\n";
376
377 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
378 out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
379 out << "if (" << kCachedHash << " != \"-1\") {\n";
380 out.Indent();
381 out << "*_aidl_return = " << kCachedHash << ";\n"
382 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
383 << "return _aidl_status;\n";
384 out.Dedent();
385 out << "}\n";
386 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
387 out << "if (" << kCachedVersion << " != -1) {\n";
388 out.Indent();
389 out << "*_aidl_return = " << kCachedVersion << ";\n"
390 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
391 << "return _aidl_status;\n";
392 out.Dedent();
393 out << "}\n";
394 }
395 out << "::ndk::ScopedAParcel _aidl_in;\n";
396 out << "::ndk::ScopedAParcel _aidl_out;\n";
397 out << "\n";
398
399 if (options.GenLog()) {
400 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
401 false /* isServer */, true /* isNdk */);
402 }
403 if (options.GenTraces()) {
404 out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
405 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
406 << "::client\");\n";
407 }
408
409 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
410 if (defined_type.IsSensitiveData()) {
411 out << "AParcel_markSensitive(_aidl_in.get());\n";
412 }
413 StatusCheckGoto(out);
414
415 for (const auto& arg : method.GetArguments()) {
416 const std::string var_name = cpp::BuildVarName(*arg);
417
418 if (arg->IsIn()) {
419 out << "_aidl_ret_status = ";
420 const std::string prefix = (arg->IsOut() ? "*" : "");
421 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
422 out << ";\n";
423 StatusCheckGoto(out);
424 } else if (arg->IsOut() && arg->GetType().IsArray()) {
425 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
426 << ");\n";
427 StatusCheckGoto(out);
428 }
429 }
430 out << "_aidl_ret_status = AIBinder_transact(\n";
431 out.Indent();
432 out << "asBinder().get(),\n";
433 out << MethodId(method) << ",\n";
434 out << "_aidl_in.getR(),\n";
435 out << "_aidl_out.getR(),\n";
436
437 std::vector<std::string> flags;
438 if (method.IsOneway()) flags.push_back("FLAG_ONEWAY");
439 if (defined_type.IsSensitiveData()) flags.push_back("FLAG_CLEAR_BUF");
440 out << (flags.empty() ? "0" : base::Join(flags, " | ")) << "\n";
441
442 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
443 out << "| FLAG_PRIVATE_LOCAL\n";
444 out << "#endif // BINDER_STABILITY_SUPPORT\n";
445 out << ");\n";
446 out.Dedent();
447
448 // If the method is not implmented in the server side but the client has
449 // provided the default implementation, call it instead of failing hard.
450 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
451 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
452 out << iface << "::getDefaultImpl()) {\n";
453 out.Indent();
454 out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
455 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
456 out << "goto _aidl_status_return;\n";
457 out.Dedent();
458 out << "}\n";
459
460 StatusCheckGoto(out);
461
462 if (!method.IsOneway()) {
463 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
464 StatusCheckGoto(out);
465
466 out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
467 }
468
469 if (method.GetType().GetName() != "void") {
470 out << "_aidl_ret_status = ";
471 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
472 out << ";\n";
473 StatusCheckGoto(out);
474 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
475 out << kCachedHash << " = *_aidl_return;\n";
476 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
477 out << kCachedVersion << " = *_aidl_return;\n";
478 }
479 }
480 for (const AidlArgument* arg : method.GetOutArguments()) {
481 out << "_aidl_ret_status = ";
482 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
483 out << ";\n";
484 StatusCheckGoto(out);
485 }
486
487 out << "_aidl_error:\n";
488 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
489 out << "_aidl_status_return:\n";
490 if (options.GenLog()) {
491 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
492 method, "_aidl_status", "_aidl_return", false /* isServer */,
493 true /* isNdk */);
494 }
495
496 out << "return _aidl_status;\n";
497 out.Dedent();
498 out << "}\n";
499 }
500
GenerateServerCaseDefinition(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const AidlMethod & method,const Options & options)501 static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
502 const AidlInterface& defined_type,
503 const AidlMethod& method, const Options& options) {
504 out << "case " << MethodId(method) << ": {\n";
505 out.Indent();
506 for (const auto& arg : method.GetArguments()) {
507 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
508 << ";\n";
509 }
510 if (method.GetType().GetName() != "void") {
511 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
512 }
513 out << "\n";
514 if (options.GenTraces()) {
515 out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
516 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
517 << "::server\");\n";
518 }
519
520 for (const auto& arg : method.GetArguments()) {
521 const std::string var_name = cpp::BuildVarName(*arg);
522
523 if (arg->IsIn()) {
524 out << "_aidl_ret_status = ";
525 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
526 out << ";\n";
527 StatusCheckBreak(out);
528 } else if (arg->IsOut() && arg->GetType().IsArray()) {
529 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
530 StatusCheckBreak(out);
531 }
532 }
533 if (options.GenLog()) {
534 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
535 true /* isServer */, true /* isNdk */);
536 }
537 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
538 << NdkArgList(types, method, FormatArgForCall) << ");\n";
539
540 if (options.GenLog()) {
541 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
542 method, "_aidl_status", "_aidl_return", true /* isServer */,
543 true /* isNdk */);
544 }
545 if (method.IsOneway()) {
546 // For a oneway transaction, the kernel will have already returned a result. This is for the
547 // in-process case when a oneway transaction is parceled/unparceled in the same process.
548 out << "_aidl_ret_status = STATUS_OK;\n";
549 } else {
550 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
551 StatusCheckBreak(out);
552
553 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
554
555 if (method.GetType().GetName() != "void") {
556 out << "_aidl_ret_status = ";
557 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
558 out << ";\n";
559 StatusCheckBreak(out);
560 }
561 for (const AidlArgument* arg : method.GetOutArguments()) {
562 out << "_aidl_ret_status = ";
563 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
564 out << ";\n";
565 StatusCheckBreak(out);
566 }
567 }
568 out << "break;\n";
569 out.Dedent();
570 out << "}\n";
571 }
572
GenerateClassSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)573 void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
574 const AidlInterface& defined_type, const Options& options) {
575 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
576 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
577 if (options.GenTraces()) {
578 out << "class ScopedTrace {\n";
579 out.Indent();
580 out << "public:\n"
581 << "inline explicit ScopedTrace(const char* name) {\n"
582 << "ATrace_beginSection(name);\n"
583 << "}\n"
584 << "inline ~ScopedTrace() {\n"
585 << "ATrace_endSection();\n"
586 << "}\n";
587 out.Dedent();
588 out << "};\n";
589 }
590 bool deprecated = defined_type.IsDeprecated() ||
591 std::any_of(defined_type.GetMethods().begin(), defined_type.GetMethods().end(),
592 [](const auto& m) { return m->IsDeprecated(); });
593 if (deprecated) {
594 out << "#pragma clang diagnostic push\n";
595 out << "#pragma clang diagnostic ignored \"-Wdeprecated\"\n";
596 }
597 out << "static binder_status_t "
598 << "_aidl_onTransact"
599 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
600 "AParcel* _aidl_out) {\n";
601 out.Indent();
602 out << "(void)_aidl_in;\n";
603 out << "(void)_aidl_out;\n";
604 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
605 if (!defined_type.GetMethods().empty()) {
606 // we know this cast is valid because this method is only called by the ICInterface
607 // AIBinder_Class object which is associated with this class.
608 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = std::static_pointer_cast<" << bn_clazz
609 << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
610 out << "switch (_aidl_code) {\n";
611 out.Indent();
612 for (const auto& method : defined_type.GetMethods()) {
613 GenerateServerCaseDefinition(out, types, defined_type, *method, options);
614 }
615 out.Dedent();
616 out << "}\n";
617 } else {
618 out << "(void)_aidl_binder;\n";
619 out << "(void)_aidl_code;\n";
620 }
621 out << "return _aidl_ret_status;\n";
622 out.Dedent();
623 out << "}\n\n";
624
625 out << "static AIBinder_Class* " << kClazz << " = ::ndk::ICInterface::defineClass(" << clazz
626 << "::" << kDescriptor << ", _aidl_onTransact);\n\n";
627 if (deprecated) {
628 out << "#pragma clang diagnostic pop\n";
629 }
630 }
631
GenerateClientSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)632 void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
633 const AidlInterface& defined_type, const Options& options) {
634 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
635
636 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
637 out << clazz << "::~" << clazz << "() {}\n";
638 if (options.GenLog()) {
639 out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
640 }
641 out << "\n";
642 for (const auto& method : defined_type.GetMethods()) {
643 GenerateClientMethodDefinition(out, types, defined_type, *method, options);
644 }
645 }
GenerateServerSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)646 void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
647 const AidlInterface& defined_type, const Options& options) {
648 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
649 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
650
651 out << "// Source for " << clazz << "\n";
652 out << clazz << "::" << clazz << "() {}\n";
653 out << clazz << "::~" << clazz << "() {}\n";
654 if (options.GenLog()) {
655 out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
656 }
657 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
658 out.Indent();
659 out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
660
661 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
662 if (defined_type.IsVintfStability()) {
663 out << "AIBinder_markVintfStability(binder);\n";
664 } else {
665 out << "AIBinder_markCompilationUnitStability(binder);\n";
666 }
667 out << "#endif // BINDER_STABILITY_SUPPORT\n";
668
669 out << "return ::ndk::SpAIBinder(binder);\n";
670 out.Dedent();
671 out << "}\n";
672
673 // Implement the meta methods
674 for (const auto& method : defined_type.GetMethods()) {
675 if (method->IsUserDefined()) {
676 continue;
677 }
678 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
679 out << NdkMethodDecl(types, *method, clazz) << " {\n";
680 out.Indent();
681 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
682 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
683 out.Dedent();
684 out << "}\n";
685 }
686 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
687 out << NdkMethodDecl(types, *method, clazz) << " {\n";
688 out.Indent();
689 out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
690 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
691 out.Dedent();
692 out << "}\n";
693 }
694 }
695 }
GenerateInterfaceSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)696 void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
697 const AidlInterface& defined_type, const Options& options) {
698 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
699 const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
700
701 out << "// Source for " << clazz << "\n";
702 out << "const char* " << clazz << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
703 << "\";\n";
704 out << clazz << "::" << clazz << "() {}\n";
705 out << clazz << "::~" << clazz << "() {}\n";
706 out << "\n";
707 GenerateConstantDefinitions(out, defined_type, clazz);
708 out << "\n";
709
710 out << "std::shared_ptr<" << clazz << "> " << clazz
711 << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
712 out.Indent();
713 out << "if (!AIBinder_associateClass(binder.get(), " << kClazz << ")) { return nullptr; }\n";
714 out << "std::shared_ptr<::ndk::ICInterface> interface = "
715 "::ndk::ICInterface::asInterface(binder.get());\n";
716 out << "if (interface) {\n";
717 out.Indent();
718 out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
719 out.Dedent();
720 out << "}\n";
721 out << "return ::ndk::SharedRefBase::make<" << bp_clazz << ">(binder);\n";
722 out.Dedent();
723 out << "}\n\n";
724
725 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
726 << clazz << ">& instance) {\n";
727 out.Indent();
728 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
729 "nullptr);\n";
730 out.Dedent();
731 out << "}\n";
732
733 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
734 << clazz << ">* instance) {\n";
735 out.Indent();
736 out << "::ndk::SpAIBinder binder;\n";
737 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
738 out << "if (status != STATUS_OK) return status;\n";
739 out << "*instance = " << clazz << "::fromBinder(binder);\n";
740 out << "return STATUS_OK;\n";
741 out.Dedent();
742 out << "}\n";
743
744 // defintion for static member setDefaultImpl
745 out << "bool " << clazz << "::setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl) {\n";
746 out.Indent();
747 out << "// Only one user of this interface can use this function\n";
748 out << "// at a time. This is a heuristic to detect if two different\n";
749 out << "// users in the same process use this function.\n";
750 out << "assert(!" << clazz << "::default_impl);\n";
751 out << "if (impl) {\n";
752 out.Indent();
753 out << clazz << "::default_impl = impl;\n";
754 out << "return true;\n";
755 out.Dedent();
756 out << "}\n";
757 out << "return false;\n";
758 out.Dedent();
759 out << "}\n";
760
761 // definition for static member getDefaultImpl
762 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
763 out.Indent();
764 out << "return " << clazz << "::default_impl;\n";
765 out.Dedent();
766 out << "}\n";
767
768 // definition for the static field default_impl
769 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
770
771 // default implementation for the <Name>Default class members
772 const std::string defaultClazz = clazz + "Default";
773 for (const auto& method : defined_type.GetMethods()) {
774 if (method->IsUserDefined()) {
775 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
776 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
777 out.Indent();
778 out << "::ndk::ScopedAStatus _aidl_status;\n";
779 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
780 out << "return _aidl_status;\n";
781 out.Dedent();
782 out << "}\n";
783 } else {
784 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
785 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
786 << "int32_t* _aidl_return) {\n";
787 out.Indent();
788 out << "*_aidl_return = 0;\n";
789 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
790 out.Dedent();
791 out << "}\n";
792 }
793 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
794 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
795 << "std::string* _aidl_return) {\n";
796 out.Indent();
797 out << "*_aidl_return = \"\";\n";
798 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
799 out.Dedent();
800 out << "}\n";
801 }
802 }
803 }
804
805 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
806 out.Indent();
807 out << "return ::ndk::SpAIBinder();\n";
808 out.Dedent();
809 out << "}\n";
810
811 out << "bool " << defaultClazz << "::isRemote() {\n";
812 out.Indent();
813 out << "return false;\n";
814 out.Dedent();
815 out << "}\n";
816 }
817
GenerateClientHeader(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)818 void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
819 const AidlInterface& defined_type, const Options& options) {
820 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
821
822 out << "#pragma once\n\n";
823 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
824 << "\"\n";
825 out << "\n";
826 out << "#include <android/binder_ibinder.h>\n";
827 if (options.GenLog()) {
828 out << "#include <functional>\n";
829 out << "#include <chrono>\n";
830 out << "#include <sstream>\n";
831 }
832 if (options.GenTraces()) {
833 out << "#include <android/trace.h>\n";
834 }
835 out << "\n";
836 EnterNdkNamespace(out, defined_type);
837 out << "class";
838 cpp::GenerateDeprecated(out, defined_type);
839 out << " " << clazz << " : public ::ndk::BpCInterface<"
840 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
841 out << "public:\n";
842 out.Indent();
843 out << "explicit " << clazz << "(const ::ndk::SpAIBinder& binder);\n";
844 out << "virtual ~" << clazz << "();\n";
845 out << "\n";
846 for (const auto& method : defined_type.GetMethods()) {
847 out << NdkMethodDecl(types, *method) << " override";
848 cpp::GenerateDeprecated(out, *method);
849 out << ";\n";
850 }
851
852 if (options.Version() > 0) {
853 out << "int32_t " << kCachedVersion << " = -1;\n";
854 }
855
856 if (!options.Hash().empty()) {
857 out << "std::string " << kCachedHash << " = \"-1\";\n";
858 out << "std::mutex " << kCachedHashMutex << ";\n";
859 }
860 if (options.GenLog()) {
861 out << cpp::kTransactionLogStruct;
862 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
863 }
864 out.Dedent();
865 out << "};\n";
866 LeaveNdkNamespace(out, defined_type);
867 }
GenerateServerHeader(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)868 void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
869 const AidlInterface& defined_type, const Options& options) {
870 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
871 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
872
873 out << "#pragma once\n\n";
874 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
875 << "\"\n";
876 out << "\n";
877 out << "#include <android/binder_ibinder.h>\n";
878 out << "\n";
879 EnterNdkNamespace(out, defined_type);
880 out << "class";
881 cpp::GenerateDeprecated(out, defined_type);
882 out << " " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
883 out << "public:\n";
884 out.Indent();
885 out << clazz << "();\n";
886 out << "virtual ~" << clazz << "();\n";
887
888 // Declare the meta methods
889 for (const auto& method : defined_type.GetMethods()) {
890 if (method->IsUserDefined()) {
891 continue;
892 }
893 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
894 out << NdkMethodDecl(types, *method) << " final;\n";
895 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
896 out << NdkMethodDecl(types, *method) << " final;\n";
897 } else {
898 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
899 }
900 }
901 if (options.GenLog()) {
902 out << cpp::kTransactionLogStruct;
903 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
904 }
905 out.Dedent();
906 out << "protected:\n";
907 out.Indent();
908 out << "::ndk::SpAIBinder createBinder() override;\n";
909 out.Dedent();
910 out << "private:\n";
911 out.Indent();
912 out.Dedent();
913 out << "};\n";
914 LeaveNdkNamespace(out, defined_type);
915 }
GenerateInterfaceHeader(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)916 void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
917 const AidlInterface& defined_type, const Options& options) {
918 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
919
920 out << "#pragma once\n\n";
921 out << "#include <android/binder_interface_utils.h>\n";
922 if (options.GenLog()) {
923 out << "#include <functional>\n";
924 out << "#include <chrono>\n";
925 out << "#include <sstream>\n";
926 }
927 out << "\n";
928
929 GenerateHeaderIncludes(out, types, defined_type);
930 out << "\n";
931
932 EnterNdkNamespace(out, defined_type);
933 out << "class";
934 cpp::GenerateDeprecated(out, defined_type);
935 out << " " << clazz << " : public ::ndk::ICInterface {\n";
936 out << "public:\n";
937 out.Indent();
938 out << "static const char* " << kDescriptor << ";\n";
939 out << clazz << "();\n";
940 out << "virtual ~" << clazz << "();\n";
941 out << "\n";
942 GenerateConstantDeclarations(out, types, defined_type);
943 if (options.Version() > 0) {
944 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
945 << ";\n";
946 }
947 if (!options.Hash().empty()) {
948 out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
949 }
950 for (const auto& method : defined_type.GetMethods()) {
951 if (!method->IsUserDefined()) {
952 continue;
953 }
954 out << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
955 << "FIRST_CALL_TRANSACTION + " << std::to_string(method->GetId()) << ";\n";
956 }
957 out << "\n";
958 out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
959 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
960 << ">& instance);";
961 out << "\n";
962 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
963 << ">* instance);";
964 out << "\n";
965 out << "static bool setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl);";
966 out << "\n";
967 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
968 out << "\n";
969 for (const auto& method : defined_type.GetMethods()) {
970 out << "virtual " << NdkMethodDecl(types, *method);
971 cpp::GenerateDeprecated(out, *method);
972 out << " = 0;\n";
973 }
974 out.Dedent();
975 out << "private:\n";
976 out.Indent();
977 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
978 out.Dedent();
979 out << "};\n";
980
981 const std::string defaultClazz = clazz + "Default";
982 out << "class";
983 cpp::GenerateDeprecated(out, defined_type);
984 out << " " << defaultClazz << " : public " << clazz << " {\n";
985 out << "public:\n";
986 out.Indent();
987 for (const auto& method : defined_type.GetMethods()) {
988 if (method->IsUserDefined()) {
989 out << NdkMethodDecl(types, *method) << " override";
990 cpp::GenerateDeprecated(out, *method);
991 out << ";\n";
992 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
993 out << NdkMethodDecl(types, *method) << " override;\n";
994 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
995 out << NdkMethodDecl(types, *method) << " override;\n";
996 }
997 }
998 out << "::ndk::SpAIBinder asBinder() override;\n";
999 out << "bool isRemote() override;\n";
1000 out.Dedent();
1001 out << "};\n";
1002
1003 LeaveNdkNamespace(out, defined_type);
1004 }
GenerateParcelHeader(CodeWriter & out,const AidlTypenames & types,const AidlStructuredParcelable & defined_type,const Options &)1005 void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
1006 const AidlStructuredParcelable& defined_type,
1007 const Options& /*options*/) {
1008 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
1009
1010 out << "#pragma once\n";
1011 out << "#include <android/binder_interface_utils.h>\n";
1012 out << "#include <android/binder_parcelable_utils.h>\n";
1013
1014 // used by toString()
1015 out << "#include <android/binder_to_string.h>\n";
1016
1017 GenerateHeaderIncludes(out, types, defined_type);
1018
1019 EnterNdkNamespace(out, defined_type);
1020 out << cpp::TemplateDecl(defined_type);
1021 out << "class";
1022 cpp::GenerateDeprecated(out, defined_type);
1023 out << " " << clazz << " {\n";
1024 out << "public:\n";
1025 out.Indent();
1026 if (defined_type.IsFixedSize()) {
1027 out << "typedef std::true_type fixed_size;\n";
1028 } else {
1029 out << "typedef std::false_type fixed_size;\n";
1030 }
1031 out << "static const char* descriptor;\n";
1032 out << "\n";
1033 for (const auto& variable : defined_type.GetFields()) {
1034 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK);
1035 cpp::GenerateDeprecated(out, *variable);
1036 out << " " << variable->GetName();
1037 if (variable->GetType().GetName() == "ParcelableHolder") {
1038 out << "{::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL")
1039 << "}";
1040 }
1041 if (defined_type.IsFixedSize()) {
1042 int alignment = NdkAlignmentOf(types, variable->GetType());
1043 if (alignment > 0) {
1044 out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
1045 }
1046 }
1047 if (variable->GetDefaultValue()) {
1048 out << " = " << variable->ValueString(ConstantValueDecorator);
1049 } else if (auto type = variable->GetType().GetDefinedType(); type) {
1050 if (auto enum_type = type->AsEnumDeclaration(); enum_type) {
1051 if (!variable->GetType().IsArray()) {
1052 // if an enum doesn't have explicit default value, do zero-initialization
1053 out << " = " << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << "(0)";
1054 }
1055 }
1056 }
1057 out << ";\n";
1058 }
1059 out << "\n";
1060 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
1061 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
1062 out << "\n";
1063
1064 cpp::GenerateParcelableComparisonOperators(out, defined_type);
1065
1066 out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1067 << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
1068
1069 GenerateConstantDeclarations(out, types, defined_type);
1070 cpp::GenerateToString(out, defined_type);
1071
1072 out.Dedent();
1073 out << "};\n";
1074 LeaveNdkNamespace(out, defined_type);
1075 }
GenerateParcelSource(CodeWriter & out,const AidlTypenames & types,const AidlStructuredParcelable & defined_type,const Options &)1076 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
1077 const AidlStructuredParcelable& defined_type,
1078 const Options& /*options*/) {
1079 std::string clazz = ClassName(defined_type, ClassNames::RAW);
1080 if (defined_type.IsGeneric()) {
1081 std::vector<std::string> template_params;
1082 for (const auto& parameter : defined_type.GetTypeParameters()) {
1083 template_params.push_back(parameter);
1084 }
1085 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1086 }
1087
1088 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
1089 << "\"\n";
1090 out << "\n";
1091 GenerateSourceIncludes(out, types, defined_type);
1092 out << "\n";
1093 EnterNdkNamespace(out, defined_type);
1094 out << cpp::TemplateDecl(defined_type);
1095 out << "const char* " << clazz << "::" << kDescriptor << " = \""
1096 << defined_type.GetCanonicalName() << "\";\n";
1097 out << "\n";
1098
1099 GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
1100
1101 out << cpp::TemplateDecl(defined_type);
1102 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
1103 out.Indent();
1104 out << "int32_t _aidl_parcelable_size;\n";
1105 out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1106 out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
1107 out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
1108 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
1109 StatusCheckReturn(out);
1110
1111 for (const auto& variable : defined_type.GetFields()) {
1112 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1113 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1114 << " return _aidl_ret_status;\n"
1115 << "}\n";
1116 out << "_aidl_ret_status = ";
1117 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
1118 out << ";\n";
1119 StatusCheckReturn(out);
1120 }
1121 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1122 << "return _aidl_ret_status;\n";
1123 out.Dedent();
1124 out << "}\n";
1125
1126 out << cpp::TemplateDecl(defined_type);
1127 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
1128 out.Indent();
1129 out << "binder_status_t _aidl_ret_status;\n";
1130
1131 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1132 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
1133 StatusCheckReturn(out);
1134
1135 for (const auto& variable : defined_type.GetFields()) {
1136 out << "_aidl_ret_status = ";
1137 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
1138 out << ";\n";
1139 StatusCheckReturn(out);
1140 }
1141 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
1142 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
1143 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
1144 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
1145
1146 out << "return _aidl_ret_status;\n";
1147 out.Dedent();
1148 out << "}\n";
1149 out << "\n";
1150 LeaveNdkNamespace(out, defined_type);
1151 }
1152
GenerateParcelHeader(CodeWriter & out,const AidlTypenames & types,const AidlUnionDecl & defined_type,const Options &)1153 void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
1154 const AidlUnionDecl& defined_type, const Options& /*options*/) {
1155 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
1156 cpp::UnionWriter uw{defined_type, types,
1157 [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1158 return NdkNameOf(types, type, StorageMode::STACK);
1159 },
1160 &ConstantValueDecorator};
1161
1162 out << "#pragma once\n";
1163 out << "#include <android/binder_interface_utils.h>\n";
1164 out << "#include <android/binder_parcelable_utils.h>\n";
1165
1166 // used by toString()
1167 out << "#include <android/binder_to_string.h>\n";
1168
1169 out << "\n";
1170
1171 for (const auto& header : cpp::UnionWriter::headers) {
1172 out << "#include <" << header << ">\n";
1173 }
1174 GenerateHeaderIncludes(out, types, defined_type);
1175
1176 // TODO(b/31559095) bionic on host should define this
1177 out << "\n";
1178 out << "#ifndef __BIONIC__\n";
1179 out << "#define __assert2(a,b,c,d) ((void)0)\n";
1180 out << "#endif\n";
1181 out << "\n";
1182
1183 EnterNdkNamespace(out, defined_type);
1184 out << cpp::TemplateDecl(defined_type);
1185 out << "class";
1186 cpp::GenerateDeprecated(out, defined_type);
1187 out << " " << clazz << " {\n";
1188 out << "public:\n";
1189 out.Indent();
1190 if (defined_type.IsFixedSize()) {
1191 out << "typedef std::true_type fixed_size;\n";
1192 } else {
1193 out << "typedef std::false_type fixed_size;\n";
1194 }
1195 out << "static const char* descriptor;\n";
1196 out << "\n";
1197 uw.PublicFields(out);
1198
1199 out << "binder_status_t readFromParcel(const AParcel* _parcel);\n";
1200 out << "binder_status_t writeToParcel(AParcel* _parcel) const;\n";
1201 out << "\n";
1202
1203 cpp::GenerateParcelableComparisonOperators(out, defined_type);
1204
1205 out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1206 << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
1207 GenerateConstantDeclarations(out, types, defined_type);
1208 cpp::GenerateToString(out, defined_type);
1209 out.Dedent();
1210 out << "private:\n";
1211 out.Indent();
1212 uw.PrivateFields(out);
1213 out.Dedent();
1214 out << "};\n";
1215 LeaveNdkNamespace(out, defined_type);
1216 }
GenerateParcelSource(CodeWriter & out,const AidlTypenames & types,const AidlUnionDecl & defined_type,const Options &)1217 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
1218 const AidlUnionDecl& defined_type, const Options& /*options*/) {
1219 std::string clazz = ClassName(defined_type, ClassNames::RAW);
1220 if (defined_type.IsGeneric()) {
1221 std::vector<std::string> template_params;
1222 for (const auto& parameter : defined_type.GetTypeParameters()) {
1223 template_params.push_back(parameter);
1224 }
1225 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1226 }
1227
1228 cpp::UnionWriter uw{defined_type, types,
1229 [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1230 return NdkNameOf(types, type, StorageMode::STACK);
1231 },
1232 &ConstantValueDecorator};
1233 cpp::ParcelWriterContext ctx{
1234 .status_type = "binder_status_t",
1235 .status_ok = "STATUS_OK",
1236 .status_bad = "STATUS_BAD_VALUE",
1237 .read_func =
1238 [&](CodeWriter& out, const std::string& var, const AidlTypeSpecifier& type) {
1239 ReadFromParcelFor({out, types, type, "_parcel", "&" + var});
1240 },
1241 .write_func =
1242 [&](CodeWriter& out, const std::string& value, const AidlTypeSpecifier& type) {
1243 WriteToParcelFor({out, types, type, "_parcel", value});
1244 },
1245 };
1246
1247 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
1248 << "\"\n";
1249 out << "\n";
1250 GenerateSourceIncludes(out, types, defined_type);
1251 out << "\n";
1252 EnterNdkNamespace(out, defined_type);
1253 out << cpp::TemplateDecl(defined_type);
1254 out << "const char* " << clazz << "::" << kDescriptor << " = \""
1255 << defined_type.GetCanonicalName() << "\";\n";
1256 out << "\n";
1257
1258 GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
1259
1260 out << cpp::TemplateDecl(defined_type);
1261 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _parcel) {\n";
1262 out.Indent();
1263 uw.ReadFromParcel(out, ctx);
1264 out.Dedent();
1265 out << "}\n";
1266
1267 out << cpp::TemplateDecl(defined_type);
1268 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* _parcel) const {\n";
1269 out.Indent();
1270 uw.WriteToParcel(out, ctx);
1271 out.Dedent();
1272 out << "}\n";
1273 out << "\n";
1274 LeaveNdkNamespace(out, defined_type);
1275 }
1276
GenerateEnumToString(const AidlTypenames & typenames,const AidlEnumDeclaration & enum_decl)1277 std::string GenerateEnumToString(const AidlTypenames& typenames,
1278 const AidlEnumDeclaration& enum_decl) {
1279 std::ostringstream code;
1280 const std::string signature =
1281 "[[nodiscard]] static inline std::string toString(" + enum_decl.GetName() + " val)";
1282 if (enum_decl.IsDeprecated()) {
1283 code << signature;
1284 cpp::GenerateDeprecated(code, enum_decl);
1285 code << ";\n";
1286 }
1287 code << signature << " {\n";
1288 code << " switch(val) {\n";
1289 std::set<std::string> unique_cases;
1290 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1291 std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
1292 // Only add a case if its value has not yet been used in the switch
1293 // statement. C++ does not allow multiple cases with the same value, but
1294 // enums does allow this. In this scenario, the first declared
1295 // enumerator with the given value is printed.
1296 if (unique_cases.count(c) == 0) {
1297 unique_cases.insert(c);
1298 code << " case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
1299 code << " return \"" << enumerator->GetName() << "\";\n";
1300 }
1301 }
1302 code << " default:\n";
1303 code << " return std::to_string(static_cast<"
1304 << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
1305 code << " }\n";
1306 code << "}\n";
1307 return code.str();
1308 }
1309
GenerateEnumHeader(CodeWriter & out,const AidlTypenames & types,const AidlEnumDeclaration & enum_decl,const Options &)1310 void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
1311 const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
1312 out << "#pragma once\n";
1313 out << "\n";
1314
1315 GenerateHeaderIncludes(out, types, enum_decl);
1316 // enum specific headers
1317 out << "#include <array>\n";
1318 out << "#include <android/binder_enums.h>\n";
1319
1320 EnterNdkNamespace(out, enum_decl);
1321 out << "enum class";
1322 cpp::GenerateDeprecated(out, enum_decl);
1323 out << " " << enum_decl.GetName() << " : "
1324 << NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK) << " {\n";
1325 out.Indent();
1326 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1327 out << enumerator->GetName() << " = "
1328 << enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator) << ",\n";
1329 }
1330 out.Dedent();
1331 out << "};\n";
1332 out << "\n";
1333 out << GenerateEnumToString(types, enum_decl);
1334 LeaveNdkNamespace(out, enum_decl);
1335
1336 out << "namespace ndk {\n";
1337 out << "namespace internal {\n";
1338 out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
1339 out << "} // namespace internal\n";
1340 out << "} // namespace android\n";
1341 }
1342
1343 } // namespace internals
1344 } // namespace ndk
1345 } // namespace aidl
1346 } // namespace android
1347