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