blob: ca8d66cc14299ef30eda61aea2be9ad68418003f [file] [log] [blame]
Steven Morelandb0057e72018-08-27 01:44:11 -07001/*
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
Jiyong Park965c5b92018-11-21 13:37:15 +090019#include "aidl.h"
Steven Morelandb0057e72018-08-27 01:44:11 -070020#include "aidl_language.h"
21#include "aidl_to_cpp_common.h"
Steven Morelandaada3422018-09-20 15:55:33 -070022#include "aidl_to_ndk.h"
Jiyong Park2a7c92b2020-07-22 19:12:36 +090023#include "logging.h"
Steven Morelandb0057e72018-08-27 01:44:11 -070024
Devin Moore53fc99c2020-08-12 08:07:52 -070025#include <android-base/stringprintf.h>
26
Steven Morelandb0057e72018-08-27 01:44:11 -070027namespace android {
28namespace aidl {
29namespace ndk {
30
Steven Moreland15b3ba72019-03-06 13:17:08 -080031static constexpr const char* kClazz = "_g_aidl_clazz";
Jiyong Park965c5b92018-11-21 13:37:15 +090032static constexpr const char* kDescriptor = "descriptor";
33static constexpr const char* kVersion = "version";
Paul Trautrimb77048c2020-01-21 16:39:32 +090034static constexpr const char* kHash = "hash";
35static constexpr const char* kCachedVersion = "_aidl_cached_version";
36static constexpr const char* kCachedHash = "_aidl_cached_hash";
37static constexpr const char* kCachedHashMutex = "_aidl_cached_hash_mutex";
Jiyong Park965c5b92018-11-21 13:37:15 +090038
Steven Morelandb0057e72018-08-27 01:44:11 -070039using namespace internals;
Jooyung Han6beac042020-10-17 21:59:43 +090040namespace internals {
41void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
42 const AidlStructuredParcelable& defined_type, const Options& options);
43void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
44 const AidlStructuredParcelable& defined_type, const Options& options);
45void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
46 const AidlUnionDecl& defined_type, const Options& options);
47void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
48 const AidlUnionDecl& defined_type, const Options& options);
49} // namespace internals
50
Steven Morelandb0057e72018-08-27 01:44:11 -070051using cpp::ClassNames;
52
53void GenerateNdkInterface(const string& output_file, const Options& options,
54 const AidlTypenames& types, const AidlInterface& defined_type,
55 const IoDelegate& io_delegate) {
Jiyong Park5b7e5322019-04-03 20:05:01 +090056 const string i_header = options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
Steven Morelandb0057e72018-08-27 01:44:11 -070057 unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
58 GenerateInterfaceHeader(*i_writer, types, defined_type, options);
Steven Moreland21780812020-09-11 01:29:45 +000059 AIDL_FATAL_IF(!i_writer->Close(), i_header);
Steven Morelandb0057e72018-08-27 01:44:11 -070060
Steven Moreland7c933372018-10-11 15:20:04 -070061 const string bp_header =
62 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070063 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
64 GenerateClientHeader(*bp_writer, types, defined_type, options);
Steven Moreland21780812020-09-11 01:29:45 +000065 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
Steven Morelandb0057e72018-08-27 01:44:11 -070066
Steven Moreland7c933372018-10-11 15:20:04 -070067 const string bn_header =
68 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070069 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
70 GenerateServerHeader(*bn_writer, types, defined_type, options);
Steven Moreland21780812020-09-11 01:29:45 +000071 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
Steven Morelandb0057e72018-08-27 01:44:11 -070072
73 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
74 GenerateSource(*source_writer, types, defined_type, options);
Steven Moreland21780812020-09-11 01:29:45 +000075 AIDL_FATAL_IF(!source_writer->Close(), output_file);
Steven Morelandb0057e72018-08-27 01:44:11 -070076}
77
Jooyung Han6beac042020-10-17 21:59:43 +090078template <typename ParcelableType>
Steven Morelandb0057e72018-08-27 01:44:11 -070079void GenerateNdkParcel(const string& output_file, const Options& options,
Jooyung Han6beac042020-10-17 21:59:43 +090080 const AidlTypenames& types, const ParcelableType& defined_type,
Steven Morelandb0057e72018-08-27 01:44:11 -070081 const IoDelegate& io_delegate) {
Steven Moreland7c933372018-10-11 15:20:04 -070082 const string header_path =
Jiyong Park5b7e5322019-04-03 20:05:01 +090083 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
Steven Morelandb0057e72018-08-27 01:44:11 -070084 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
85 GenerateParcelHeader(*header_writer, types, defined_type, options);
Devin Moore53fc99c2020-08-12 08:07:52 -070086
87 unique_ptr<CodeWriter> source_writer(io_delegate.GetCodeWriter(output_file));
88 if (defined_type.IsGeneric()) {
89 // Need to write source to header if this is a template
90 GenerateParcelSource(*header_writer, types, defined_type, options);
91 } else {
92 GenerateParcelSource(*source_writer, types, defined_type, options);
93 }
Steven Moreland21780812020-09-11 01:29:45 +000094 (source_writer->Close());
95 AIDL_FATAL_IF(!header_writer->Close(), header_path);
Steven Morelandb0057e72018-08-27 01:44:11 -070096
Steven Moreland7c933372018-10-11 15:20:04 -070097 const string bp_header =
98 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070099 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
100 *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
Steven Moreland21780812020-09-11 01:29:45 +0000101 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
Steven Morelandb0057e72018-08-27 01:44:11 -0700102
Steven Moreland7c933372018-10-11 15:20:04 -0700103 const string bn_header =
104 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -0700105 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
106 *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
Steven Moreland21780812020-09-11 01:29:45 +0000107 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
Steven Morelandb0057e72018-08-27 01:44:11 -0700108}
109
Steven Moreland2a9a7d62019-02-05 16:11:54 -0800110void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
111 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
112 *code_writer
113 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
Steven Moreland21780812020-09-11 01:29:45 +0000114 AIDL_FATAL_IF(!code_writer->Close(), filename);
Steven Moreland2a9a7d62019-02-05 16:11:54 -0800115}
116
Daniel Norman37d43dd2019-09-09 17:22:34 -0700117void GenerateNdkEnumDeclaration(const string& output_file, const Options& options,
118 const AidlTypenames& types, const AidlEnumDeclaration& defined_type,
119 const IoDelegate& io_delegate) {
120 const string header_path =
121 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
122 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
123 GenerateEnumHeader(*header_writer, types, defined_type, options);
Steven Moreland21780812020-09-11 01:29:45 +0000124 AIDL_FATAL_IF(!header_writer->Close(), header_path);
Daniel Norman37d43dd2019-09-09 17:22:34 -0700125
126 const string bp_header =
127 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
128 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
129 *bp_writer << "#error TODO(b/111362593) enums do not have bp classes\n";
Steven Moreland21780812020-09-11 01:29:45 +0000130 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
Daniel Norman37d43dd2019-09-09 17:22:34 -0700131
132 const string bn_header =
133 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
134 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
135 *bn_writer << "#error TODO(b/111362593) enums do not have bn classes\n";
Steven Moreland21780812020-09-11 01:29:45 +0000136 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
Daniel Norman37d43dd2019-09-09 17:22:34 -0700137
138 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
139 *source_writer
140 << "// This file is intentionally left blank as placeholder for enum declaration.\n";
Steven Moreland21780812020-09-11 01:29:45 +0000141 AIDL_FATAL_IF(!source_writer->Close(), output_file);
Daniel Norman37d43dd2019-09-09 17:22:34 -0700142}
143
Steven Morelandb0057e72018-08-27 01:44:11 -0700144void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
145 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700146 if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
147 parcelable != nullptr) {
Jooyung Han6beac042020-10-17 21:59:43 +0900148 GenerateNdkParcel<AidlStructuredParcelable>(output_file, options, types, *parcelable,
149 io_delegate);
150 return;
151 }
152
153 if (const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration(); union_decl != nullptr) {
154 GenerateNdkParcel<AidlUnionDecl>(output_file, options, types, *union_decl, io_delegate);
Steven Morelandb0057e72018-08-27 01:44:11 -0700155 return;
156 }
157
Daniel Norman37d43dd2019-09-09 17:22:34 -0700158 if (const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
159 parcelable_decl != nullptr) {
Steven Moreland2a9a7d62019-02-05 16:11:54 -0800160 GenerateNdkParcelDeclaration(output_file, io_delegate);
161 return;
162 }
163
Daniel Norman37d43dd2019-09-09 17:22:34 -0700164 if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
165 enum_decl != nullptr) {
166 GenerateNdkEnumDeclaration(output_file, options, types, *enum_decl, io_delegate);
167 return;
168 }
169
170 if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700171 GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
172 return;
173 }
174
Steven Moreland21780812020-09-11 01:29:45 +0000175 AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK cpp generation.";
Steven Morelandb0057e72018-08-27 01:44:11 -0700176}
177namespace internals {
178
179void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
180 out << "namespace aidl {\n";
181 cpp::EnterNamespace(out, defined_type);
182}
183void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
184 cpp::LeaveNamespace(out, defined_type);
185 out << "} // namespace aidl\n";
186}
187
Steven Morelandaada3422018-09-20 15:55:33 -0700188static void StatusCheckGoto(CodeWriter& out) {
189 out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
190}
191static void StatusCheckBreak(CodeWriter& out) {
192 out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
193}
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700194static void StatusCheckReturn(CodeWriter& out) {
195 out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
196}
Steven Morelandaada3422018-09-20 15:55:33 -0700197
Steven Moreland2bea13b2018-10-03 15:12:33 -0700198static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
199 const AidlDefinedType& defined_type) {
Steven Moreland8769f932019-10-30 15:38:10 -0700200 out << "#include <cstdint>\n";
201 out << "#include <memory>\n";
202 out << "#include <optional>\n";
203 out << "#include <string>\n";
204 out << "#include <vector>\n";
Steven Moreland88378b12019-10-11 13:13:24 -0700205 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700206 out << "#include <android/binder_stability.h>\n";
Steven Moreland88378b12019-10-11 13:13:24 -0700207 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700208
Steven Morelanda7764e52020-10-27 17:29:29 +0000209 if (defined_type.IsSensitiveData()) {
210 out << "#include <android/binder_parcel_platform.h>\n";
211 out << "#include <android/binder_ibinder_platform.h>\n";
212 }
213
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900214 auto headerFilePath = [&types](const AidlTypeSpecifier& typespec) -> std::string {
215 const AidlDefinedType* type = types.TryGetDefinedType(typespec.GetName());
216 if (type == nullptr) {
217 // could be a primitive type.
218 return "";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700219 }
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900220
221 if (type->AsInterface() != nullptr) {
222 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
223 } else if (type->AsStructuredParcelable() != nullptr) {
224 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
Jooyung Han6beac042020-10-17 21:59:43 +0900225 } else if (type->AsUnionDeclaration() != nullptr) {
226 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900227 } else if (type->AsParcelable() != nullptr) {
228 return type->AsParcelable()->GetCppHeader();
229 } else if (type->AsEnumDeclaration() != nullptr) {
230 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
231 } else {
232 AIDL_FATAL(*type) << "Unrecognized type.";
233 return "";
234 }
235 };
236
237 std::set<std::string> includes;
238
Jooyung Han14004ed2020-10-16 03:49:57 +0900239 // visit a type and collect all reference types' headers
240 std::function<void(const AidlTypeSpecifier& type)> visit = [&](const AidlTypeSpecifier& type) {
241 includes.insert(headerFilePath(type));
242 if (type.IsGeneric()) {
243 for (const auto& param : type.GetTypeParameters()) {
244 visit(*param);
245 }
246 }
247 };
248
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900249 const AidlInterface* interface = defined_type.AsInterface();
250 if (interface != nullptr) {
251 for (const auto& method : interface->GetMethods()) {
Jooyung Han14004ed2020-10-16 03:49:57 +0900252 visit(method->GetType());
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900253 for (const auto& argument : method->GetArguments()) {
Jooyung Han14004ed2020-10-16 03:49:57 +0900254 visit(argument->GetType());
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900255 }
256 }
257 }
258
Jooyung Han6beac042020-10-17 21:59:43 +0900259 auto visit_parcelable = [&](const auto& parcelable) {
260 for (const auto& field : parcelable.GetFields()) {
Jooyung Han14004ed2020-10-16 03:49:57 +0900261 visit(field->GetType());
Devin Moore53fc99c2020-08-12 08:07:52 -0700262 // Check the fields for generic type arguments
263 if (field->GetType().IsGeneric()) {
264 for (const auto& type_argument : field->GetType().GetTypeParameters()) {
Jooyung Han14004ed2020-10-16 03:49:57 +0900265 visit(*type_argument);
Devin Moore53fc99c2020-08-12 08:07:52 -0700266 }
267 }
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900268 }
Jooyung Han6beac042020-10-17 21:59:43 +0900269 };
270
271 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
272 if (parcelable != nullptr) {
273 visit_parcelable(*parcelable);
274 }
275
276 const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
277 if (union_decl != nullptr) {
278 visit_parcelable(*union_decl);
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900279 }
280
281 const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
282 if (enum_decl != nullptr) {
Jooyung Han14004ed2020-10-16 03:49:57 +0900283 visit(enum_decl->GetBackingType());
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900284 }
285
286 for (const auto& path : includes) {
287 if (path == "") {
288 continue;
289 }
290 out << "#include <" << path << ">\n";
291 }
Steven Moreland2bea13b2018-10-03 15:12:33 -0700292}
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900293
Steven Moreland2bea13b2018-10-03 15:12:33 -0700294static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
295 const AidlDefinedType& /*defined_type*/) {
Steven Moreland8769f932019-10-30 15:38:10 -0700296 out << "#include <android/binder_parcel_utils.h>\n";
297
Steven Moreland2bea13b2018-10-03 15:12:33 -0700298 types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
299 if (a_defined_type.AsInterface() != nullptr) {
Steven Moreland7c933372018-10-11 15:20:04 -0700300 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700301 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700302 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700303 << ">\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900304 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/)
305 << ">\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700306 }
307 });
308}
309
Jooyung Han3f347ca2020-12-01 12:41:50 +0900310template <typename TypeWithConstants>
Steven Morelande689da22020-11-10 02:06:30 +0000311static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types,
Jooyung Han3f347ca2020-12-01 12:41:50 +0900312 const TypeWithConstants& type) {
313 for (const auto& constant : type.GetConstantDeclarations()) {
Steven Morelande689da22020-11-10 02:06:30 +0000314 const AidlTypeSpecifier& type = constant->GetType();
315
Jooyung Han965e31d2020-11-27 12:30:16 +0900316 if (type.Signature() == "String") {
Jooyung Han720253d2021-01-05 19:13:17 +0900317 out << "static const char*";
318 cpp::GenerateDeprecated(out, *constant);
319 out << " " << constant->GetName() << ";\n";
Steven Morelande689da22020-11-10 02:06:30 +0000320 } else {
Jooyung Han720253d2021-01-05 19:13:17 +0900321 out << "enum : " << NdkNameOf(types, type, StorageMode::STACK) << " { ";
322 out << constant->GetName();
323 cpp::GenerateDeprecated(out, *constant);
324 out << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700325 }
326 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700327}
Steven Morelande689da22020-11-10 02:06:30 +0000328
Jooyung Han3f347ca2020-12-01 12:41:50 +0900329template <typename TypeWithConstants>
330static void GenerateConstantDefinitions(CodeWriter& out, const TypeWithConstants& interface,
331 const std::string& clazz,
332 const std::string& tmpl_decl = "") {
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700333 for (const auto& constant : interface.GetConstantDeclarations()) {
334 const AidlConstantValue& value = constant->GetValue();
Steven Moreland21780812020-09-11 01:29:45 +0000335 AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
336 value.GetType() == AidlConstantValue::Type::BINARY,
337 value);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700338 if (value.GetType() == AidlConstantValue::Type::STRING) {
Jooyung Han3f347ca2020-12-01 12:41:50 +0900339 out << tmpl_decl;
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700340 out << "const char* " << clazz << "::" << constant->GetName() << " = "
Daniel Norman37d43dd2019-09-09 17:22:34 -0700341 << constant->ValueString(ConstantValueDecorator) << ";\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700342 }
343 }
344}
345
Steven Morelandb0057e72018-08-27 01:44:11 -0700346void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
347 const Options& options) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700348 GenerateSourceIncludes(out, types, defined_type);
Jooyung Han90a0bf72021-02-04 10:11:07 +0900349 if (options.GenLog()) {
350 out << "#include <android/binder_to_string.h>\n";
351 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700352 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700353
Steven Morelandb0057e72018-08-27 01:44:11 -0700354 EnterNdkNamespace(out, defined_type);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700355 GenerateClassSource(out, types, defined_type, options);
Steven Morelandb0057e72018-08-27 01:44:11 -0700356 GenerateClientSource(out, types, defined_type, options);
357 GenerateServerSource(out, types, defined_type, options);
358 GenerateInterfaceSource(out, types, defined_type, options);
359 LeaveNdkNamespace(out, defined_type);
360}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700361
Steven Morelandaada3422018-09-20 15:55:33 -0700362static std::string MethodId(const AidlMethod& m) {
363 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
364}
365
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900366static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
367 const AidlInterface& defined_type,
368 const AidlMethod& method,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900369 const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700370 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
371
Steven Moreland2bea13b2018-10-03 15:12:33 -0700372 out << NdkMethodDecl(types, method, clazz) << " {\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700373 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700374 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
Steven Moreland63404532018-10-08 14:31:00 -0700375 out << "::ndk::ScopedAStatus _aidl_status;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900376
Paul Trautrimb77048c2020-01-21 16:39:32 +0900377 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
378 out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
379 out << "if (" << kCachedHash << " != \"-1\") {\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900380 out.Indent();
Paul Trautrimb77048c2020-01-21 16:39:32 +0900381 out << "*_aidl_return = " << kCachedHash << ";\n"
382 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
383 << "return _aidl_status;\n";
384 out.Dedent();
385 out << "}\n";
386 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
387 out << "if (" << kCachedVersion << " != -1) {\n";
388 out.Indent();
389 out << "*_aidl_return = " << kCachedVersion << ";\n"
Jeongik Chac9972922019-02-11 12:41:16 +0900390 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
391 << "return _aidl_status;\n";
392 out.Dedent();
393 out << "}\n";
394 }
395 out << "::ndk::ScopedAParcel _aidl_in;\n";
396 out << "::ndk::ScopedAParcel _aidl_out;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700397 out << "\n";
398
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900399 if (options.GenLog()) {
400 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
401 false /* isServer */, true /* isNdk */);
402 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700403 if (options.GenTraces()) {
Jooyung Han9435e9a2021-01-06 10:16:31 +0900404 out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
Devin Moore7d5a4542020-04-29 15:37:25 -0700405 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
406 << "::client\");\n";
407 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900408
Steven Morelandaada3422018-09-20 15:55:33 -0700409 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
Steven Morelanda7764e52020-10-27 17:29:29 +0000410 if (defined_type.IsSensitiveData()) {
411 out << "AParcel_markSensitive(_aidl_in.get());\n";
412 }
Steven Morelandaada3422018-09-20 15:55:33 -0700413 StatusCheckGoto(out);
414
Steven Morelandeb38ee72018-10-15 14:20:04 -0700415 for (const auto& arg : method.GetArguments()) {
416 const std::string var_name = cpp::BuildVarName(*arg);
417
418 if (arg->IsIn()) {
419 out << "_aidl_ret_status = ";
420 const std::string prefix = (arg->IsOut() ? "*" : "");
421 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
422 out << ";\n";
423 StatusCheckGoto(out);
424 } else if (arg->IsOut() && arg->GetType().IsArray()) {
425 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
426 << ");\n";
Steven Moreland823e4db2020-12-11 18:37:11 +0000427 StatusCheckGoto(out);
Steven Morelandeb38ee72018-10-15 14:20:04 -0700428 }
Steven Morelandaada3422018-09-20 15:55:33 -0700429 }
430 out << "_aidl_ret_status = AIBinder_transact(\n";
431 out.Indent();
432 out << "asBinder().get(),\n";
433 out << MethodId(method) << ",\n";
434 out << "_aidl_in.getR(),\n";
435 out << "_aidl_out.getR(),\n";
Steven Morelanda7764e52020-10-27 17:29:29 +0000436
437 std::vector<std::string> flags;
438 if (method.IsOneway()) flags.push_back("FLAG_ONEWAY");
439 if (defined_type.IsSensitiveData()) flags.push_back("FLAG_CLEAR_BUF");
440 out << (flags.empty() ? "0" : base::Join(flags, " | ")) << "\n";
441
Steven Morelandb72a1e72019-10-15 11:23:26 -0700442 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
443 out << "| FLAG_PRIVATE_LOCAL\n";
444 out << "#endif // BINDER_STABILITY_SUPPORT\n";
445 out << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700446 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900447
448 // If the method is not implmented in the server side but the client has
449 // provided the default implementation, call it instead of failing hard.
450 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
451 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
452 out << iface << "::getDefaultImpl()) {\n";
453 out.Indent();
Devin Moore7d5a4542020-04-29 15:37:25 -0700454 out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
Jiyong Park965c5b92018-11-21 13:37:15 +0900455 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700456 out << "goto _aidl_status_return;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900457 out.Dedent();
458 out << "}\n";
459
Steven Morelandaada3422018-09-20 15:55:33 -0700460 StatusCheckGoto(out);
461
462 if (!method.IsOneway()) {
463 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
464 StatusCheckGoto(out);
465
Devin Moore7d5a4542020-04-29 15:37:25 -0700466 out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700467 }
468
Steven Morelandaada3422018-09-20 15:55:33 -0700469 if (method.GetType().GetName() != "void") {
470 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700471 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700472 out << ";\n";
473 StatusCheckGoto(out);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900474 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
475 out << kCachedHash << " = *_aidl_return;\n";
476 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
477 out << kCachedVersion << " = *_aidl_return;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900478 }
Steven Morelandaada3422018-09-20 15:55:33 -0700479 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700480 for (const AidlArgument* arg : method.GetOutArguments()) {
481 out << "_aidl_ret_status = ";
482 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
483 out << ";\n";
484 StatusCheckGoto(out);
485 }
Steven Morelandaada3422018-09-20 15:55:33 -0700486
487 out << "_aidl_error:\n";
488 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700489 out << "_aidl_status_return:\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900490 if (options.GenLog()) {
491 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
492 method, "_aidl_status", "_aidl_return", false /* isServer */,
493 true /* isNdk */);
494 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700495
Steven Morelandaada3422018-09-20 15:55:33 -0700496 out << "return _aidl_status;\n";
497 out.Dedent();
498 out << "}\n";
499}
500
Steven Moreland2bea13b2018-10-03 15:12:33 -0700501static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900502 const AidlInterface& defined_type,
503 const AidlMethod& method, const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700504 out << "case " << MethodId(method) << ": {\n";
505 out.Indent();
506 for (const auto& arg : method.GetArguments()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700507 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
508 << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700509 }
510 if (method.GetType().GetName() != "void") {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700511 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700512 }
513 out << "\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700514 if (options.GenTraces()) {
Jooyung Han9435e9a2021-01-06 10:16:31 +0900515 out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
Devin Moore7d5a4542020-04-29 15:37:25 -0700516 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
517 << "::server\");\n";
518 }
Steven Morelandaada3422018-09-20 15:55:33 -0700519
Steven Morelandeb38ee72018-10-15 14:20:04 -0700520 for (const auto& arg : method.GetArguments()) {
521 const std::string var_name = cpp::BuildVarName(*arg);
522
523 if (arg->IsIn()) {
524 out << "_aidl_ret_status = ";
525 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
526 out << ";\n";
527 StatusCheckBreak(out);
528 } else if (arg->IsOut() && arg->GetType().IsArray()) {
529 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
Steven Moreland823e4db2020-12-11 18:37:11 +0000530 StatusCheckBreak(out);
Steven Morelandeb38ee72018-10-15 14:20:04 -0700531 }
Steven Morelandaada3422018-09-20 15:55:33 -0700532 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900533 if (options.GenLog()) {
534 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
535 true /* isServer */, true /* isNdk */);
536 }
Steven Moreland63404532018-10-08 14:31:00 -0700537 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
Jiyong Park965c5b92018-11-21 13:37:15 +0900538 << NdkArgList(types, method, FormatArgForCall) << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700539
Jeongik Chaeaf978e2019-05-04 00:32:35 +0900540 if (options.GenLog()) {
541 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
542 method, "_aidl_status", "_aidl_return", true /* isServer */,
543 true /* isNdk */);
544 }
Steven Morelandaada3422018-09-20 15:55:33 -0700545 if (method.IsOneway()) {
546 // For a oneway transaction, the kernel will have already returned a result. This is for the
547 // in-process case when a oneway transaction is parceled/unparceled in the same process.
548 out << "_aidl_ret_status = STATUS_OK;\n";
549 } else {
550 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
551 StatusCheckBreak(out);
552
553 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
554
Steven Morelandaada3422018-09-20 15:55:33 -0700555 if (method.GetType().GetName() != "void") {
556 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700557 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700558 out << ";\n";
559 StatusCheckBreak(out);
560 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700561 for (const AidlArgument* arg : method.GetOutArguments()) {
562 out << "_aidl_ret_status = ";
563 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
564 out << ";\n";
565 StatusCheckBreak(out);
566 }
Steven Morelandaada3422018-09-20 15:55:33 -0700567 }
Steven Morelandaada3422018-09-20 15:55:33 -0700568 out << "break;\n";
569 out.Dedent();
570 out << "}\n";
571}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700572
Steven Moreland2bea13b2018-10-03 15:12:33 -0700573void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900574 const AidlInterface& defined_type, const Options& options) {
Steven Moreland0cf3f082018-09-20 19:09:46 -0700575 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
576 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
Devin Mooref7600872020-05-13 15:47:50 -0700577 if (options.GenTraces()) {
578 out << "class ScopedTrace {\n";
579 out.Indent();
580 out << "public:\n"
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900581 << "inline explicit ScopedTrace(const char* name) {\n"
Devin Mooref7600872020-05-13 15:47:50 -0700582 << "ATrace_beginSection(name);\n"
583 << "}\n"
584 << "inline ~ScopedTrace() {\n"
585 << "ATrace_endSection();\n"
586 << "}\n";
587 out.Dedent();
588 out << "};\n";
589 }
Jooyung Han720253d2021-01-05 19:13:17 +0900590 bool deprecated = defined_type.IsDeprecated() ||
591 std::any_of(defined_type.GetMethods().begin(), defined_type.GetMethods().end(),
592 [](const auto& m) { return m->IsDeprecated(); });
593 if (deprecated) {
594 out << "#pragma clang diagnostic push\n";
595 out << "#pragma clang diagnostic ignored \"-Wdeprecated\"\n";
596 }
Steven Moreland15b3ba72019-03-06 13:17:08 -0800597 out << "static binder_status_t "
598 << "_aidl_onTransact"
Steven Morelandaada3422018-09-20 15:55:33 -0700599 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
600 "AParcel* _aidl_out) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700601 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700602 out << "(void)_aidl_in;\n";
603 out << "(void)_aidl_out;\n";
604 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
605 if (!defined_type.GetMethods().empty()) {
Steven Moreland15b3ba72019-03-06 13:17:08 -0800606 // we know this cast is valid because this method is only called by the ICInterface
607 // AIBinder_Class object which is associated with this class.
608 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = std::static_pointer_cast<" << bn_clazz
609 << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700610 out << "switch (_aidl_code) {\n";
611 out.Indent();
612 for (const auto& method : defined_type.GetMethods()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900613 GenerateServerCaseDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700614 }
615 out.Dedent();
616 out << "}\n";
617 } else {
618 out << "(void)_aidl_binder;\n";
619 out << "(void)_aidl_code;\n";
620 }
621 out << "return _aidl_ret_status;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700622 out.Dedent();
Steven Moreland73d66242019-09-26 16:03:54 -0700623 out << "}\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700624
Steven Moreland15b3ba72019-03-06 13:17:08 -0800625 out << "static AIBinder_Class* " << kClazz << " = ::ndk::ICInterface::defineClass(" << clazz
626 << "::" << kDescriptor << ", _aidl_onTransact);\n\n";
Jooyung Han720253d2021-01-05 19:13:17 +0900627 if (deprecated) {
628 out << "#pragma clang diagnostic pop\n";
629 }
Steven Moreland0cf3f082018-09-20 19:09:46 -0700630}
Jooyung Han720253d2021-01-05 19:13:17 +0900631
Steven Morelandb0057e72018-08-27 01:44:11 -0700632void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900633 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700634 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700635
Steven Moreland63404532018-10-08 14:31:00 -0700636 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700637 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900638 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900639 out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900640 }
Steven Morelandaada3422018-09-20 15:55:33 -0700641 out << "\n";
642 for (const auto& method : defined_type.GetMethods()) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900643 GenerateClientMethodDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700644 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700645}
Jiyong Park965c5b92018-11-21 13:37:15 +0900646void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
647 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700648 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900649 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700650
651 out << "// Source for " << clazz << "\n";
652 out << clazz << "::" << clazz << "() {}\n";
653 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900654 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900655 out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900656 }
Steven Moreland63404532018-10-08 14:31:00 -0700657 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700658 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800659 out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700660
Steven Moreland88378b12019-10-11 13:13:24 -0700661 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700662 if (defined_type.IsVintfStability()) {
663 out << "AIBinder_markVintfStability(binder);\n";
664 } else {
665 out << "AIBinder_markCompilationUnitStability(binder);\n";
666 }
Steven Moreland88378b12019-10-11 13:13:24 -0700667 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700668
Steven Moreland63404532018-10-08 14:31:00 -0700669 out << "return ::ndk::SpAIBinder(binder);\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700670 out.Dedent();
671 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900672
673 // Implement the meta methods
674 for (const auto& method : defined_type.GetMethods()) {
675 if (method->IsUserDefined()) {
676 continue;
677 }
678 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
679 out << NdkMethodDecl(types, *method, clazz) << " {\n";
680 out.Indent();
681 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
682 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
683 out.Dedent();
684 out << "}\n";
685 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900686 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
687 out << NdkMethodDecl(types, *method, clazz) << " {\n";
688 out.Indent();
689 out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
690 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
691 out.Dedent();
692 out << "}\n";
693 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900694 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700695}
Jiyong Park965c5b92018-11-21 13:37:15 +0900696void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
697 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700698 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland15b3ba72019-03-06 13:17:08 -0800699 const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -0700700
701 out << "// Source for " << clazz << "\n";
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900702 out << "const char* " << clazz << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
703 << "\";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700704 out << clazz << "::" << clazz << "() {}\n";
705 out << clazz << "::~" << clazz << "() {}\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700706 out << "\n";
Jooyung Han3f347ca2020-12-01 12:41:50 +0900707 GenerateConstantDefinitions(out, defined_type, clazz);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700708 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700709
Steven Moreland3c316ed2019-01-17 09:39:37 -0800710 out << "std::shared_ptr<" << clazz << "> " << clazz
711 << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800712 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800713 out << "if (!AIBinder_associateClass(binder.get(), " << kClazz << ")) { return nullptr; }\n";
714 out << "std::shared_ptr<::ndk::ICInterface> interface = "
715 "::ndk::ICInterface::asInterface(binder.get());\n";
716 out << "if (interface) {\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800717 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800718 out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800719 out.Dedent();
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800720 out << "}\n";
Steven Morelandc09d34c2020-02-13 09:42:49 -0800721 out << "return ::ndk::SharedRefBase::make<" << bp_clazz << ">(binder);\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800722 out.Dedent();
Steven Moreland3c316ed2019-01-17 09:39:37 -0800723 out << "}\n\n";
724
Steven Moreland2bea13b2018-10-03 15:12:33 -0700725 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
726 << clazz << ">& instance) {\n";
727 out.Indent();
728 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
729 "nullptr);\n";
730 out.Dedent();
731 out << "}\n";
732
733 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
734 << clazz << ">* instance) {\n";
735 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700736 out << "::ndk::SpAIBinder binder;\n";
Steven Moreland055d8792018-11-14 12:48:42 -0800737 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700738 out << "if (status != STATUS_OK) return status;\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800739 out << "*instance = " << clazz << "::fromBinder(binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700740 out << "return STATUS_OK;\n";
741 out.Dedent();
742 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900743
744 // defintion for static member setDefaultImpl
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900745 out << "bool " << clazz << "::setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl) {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900746 out.Indent();
Jooyung Han4a044662020-05-13 17:17:07 +0900747 out << "// Only one user of this interface can use this function\n";
748 out << "// at a time. This is a heuristic to detect if two different\n";
749 out << "// users in the same process use this function.\n";
750 out << "assert(!" << clazz << "::default_impl);\n";
751 out << "if (impl) {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900752 out.Indent();
753 out << clazz << "::default_impl = impl;\n";
754 out << "return true;\n";
755 out.Dedent();
756 out << "}\n";
757 out << "return false;\n";
758 out.Dedent();
759 out << "}\n";
760
761 // definition for static member getDefaultImpl
762 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
763 out.Indent();
764 out << "return " << clazz << "::default_impl;\n";
765 out.Dedent();
766 out << "}\n";
767
768 // definition for the static field default_impl
769 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
770
771 // default implementation for the <Name>Default class members
772 const std::string defaultClazz = clazz + "Default";
773 for (const auto& method : defined_type.GetMethods()) {
774 if (method->IsUserDefined()) {
775 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
776 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
777 out.Indent();
778 out << "::ndk::ScopedAStatus _aidl_status;\n";
779 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
780 out << "return _aidl_status;\n";
781 out.Dedent();
782 out << "}\n";
783 } else {
784 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
785 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
786 << "int32_t* _aidl_return) {\n";
787 out.Indent();
788 out << "*_aidl_return = 0;\n";
789 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
790 out.Dedent();
791 out << "}\n";
792 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900793 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
794 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
795 << "std::string* _aidl_return) {\n";
796 out.Indent();
797 out << "*_aidl_return = \"\";\n";
798 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
799 out.Dedent();
800 out << "}\n";
801 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900802 }
803 }
804
805 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
806 out.Indent();
807 out << "return ::ndk::SpAIBinder();\n";
808 out.Dedent();
809 out << "}\n";
810
811 out << "bool " << defaultClazz << "::isRemote() {\n";
812 out.Indent();
813 out << "return false;\n";
814 out.Dedent();
815 out << "}\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700816}
Jiyong Park965c5b92018-11-21 13:37:15 +0900817
Steven Morelandb0057e72018-08-27 01:44:11 -0700818void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900819 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700820 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
821
822 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900823 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700824 << "\"\n";
825 out << "\n";
826 out << "#include <android/binder_ibinder.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900827 if (options.GenLog()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900828 out << "#include <functional>\n";
829 out << "#include <chrono>\n";
830 out << "#include <sstream>\n";
831 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700832 if (options.GenTraces()) {
833 out << "#include <android/trace.h>\n";
834 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700835 out << "\n";
836 EnterNdkNamespace(out, defined_type);
Jooyung Han720253d2021-01-05 19:13:17 +0900837 out << "class";
838 cpp::GenerateDeprecated(out, defined_type);
839 out << " " << clazz << " : public ::ndk::BpCInterface<"
Steven Morelandb0057e72018-08-27 01:44:11 -0700840 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
841 out << "public:\n";
842 out.Indent();
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900843 out << "explicit " << clazz << "(const ::ndk::SpAIBinder& binder);\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700844 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700845 out << "\n";
846 for (const auto& method : defined_type.GetMethods()) {
Jooyung Han720253d2021-01-05 19:13:17 +0900847 out << NdkMethodDecl(types, *method) << " override";
848 cpp::GenerateDeprecated(out, *method);
849 out << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700850 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900851
852 if (options.Version() > 0) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900853 out << "int32_t " << kCachedVersion << " = -1;\n";
854 }
855
856 if (!options.Hash().empty()) {
857 out << "std::string " << kCachedHash << " = \"-1\";\n";
858 out << "std::mutex " << kCachedHashMutex << ";\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900859 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900860 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900861 out << cpp::kTransactionLogStruct;
862 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900863 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700864 out.Dedent();
865 out << "};\n";
866 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700867}
Jiyong Park965c5b92018-11-21 13:37:15 +0900868void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
869 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700870 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900871 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700872
873 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900874 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700875 << "\"\n";
876 out << "\n";
877 out << "#include <android/binder_ibinder.h>\n";
878 out << "\n";
879 EnterNdkNamespace(out, defined_type);
Jooyung Han720253d2021-01-05 19:13:17 +0900880 out << "class";
881 cpp::GenerateDeprecated(out, defined_type);
882 out << " " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700883 out << "public:\n";
884 out.Indent();
885 out << clazz << "();\n";
886 out << "virtual ~" << clazz << "();\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900887
888 // Declare the meta methods
889 for (const auto& method : defined_type.GetMethods()) {
890 if (method->IsUserDefined()) {
891 continue;
892 }
893 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
Steven Moreland31aa2642021-05-10 22:33:00 +0000894 out << NdkMethodDecl(types, *method) << " final;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900895 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
Steven Moreland31aa2642021-05-10 22:33:00 +0000896 out << NdkMethodDecl(types, *method) << " final;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900897 } else {
898 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
899 }
900 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900901 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900902 out << cpp::kTransactionLogStruct;
903 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900904 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700905 out.Dedent();
Steven Moreland0cf3f082018-09-20 19:09:46 -0700906 out << "protected:\n";
907 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700908 out << "::ndk::SpAIBinder createBinder() override;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700909 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700910 out << "private:\n";
911 out.Indent();
912 out.Dedent();
913 out << "};\n";
914 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700915}
916void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900917 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700918 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
919
920 out << "#pragma once\n\n";
921 out << "#include <android/binder_interface_utils.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900922 if (options.GenLog()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900923 out << "#include <functional>\n";
924 out << "#include <chrono>\n";
925 out << "#include <sstream>\n";
926 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700927 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700928
929 GenerateHeaderIncludes(out, types, defined_type);
930 out << "\n";
931
Steven Morelandb0057e72018-08-27 01:44:11 -0700932 EnterNdkNamespace(out, defined_type);
Jooyung Han720253d2021-01-05 19:13:17 +0900933 out << "class";
934 cpp::GenerateDeprecated(out, defined_type);
935 out << " " << clazz << " : public ::ndk::ICInterface {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700936 out << "public:\n";
937 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900938 out << "static const char* " << kDescriptor << ";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700939 out << clazz << "();\n";
940 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700941 out << "\n";
Steven Morelande689da22020-11-10 02:06:30 +0000942 GenerateConstantDeclarations(out, types, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900943 if (options.Version() > 0) {
944 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
945 << ";\n";
946 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900947 if (!options.Hash().empty()) {
948 out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
949 }
Jiyong Park717fc692020-11-25 16:31:32 +0900950 for (const auto& method : defined_type.GetMethods()) {
951 if (!method->IsUserDefined()) {
952 continue;
953 }
954 out << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
955 << "FIRST_CALL_TRANSACTION + " << std::to_string(method->GetId()) << ";\n";
956 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700957 out << "\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800958 out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700959 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
960 << ">& instance);";
Jiyong Park1b88cce2018-11-19 19:53:44 +0900961 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700962 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
963 << ">* instance);";
964 out << "\n";
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900965 out << "static bool setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl);";
Jiyong Park965c5b92018-11-21 13:37:15 +0900966 out << "\n";
967 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
968 out << "\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700969 for (const auto& method : defined_type.GetMethods()) {
Jooyung Han720253d2021-01-05 19:13:17 +0900970 out << "virtual " << NdkMethodDecl(types, *method);
971 cpp::GenerateDeprecated(out, *method);
972 out << " = 0;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700973 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700974 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900975 out << "private:\n";
976 out.Indent();
977 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
978 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700979 out << "};\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900980
981 const std::string defaultClazz = clazz + "Default";
Jooyung Han720253d2021-01-05 19:13:17 +0900982 out << "class";
983 cpp::GenerateDeprecated(out, defined_type);
984 out << " " << defaultClazz << " : public " << clazz << " {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900985 out << "public:\n";
986 out.Indent();
987 for (const auto& method : defined_type.GetMethods()) {
988 if (method->IsUserDefined()) {
Jooyung Han720253d2021-01-05 19:13:17 +0900989 out << NdkMethodDecl(types, *method) << " override";
990 cpp::GenerateDeprecated(out, *method);
991 out << ";\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900992 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
993 out << NdkMethodDecl(types, *method) << " override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900994 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
995 out << NdkMethodDecl(types, *method) << " override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900996 }
997 }
998 out << "::ndk::SpAIBinder asBinder() override;\n";
999 out << "bool isRemote() override;\n";
1000 out.Dedent();
1001 out << "};\n";
1002
Steven Morelandb0057e72018-08-27 01:44:11 -07001003 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -07001004}
1005void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001006 const AidlStructuredParcelable& defined_type,
1007 const Options& /*options*/) {
Steven Morelandb8df37d2019-11-21 12:33:24 -08001008 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001009
Steven Morelandb0057e72018-08-27 01:44:11 -07001010 out << "#pragma once\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001011 out << "#include <android/binder_interface_utils.h>\n";
Jeongik Cha93741c42020-09-22 11:57:28 +09001012 out << "#include <android/binder_parcelable_utils.h>\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001013
1014 // used by toString()
Jooyung Han90a0bf72021-02-04 10:11:07 +09001015 out << "#include <android/binder_to_string.h>\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001016
1017 GenerateHeaderIncludes(out, types, defined_type);
Steven Moreland2bea13b2018-10-03 15:12:33 -07001018
Steven Morelandb0057e72018-08-27 01:44:11 -07001019 EnterNdkNamespace(out, defined_type);
Devin Moore53fc99c2020-08-12 08:07:52 -07001020 out << cpp::TemplateDecl(defined_type);
Jooyung Han720253d2021-01-05 19:13:17 +09001021 out << "class";
1022 cpp::GenerateDeprecated(out, defined_type);
1023 out << " " << clazz << " {\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001024 out << "public:\n";
1025 out.Indent();
Devin Moore369fdc02020-09-11 14:21:34 -07001026 if (defined_type.IsFixedSize()) {
1027 out << "typedef std::true_type fixed_size;\n";
1028 } else {
1029 out << "typedef std::false_type fixed_size;\n";
1030 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001031 out << "static const char* descriptor;\n";
1032 out << "\n";
1033 for (const auto& variable : defined_type.GetFields()) {
Jooyung Han720253d2021-01-05 19:13:17 +09001034 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK);
1035 cpp::GenerateDeprecated(out, *variable);
1036 out << " " << variable->GetName();
Jeongik Cha8f02a532020-10-14 00:16:28 +09001037 if (variable->GetType().GetName() == "ParcelableHolder") {
1038 out << "{::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL")
1039 << "}";
1040 }
Devin Moore83e76982020-09-30 09:32:35 -07001041 if (defined_type.IsFixedSize()) {
1042 int alignment = NdkAlignmentOf(types, variable->GetType());
1043 if (alignment > 0) {
1044 out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
1045 }
1046 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001047 if (variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -07001048 out << " = " << variable->ValueString(ConstantValueDecorator);
Jeongik Cha4bdd8e92021-09-25 01:13:39 +09001049 } else if (auto type = variable->GetType().GetDefinedType(); type) {
1050 if (auto enum_type = type->AsEnumDeclaration(); enum_type) {
1051 if (!variable->GetType().IsArray()) {
1052 // if an enum doesn't have explicit default value, do zero-initialization
1053 out << " = " << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << "(0)";
1054 }
1055 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001056 }
1057 out << ";\n";
1058 }
1059 out << "\n";
1060 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
1061 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
Steven Morelandf58804a2020-12-07 18:12:15 +00001062 out << "\n";
1063
1064 cpp::GenerateParcelableComparisonOperators(out, defined_type);
Jeongik Cha92d33d02020-05-14 00:53:57 +09001065
Jeongik Cha93741c42020-09-22 11:57:28 +09001066 out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1067 << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001068
Jooyung Han3f347ca2020-12-01 12:41:50 +09001069 GenerateConstantDeclarations(out, types, defined_type);
Jooyung Han74b1dd42020-11-01 22:17:16 +09001070 cpp::GenerateToString(out, defined_type);
1071
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001072 out.Dedent();
1073 out << "};\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001074 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -07001075}
1076void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001077 const AidlStructuredParcelable& defined_type,
1078 const Options& /*options*/) {
Devin Moore53fc99c2020-08-12 08:07:52 -07001079 std::string clazz = ClassName(defined_type, ClassNames::RAW);
1080 if (defined_type.IsGeneric()) {
1081 std::vector<std::string> template_params;
1082 for (const auto& parameter : defined_type.GetTypeParameters()) {
1083 template_params.push_back(parameter);
1084 }
1085 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1086 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001087
Jiyong Park5b7e5322019-04-03 20:05:01 +09001088 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -07001089 << "\"\n";
1090 out << "\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001091 GenerateSourceIncludes(out, types, defined_type);
1092 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001093 EnterNdkNamespace(out, defined_type);
Devin Moore53fc99c2020-08-12 08:07:52 -07001094 out << cpp::TemplateDecl(defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +09001095 out << "const char* " << clazz << "::" << kDescriptor << " = \""
1096 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001097 out << "\n";
1098
Jooyung Han3f347ca2020-12-01 12:41:50 +09001099 GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
1100
Devin Moore53fc99c2020-08-12 08:07:52 -07001101 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001102 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
1103 out.Indent();
Jeongik Cha95eba572018-11-22 09:14:52 +09001104 out << "int32_t _aidl_parcelable_size;\n";
Steven Moreland4348f9a2019-12-16 16:33:01 -08001105 out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1106 out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
Jeongik Cha8b329982020-09-01 20:59:36 +09001107 out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
Jeongik Cha95eba572018-11-22 09:14:52 +09001108 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
1109 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001110
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001111 for (const auto& variable : defined_type.GetFields()) {
Jeongik Cha95eba572018-11-22 09:14:52 +09001112 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1113 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1114 << " return _aidl_ret_status;\n"
1115 << "}\n";
Jooyung Han9e85bce2021-04-29 01:28:19 +09001116 out << "_aidl_ret_status = ";
1117 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
1118 out << ";\n";
1119 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001120 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001121 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1122 << "return _aidl_ret_status;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001123 out.Dedent();
1124 out << "}\n";
1125
Devin Moore53fc99c2020-08-12 08:07:52 -07001126 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001127 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
1128 out.Indent();
1129 out << "binder_status_t _aidl_ret_status;\n";
1130
Jeongik Cha95eba572018-11-22 09:14:52 +09001131 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1132 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
1133 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001134
1135 for (const auto& variable : defined_type.GetFields()) {
1136 out << "_aidl_ret_status = ";
1137 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
1138 out << ";\n";
1139 StatusCheckReturn(out);
1140 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001141 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
1142 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
1143 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
1144 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
1145
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001146 out << "return _aidl_ret_status;\n";
1147 out.Dedent();
1148 out << "}\n";
1149 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001150 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -07001151}
Daniel Norman37d43dd2019-09-09 17:22:34 -07001152
Jooyung Han6beac042020-10-17 21:59:43 +09001153void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
1154 const AidlUnionDecl& defined_type, const Options& /*options*/) {
1155 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
1156 cpp::UnionWriter uw{defined_type, types,
1157 [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1158 return NdkNameOf(types, type, StorageMode::STACK);
1159 },
1160 &ConstantValueDecorator};
1161
1162 out << "#pragma once\n";
1163 out << "#include <android/binder_interface_utils.h>\n";
1164 out << "#include <android/binder_parcelable_utils.h>\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001165
1166 // used by toString()
Jooyung Han90a0bf72021-02-04 10:11:07 +09001167 out << "#include <android/binder_to_string.h>\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001168
Jooyung Han6beac042020-10-17 21:59:43 +09001169 out << "\n";
1170
1171 for (const auto& header : cpp::UnionWriter::headers) {
1172 out << "#include <" << header << ">\n";
1173 }
1174 GenerateHeaderIncludes(out, types, defined_type);
1175
Jooyung Handf39e192020-11-23 15:59:46 +09001176 // TODO(b/31559095) bionic on host should define this
1177 out << "\n";
1178 out << "#ifndef __BIONIC__\n";
1179 out << "#define __assert2(a,b,c,d) ((void)0)\n";
1180 out << "#endif\n";
1181 out << "\n";
1182
Jooyung Han6beac042020-10-17 21:59:43 +09001183 EnterNdkNamespace(out, defined_type);
1184 out << cpp::TemplateDecl(defined_type);
Jooyung Han720253d2021-01-05 19:13:17 +09001185 out << "class";
1186 cpp::GenerateDeprecated(out, defined_type);
1187 out << " " << clazz << " {\n";
Jooyung Han6beac042020-10-17 21:59:43 +09001188 out << "public:\n";
1189 out.Indent();
1190 if (defined_type.IsFixedSize()) {
1191 out << "typedef std::true_type fixed_size;\n";
1192 } else {
1193 out << "typedef std::false_type fixed_size;\n";
1194 }
1195 out << "static const char* descriptor;\n";
1196 out << "\n";
1197 uw.PublicFields(out);
1198
1199 out << "binder_status_t readFromParcel(const AParcel* _parcel);\n";
1200 out << "binder_status_t writeToParcel(AParcel* _parcel) const;\n";
Steven Morelandf58804a2020-12-07 18:12:15 +00001201 out << "\n";
1202
1203 cpp::GenerateParcelableComparisonOperators(out, defined_type);
Jooyung Han6beac042020-10-17 21:59:43 +09001204
1205 out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1206 << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
Jooyung Han3f347ca2020-12-01 12:41:50 +09001207 GenerateConstantDeclarations(out, types, defined_type);
Jooyung Han74b1dd42020-11-01 22:17:16 +09001208 cpp::GenerateToString(out, defined_type);
Jooyung Han6beac042020-10-17 21:59:43 +09001209 out.Dedent();
1210 out << "private:\n";
1211 out.Indent();
1212 uw.PrivateFields(out);
1213 out.Dedent();
1214 out << "};\n";
1215 LeaveNdkNamespace(out, defined_type);
1216}
1217void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
1218 const AidlUnionDecl& defined_type, const Options& /*options*/) {
1219 std::string clazz = ClassName(defined_type, ClassNames::RAW);
1220 if (defined_type.IsGeneric()) {
1221 std::vector<std::string> template_params;
1222 for (const auto& parameter : defined_type.GetTypeParameters()) {
1223 template_params.push_back(parameter);
1224 }
1225 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1226 }
1227
1228 cpp::UnionWriter uw{defined_type, types,
1229 [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1230 return NdkNameOf(types, type, StorageMode::STACK);
1231 },
1232 &ConstantValueDecorator};
1233 cpp::ParcelWriterContext ctx{
1234 .status_type = "binder_status_t",
1235 .status_ok = "STATUS_OK",
1236 .status_bad = "STATUS_BAD_VALUE",
1237 .read_func =
1238 [&](CodeWriter& out, const std::string& var, const AidlTypeSpecifier& type) {
1239 ReadFromParcelFor({out, types, type, "_parcel", "&" + var});
1240 },
1241 .write_func =
1242 [&](CodeWriter& out, const std::string& value, const AidlTypeSpecifier& type) {
1243 WriteToParcelFor({out, types, type, "_parcel", value});
1244 },
1245 };
1246
1247 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
1248 << "\"\n";
1249 out << "\n";
1250 GenerateSourceIncludes(out, types, defined_type);
1251 out << "\n";
1252 EnterNdkNamespace(out, defined_type);
1253 out << cpp::TemplateDecl(defined_type);
1254 out << "const char* " << clazz << "::" << kDescriptor << " = \""
1255 << defined_type.GetCanonicalName() << "\";\n";
1256 out << "\n";
1257
Jooyung Han3f347ca2020-12-01 12:41:50 +09001258 GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
1259
Jooyung Han6beac042020-10-17 21:59:43 +09001260 out << cpp::TemplateDecl(defined_type);
1261 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _parcel) {\n";
1262 out.Indent();
1263 uw.ReadFromParcel(out, ctx);
1264 out.Dedent();
1265 out << "}\n";
1266
1267 out << cpp::TemplateDecl(defined_type);
1268 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* _parcel) const {\n";
1269 out.Indent();
1270 uw.WriteToParcel(out, ctx);
1271 out.Dedent();
1272 out << "}\n";
1273 out << "\n";
1274 LeaveNdkNamespace(out, defined_type);
1275}
1276
Daniel Norman455d95c2019-11-19 09:55:39 -08001277std::string GenerateEnumToString(const AidlTypenames& typenames,
1278 const AidlEnumDeclaration& enum_decl) {
1279 std::ostringstream code;
Jooyung Han720253d2021-01-05 19:13:17 +09001280 const std::string signature =
Steven Morelanda7dadbe2021-05-10 22:36:38 +00001281 "[[nodiscard]] static inline std::string toString(" + enum_decl.GetName() + " val)";
Jooyung Han720253d2021-01-05 19:13:17 +09001282 if (enum_decl.IsDeprecated()) {
1283 code << signature;
1284 cpp::GenerateDeprecated(code, enum_decl);
1285 code << ";\n";
1286 }
1287 code << signature << " {\n";
Daniel Norman455d95c2019-11-19 09:55:39 -08001288 code << " switch(val) {\n";
1289 std::set<std::string> unique_cases;
1290 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1291 std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
1292 // Only add a case if its value has not yet been used in the switch
1293 // statement. C++ does not allow multiple cases with the same value, but
1294 // enums does allow this. In this scenario, the first declared
1295 // enumerator with the given value is printed.
1296 if (unique_cases.count(c) == 0) {
1297 unique_cases.insert(c);
1298 code << " case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
1299 code << " return \"" << enumerator->GetName() << "\";\n";
1300 }
1301 }
1302 code << " default:\n";
1303 code << " return std::to_string(static_cast<"
1304 << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
1305 code << " }\n";
1306 code << "}\n";
1307 return code.str();
1308}
1309
Daniel Norman37d43dd2019-09-09 17:22:34 -07001310void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
1311 const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
1312 out << "#pragma once\n";
1313 out << "\n";
1314
1315 GenerateHeaderIncludes(out, types, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001316 // enum specific headers
1317 out << "#include <array>\n";
1318 out << "#include <android/binder_enums.h>\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001319
1320 EnterNdkNamespace(out, enum_decl);
Jooyung Han720253d2021-01-05 19:13:17 +09001321 out << "enum class";
1322 cpp::GenerateDeprecated(out, enum_decl);
1323 out << " " << enum_decl.GetName() << " : "
Daniel Norman37d43dd2019-09-09 17:22:34 -07001324 << NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK) << " {\n";
1325 out.Indent();
1326 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1327 out << enumerator->GetName() << " = "
1328 << enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator) << ",\n";
1329 }
1330 out.Dedent();
1331 out << "};\n";
Daniel Norman455d95c2019-11-19 09:55:39 -08001332 out << "\n";
1333 out << GenerateEnumToString(types, enum_decl);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001334 LeaveNdkNamespace(out, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001335
1336 out << "namespace ndk {\n";
1337 out << "namespace internal {\n";
1338 out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
1339 out << "} // namespace internal\n";
1340 out << "} // namespace android\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001341}
1342
Steven Morelandb0057e72018-08-27 01:44:11 -07001343} // namespace internals
1344} // namespace ndk
1345} // namespace aidl
1346} // namespace android