• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_common.h"
22 #include "aidl_to_cpp_common.h"
23 #include "aidl_to_ndk.h"
24 #include "logging.h"
25 
26 #include <android-base/stringprintf.h>
27 
28 namespace android {
29 namespace aidl {
30 namespace ndk {
31 
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 namespace internals {
40 // 4 outputs for NDK for each type: Header, BpHeader, BnHeader, Source
41 void GenerateHeader(CodeWriter& out, const AidlTypenames& types,
42                     const AidlDefinedType& defined_type, const Options& options);
43 void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
44                           const AidlDefinedType& defined_type, const Options& options);
45 void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
46                           const AidlDefinedType& defined_type, const Options& options);
47 void GenerateSource(CodeWriter& out, const AidlTypenames& types,
48                     const AidlDefinedType& defined_type, const Options& options);
49 
50 // Header contains ClassDecl of a root type
51 void GenerateInterfaceClassDecl(CodeWriter& out, const AidlTypenames& types,
52                                 const AidlInterface& iface, const Options& options);
53 void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
54                              const AidlStructuredParcelable& parcelable, const Options& options);
55 void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
56                              const AidlUnionDecl& union_decl, const Options& options);
57 void GenerateEnumClassDecl(CodeWriter& out, const AidlTypenames& types,
58                            const AidlEnumDeclaration& enum_decl, const Options& options);
59 
60 // BpHeader/BnHeader for interface
61 void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
62                           const AidlInterface& defined_type, const Options& options);
63 void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
64                           const AidlInterface& defined_type, const Options& options);
65 
66 // Source for interface
67 void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& iface,
68                     const Options& options);
69 void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
70                          const AidlInterface& defined_type, const Options& options);
71 void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
72                           const AidlInterface& defined_type, const Options& options);
73 void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
74                           const AidlInterface& defined_type, const Options& options);
75 void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
76                              const AidlInterface& defined_type, const Options& options);
77 
78 // Source for structured parcelable
79 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
80                           const AidlStructuredParcelable& defined_type, const Options& options);
81 
82 // Source for union
83 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
84                           const AidlUnionDecl& defined_type, const Options& options);
85 
86 // Compare headers so that <android/..> and <aidl/..> comes after other (probably) std headers.
87 struct HeaderComp {
rankandroid::aidl::ndk::internals::HeaderComp88   static int rank(const string& a) {
89     return base::StartsWith(a, "aidl/") ? 2 : base::StartsWith(a, "android/") ? 1 : 0;
90   }
operator ()android::aidl::ndk::internals::HeaderComp91   bool operator()(const string& a, const string& b) const {
92     return std::make_tuple(rank(a), a) < std::make_tuple(rank(b), b);
93   }
94 };
95 }  // namespace internals
96 
97 using namespace internals;
98 using cpp::ClassNames;
99 using cpp::GetQualifiedName;
100 
GenerateNdk(const string & output_file,const Options & options,const AidlTypenames & types,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)101 void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
102                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
103   using GenFn = void (*)(CodeWriter & out, const AidlTypenames& types,
104                          const AidlDefinedType& defined_type, const Options& options);
105   // Wrap Generate* function to handle CodeWriter for a file.
106   auto gen = [&](auto file, GenFn fn) {
107     unique_ptr<CodeWriter> writer(io_delegate.GetCodeWriter(file));
108 
109     GenerateAutoGenHeader(*writer, options);
110 
111     fn(*writer, types, defined_type, options);
112     AIDL_FATAL_IF(!writer->Close(), defined_type) << "I/O Error!";
113   };
114 
115   gen(options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW), &GenerateHeader);
116   gen(options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT),
117       &GenerateClientHeader);
118   gen(options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER),
119       &GenerateServerHeader);
120   gen(output_file, &GenerateSource);
121 }
122 
123 namespace internals {
124 
EnterNdkNamespace(CodeWriter & out,const AidlDefinedType & defined_type)125 void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
126   out << "namespace aidl {\n";
127   cpp::EnterNamespace(out, defined_type);
128 }
LeaveNdkNamespace(CodeWriter & out,const AidlDefinedType & defined_type)129 void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
130   cpp::LeaveNamespace(out, defined_type);
131   out << "}  // namespace aidl\n";
132 }
133 
StatusCheckGoto(CodeWriter & out)134 static void StatusCheckGoto(CodeWriter& out) {
135   out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
136 }
StatusCheckBreak(CodeWriter & out)137 static void StatusCheckBreak(CodeWriter& out) {
138   out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
139 }
StatusCheckReturn(CodeWriter & out)140 static void StatusCheckReturn(CodeWriter& out) {
141   out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
142 }
143 
144 void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
145                             const AidlDefinedType& defined_type, const Options& options);
146 
147 void GenerateClassDecl(CodeWriter& out, const AidlTypenames& types,
148                        const AidlDefinedType& defined_type, const Options& options);
149 
GenerateNestedTypeDecls(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)150 void GenerateNestedTypeDecls(CodeWriter& out, const AidlTypenames& types,
151                              const AidlDefinedType& defined_type, const Options& options) {
152   auto visit = [&](const auto& nested) { GenerateClassDecl(out, types, nested, options); };
153   AIDL_FATAL_IF(!TopologicalVisit(defined_type.GetNestedTypes(), visit), defined_type)
154       << "Cycle detected.";
155 }
156 
GenerateHeaderDefinitions(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)157 void GenerateHeaderDefinitions(CodeWriter& out, const AidlTypenames& types,
158                                const AidlDefinedType& defined_type, const Options& options) {
159   struct Visitor : AidlVisitor {
160     CodeWriter& out;
161     const AidlTypenames& types;
162     const Options& options;
163     Visitor(CodeWriter& out, const AidlTypenames& types, const Options& options)
164         : out(out), types(types), options(options) {}
165 
166     void Visit(const AidlEnumDeclaration& enum_decl) override {
167       const auto backing_type = NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK);
168       EnterNdkNamespace(out, enum_decl);
169       out << cpp::GenerateEnumToString(enum_decl, backing_type);
170       LeaveNdkNamespace(out, enum_decl);
171 
172       out << "namespace ndk {\n";
173       out << "namespace internal {\n";
174       out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
175       out << "}  // namespace internal\n";
176       out << "}  // namespace ndk\n";
177     }
178 
179     void Visit(const AidlStructuredParcelable& parcelable) override {
180       if (parcelable.IsGeneric()) {
181         GenerateParcelSource(out, types, parcelable, options);
182       }
183     }
184 
185     void Visit(const AidlUnionDecl& union_decl) override {
186       if (union_decl.IsGeneric()) {
187         GenerateParcelSource(out, types, union_decl, options);
188       }
189     }
190 
191   } v(out, types, options);
192   VisitTopDown(v, defined_type);
193 }
194 
GenerateHeader(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)195 void GenerateHeader(CodeWriter& out, const AidlTypenames& types,
196                     const AidlDefinedType& defined_type, const Options& options) {
197   out << "#pragma once\n\n";
198   GenerateHeaderIncludes(out, types, defined_type, options);
199   cpp::GenerateForwardDecls(out, defined_type, true);
200   EnterNdkNamespace(out, defined_type);
201   GenerateClassDecl(out, types, defined_type, options);
202   LeaveNdkNamespace(out, defined_type);
203   GenerateHeaderDefinitions(out, types, defined_type, options);
204 }
205 
GenerateClientHeader(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)206 void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
207                           const AidlDefinedType& defined_type, const Options& options) {
208   if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
209     GenerateClientHeader(out, types, *iface, options);
210   } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
211     out << "#error TODO(b/111362593) defined_types do not have bp classes\n";
212   } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
213     out << "#error TODO(b/111362593) defined_types do not have bp classes\n";
214   } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
215     out << "#error TODO(b/111362593) enums do not have bp classes\n";
216   } else {
217     AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK generation.";
218   }
219 }
220 
GenerateServerHeader(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)221 void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
222                           const AidlDefinedType& defined_type, const Options& options) {
223   if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
224     GenerateServerHeader(out, types, *iface, options);
225   } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
226     out << "#error TODO(b/111362593) defined_types do not have bn classes\n";
227   } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
228     out << "#error TODO(b/111362593) defined_types do not have bn classes\n";
229   } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
230     out << "#error TODO(b/111362593) enums do not have bn classes\n";
231   } else {
232     AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
233   }
234 }
235 
GenerateSource(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)236 void GenerateSource(CodeWriter& out, const AidlTypenames& types,
237                     const AidlDefinedType& defined_type, const Options& options) {
238   struct Visitor : AidlVisitor {
239     CodeWriter& out;
240     const AidlTypenames& types;
241     const Options& options;
242     Visitor(CodeWriter& out, const AidlTypenames& types, const Options& options)
243         : out(out), types(types), options(options) {}
244 
245     void Visit(const AidlInterface& interface) override {
246       GenerateSource(out, types, interface, options);
247     }
248 
249     void Visit(const AidlStructuredParcelable& parcelable) override {
250       if (!parcelable.IsGeneric()) {
251         GenerateParcelSource(out, types, parcelable, options);
252       }
253     }
254 
255     void Visit(const AidlUnionDecl& union_decl) override {
256       if (!union_decl.IsGeneric()) {
257         GenerateParcelSource(out, types, union_decl, options);
258       }
259     }
260 
261     void Visit(const AidlEnumDeclaration& enum_decl) override {
262       if (!enum_decl.GetParentType()) {
263         out << "// This file is intentionally left blank as placeholder for enum declaration.\n";
264       }
265     }
266   } v(out, types, options);
267   VisitTopDown(v, defined_type);
268 }
269 
GenerateHeaderIncludes(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)270 void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
271                             const AidlDefinedType& defined_type, const Options& options) {
272   // Collect implementation related headers and referenced defined types by recursivly visiting
273   // nested types
274   struct Visitor : AidlVisitor {
275     const AidlTypenames& types;
276     const Options& options;
277     std::set<std::string, HeaderComp> includes;
278     Visitor(const AidlTypenames& types, const Options& options) : types(types), options(options) {}
279 
280     // Collect includes for each type reference
281     void Visit(const AidlTypeSpecifier& type) override {
282       auto defined = type.GetDefinedType();
283       if (!defined) return;
284       includes.insert(NdkHeaderFile(*defined, ClassNames::RAW, false /*use_os_sep*/));
285     }
286 
287     // Collect implementation-specific includes for each type definition
288     void Visit(const AidlInterface& interface) override {
289       AddCommonHeaders(interface);
290       includes.insert("android/binder_interface_utils.h");
291       if (options.GenLog()) {
292         includes.insert("functional");
293         includes.insert("chrono");
294         includes.insert("sstream");
295       }
296       // For nested interfaces client/server classes are defined in the same header.
297       // So we need includes for client/server class as well.
298       if (interface.GetParentType()) {
299         includes.insert("android/binder_ibinder.h");
300         if (options.GenTraces()) {
301           includes.insert("android/trace.h");
302         }
303       }
304     }
305 
306     void Visit(const AidlStructuredParcelable& parcelable) override {
307       AddCommonHeaders(parcelable);
308       includes.insert("android/binder_interface_utils.h");
309       includes.insert("android/binder_parcelable_utils.h");
310       includes.insert("android/binder_to_string.h");  // used by toString()
311     }
312 
313     void Visit(const AidlUnionDecl& union_decl) override {
314       AddCommonHeaders(union_decl);
315       includes.insert("android/binder_interface_utils.h");
316       includes.insert("android/binder_parcelable_utils.h");
317       includes.insert("android/binder_to_string.h");  // used by toString()
318       auto union_headers = cpp::UnionWriter::GetHeaders(union_decl);
319       includes.insert(std::begin(union_headers), std::end(union_headers));
320     }
321 
322     void Visit(const AidlEnumDeclaration& enum_decl) override {
323       AddCommonHeaders(enum_decl);
324       includes.insert("array");
325       includes.insert("android/binder_enums.h");
326     }
327 
328     void AddCommonHeaders(const AidlDefinedType& defined_type) {
329       includes.insert("cstdint");
330       includes.insert("memory");
331       includes.insert("optional");
332       includes.insert("string");
333       includes.insert("vector");
334       if (defined_type.IsSensitiveData()) {
335         includes.insert("android/binder_parcel_platform.h");
336         includes.insert("android/binder_ibinder_platform.h");
337       }
338     }
339   } v(types, options);
340   VisitTopDown(v, defined_type);
341 
342   for (const auto& path : v.includes) {
343     out << "#include <" << path << ">\n";
344   }
345   out << "#ifdef BINDER_STABILITY_SUPPORT\n";
346   out << "#include <android/binder_stability.h>\n";
347   out << "#endif  // BINDER_STABILITY_SUPPORT\n";
348   out << "\n";
349 
350   if (v.includes.count("cassert")) {
351     // TODO(b/31559095) bionic on host should define __assert2
352     out << "#ifndef __BIONIC__\n#define __assert2(a,b,c,d) ((void)0)\n#endif\n\n";
353   }
354 }
355 
GenerateClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)356 void GenerateClassDecl(CodeWriter& out, const AidlTypenames& types,
357                        const AidlDefinedType& defined_type, const Options& options) {
358   if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
359     GenerateInterfaceClassDecl(out, types, *iface, options);
360   } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
361     GenerateParcelClassDecl(out, types, *parcelable, options);
362   } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
363     GenerateParcelClassDecl(out, types, *union_decl, options);
364   } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
365     GenerateEnumClassDecl(out, types, *enum_decl, options);
366   } else {
367     AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK generation.";
368   }
369 }
370 
GenerateSourceIncludes(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & defined_type,const Options & options)371 static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
372                                    const AidlDefinedType& defined_type, const Options& options) {
373   // Once in a .cpp file
374   if (defined_type.GetParentType() != nullptr) {
375     return;
376   }
377 
378   const string self_header = NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/);
379   out << "#include \"" << self_header << "\"\n";
380   out << "\n";
381 
382   std::set<std::string, HeaderComp> includes = {self_header};
383   includes.insert("android/binder_parcel_utils.h");
384   types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
385     if (a_defined_type.AsInterface() != nullptr) {
386       includes.insert(NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/));
387       includes.insert(NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/));
388       includes.insert(NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/));
389     }
390   });
391 
392   struct Visitor : AidlVisitor {
393     bool has_interface = false;
394     void Visit(const AidlInterface&) override { has_interface = true; }
395   } v;
396   VisitTopDown(v, defined_type);
397 
398   if (v.has_interface && options.GenLog()) {
399     includes.insert("android/binder_to_string.h");
400   }
401 
402   // Emit includes except self_header
403   includes.erase(includes.find(self_header));
404   for (const auto& inc : includes) {
405     out << "#include <" << inc << ">\n";
406   }
407   out << "\n";
408 
409   // Emit additional definition for gen_traces
410   if (v.has_interface && options.GenTraces()) {
411     out << "namespace {\n";
412     out << "struct ScopedTrace {\n";
413     out.Indent();
414     out << "inline explicit ScopedTrace(const char* name) { ATrace_beginSection(name); }\n";
415     out << "inline ~ScopedTrace() { ATrace_endSection(); }\n";
416     out.Dedent();
417     out << "};\n";
418     out << "}  // namespace\n";
419     out << "\n";
420   }
421 }
422 
GenerateConstantDeclarations(CodeWriter & out,const AidlTypenames & types,const AidlDefinedType & type)423 static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types,
424                                          const AidlDefinedType& type) {
425   for (const auto& constant : type.GetConstantDeclarations()) {
426     const AidlTypeSpecifier& type = constant->GetType();
427 
428     if (type.Signature() == "String") {
429       out << "static const char*";
430       cpp::GenerateDeprecated(out, *constant);
431       out << " " << constant->GetName() << ";\n";
432     } else if (type.Signature() == "float" || type.Signature() == "double") {
433       out << "static constexpr " << NdkNameOf(types, type, StorageMode::STACK) << " ";
434       out << constant->GetName();
435       cpp::GenerateDeprecated(out, *constant);
436       out << " = " << constant->ValueString(ConstantValueDecorator) << ";\n";
437     } else {
438       out << "enum : " << NdkNameOf(types, type, StorageMode::STACK) << " { ";
439       out << constant->GetName();
440       cpp::GenerateDeprecated(out, *constant);
441       out << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
442     }
443   }
444 }
445 
GenerateConstantDefinitions(CodeWriter & out,const AidlDefinedType & interface,const std::string & clazz,const std::string & tmpl_decl="")446 static void GenerateConstantDefinitions(CodeWriter& out, const AidlDefinedType& interface,
447                                         const std::string& clazz,
448                                         const std::string& tmpl_decl = "") {
449   for (const auto& constant : interface.GetConstantDeclarations()) {
450     const AidlConstantValue& value = constant->GetValue();
451     AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
452                       value.GetType() == AidlConstantValue::Type::BINARY,
453                   value);
454     if (value.GetType() == AidlConstantValue::Type::STRING) {
455       out << tmpl_decl;
456       out << "const char* " << clazz << "::" << constant->GetName() << " = "
457           << constant->ValueString(ConstantValueDecorator) << ";\n";
458     }
459   }
460 }
461 
GenerateSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)462 void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
463                     const Options& options) {
464   GenerateSourceIncludes(out, types, defined_type, options);
465   EnterNdkNamespace(out, defined_type);
466   GenerateClassSource(out, types, defined_type, options);
467   GenerateClientSource(out, types, defined_type, options);
468   GenerateServerSource(out, types, defined_type, options);
469   GenerateInterfaceSource(out, types, defined_type, options);
470   LeaveNdkNamespace(out, defined_type);
471 }
472 
MethodId(const AidlMethod & m)473 static std::string MethodId(const AidlMethod& m) {
474   return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
475 }
476 
GenerateClientMethodDefinition(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const AidlMethod & method,const Options & options)477 static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
478                                            const AidlInterface& defined_type,
479                                            const AidlMethod& method, const Options& options) {
480   const std::string q_name = GetQualifiedName(defined_type, ClassNames::CLIENT);
481   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
482 
483   out << NdkMethodDecl(types, method, q_name) << " {\n";
484   out.Indent();
485   out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
486   out << "::ndk::ScopedAStatus _aidl_status;\n";
487 
488   if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
489     out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
490     out << "if (" << kCachedHash << " != \"-1\") {\n";
491     out.Indent();
492     out << "*_aidl_return = " << kCachedHash << ";\n"
493         << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
494         << "return _aidl_status;\n";
495     out.Dedent();
496     out << "}\n";
497   } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
498     out << "if (" << kCachedVersion << " != -1) {\n";
499     out.Indent();
500     out << "*_aidl_return = " << kCachedVersion << ";\n"
501         << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
502         << "return _aidl_status;\n";
503     out.Dedent();
504     out << "}\n";
505   }
506   out << "::ndk::ScopedAParcel _aidl_in;\n";
507   out << "::ndk::ScopedAParcel _aidl_out;\n";
508   out << "\n";
509 
510   if (options.GenLog()) {
511     out << cpp::GenLogBeforeExecute(q_name, method, false /* isServer */, true /* isNdk */);
512   }
513   if (options.GenTraces()) {
514     out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
515         << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
516         << "::client\");\n";
517   }
518 
519   if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE) &&
520       method.IsUserDefined()) {
521     out << "if (true) {\n";
522     out << "  _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
523     out << "  goto _aidl_error;\n";
524     out << "}\n";
525   }
526 
527   out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
528   if (defined_type.IsSensitiveData()) {
529     out << "AParcel_markSensitive(_aidl_in.get());\n";
530   }
531   StatusCheckGoto(out);
532 
533   for (const auto& arg : method.GetArguments()) {
534     const std::string var_name = cpp::BuildVarName(*arg);
535 
536     if (arg->IsIn()) {
537       out << "_aidl_ret_status = ";
538       const std::string prefix = (arg->IsOut() ? "*" : "");
539       WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
540       out << ";\n";
541       StatusCheckGoto(out);
542     } else if (arg->IsOut() && arg->GetType().IsDynamicArray()) {
543       out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
544           << ");\n";
545       StatusCheckGoto(out);
546     }
547   }
548   out << "_aidl_ret_status = AIBinder_transact(\n";
549   out.Indent();
550   out << "asBinder().get(),\n";
551   out << MethodId(method) << ",\n";
552   out << "_aidl_in.getR(),\n";
553   out << "_aidl_out.getR(),\n";
554 
555   std::vector<std::string> flags;
556   if (method.IsOneway()) flags.push_back("FLAG_ONEWAY");
557   if (defined_type.IsSensitiveData()) flags.push_back("FLAG_CLEAR_BUF");
558   out << (flags.empty() ? "0" : base::Join(flags, " | ")) << "\n";
559 
560   out << "#ifdef BINDER_STABILITY_SUPPORT\n";
561   out << "| FLAG_PRIVATE_LOCAL\n";
562   out << "#endif  // BINDER_STABILITY_SUPPORT\n";
563   out << ");\n";
564   out.Dedent();
565 
566   // If the method is not implmented in the server side but the client has
567   // provided the default implementation, call it instead of failing hard.
568   const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
569   out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
570   out << iface << "::getDefaultImpl()) {\n";
571   out.Indent();
572   out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
573   out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
574   out << "goto _aidl_status_return;\n";
575   out.Dedent();
576   out << "}\n";
577 
578   StatusCheckGoto(out);
579 
580   if (!method.IsOneway()) {
581     out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
582     StatusCheckGoto(out);
583 
584     out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
585   }
586 
587   if (method.GetType().GetName() != "void") {
588     out << "_aidl_ret_status = ";
589     ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
590     out << ";\n";
591     StatusCheckGoto(out);
592     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
593       out << kCachedHash << " = *_aidl_return;\n";
594     } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
595       out << kCachedVersion << " = *_aidl_return;\n";
596     }
597   }
598   for (const AidlArgument* arg : method.GetOutArguments()) {
599     out << "_aidl_ret_status = ";
600     ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
601     out << ";\n";
602     StatusCheckGoto(out);
603   }
604 
605   out << "_aidl_error:\n";
606   out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
607   out << "_aidl_status_return:\n";
608   if (options.GenLog()) {
609     out << cpp::GenLogAfterExecute(q_name, defined_type, method, "_aidl_status", "_aidl_return",
610                                    false /* isServer */, true /* isNdk */);
611   }
612 
613   out << "return _aidl_status;\n";
614   out.Dedent();
615   out << "}\n";
616 }
617 
GenerateServerCaseDefinition(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const AidlMethod & method,const Options & options)618 static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
619                                          const AidlInterface& defined_type,
620                                          const AidlMethod& method, const Options& options) {
621   const string q_name = GetQualifiedName(defined_type, ClassNames::SERVER);
622 
623   out << "case " << MethodId(method) << ": {\n";
624   out.Indent();
625 
626   if (defined_type.EnforceExpression() || method.GetType().EnforceExpression()) {
627     out.Write("#error Permission checks not implemented for the ndk backend\n");
628   }
629 
630   if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ) &&
631       method.IsUserDefined()) {
632     out << "if (true) break;\n";
633   }
634   for (const auto& arg : method.GetArguments()) {
635     out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
636         << ";\n";
637   }
638   if (method.GetType().GetName() != "void") {
639     out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
640   }
641   out << "\n";
642   if (options.GenTraces()) {
643     out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
644         << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
645         << "::server\");\n";
646   }
647 
648   for (const auto& arg : method.GetArguments()) {
649     const std::string var_name = cpp::BuildVarName(*arg);
650 
651     if (arg->IsIn()) {
652       out << "_aidl_ret_status = ";
653       ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
654       out << ";\n";
655       StatusCheckBreak(out);
656     } else if (arg->IsOut() && arg->GetType().IsDynamicArray()) {
657       out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
658       StatusCheckBreak(out);
659     }
660   }
661   if (options.GenLog()) {
662     out << cpp::GenLogBeforeExecute(q_name, method, true /* isServer */, true /* isNdk */);
663   }
664   out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
665       << NdkArgList(types, method, FormatArgForCall) << ");\n";
666 
667   if (options.GenLog()) {
668     out << cpp::GenLogAfterExecute(q_name, defined_type, method, "_aidl_status", "_aidl_return",
669                                    true /* isServer */, true /* isNdk */);
670   }
671   if (method.IsOneway()) {
672     // For a oneway transaction, the kernel will have already returned a result. This is for the
673     // in-process case when a oneway transaction is parceled/unparceled in the same process.
674     out << "_aidl_ret_status = STATUS_OK;\n";
675   } else {
676     out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
677     StatusCheckBreak(out);
678 
679     out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
680 
681     if (method.GetType().GetName() != "void") {
682       out << "_aidl_ret_status = ";
683       WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
684       out << ";\n";
685       StatusCheckBreak(out);
686     }
687     for (const AidlArgument* arg : method.GetOutArguments()) {
688       out << "_aidl_ret_status = ";
689       WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
690       out << ";\n";
691       StatusCheckBreak(out);
692     }
693   }
694   out << "break;\n";
695   out.Dedent();
696   out << "}\n";
697 }
698 
OnTransactFuncName(const AidlInterface & interface)699 static string OnTransactFuncName(const AidlInterface& interface) {
700   string name = interface.GetCanonicalName();
701   std::replace(name.begin(), name.end(), '.', '_');
702   return "_aidl_" + name + "_onTransact";
703 }
704 
GlobalClassVarName(const AidlInterface & interface)705 static string GlobalClassVarName(const AidlInterface& interface) {
706   string name = interface.GetCanonicalName();
707   std::replace(name.begin(), name.end(), '.', '_');
708   return "_g_aidl_" + name + "_clazz";
709 }
710 
GenerateClassSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)711 void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
712                          const AidlInterface& defined_type, const Options& options) {
713   const std::string i_name = GetQualifiedName(defined_type, ClassNames::INTERFACE);
714   const std::string q_name = GetQualifiedName(defined_type, ClassNames::SERVER);
715 
716   const string on_transact = OnTransactFuncName(defined_type);
717   bool deprecated = defined_type.IsDeprecated() ||
718                     std::any_of(defined_type.GetMethods().begin(), defined_type.GetMethods().end(),
719                                 [](const auto& m) { return m->IsDeprecated(); });
720   if (deprecated) {
721     out << "#pragma clang diagnostic push\n";
722     out << "#pragma clang diagnostic ignored \"-Wdeprecated\"\n";
723   }
724   out << "static binder_status_t " << on_transact
725       << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
726          "AParcel* _aidl_out) {\n";
727   out.Indent();
728   out << "(void)_aidl_in;\n";
729   out << "(void)_aidl_out;\n";
730   out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
731   if (!defined_type.GetMethods().empty()) {
732     // we know this cast is valid because this method is only called by the ICInterface
733     // AIBinder_Class object which is associated with this class.
734     out << "std::shared_ptr<" << q_name << "> _aidl_impl = std::static_pointer_cast<" << q_name
735         << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
736     out << "switch (_aidl_code) {\n";
737     out.Indent();
738     for (const auto& method : defined_type.GetMethods()) {
739       GenerateServerCaseDefinition(out, types, defined_type, *method, options);
740     }
741     out.Dedent();
742     out << "}\n";
743   } else {
744     out << "(void)_aidl_binder;\n";
745     out << "(void)_aidl_code;\n";
746   }
747   out << "return _aidl_ret_status;\n";
748   out.Dedent();
749   out << "}\n\n";
750 
751   out << "static AIBinder_Class* " << GlobalClassVarName(defined_type)
752       << " = ::ndk::ICInterface::defineClass(" << i_name << "::" << kDescriptor << ", "
753       << on_transact << ");\n\n";
754   if (deprecated) {
755     out << "#pragma clang diagnostic pop\n";
756   }
757 }
758 
GenerateClientSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)759 void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
760                           const AidlInterface& defined_type, const Options& options) {
761   const std::string q_name = GetQualifiedName(defined_type, ClassNames::CLIENT);
762   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
763 
764   out << q_name << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
765   out << q_name << "::~" << clazz << "() {}\n";
766   if (options.GenLog()) {
767     out << "std::function<void(const " << q_name << "::TransactionLog&)> " << q_name
768         << "::logFunc;\n";
769   }
770   out << "\n";
771   for (const auto& method : defined_type.GetMethods()) {
772     GenerateClientMethodDefinition(out, types, defined_type, *method, options);
773   }
774 }
775 
GenerateServerSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)776 void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
777                           const AidlInterface& defined_type, const Options& options) {
778   const std::string q_name = GetQualifiedName(defined_type, ClassNames::SERVER);
779   const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
780   const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
781 
782   out << "// Source for " << clazz << "\n";
783   out << q_name << "::" << clazz << "() {}\n";
784   out << q_name << "::~" << clazz << "() {}\n";
785   if (options.GenLog()) {
786     out << "std::function<void(const " << q_name << "::TransactionLog&)> " << q_name
787         << "::logFunc;\n";
788   }
789   out << "::ndk::SpAIBinder " << q_name << "::createBinder() {\n";
790   out.Indent();
791   out << "AIBinder* binder = AIBinder_new(" << GlobalClassVarName(defined_type)
792       << ", static_cast<void*>(this));\n";
793 
794   out << "#ifdef BINDER_STABILITY_SUPPORT\n";
795   if (defined_type.IsVintfStability()) {
796     out << "AIBinder_markVintfStability(binder);\n";
797   } else {
798     out << "AIBinder_markCompilationUnitStability(binder);\n";
799   }
800   out << "#endif  // BINDER_STABILITY_SUPPORT\n";
801 
802   out << "return ::ndk::SpAIBinder(binder);\n";
803   out.Dedent();
804   out << "}\n";
805 
806   // Implement the meta methods
807   for (const auto& method : defined_type.GetMethods()) {
808     if (method->IsUserDefined()) {
809       continue;
810     }
811     if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
812       out << NdkMethodDecl(types, *method, q_name) << " {\n";
813       out.Indent();
814       out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
815       out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
816       out.Dedent();
817       out << "}\n";
818     }
819     if (method->GetName() == kGetInterfaceHash && (!options.Hash().empty())) {
820       out << NdkMethodDecl(types, *method, q_name) << " {\n";
821       out.Indent();
822       out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
823       out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
824       out.Dedent();
825       out << "}\n";
826     }
827   }
828 }
GenerateInterfaceSource(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)829 void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
830                              const AidlInterface& defined_type, const Options& options) {
831   const std::string q_name = GetQualifiedName(defined_type, ClassNames::INTERFACE);
832   const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
833   const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
834 
835   out << "// Source for " << clazz << "\n";
836   out << "const char* " << q_name << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
837       << "\";\n";
838   out << q_name << "::" << clazz << "() {}\n";
839   out << q_name << "::~" << clazz << "() {}\n";
840   out << "\n";
841   GenerateConstantDefinitions(out, defined_type, q_name);
842   out << "\n";
843 
844   out << "std::shared_ptr<" << q_name << "> " << q_name
845       << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
846   out.Indent();
847   out << "if (!AIBinder_associateClass(binder.get(), " << GlobalClassVarName(defined_type)
848       << ")) {\n";
849   out.Indent();
850   // since NDK users don't use weak symbol support, we don't check builtin available. We could
851   // optionally check it if __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ is defined, but this would
852   // also mean that app developers relying on this behavior would be missing test parity, and if
853   // local transactions aren't supported, due to missing the descriptor API, they will need to
854   // work around it a different way, so it's best to check based on __ANDROID_API__
855   out << "#if __ANDROID_API__ >= 31\n";
856   out << "const AIBinder_Class* originalClass = AIBinder_getClass(binder.get());\n";
857   out << "if (originalClass == nullptr) return nullptr;\n";
858   out << "if (0 == strcmp(AIBinder_Class_getDescriptor(originalClass), descriptor)) {\n";
859   out.Indent();
860   // parcel transactions in process, e.g. NDK<->Rust (okay..)
861   out << "return ::ndk::SharedRefBase::make<" << GetQualifiedName(defined_type, ClassNames::CLIENT)
862       << ">(binder);\n";
863   out.Dedent();
864   out << "}\n";
865   out << "#endif\n";
866   out << "return nullptr;\n";
867   out.Dedent();
868   out << "}\n";
869   out << "std::shared_ptr<::ndk::ICInterface> interface = "
870          "::ndk::ICInterface::asInterface(binder.get());\n";
871   out << "if (interface) {\n";
872   out.Indent();
873   out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
874   out.Dedent();
875   out << "}\n";
876   out << "return ::ndk::SharedRefBase::make<" << GetQualifiedName(defined_type, ClassNames::CLIENT)
877       << ">(binder);\n";
878   out.Dedent();
879   out << "}\n\n";
880 
881   out << "binder_status_t " << q_name << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
882       << clazz << ">& instance) {\n";
883   out.Indent();
884   out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
885          "nullptr);\n";
886   out.Dedent();
887   out << "}\n";
888 
889   out << "binder_status_t " << q_name << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
890       << clazz << ">* instance) {\n";
891   out.Indent();
892   out << "::ndk::SpAIBinder binder;\n";
893   out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
894   out << "if (status != STATUS_OK) return status;\n";
895   out << "*instance = " << clazz << "::fromBinder(binder);\n";
896   out << "return STATUS_OK;\n";
897   out.Dedent();
898   out << "}\n";
899 
900   // defintion for static member setDefaultImpl
901   out << "bool " << q_name << "::setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl) {\n";
902   out.Indent();
903   out << "// Only one user of this interface can use this function\n";
904   out << "// at a time. This is a heuristic to detect if two different\n";
905   out << "// users in the same process use this function.\n";
906   out << "assert(!" << clazz << "::default_impl);\n";
907   out << "if (impl) {\n";
908   out.Indent();
909   out << clazz << "::default_impl = impl;\n";
910   out << "return true;\n";
911   out.Dedent();
912   out << "}\n";
913   out << "return false;\n";
914   out.Dedent();
915   out << "}\n";
916 
917   // definition for static member getDefaultImpl
918   out << "const std::shared_ptr<" << q_name << ">& " << q_name << "::getDefaultImpl() {\n";
919   out.Indent();
920   out << "return " << clazz << "::default_impl;\n";
921   out.Dedent();
922   out << "}\n";
923 
924   // definition for the static field default_impl
925   out << "std::shared_ptr<" << q_name << "> " << q_name << "::default_impl = nullptr;\n";
926 
927   // default implementation for the <Name>Default class members
928   const std::string defaultClazz = q_name + "Default";
929   for (const auto& method : defined_type.GetMethods()) {
930     if (method->IsUserDefined()) {
931       out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
932           << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
933       out.Indent();
934       out << "::ndk::ScopedAStatus _aidl_status;\n";
935       out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
936       out << "return _aidl_status;\n";
937       out.Dedent();
938       out << "}\n";
939     } else {
940       if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
941         out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
942             << "int32_t* _aidl_return) {\n";
943         out.Indent();
944         out << "*_aidl_return = 0;\n";
945         out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
946         out.Dedent();
947         out << "}\n";
948       }
949       if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
950         out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
951             << "std::string* _aidl_return) {\n";
952         out.Indent();
953         out << "*_aidl_return = \"\";\n";
954         out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
955         out.Dedent();
956         out << "}\n";
957       }
958     }
959   }
960 
961   out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
962   out.Indent();
963   out << "return ::ndk::SpAIBinder();\n";
964   out.Dedent();
965   out << "}\n";
966 
967   out << "bool " << defaultClazz << "::isRemote() {\n";
968   out.Indent();
969   out << "return false;\n";
970   out.Dedent();
971   out << "}\n";
972 }
973 
GenerateClientClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)974 void GenerateClientClassDecl(CodeWriter& out, const AidlTypenames& types,
975                              const AidlInterface& defined_type, const Options& options) {
976   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
977 
978   out << "class";
979   cpp::GenerateDeprecated(out, defined_type);
980   out << " " << clazz << " : public ::ndk::BpCInterface<"
981       << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
982   out << "public:\n";
983   out.Indent();
984   out << "explicit " << clazz << "(const ::ndk::SpAIBinder& binder);\n";
985   out << "virtual ~" << clazz << "();\n";
986   out << "\n";
987   for (const auto& method : defined_type.GetMethods()) {
988     out << NdkMethodDecl(types, *method) << " override";
989     cpp::GenerateDeprecated(out, *method);
990     out << ";\n";
991   }
992 
993   if (options.Version() > 0) {
994     out << "int32_t " << kCachedVersion << " = -1;\n";
995   }
996 
997   if (!options.Hash().empty()) {
998     out << "std::string " << kCachedHash << " = \"-1\";\n";
999     out << "std::mutex " << kCachedHashMutex << ";\n";
1000   }
1001   if (options.GenLog()) {
1002     out << cpp::kTransactionLogStruct;
1003     out << "static std::function<void(const TransactionLog&)> logFunc;\n";
1004   }
1005   out.Dedent();
1006   out << "};\n";
1007 }
1008 
GenerateClientHeader(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)1009 void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
1010                           const AidlInterface& defined_type, const Options& options) {
1011   out << "#pragma once\n\n";
1012   out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
1013       << "\"\n";
1014   out << "\n";
1015   out << "#include <android/binder_ibinder.h>\n";
1016   if (options.GenLog()) {
1017     out << "#include <functional>\n";
1018     out << "#include <chrono>\n";
1019     out << "#include <sstream>\n";
1020   }
1021   if (options.GenTraces()) {
1022     out << "#include <android/trace.h>\n";
1023   }
1024   out << "\n";
1025   EnterNdkNamespace(out, defined_type);
1026   GenerateClientClassDecl(out, types, defined_type, options);
1027   LeaveNdkNamespace(out, defined_type);
1028 }
1029 
GenerateDelegatorClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)1030 void GenerateDelegatorClassDecl(CodeWriter& out, const AidlTypenames& types,
1031                                 const AidlInterface& defined_type, const Options& options) {
1032   const std::string clazz = ClassName(defined_type, ClassNames::DELEGATOR_IMPL);
1033   const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
1034   const std::string bn_name = ClassName(defined_type, ClassNames::SERVER);
1035   const std::string kDelegateImplVarName = "_impl";
1036   const std::string kStatusType = "::ndk::ScopedAStatus";
1037 
1038   out << "class";
1039   cpp::GenerateDeprecated(out, defined_type);
1040   out << " " << clazz << " : public " << bn_name << " {\n";
1041   out << "public:\n";
1042   out.Indent();
1043   out << "explicit " << clazz << "(const std::shared_ptr<" << iface << "> &impl)"
1044       << " : " << kDelegateImplVarName << "(impl) {\n";
1045   if (options.Version() > 0) {
1046     // TODO(b/222347502) If we need to support mismatched versions of delegator and
1047     // impl, this check will be removed. The NDK backend can't override the
1048     // getInterface* meta methods because they are marked "final". Removing
1049     // "final" changes the ABI and breaks prebuilts.
1050     out << "   int32_t _impl_ver = 0;\n";
1051     out << "   if (!impl->" << kGetInterfaceVersion << "(&_impl_ver).isOk()) {;\n";
1052     out << "      __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"Delegator failed to get "
1053            "version of the implementation.\");\n";
1054     out << "   }\n";
1055     out << "   if (_impl_ver != " << iface << "::" << kVersion << ") {\n";
1056     out << "      __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"Mismatched versions of "
1057            "delegator and implementation is not allowed.\");\n";
1058     out << "   }\n";
1059   }
1060   out << "}\n\n";
1061   for (const auto& method : defined_type.GetMethods()) {
1062     if (method->IsUserDefined()) {
1063       out << kStatusType << " " << method->GetName() << "("
1064           << NdkArgList(types, *method, FormatArgForDecl) << ") override";
1065       cpp::GenerateDeprecated(out, *method);
1066       out << " {\n"
1067           << "  return " << kDelegateImplVarName << "->" << method->GetName() << "("
1068           << NdkArgList(types, *method, FormatArgNameOnly) << ");\n";
1069       out << "}\n";
1070     }
1071   }
1072   out.Dedent();
1073   out << "protected:\n";
1074   out.Indent();
1075   out.Dedent();
1076   out << "private:\n";
1077   out.Indent();
1078   out << "std::shared_ptr<" << iface << "> " << kDelegateImplVarName << ";\n";
1079   out.Dedent();
1080   out << "};\n\n";
1081 }
1082 
GenerateServerClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)1083 void GenerateServerClassDecl(CodeWriter& out, const AidlTypenames& types,
1084                              const AidlInterface& defined_type, const Options& options) {
1085   const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
1086   const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
1087 
1088   out << "class";
1089   cpp::GenerateDeprecated(out, defined_type);
1090   out << " " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
1091   out << "public:\n";
1092   out.Indent();
1093   out << clazz << "();\n";
1094   out << "virtual ~" << clazz << "();\n";
1095 
1096   // Declare the meta methods
1097   for (const auto& method : defined_type.GetMethods()) {
1098     if (method->IsUserDefined()) {
1099       continue;
1100     }
1101     if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1102       out << NdkMethodDecl(types, *method) << " final;\n";
1103     } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1104       out << NdkMethodDecl(types, *method) << " final;\n";
1105     } else {
1106       AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
1107     }
1108   }
1109   if (options.GenLog()) {
1110     out << cpp::kTransactionLogStruct;
1111     out << "static std::function<void(const TransactionLog&)> logFunc;\n";
1112   }
1113   out.Dedent();
1114   out << "protected:\n";
1115   out.Indent();
1116   out << "::ndk::SpAIBinder createBinder() override;\n";
1117   out.Dedent();
1118   out << "private:\n";
1119   out.Indent();
1120   out.Dedent();
1121   out << "};\n";
1122 }
1123 
GenerateServerHeader(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)1124 void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
1125                           const AidlInterface& defined_type, const Options& options) {
1126   out << "#pragma once\n\n";
1127   out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
1128       << "\"\n";
1129   out << "\n";
1130   out << "#include <android/binder_ibinder.h>\n";
1131   // Needed for *Delegator classes while delegator version is required to be
1132   // the same as the implementation version
1133   // TODO(b/222347502) If we ever need to support mismatched versions of delegator and
1134   // impl, this include can be removed.
1135   out << "#include <cassert>\n\n";
1136   // TODO(b/31559095) bionic on host should define __assert2
1137   out << "#ifndef __BIONIC__\n#ifndef __assert2\n#define __assert2(a,b,c,d) "
1138          "((void)0)\n#endif\n#endif\n";
1139   out << "\n";
1140   EnterNdkNamespace(out, defined_type);
1141   GenerateServerClassDecl(out, types, defined_type, options);
1142   GenerateDelegatorClassDecl(out, types, defined_type, options);
1143   LeaveNdkNamespace(out, defined_type);
1144 }
1145 
GenerateInterfaceClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlInterface & defined_type,const Options & options)1146 void GenerateInterfaceClassDecl(CodeWriter& out, const AidlTypenames& types,
1147                                 const AidlInterface& defined_type, const Options& options) {
1148   const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
1149   out << "class " << ClassName(defined_type, ClassNames::DELEGATOR_IMPL) << ";\n\n";
1150   out << "class";
1151   cpp::GenerateDeprecated(out, defined_type);
1152   out << " " << clazz << " : public ::ndk::ICInterface {\n";
1153   out << "public:\n";
1154   out.Indent();
1155   out << "typedef " << ClassName(defined_type, ClassNames::DELEGATOR_IMPL)
1156       << " DefaultDelegator;\n";
1157   out << "static const char* " << kDescriptor << ";\n";
1158   out << clazz << "();\n";
1159   out << "virtual ~" << clazz << "();\n";
1160   out << "\n";
1161   GenerateNestedTypeDecls(out, types, defined_type, options);
1162   GenerateConstantDeclarations(out, types, defined_type);
1163   if (options.Version() > 0) {
1164     if (options.IsLatestUnfrozenVersion()) {
1165       out << "static inline const int32_t " << kVersion << " = true ? "
1166           << std::to_string(options.PreviousVersion()) << " : " << std::to_string(options.Version())
1167           << ";\n";
1168     } else {
1169       out << "static inline const int32_t " << kVersion << " = "
1170           << std::to_string(options.Version()) << ";\n";
1171     }
1172   }
1173   if (!options.Hash().empty()) {
1174     if (options.IsLatestUnfrozenVersion()) {
1175       out << "static inline const std::string " << kHash << " = true ? \"" << options.PreviousHash()
1176           << "\" : \"" << options.Hash() << "\";\n";
1177     } else {
1178       out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
1179     }
1180   }
1181   for (const auto& method : defined_type.GetMethods()) {
1182     if (!method->IsUserDefined()) {
1183       continue;
1184     }
1185     out << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
1186         << "FIRST_CALL_TRANSACTION + " << std::to_string(method->GetId()) << ";\n";
1187   }
1188   out << "\n";
1189   out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
1190   out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
1191       << ">& instance);";
1192   out << "\n";
1193   out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
1194       << ">* instance);";
1195   out << "\n";
1196   out << "static bool setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl);";
1197   out << "\n";
1198   out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
1199   out << "\n";
1200   for (const auto& method : defined_type.GetMethods()) {
1201     out << "virtual " << NdkMethodDecl(types, *method);
1202     cpp::GenerateDeprecated(out, *method);
1203     out << " = 0;\n";
1204   }
1205   out.Dedent();
1206   out << "private:\n";
1207   out.Indent();
1208   out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
1209   out.Dedent();
1210   out << "};\n";
1211 
1212   const std::string defaultClazz = clazz + "Default";
1213   out << "class";
1214   cpp::GenerateDeprecated(out, defined_type);
1215   out << " " << defaultClazz << " : public " << clazz << " {\n";
1216   out << "public:\n";
1217   out.Indent();
1218   for (const auto& method : defined_type.GetMethods()) {
1219     if (method->IsUserDefined()) {
1220       out << NdkMethodDecl(types, *method) << " override";
1221       cpp::GenerateDeprecated(out, *method);
1222       out << ";\n";
1223     } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1224       out << NdkMethodDecl(types, *method) << " override;\n";
1225     } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1226       out << NdkMethodDecl(types, *method) << " override;\n";
1227     }
1228   }
1229   out << "::ndk::SpAIBinder asBinder() override;\n";
1230   out << "bool isRemote() override;\n";
1231   out.Dedent();
1232   out << "};\n";
1233 
1234   // When an interface is nested, every class should be defined together here
1235   // because we don't have separate headers for them.
1236   // (e.g. IFoo, IFooDefault, BpFoo, BnFoo, IFooDelegator)
1237   if (defined_type.GetParentType()) {
1238     GenerateClientClassDecl(out, types, defined_type, options);
1239     GenerateServerClassDecl(out, types, defined_type, options);
1240   }
1241 }
1242 
GenerateParcelClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlStructuredParcelable & defined_type,const Options & options)1243 void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
1244                              const AidlStructuredParcelable& defined_type, const Options& options) {
1245   const std::string clazz = ClassName(defined_type, ClassNames::RAW);
1246 
1247   cpp::ClangDiagnosticIgnoreDeprecated guard(out, cpp::HasDeprecatedField(defined_type));
1248   out << cpp::TemplateDecl(defined_type);
1249   out << "class";
1250   cpp::GenerateDeprecated(out, defined_type);
1251   out << " " << clazz << " {\n";
1252   out << "public:\n";
1253   out.Indent();
1254   if (defined_type.IsFixedSize()) {
1255     out << "typedef std::true_type fixed_size;\n";
1256   } else {
1257     out << "typedef std::false_type fixed_size;\n";
1258   }
1259   out << "static const char* descriptor;\n";
1260   out << "\n";
1261   GenerateNestedTypeDecls(out, types, defined_type, options);
1262   for (const auto& variable : defined_type.GetFields()) {
1263     const auto& type = variable->GetType();
1264     std::string cpp_type = NdkNameOf(types, type, StorageMode::STACK);
1265     out << cpp_type;
1266     cpp::GenerateDeprecated(out, *variable);
1267     out << " " << variable->GetName();
1268     if (defined_type.IsFixedSize()) {
1269       auto alignment = cpp::AlignmentOf(type, types);
1270       if (alignment) {
1271         out << " __attribute__((aligned (" << std::to_string(*alignment) << ")))";
1272       }
1273     }
1274     if (variable->GetDefaultValue()) {
1275       out << " = " << variable->ValueString(ConstantValueDecorator);
1276     } else {
1277       // Some types needs to be explicitly initialized even when no default value is set.
1278       // - ParcelableHolder should be initialized with stability.
1279       // - enum should be zero initialized, otherwise the value will be indeterminate
1280       // - fixed-size arrays should be initialized, otherwise the value will be indeterminate
1281       if (type.GetName() == "ParcelableHolder") {
1282         if (defined_type.IsVintfStability()) {
1283           out << "{::ndk::STABILITY_VINTF}";
1284         } else {
1285           out << "{::ndk::STABILITY_LOCAL}";
1286         }
1287       } else if (types.GetEnumDeclaration(type) && !type.IsArray()) {
1288         out << " = " << cpp_type << "(0)";
1289       } else if (type.IsFixedSizeArray() && !type.IsNullable()) {
1290         out << " = {{}}";
1291       }
1292     }
1293     out << ";\n";
1294   }
1295   out << "\n";
1296   out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
1297   out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
1298   out << "\n";
1299 
1300   cpp::GenerateParcelableComparisonOperators(out, defined_type);
1301 
1302   out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1303       << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
1304 
1305   GenerateConstantDeclarations(out, types, defined_type);
1306   cpp::GenerateToString(out, defined_type);
1307 
1308   out.Dedent();
1309   out << "};\n";
1310 
1311   if (defined_type.IsFixedSize()) {
1312     size_t variable_offset = 0;
1313     for (const auto& variable : defined_type.GetFields()) {
1314       const auto& var_type = variable->GetType();
1315       // Assert the offset of each field within the struct
1316       auto alignment = cpp::AlignmentOf(var_type, types);
1317       AIDL_FATAL_IF(alignment == std::nullopt, var_type);
1318       variable_offset = cpp::AlignTo(variable_offset, *alignment);
1319       out << "static_assert(offsetof(" << defined_type.GetName() << ", " << variable->GetName()
1320           << ") == " << std::to_string(variable_offset) << ");\n";
1321 
1322       // Assert the size of each field
1323       std::string cpp_type = NdkNameOf(types, var_type, StorageMode::STACK);
1324       auto variable_size = cpp::SizeOf(var_type, types);
1325       AIDL_FATAL_IF(variable_size == std::nullopt, var_type);
1326       out << "static_assert(sizeof(" << cpp_type << ") == " << std::to_string(*variable_size)
1327           << ");\n";
1328 
1329       variable_offset += *variable_size;
1330     }
1331     auto parcelable_alignment = cpp::AlignmentOfDefinedType(defined_type, types);
1332     AIDL_FATAL_IF(parcelable_alignment == std::nullopt, defined_type);
1333     // Assert the alignment of the struct. Since we asserted the field offsets, this also ensures
1334     // fields have the right alignment
1335     out << "static_assert(alignof(" << defined_type.GetName()
1336         << ") == " << std::to_string(*parcelable_alignment) << ");\n";
1337 
1338     auto parcelable_size = cpp::SizeOfDefinedType(defined_type, types);
1339     AIDL_FATAL_IF(parcelable_size == std::nullopt, defined_type);
1340     // Assert the size of the struct
1341     out << "static_assert(sizeof(" << defined_type.GetName()
1342         << ") == " << std::to_string(*parcelable_size) << ");\n";
1343   }
1344 }
1345 
GenerateParcelSource(CodeWriter & out,const AidlTypenames & types,const AidlStructuredParcelable & defined_type,const Options & options)1346 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
1347                           const AidlStructuredParcelable& defined_type, const Options& options) {
1348   std::string clazz = GetQualifiedName(defined_type);
1349   if (defined_type.IsGeneric()) {
1350     std::vector<std::string> template_params;
1351     for (const auto& parameter : defined_type.GetTypeParameters()) {
1352       template_params.push_back(parameter);
1353     }
1354     clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1355   }
1356 
1357   GenerateSourceIncludes(out, types, defined_type, options);
1358   EnterNdkNamespace(out, defined_type);
1359   out << cpp::TemplateDecl(defined_type);
1360   out << "const char* " << clazz << "::" << kDescriptor << " = \""
1361       << defined_type.GetCanonicalName() << "\";\n";
1362   out << "\n";
1363 
1364   GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
1365 
1366   {
1367     cpp::ClangDiagnosticIgnoreDeprecated guard(out, cpp::HasDeprecatedField(defined_type));
1368     out << cpp::TemplateDecl(defined_type);
1369     out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _aidl_parcel) {\n";
1370     out.Indent();
1371     out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
1372     out << "int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);\n";
1373     out << "int32_t _aidl_parcelable_size = 0;\n";
1374     out << "_aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);\n";
1375     StatusCheckReturn(out);
1376     out << "if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;\n";
1377     out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
1378     for (const auto& variable : defined_type.GetFields()) {
1379       if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ)) {
1380         out << "if (false) {\n";
1381         out.Indent();
1382       }
1383 
1384       out << "if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= "
1385              "_aidl_parcelable_size) "
1386              "{\n"
1387           << "  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1388           << "  return _aidl_ret_status;\n"
1389           << "}\n";
1390       out << "_aidl_ret_status = ";
1391       ReadFromParcelFor(
1392           {out, types, variable->GetType(), "_aidl_parcel", "&" + variable->GetName()});
1393       out << ";\n";
1394       StatusCheckReturn(out);
1395       if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ)) {
1396         out.Dedent();
1397         out << "}\n";
1398       }
1399     }
1400     out << "AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1401         << "return _aidl_ret_status;\n";
1402     out.Dedent();
1403     out << "}\n";
1404 
1405     out << cpp::TemplateDecl(defined_type);
1406     out << "binder_status_t " << clazz << "::writeToParcel(AParcel* _aidl_parcel) const {\n";
1407     out.Indent();
1408     out << "binder_status_t _aidl_ret_status;\n";
1409 
1410     out << "size_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);\n";
1411     out << "_aidl_ret_status = AParcel_writeInt32(_aidl_parcel, 0);\n";
1412     StatusCheckReturn(out);
1413 
1414     for (const auto& variable : defined_type.GetFields()) {
1415       if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
1416         out << "if (false) {\n";
1417         out.Indent();
1418       }
1419       out << "_aidl_ret_status = ";
1420       WriteToParcelFor({out, types, variable->GetType(), "_aidl_parcel", variable->GetName()});
1421       out << ";\n";
1422       StatusCheckReturn(out);
1423       if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
1424         out.Dedent();
1425         out << "}\n";
1426       }
1427     }
1428     out << "size_t _aidl_end_pos = AParcel_getDataPosition(_aidl_parcel);\n";
1429     out << "AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos);\n";
1430     out << "AParcel_writeInt32(_aidl_parcel, _aidl_end_pos - _aidl_start_pos);\n";
1431     out << "AParcel_setDataPosition(_aidl_parcel, _aidl_end_pos);\n";
1432 
1433     out << "return _aidl_ret_status;\n";
1434     out.Dedent();
1435     out << "}\n";
1436   }
1437   out << "\n";
1438   LeaveNdkNamespace(out, defined_type);
1439 }
1440 
GenerateParcelClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlUnionDecl & defined_type,const Options & options)1441 void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
1442                              const AidlUnionDecl& defined_type, const Options& options) {
1443   const std::string clazz = ClassName(defined_type, ClassNames::RAW);
1444 
1445   cpp::ClangDiagnosticIgnoreDeprecated guard(out, cpp::HasDeprecatedField(defined_type));
1446   cpp::UnionWriter uw{defined_type, types,
1447                       [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1448                         return NdkNameOf(types, type, StorageMode::STACK);
1449                       },
1450                       &ConstantValueDecorator};
1451 
1452   out << cpp::TemplateDecl(defined_type);
1453   out << "class";
1454   cpp::GenerateDeprecated(out, defined_type);
1455   out << " " << clazz << " {\n";
1456   out << "public:\n";
1457   out.Indent();
1458   if (defined_type.IsFixedSize()) {
1459     out << "typedef std::true_type fixed_size;\n";
1460   } else {
1461     out << "typedef std::false_type fixed_size;\n";
1462   }
1463   out << "static const char* descriptor;\n";
1464   out << "\n";
1465   GenerateNestedTypeDecls(out, types, defined_type, options);
1466   uw.PublicFields(out);
1467 
1468   out << "binder_status_t readFromParcel(const AParcel* _parcel);\n";
1469   out << "binder_status_t writeToParcel(AParcel* _parcel) const;\n";
1470   out << "\n";
1471 
1472   cpp::GenerateParcelableComparisonOperators(out, defined_type);
1473 
1474   out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1475       << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
1476   GenerateConstantDeclarations(out, types, defined_type);
1477   cpp::GenerateToString(out, defined_type);
1478   out.Dedent();
1479   out << "private:\n";
1480   out.Indent();
1481   uw.PrivateFields(out);
1482   out.Dedent();
1483   out << "};\n";
1484   if (defined_type.IsFixedSize()) {
1485     auto alignment = cpp::AlignmentOfDefinedType(defined_type, types);
1486     AIDL_FATAL_IF(alignment == std::nullopt, defined_type);
1487     for (const auto& variable : defined_type.GetFields()) {
1488       // Assert the size of each union variant
1489       const auto& var_type = variable->GetType();
1490       std::string cpp_type = NdkNameOf(types, var_type, StorageMode::STACK);
1491       auto variable_size = cpp::SizeOf(var_type, types);
1492       AIDL_FATAL_IF(variable_size == std::nullopt, var_type);
1493       out << "static_assert(sizeof(" << cpp_type << ") == " << std::to_string(*variable_size)
1494           << ");\n";
1495     }
1496     // Assert the alignment of the tagged union
1497     out << "static_assert(alignof(" << clazz << ") == " << std::to_string(*alignment) << ");\n";
1498 
1499     // Assert the size of the tagged union, taking the tag and its padding into account
1500     auto union_size = cpp::SizeOfDefinedType(defined_type, types);
1501     AIDL_FATAL_IF(union_size == std::nullopt, defined_type);
1502     out << "static_assert(sizeof(" << clazz << ") == " << std::to_string(*union_size) << ");\n";
1503   }
1504 }
1505 
GenerateParcelSource(CodeWriter & out,const AidlTypenames & types,const AidlUnionDecl & defined_type,const Options & options)1506 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
1507                           const AidlUnionDecl& defined_type, const Options& options) {
1508   std::string clazz = GetQualifiedName(defined_type);
1509   if (defined_type.IsGeneric()) {
1510     std::vector<std::string> template_params;
1511     for (const auto& parameter : defined_type.GetTypeParameters()) {
1512       template_params.push_back(parameter);
1513     }
1514     clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1515   }
1516 
1517   cpp::UnionWriter uw{defined_type, types,
1518                       [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1519                         return NdkNameOf(types, type, StorageMode::STACK);
1520                       },
1521                       &ConstantValueDecorator};
1522   cpp::ParcelWriterContext ctx{
1523       .status_type = "binder_status_t",
1524       .status_ok = "STATUS_OK",
1525       .status_bad = "STATUS_BAD_VALUE",
1526       .read_func =
1527           [&](CodeWriter& out, const std::string& var, const AidlTypeSpecifier& type) {
1528             ReadFromParcelFor({out, types, type, "_parcel", "&" + var});
1529           },
1530       .write_func =
1531           [&](CodeWriter& out, const std::string& value, const AidlTypeSpecifier& type) {
1532             WriteToParcelFor({out, types, type, "_parcel", value});
1533           },
1534   };
1535 
1536   GenerateSourceIncludes(out, types, defined_type, options);
1537   EnterNdkNamespace(out, defined_type);
1538   out << cpp::TemplateDecl(defined_type);
1539   out << "const char* " << clazz << "::" << kDescriptor << " = \""
1540       << defined_type.GetCanonicalName() << "\";\n";
1541   out << "\n";
1542 
1543   GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
1544 
1545   {
1546     cpp::ClangDiagnosticIgnoreDeprecated guard(out, cpp::HasDeprecatedField(defined_type));
1547     out << cpp::TemplateDecl(defined_type);
1548     out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _parcel) {\n";
1549     out.Indent();
1550     uw.ReadFromParcel(out, ctx);
1551     out.Dedent();
1552     out << "}\n";
1553 
1554     out << cpp::TemplateDecl(defined_type);
1555     out << "binder_status_t " << clazz << "::writeToParcel(AParcel* _parcel) const {\n";
1556     out.Indent();
1557     uw.WriteToParcel(out, ctx);
1558     out.Dedent();
1559     out << "}\n";
1560   }
1561 
1562   out << "\n";
1563   LeaveNdkNamespace(out, defined_type);
1564 }
1565 
GenerateEnumClassDecl(CodeWriter & out,const AidlTypenames & types,const AidlEnumDeclaration & enum_decl,const Options &)1566 void GenerateEnumClassDecl(CodeWriter& out, const AidlTypenames& types,
1567                            const AidlEnumDeclaration& enum_decl, const Options&) {
1568   cpp::GenerateEnumClassDecl(out, enum_decl,
1569                              NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK),
1570                              ConstantValueDecorator);
1571   out << "\n";
1572 }
1573 
1574 }  // namespace internals
1575 }  // namespace ndk
1576 }  // namespace aidl
1577 }  // namespace android
1578