blob: e84145726ab9656e6cc288bcfd3c8486812612c8 [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
Steven Morelande689da22020-11-10 02:06:30 +0000310static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types,
311 const AidlInterface& interface) {
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700312 for (const auto& constant : interface.GetConstantDeclarations()) {
Steven Morelande689da22020-11-10 02:06:30 +0000313 const AidlTypeSpecifier& type = constant->GetType();
314
315 if (type.ToString() == "String") {
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700316 out << "static const char* " << constant->GetName() << ";\n";
Steven Morelande689da22020-11-10 02:06:30 +0000317 } else {
318 out << "enum : " << NdkNameOf(types, type, StorageMode::STACK) << " { " << constant->GetName()
319 << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700320 }
321 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700322}
Steven Morelande689da22020-11-10 02:06:30 +0000323
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700324static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) {
325 const std::string clazz = ClassName(interface, ClassNames::INTERFACE);
326
327 for (const auto& constant : interface.GetConstantDeclarations()) {
328 const AidlConstantValue& value = constant->GetValue();
Steven Moreland21780812020-09-11 01:29:45 +0000329 AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
330 value.GetType() == AidlConstantValue::Type::BINARY,
331 value);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700332 if (value.GetType() == AidlConstantValue::Type::STRING) {
333 out << "const char* " << clazz << "::" << constant->GetName() << " = "
Daniel Norman37d43dd2019-09-09 17:22:34 -0700334 << constant->ValueString(ConstantValueDecorator) << ";\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700335 }
336 }
337}
338
Steven Morelandb0057e72018-08-27 01:44:11 -0700339void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
340 const Options& options) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700341 GenerateSourceIncludes(out, types, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700342 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700343
Steven Morelandb0057e72018-08-27 01:44:11 -0700344 EnterNdkNamespace(out, defined_type);
Jooyung Hanb8e01b92020-11-01 16:49:13 +0900345 if (options.GenLog()) {
346 out << cpp::kToStringHelper;
347 }
Steven Moreland0cf3f082018-09-20 19:09:46 -0700348 GenerateClassSource(out, types, defined_type, options);
Steven Morelandb0057e72018-08-27 01:44:11 -0700349 GenerateClientSource(out, types, defined_type, options);
350 GenerateServerSource(out, types, defined_type, options);
351 GenerateInterfaceSource(out, types, defined_type, options);
352 LeaveNdkNamespace(out, defined_type);
353}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700354
Steven Morelandaada3422018-09-20 15:55:33 -0700355static std::string MethodId(const AidlMethod& m) {
356 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
357}
358
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900359static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
360 const AidlInterface& defined_type,
361 const AidlMethod& method,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900362 const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700363 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
364
Steven Moreland2bea13b2018-10-03 15:12:33 -0700365 out << NdkMethodDecl(types, method, clazz) << " {\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700366 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700367 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
Steven Moreland63404532018-10-08 14:31:00 -0700368 out << "::ndk::ScopedAStatus _aidl_status;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900369
Paul Trautrimb77048c2020-01-21 16:39:32 +0900370 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
371 out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
372 out << "if (" << kCachedHash << " != \"-1\") {\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900373 out.Indent();
Paul Trautrimb77048c2020-01-21 16:39:32 +0900374 out << "*_aidl_return = " << kCachedHash << ";\n"
375 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
376 << "return _aidl_status;\n";
377 out.Dedent();
378 out << "}\n";
379 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
380 out << "if (" << kCachedVersion << " != -1) {\n";
381 out.Indent();
382 out << "*_aidl_return = " << kCachedVersion << ";\n"
Jeongik Chac9972922019-02-11 12:41:16 +0900383 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
384 << "return _aidl_status;\n";
385 out.Dedent();
386 out << "}\n";
387 }
388 out << "::ndk::ScopedAParcel _aidl_in;\n";
389 out << "::ndk::ScopedAParcel _aidl_out;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700390 out << "\n";
391
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900392 if (options.GenLog()) {
393 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
394 false /* isServer */, true /* isNdk */);
395 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700396 if (options.GenTraces()) {
Devin Mooref7600872020-05-13 15:47:50 -0700397 out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
Devin Moore7d5a4542020-04-29 15:37:25 -0700398 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
399 << "::client\");\n";
400 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900401
Steven Morelandaada3422018-09-20 15:55:33 -0700402 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
Steven Morelanda7764e52020-10-27 17:29:29 +0000403 if (defined_type.IsSensitiveData()) {
404 out << "AParcel_markSensitive(_aidl_in.get());\n";
405 }
Steven Morelandaada3422018-09-20 15:55:33 -0700406 StatusCheckGoto(out);
407
Steven Morelandeb38ee72018-10-15 14:20:04 -0700408 for (const auto& arg : method.GetArguments()) {
409 const std::string var_name = cpp::BuildVarName(*arg);
410
411 if (arg->IsIn()) {
412 out << "_aidl_ret_status = ";
413 const std::string prefix = (arg->IsOut() ? "*" : "");
414 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
415 out << ";\n";
416 StatusCheckGoto(out);
417 } else if (arg->IsOut() && arg->GetType().IsArray()) {
418 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
419 << ");\n";
420 }
Steven Morelandaada3422018-09-20 15:55:33 -0700421 }
422 out << "_aidl_ret_status = AIBinder_transact(\n";
423 out.Indent();
424 out << "asBinder().get(),\n";
425 out << MethodId(method) << ",\n";
426 out << "_aidl_in.getR(),\n";
427 out << "_aidl_out.getR(),\n";
Steven Morelanda7764e52020-10-27 17:29:29 +0000428
429 std::vector<std::string> flags;
430 if (method.IsOneway()) flags.push_back("FLAG_ONEWAY");
431 if (defined_type.IsSensitiveData()) flags.push_back("FLAG_CLEAR_BUF");
432 out << (flags.empty() ? "0" : base::Join(flags, " | ")) << "\n";
433
Steven Morelandb72a1e72019-10-15 11:23:26 -0700434 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
435 out << "| FLAG_PRIVATE_LOCAL\n";
436 out << "#endif // BINDER_STABILITY_SUPPORT\n";
437 out << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700438 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900439
440 // If the method is not implmented in the server side but the client has
441 // provided the default implementation, call it instead of failing hard.
442 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
443 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
444 out << iface << "::getDefaultImpl()) {\n";
445 out.Indent();
Devin Moore7d5a4542020-04-29 15:37:25 -0700446 out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
Jiyong Park965c5b92018-11-21 13:37:15 +0900447 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700448 out << "goto _aidl_status_return;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900449 out.Dedent();
450 out << "}\n";
451
Steven Morelandaada3422018-09-20 15:55:33 -0700452 StatusCheckGoto(out);
453
454 if (!method.IsOneway()) {
455 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
456 StatusCheckGoto(out);
457
Devin Moore7d5a4542020-04-29 15:37:25 -0700458 out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700459 }
460
Steven Morelandaada3422018-09-20 15:55:33 -0700461 if (method.GetType().GetName() != "void") {
462 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700463 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700464 out << ";\n";
465 StatusCheckGoto(out);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900466 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
467 out << kCachedHash << " = *_aidl_return;\n";
468 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
469 out << kCachedVersion << " = *_aidl_return;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900470 }
Steven Morelandaada3422018-09-20 15:55:33 -0700471 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700472 for (const AidlArgument* arg : method.GetOutArguments()) {
473 out << "_aidl_ret_status = ";
474 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
475 out << ";\n";
476 StatusCheckGoto(out);
477 }
Steven Morelandaada3422018-09-20 15:55:33 -0700478
479 out << "_aidl_error:\n";
480 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700481 out << "_aidl_status_return:\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900482 if (options.GenLog()) {
483 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
484 method, "_aidl_status", "_aidl_return", false /* isServer */,
485 true /* isNdk */);
486 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700487
Steven Morelandaada3422018-09-20 15:55:33 -0700488 out << "return _aidl_status;\n";
489 out.Dedent();
490 out << "}\n";
491}
492
Steven Moreland2bea13b2018-10-03 15:12:33 -0700493static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900494 const AidlInterface& defined_type,
495 const AidlMethod& method, const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700496 out << "case " << MethodId(method) << ": {\n";
497 out.Indent();
498 for (const auto& arg : method.GetArguments()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700499 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
500 << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700501 }
502 if (method.GetType().GetName() != "void") {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700503 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700504 }
505 out << "\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700506 if (options.GenTraces()) {
Devin Mooref7600872020-05-13 15:47:50 -0700507 out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
Devin Moore7d5a4542020-04-29 15:37:25 -0700508 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
509 << "::server\");\n";
510 }
Steven Morelandaada3422018-09-20 15:55:33 -0700511
Steven Morelandeb38ee72018-10-15 14:20:04 -0700512 for (const auto& arg : method.GetArguments()) {
513 const std::string var_name = cpp::BuildVarName(*arg);
514
515 if (arg->IsIn()) {
516 out << "_aidl_ret_status = ";
517 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
518 out << ";\n";
519 StatusCheckBreak(out);
520 } else if (arg->IsOut() && arg->GetType().IsArray()) {
521 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
522 }
Steven Morelandaada3422018-09-20 15:55:33 -0700523 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900524 if (options.GenLog()) {
525 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
526 true /* isServer */, true /* isNdk */);
527 }
Steven Moreland63404532018-10-08 14:31:00 -0700528 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
Jiyong Park965c5b92018-11-21 13:37:15 +0900529 << NdkArgList(types, method, FormatArgForCall) << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700530
Jeongik Chaeaf978e2019-05-04 00:32:35 +0900531 if (options.GenLog()) {
532 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
533 method, "_aidl_status", "_aidl_return", true /* isServer */,
534 true /* isNdk */);
535 }
Steven Morelandaada3422018-09-20 15:55:33 -0700536 if (method.IsOneway()) {
537 // For a oneway transaction, the kernel will have already returned a result. This is for the
538 // in-process case when a oneway transaction is parceled/unparceled in the same process.
539 out << "_aidl_ret_status = STATUS_OK;\n";
540 } else {
541 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
542 StatusCheckBreak(out);
543
544 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
545
Steven Morelandaada3422018-09-20 15:55:33 -0700546 if (method.GetType().GetName() != "void") {
547 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700548 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700549 out << ";\n";
550 StatusCheckBreak(out);
551 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700552 for (const AidlArgument* arg : method.GetOutArguments()) {
553 out << "_aidl_ret_status = ";
554 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
555 out << ";\n";
556 StatusCheckBreak(out);
557 }
Steven Morelandaada3422018-09-20 15:55:33 -0700558 }
Steven Morelandaada3422018-09-20 15:55:33 -0700559 out << "break;\n";
560 out.Dedent();
561 out << "}\n";
562}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700563
Steven Moreland2bea13b2018-10-03 15:12:33 -0700564void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900565 const AidlInterface& defined_type, const Options& options) {
Steven Moreland0cf3f082018-09-20 19:09:46 -0700566 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
567 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
Devin Mooref7600872020-05-13 15:47:50 -0700568 if (options.GenTraces()) {
569 out << "class ScopedTrace {\n";
570 out.Indent();
571 out << "public:\n"
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900572 << "inline explicit ScopedTrace(const char* name) {\n"
Devin Mooref7600872020-05-13 15:47:50 -0700573 << "ATrace_beginSection(name);\n"
574 << "}\n"
575 << "inline ~ScopedTrace() {\n"
576 << "ATrace_endSection();\n"
577 << "}\n";
578 out.Dedent();
579 out << "};\n";
580 }
Steven Moreland15b3ba72019-03-06 13:17:08 -0800581 out << "static binder_status_t "
582 << "_aidl_onTransact"
Steven Morelandaada3422018-09-20 15:55:33 -0700583 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
584 "AParcel* _aidl_out) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700585 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700586 out << "(void)_aidl_in;\n";
587 out << "(void)_aidl_out;\n";
588 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
589 if (!defined_type.GetMethods().empty()) {
Steven Moreland15b3ba72019-03-06 13:17:08 -0800590 // we know this cast is valid because this method is only called by the ICInterface
591 // AIBinder_Class object which is associated with this class.
592 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = std::static_pointer_cast<" << bn_clazz
593 << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700594 out << "switch (_aidl_code) {\n";
595 out.Indent();
596 for (const auto& method : defined_type.GetMethods()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900597 GenerateServerCaseDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700598 }
599 out.Dedent();
600 out << "}\n";
601 } else {
602 out << "(void)_aidl_binder;\n";
603 out << "(void)_aidl_code;\n";
604 }
605 out << "return _aidl_ret_status;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700606 out.Dedent();
Steven Moreland73d66242019-09-26 16:03:54 -0700607 out << "}\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700608
Steven Moreland15b3ba72019-03-06 13:17:08 -0800609 out << "static AIBinder_Class* " << kClazz << " = ::ndk::ICInterface::defineClass(" << clazz
610 << "::" << kDescriptor << ", _aidl_onTransact);\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700611}
Steven Morelandb0057e72018-08-27 01:44:11 -0700612void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900613 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700614 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700615
Steven Moreland63404532018-10-08 14:31:00 -0700616 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700617 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900618 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900619 out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900620 }
Steven Morelandaada3422018-09-20 15:55:33 -0700621 out << "\n";
622 for (const auto& method : defined_type.GetMethods()) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900623 GenerateClientMethodDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700624 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700625}
Jiyong Park965c5b92018-11-21 13:37:15 +0900626void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
627 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700628 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900629 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700630
631 out << "// Source for " << clazz << "\n";
632 out << clazz << "::" << clazz << "() {}\n";
633 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900634 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900635 out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900636 }
Steven Moreland63404532018-10-08 14:31:00 -0700637 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700638 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800639 out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700640
Steven Moreland88378b12019-10-11 13:13:24 -0700641 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700642 if (defined_type.IsVintfStability()) {
643 out << "AIBinder_markVintfStability(binder);\n";
644 } else {
645 out << "AIBinder_markCompilationUnitStability(binder);\n";
646 }
Steven Moreland88378b12019-10-11 13:13:24 -0700647 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700648
Steven Moreland63404532018-10-08 14:31:00 -0700649 out << "return ::ndk::SpAIBinder(binder);\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700650 out.Dedent();
651 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900652
653 // Implement the meta methods
654 for (const auto& method : defined_type.GetMethods()) {
655 if (method->IsUserDefined()) {
656 continue;
657 }
658 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
659 out << NdkMethodDecl(types, *method, clazz) << " {\n";
660 out.Indent();
661 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
662 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
663 out.Dedent();
664 out << "}\n";
665 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900666 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
667 out << NdkMethodDecl(types, *method, clazz) << " {\n";
668 out.Indent();
669 out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
670 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
671 out.Dedent();
672 out << "}\n";
673 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900674 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700675}
Jiyong Park965c5b92018-11-21 13:37:15 +0900676void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
677 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700678 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland15b3ba72019-03-06 13:17:08 -0800679 const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -0700680
681 out << "// Source for " << clazz << "\n";
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900682 out << "const char* " << clazz << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
683 << "\";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700684 out << clazz << "::" << clazz << "() {}\n";
685 out << clazz << "::~" << clazz << "() {}\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700686 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700687 GenerateConstantDefinitions(out, defined_type);
688 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700689
Steven Moreland3c316ed2019-01-17 09:39:37 -0800690 out << "std::shared_ptr<" << clazz << "> " << clazz
691 << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800692 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800693 out << "if (!AIBinder_associateClass(binder.get(), " << kClazz << ")) { return nullptr; }\n";
694 out << "std::shared_ptr<::ndk::ICInterface> interface = "
695 "::ndk::ICInterface::asInterface(binder.get());\n";
696 out << "if (interface) {\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800697 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800698 out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800699 out.Dedent();
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800700 out << "}\n";
Steven Morelandc09d34c2020-02-13 09:42:49 -0800701 out << "return ::ndk::SharedRefBase::make<" << bp_clazz << ">(binder);\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800702 out.Dedent();
Steven Moreland3c316ed2019-01-17 09:39:37 -0800703 out << "}\n\n";
704
Steven Moreland2bea13b2018-10-03 15:12:33 -0700705 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
706 << clazz << ">& instance) {\n";
707 out.Indent();
708 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
709 "nullptr);\n";
710 out.Dedent();
711 out << "}\n";
712
713 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
714 << clazz << ">* instance) {\n";
715 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700716 out << "::ndk::SpAIBinder binder;\n";
Steven Moreland055d8792018-11-14 12:48:42 -0800717 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700718 out << "if (status != STATUS_OK) return status;\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800719 out << "*instance = " << clazz << "::fromBinder(binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700720 out << "return STATUS_OK;\n";
721 out.Dedent();
722 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900723
724 // defintion for static member setDefaultImpl
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900725 out << "bool " << clazz << "::setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl) {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900726 out.Indent();
Jooyung Han4a044662020-05-13 17:17:07 +0900727 out << "// Only one user of this interface can use this function\n";
728 out << "// at a time. This is a heuristic to detect if two different\n";
729 out << "// users in the same process use this function.\n";
730 out << "assert(!" << clazz << "::default_impl);\n";
731 out << "if (impl) {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900732 out.Indent();
733 out << clazz << "::default_impl = impl;\n";
734 out << "return true;\n";
735 out.Dedent();
736 out << "}\n";
737 out << "return false;\n";
738 out.Dedent();
739 out << "}\n";
740
741 // definition for static member getDefaultImpl
742 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
743 out.Indent();
744 out << "return " << clazz << "::default_impl;\n";
745 out.Dedent();
746 out << "}\n";
747
748 // definition for the static field default_impl
749 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
750
751 // default implementation for the <Name>Default class members
752 const std::string defaultClazz = clazz + "Default";
753 for (const auto& method : defined_type.GetMethods()) {
754 if (method->IsUserDefined()) {
755 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
756 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
757 out.Indent();
758 out << "::ndk::ScopedAStatus _aidl_status;\n";
759 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
760 out << "return _aidl_status;\n";
761 out.Dedent();
762 out << "}\n";
763 } else {
764 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
765 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
766 << "int32_t* _aidl_return) {\n";
767 out.Indent();
768 out << "*_aidl_return = 0;\n";
769 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
770 out.Dedent();
771 out << "}\n";
772 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900773 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
774 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
775 << "std::string* _aidl_return) {\n";
776 out.Indent();
777 out << "*_aidl_return = \"\";\n";
778 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
779 out.Dedent();
780 out << "}\n";
781 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900782 }
783 }
784
785 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
786 out.Indent();
787 out << "return ::ndk::SpAIBinder();\n";
788 out.Dedent();
789 out << "}\n";
790
791 out << "bool " << defaultClazz << "::isRemote() {\n";
792 out.Indent();
793 out << "return false;\n";
794 out.Dedent();
795 out << "}\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700796}
Jiyong Park965c5b92018-11-21 13:37:15 +0900797
Steven Morelandb0057e72018-08-27 01:44:11 -0700798void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900799 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700800 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
801
802 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900803 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700804 << "\"\n";
805 out << "\n";
806 out << "#include <android/binder_ibinder.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900807 if (options.GenLog()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900808 out << "#include <functional>\n";
809 out << "#include <chrono>\n";
810 out << "#include <sstream>\n";
811 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700812 if (options.GenTraces()) {
813 out << "#include <android/trace.h>\n";
814 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700815 out << "\n";
816 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700817 out << "class " << clazz << " : public ::ndk::BpCInterface<"
Steven Morelandb0057e72018-08-27 01:44:11 -0700818 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
819 out << "public:\n";
820 out.Indent();
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900821 out << "explicit " << clazz << "(const ::ndk::SpAIBinder& binder);\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700822 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700823 out << "\n";
824 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700825 out << NdkMethodDecl(types, *method) << " override;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700826 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900827
828 if (options.Version() > 0) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900829 out << "int32_t " << kCachedVersion << " = -1;\n";
830 }
831
832 if (!options.Hash().empty()) {
833 out << "std::string " << kCachedHash << " = \"-1\";\n";
834 out << "std::mutex " << kCachedHashMutex << ";\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900835 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900836 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900837 out << cpp::kTransactionLogStruct;
838 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900839 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700840 out.Dedent();
841 out << "};\n";
842 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700843}
Jiyong Park965c5b92018-11-21 13:37:15 +0900844void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
845 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700846 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900847 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700848
849 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900850 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700851 << "\"\n";
852 out << "\n";
853 out << "#include <android/binder_ibinder.h>\n";
854 out << "\n";
855 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900856 out << "class " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700857 out << "public:\n";
858 out.Indent();
859 out << clazz << "();\n";
860 out << "virtual ~" << clazz << "();\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900861
862 // Declare the meta methods
863 for (const auto& method : defined_type.GetMethods()) {
864 if (method->IsUserDefined()) {
865 continue;
866 }
867 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
868 out << NdkMethodDecl(types, *method) << " final override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900869 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
870 out << NdkMethodDecl(types, *method) << " final override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900871 } else {
872 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
873 }
874 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900875 if (options.GenLog()) {
Jooyung Han81003c32020-11-04 14:08:26 +0900876 out << cpp::kTransactionLogStruct;
877 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900878 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700879 out.Dedent();
Steven Moreland0cf3f082018-09-20 19:09:46 -0700880 out << "protected:\n";
881 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700882 out << "::ndk::SpAIBinder createBinder() override;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700883 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700884 out << "private:\n";
885 out.Indent();
886 out.Dedent();
887 out << "};\n";
888 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700889}
890void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900891 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700892 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
893
894 out << "#pragma once\n\n";
895 out << "#include <android/binder_interface_utils.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900896 if (options.GenLog()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900897 out << "#include <functional>\n";
898 out << "#include <chrono>\n";
899 out << "#include <sstream>\n";
900 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700901 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700902
903 GenerateHeaderIncludes(out, types, defined_type);
904 out << "\n";
905
Steven Morelandb0057e72018-08-27 01:44:11 -0700906 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700907 out << "class " << clazz << " : public ::ndk::ICInterface {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700908 out << "public:\n";
909 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900910 out << "static const char* " << kDescriptor << ";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700911 out << clazz << "();\n";
912 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700913 out << "\n";
Steven Morelande689da22020-11-10 02:06:30 +0000914 GenerateConstantDeclarations(out, types, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900915 if (options.Version() > 0) {
916 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
917 << ";\n";
918 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900919 if (!options.Hash().empty()) {
920 out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
921 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700922 out << "\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800923 out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700924 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
925 << ">& instance);";
Jiyong Park1b88cce2018-11-19 19:53:44 +0900926 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700927 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
928 << ">* instance);";
929 out << "\n";
Jiyong Parkdd57f1a2020-11-16 20:19:55 +0900930 out << "static bool setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl);";
Jiyong Park965c5b92018-11-21 13:37:15 +0900931 out << "\n";
932 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
933 out << "\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700934 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700935 out << "virtual " << NdkMethodDecl(types, *method) << " = 0;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700936 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700937 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900938 out << "private:\n";
939 out.Indent();
940 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
941 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700942 out << "};\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900943
944 const std::string defaultClazz = clazz + "Default";
945
946 out << "class " << defaultClazz << " : public " << clazz << " {\n";
947 out << "public:\n";
948 out.Indent();
949 for (const auto& method : defined_type.GetMethods()) {
950 if (method->IsUserDefined()) {
951 out << NdkMethodDecl(types, *method) << " override;\n";
952 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
953 out << NdkMethodDecl(types, *method) << " override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900954 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
955 out << NdkMethodDecl(types, *method) << " override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900956 }
957 }
958 out << "::ndk::SpAIBinder asBinder() override;\n";
959 out << "bool isRemote() override;\n";
960 out.Dedent();
961 out << "};\n";
962
Steven Morelandb0057e72018-08-27 01:44:11 -0700963 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700964}
965void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700966 const AidlStructuredParcelable& defined_type,
967 const Options& /*options*/) {
Steven Morelandb8df37d2019-11-21 12:33:24 -0800968 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700969
Steven Morelandb0057e72018-08-27 01:44:11 -0700970 out << "#pragma once\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700971 out << "#include <android/binder_interface_utils.h>\n";
Jeongik Cha93741c42020-09-22 11:57:28 +0900972 out << "#include <android/binder_parcelable_utils.h>\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +0900973
974 // used by toString()
975 out << "#include <codecvt>\n";
976 out << "#include <locale>\n";
977 out << "#include <sstream>\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700978
979 GenerateHeaderIncludes(out, types, defined_type);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700980
Steven Morelandb0057e72018-08-27 01:44:11 -0700981 EnterNdkNamespace(out, defined_type);
Devin Moore53fc99c2020-08-12 08:07:52 -0700982 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700983 out << "class " << clazz << " {\n";
984 out << "public:\n";
985 out.Indent();
Devin Moore369fdc02020-09-11 14:21:34 -0700986 if (defined_type.IsFixedSize()) {
987 out << "typedef std::true_type fixed_size;\n";
988 } else {
989 out << "typedef std::false_type fixed_size;\n";
990 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700991 out << "static const char* descriptor;\n";
992 out << "\n";
993 for (const auto& variable : defined_type.GetFields()) {
994 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << " " << variable->GetName();
Jeongik Cha8f02a532020-10-14 00:16:28 +0900995 if (variable->GetType().GetName() == "ParcelableHolder") {
996 out << "{::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL")
997 << "}";
998 }
Devin Moore83e76982020-09-30 09:32:35 -0700999 if (defined_type.IsFixedSize()) {
1000 int alignment = NdkAlignmentOf(types, variable->GetType());
1001 if (alignment > 0) {
1002 out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
1003 }
1004 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001005 if (variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -07001006 out << " = " << variable->ValueString(ConstantValueDecorator);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001007 }
1008 out << ";\n";
1009 }
1010 out << "\n";
1011 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
1012 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
Jeongik Cha92d33d02020-05-14 00:53:57 +09001013
Jeongik Cha93741c42020-09-22 11:57:28 +09001014 out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1015 << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001016
1017 cpp::GenerateToString(out, defined_type);
1018
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001019 out.Dedent();
1020 out << "};\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001021 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -07001022}
1023void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001024 const AidlStructuredParcelable& defined_type,
1025 const Options& /*options*/) {
Devin Moore53fc99c2020-08-12 08:07:52 -07001026 std::string clazz = ClassName(defined_type, ClassNames::RAW);
1027 if (defined_type.IsGeneric()) {
1028 std::vector<std::string> template_params;
1029 for (const auto& parameter : defined_type.GetTypeParameters()) {
1030 template_params.push_back(parameter);
1031 }
1032 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1033 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001034
Jiyong Park5b7e5322019-04-03 20:05:01 +09001035 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -07001036 << "\"\n";
1037 out << "\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001038 GenerateSourceIncludes(out, types, defined_type);
1039 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001040 EnterNdkNamespace(out, defined_type);
Devin Moore53fc99c2020-08-12 08:07:52 -07001041 out << cpp::TemplateDecl(defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +09001042 out << "const char* " << clazz << "::" << kDescriptor << " = \""
1043 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001044 out << "\n";
1045
Devin Moore53fc99c2020-08-12 08:07:52 -07001046 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001047 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
1048 out.Indent();
Jeongik Cha95eba572018-11-22 09:14:52 +09001049 out << "int32_t _aidl_parcelable_size;\n";
Steven Moreland4348f9a2019-12-16 16:33:01 -08001050 out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1051 out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
Jeongik Cha8b329982020-09-01 20:59:36 +09001052 out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
Jeongik Cha95eba572018-11-22 09:14:52 +09001053 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
1054 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001055
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001056 for (const auto& variable : defined_type.GetFields()) {
1057 out << "_aidl_ret_status = ";
1058 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
1059 out << ";\n";
1060 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +09001061 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1062 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1063 << " return _aidl_ret_status;\n"
1064 << "}\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001065 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001066 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1067 << "return _aidl_ret_status;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001068 out.Dedent();
1069 out << "}\n";
1070
Devin Moore53fc99c2020-08-12 08:07:52 -07001071 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001072 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
1073 out.Indent();
1074 out << "binder_status_t _aidl_ret_status;\n";
1075
Jeongik Cha95eba572018-11-22 09:14:52 +09001076 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1077 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
1078 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001079
1080 for (const auto& variable : defined_type.GetFields()) {
1081 out << "_aidl_ret_status = ";
1082 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
1083 out << ";\n";
1084 StatusCheckReturn(out);
1085 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001086 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
1087 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
1088 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
1089 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
1090
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001091 out << "return _aidl_ret_status;\n";
1092 out.Dedent();
1093 out << "}\n";
1094 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001095 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -07001096}
Daniel Norman37d43dd2019-09-09 17:22:34 -07001097
Jooyung Han6beac042020-10-17 21:59:43 +09001098void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
1099 const AidlUnionDecl& defined_type, const Options& /*options*/) {
1100 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
1101 cpp::UnionWriter uw{defined_type, types,
1102 [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1103 return NdkNameOf(types, type, StorageMode::STACK);
1104 },
1105 &ConstantValueDecorator};
1106
1107 out << "#pragma once\n";
1108 out << "#include <android/binder_interface_utils.h>\n";
1109 out << "#include <android/binder_parcelable_utils.h>\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001110
1111 // used by toString()
1112 out << "#include <codecvt>\n";
1113 out << "#include <locale>\n";
1114 out << "#include <sstream>\n";
1115
Jooyung Han6beac042020-10-17 21:59:43 +09001116 out << "\n";
1117
1118 for (const auto& header : cpp::UnionWriter::headers) {
1119 out << "#include <" << header << ">\n";
1120 }
1121 GenerateHeaderIncludes(out, types, defined_type);
1122
1123 EnterNdkNamespace(out, defined_type);
1124 out << cpp::TemplateDecl(defined_type);
1125 out << "class " << clazz << " {\n";
1126 out << "public:\n";
1127 out.Indent();
1128 if (defined_type.IsFixedSize()) {
1129 out << "typedef std::true_type fixed_size;\n";
1130 } else {
1131 out << "typedef std::false_type fixed_size;\n";
1132 }
1133 out << "static const char* descriptor;\n";
1134 out << "\n";
1135 uw.PublicFields(out);
1136
1137 out << "binder_status_t readFromParcel(const AParcel* _parcel);\n";
1138 out << "binder_status_t writeToParcel(AParcel* _parcel) const;\n";
1139
1140 out << "static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::"
1141 << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL") << ";\n";
Jooyung Han74b1dd42020-11-01 22:17:16 +09001142 cpp::GenerateToString(out, defined_type);
Jooyung Han6beac042020-10-17 21:59:43 +09001143 out.Dedent();
1144 out << "private:\n";
1145 out.Indent();
1146 uw.PrivateFields(out);
1147 out.Dedent();
1148 out << "};\n";
1149 LeaveNdkNamespace(out, defined_type);
1150}
1151void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
1152 const AidlUnionDecl& defined_type, const Options& /*options*/) {
1153 std::string clazz = ClassName(defined_type, ClassNames::RAW);
1154 if (defined_type.IsGeneric()) {
1155 std::vector<std::string> template_params;
1156 for (const auto& parameter : defined_type.GetTypeParameters()) {
1157 template_params.push_back(parameter);
1158 }
1159 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
1160 }
1161
1162 cpp::UnionWriter uw{defined_type, types,
1163 [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
1164 return NdkNameOf(types, type, StorageMode::STACK);
1165 },
1166 &ConstantValueDecorator};
1167 cpp::ParcelWriterContext ctx{
1168 .status_type = "binder_status_t",
1169 .status_ok = "STATUS_OK",
1170 .status_bad = "STATUS_BAD_VALUE",
1171 .read_func =
1172 [&](CodeWriter& out, const std::string& var, const AidlTypeSpecifier& type) {
1173 ReadFromParcelFor({out, types, type, "_parcel", "&" + var});
1174 },
1175 .write_func =
1176 [&](CodeWriter& out, const std::string& value, const AidlTypeSpecifier& type) {
1177 WriteToParcelFor({out, types, type, "_parcel", value});
1178 },
1179 };
1180
1181 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
1182 << "\"\n";
1183 out << "\n";
1184 GenerateSourceIncludes(out, types, defined_type);
1185 out << "\n";
1186 EnterNdkNamespace(out, defined_type);
1187 out << cpp::TemplateDecl(defined_type);
1188 out << "const char* " << clazz << "::" << kDescriptor << " = \""
1189 << defined_type.GetCanonicalName() << "\";\n";
1190 out << "\n";
1191
1192 out << cpp::TemplateDecl(defined_type);
1193 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _parcel) {\n";
1194 out.Indent();
1195 uw.ReadFromParcel(out, ctx);
1196 out.Dedent();
1197 out << "}\n";
1198
1199 out << cpp::TemplateDecl(defined_type);
1200 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* _parcel) const {\n";
1201 out.Indent();
1202 uw.WriteToParcel(out, ctx);
1203 out.Dedent();
1204 out << "}\n";
1205 out << "\n";
1206 LeaveNdkNamespace(out, defined_type);
1207}
1208
Daniel Norman455d95c2019-11-19 09:55:39 -08001209std::string GenerateEnumToString(const AidlTypenames& typenames,
1210 const AidlEnumDeclaration& enum_decl) {
1211 std::ostringstream code;
1212 code << "static inline std::string toString(" << enum_decl.GetName() << " val) {\n";
1213 code << " switch(val) {\n";
1214 std::set<std::string> unique_cases;
1215 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1216 std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
1217 // Only add a case if its value has not yet been used in the switch
1218 // statement. C++ does not allow multiple cases with the same value, but
1219 // enums does allow this. In this scenario, the first declared
1220 // enumerator with the given value is printed.
1221 if (unique_cases.count(c) == 0) {
1222 unique_cases.insert(c);
1223 code << " case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
1224 code << " return \"" << enumerator->GetName() << "\";\n";
1225 }
1226 }
1227 code << " default:\n";
1228 code << " return std::to_string(static_cast<"
1229 << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
1230 code << " }\n";
1231 code << "}\n";
1232 return code.str();
1233}
1234
Daniel Norman37d43dd2019-09-09 17:22:34 -07001235void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
1236 const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
1237 out << "#pragma once\n";
1238 out << "\n";
1239
1240 GenerateHeaderIncludes(out, types, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001241 // enum specific headers
1242 out << "#include <array>\n";
1243 out << "#include <android/binder_enums.h>\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001244
1245 EnterNdkNamespace(out, enum_decl);
1246 out << "enum class " << enum_decl.GetName() << " : "
1247 << NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK) << " {\n";
1248 out.Indent();
1249 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1250 out << enumerator->GetName() << " = "
1251 << enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator) << ",\n";
1252 }
1253 out.Dedent();
1254 out << "};\n";
Daniel Norman455d95c2019-11-19 09:55:39 -08001255 out << "\n";
1256 out << GenerateEnumToString(types, enum_decl);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001257 LeaveNdkNamespace(out, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001258
1259 out << "namespace ndk {\n";
1260 out << "namespace internal {\n";
1261 out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
1262 out << "} // namespace internal\n";
1263 out << "} // namespace android\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001264}
1265
Steven Morelandb0057e72018-08-27 01:44:11 -07001266} // namespace internals
1267} // namespace ndk
1268} // namespace aidl
1269} // namespace android