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