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