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