blob: d8a29aa743d35ebdd12ad40cef36a0e7d20acba4 [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"
Steven Morelandb0057e72018-08-27 01:44:11 -070023
24#include <android-base/logging.h>
25
26namespace android {
27namespace aidl {
28namespace ndk {
29
Steven Moreland15b3ba72019-03-06 13:17:08 -080030static constexpr const char* kClazz = "_g_aidl_clazz";
Jiyong Park965c5b92018-11-21 13:37:15 +090031static constexpr const char* kDescriptor = "descriptor";
32static constexpr const char* kVersion = "version";
Paul Trautrimb77048c2020-01-21 16:39:32 +090033static constexpr const char* kHash = "hash";
34static constexpr const char* kCachedVersion = "_aidl_cached_version";
35static constexpr const char* kCachedHash = "_aidl_cached_hash";
36static constexpr const char* kCachedHashMutex = "_aidl_cached_hash_mutex";
Jiyong Park965c5b92018-11-21 13:37:15 +090037
Steven Morelandb0057e72018-08-27 01:44:11 -070038using namespace internals;
39using cpp::ClassNames;
40
41void GenerateNdkInterface(const string& output_file, const Options& options,
42 const AidlTypenames& types, const AidlInterface& defined_type,
43 const IoDelegate& io_delegate) {
Jiyong Park5b7e5322019-04-03 20:05:01 +090044 const string i_header = options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
Steven Morelandb0057e72018-08-27 01:44:11 -070045 unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
46 GenerateInterfaceHeader(*i_writer, types, defined_type, options);
47 CHECK(i_writer->Close());
48
Steven Moreland7c933372018-10-11 15:20:04 -070049 const string bp_header =
50 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070051 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
52 GenerateClientHeader(*bp_writer, types, defined_type, options);
53 CHECK(bp_writer->Close());
54
Steven Moreland7c933372018-10-11 15:20:04 -070055 const string bn_header =
56 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070057 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
58 GenerateServerHeader(*bn_writer, types, defined_type, options);
59 CHECK(bn_writer->Close());
60
61 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
62 GenerateSource(*source_writer, types, defined_type, options);
63 CHECK(source_writer->Close());
64}
65
66void GenerateNdkParcel(const string& output_file, const Options& options,
67 const AidlTypenames& types, const AidlStructuredParcelable& defined_type,
68 const IoDelegate& io_delegate) {
Steven Moreland7c933372018-10-11 15:20:04 -070069 const string header_path =
Jiyong Park5b7e5322019-04-03 20:05:01 +090070 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
Steven Morelandb0057e72018-08-27 01:44:11 -070071 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
72 GenerateParcelHeader(*header_writer, types, defined_type, options);
73 CHECK(header_writer->Close());
74
Steven Moreland7c933372018-10-11 15:20:04 -070075 const string bp_header =
76 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070077 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
78 *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
79 CHECK(bp_writer->Close());
80
Steven Moreland7c933372018-10-11 15:20:04 -070081 const string bn_header =
82 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070083 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
84 *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
85 CHECK(bn_writer->Close());
86
87 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
88 GenerateParcelSource(*source_writer, types, defined_type, options);
89 CHECK(source_writer->Close());
90}
91
Steven Moreland2a9a7d62019-02-05 16:11:54 -080092void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
93 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
94 *code_writer
95 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
96 CHECK(code_writer->Close());
97}
98
Daniel Norman37d43dd2019-09-09 17:22:34 -070099void GenerateNdkEnumDeclaration(const string& output_file, const Options& options,
100 const AidlTypenames& types, const AidlEnumDeclaration& defined_type,
101 const IoDelegate& io_delegate) {
102 const string header_path =
103 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
104 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
105 GenerateEnumHeader(*header_writer, types, defined_type, options);
106 CHECK(header_writer->Close());
107
108 const string bp_header =
109 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
110 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
111 *bp_writer << "#error TODO(b/111362593) enums do not have bp classes\n";
112 CHECK(bp_writer->Close());
113
114 const string bn_header =
115 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
116 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
117 *bn_writer << "#error TODO(b/111362593) enums do not have bn classes\n";
118 CHECK(bn_writer->Close());
119
120 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
121 *source_writer
122 << "// This file is intentionally left blank as placeholder for enum declaration.\n";
123 CHECK(source_writer->Close());
124}
125
Steven Morelandb0057e72018-08-27 01:44:11 -0700126void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
127 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700128 if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
129 parcelable != nullptr) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700130 GenerateNdkParcel(output_file, options, types, *parcelable, io_delegate);
131 return;
132 }
133
Daniel Norman37d43dd2019-09-09 17:22:34 -0700134 if (const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
135 parcelable_decl != nullptr) {
Steven Moreland2a9a7d62019-02-05 16:11:54 -0800136 GenerateNdkParcelDeclaration(output_file, io_delegate);
137 return;
138 }
139
Daniel Norman37d43dd2019-09-09 17:22:34 -0700140 if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
141 enum_decl != nullptr) {
142 GenerateNdkEnumDeclaration(output_file, options, types, *enum_decl, io_delegate);
143 return;
144 }
145
146 if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700147 GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
148 return;
149 }
150
Daniel Norman85aed542019-08-21 12:01:14 -0700151 CHECK(false) << "Unrecognized type sent for NDK cpp generation.";
Steven Morelandb0057e72018-08-27 01:44:11 -0700152}
153namespace internals {
154
155void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
156 out << "namespace aidl {\n";
157 cpp::EnterNamespace(out, defined_type);
158}
159void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
160 cpp::LeaveNamespace(out, defined_type);
161 out << "} // namespace aidl\n";
162}
163
Steven Morelandaada3422018-09-20 15:55:33 -0700164static void StatusCheckGoto(CodeWriter& out) {
165 out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
166}
167static void StatusCheckBreak(CodeWriter& out) {
168 out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
169}
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700170static void StatusCheckReturn(CodeWriter& out) {
171 out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
172}
Steven Morelandaada3422018-09-20 15:55:33 -0700173
Steven Moreland2bea13b2018-10-03 15:12:33 -0700174static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
175 const AidlDefinedType& defined_type) {
Steven Moreland8769f932019-10-30 15:38:10 -0700176 out << "#include <cstdint>\n";
177 out << "#include <memory>\n";
178 out << "#include <optional>\n";
179 out << "#include <string>\n";
180 out << "#include <vector>\n";
Steven Moreland88378b12019-10-11 13:13:24 -0700181 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700182 out << "#include <android/binder_stability.h>\n";
Steven Moreland88378b12019-10-11 13:13:24 -0700183 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700184
Steven Moreland2bea13b2018-10-03 15:12:33 -0700185 types.IterateTypes([&](const AidlDefinedType& other_defined_type) {
186 if (&other_defined_type == &defined_type) return;
187
188 if (other_defined_type.AsInterface() != nullptr) {
189 out << "#include <"
Jiyong Park5b7e5322019-04-03 20:05:01 +0900190 << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700191 } else if (other_defined_type.AsStructuredParcelable() != nullptr) {
192 out << "#include <"
Steven Morelandb8df37d2019-11-21 12:33:24 -0800193 << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700194 } else if (other_defined_type.AsParcelable() != nullptr) {
195 out << "#include \"" << other_defined_type.AsParcelable()->GetCppHeader() << "\"\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -0700196 } else if (other_defined_type.AsEnumDeclaration() != nullptr) {
197 out << "#include <"
Steven Morelandb8df37d2019-11-21 12:33:24 -0800198 << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700199 } else {
200 AIDL_FATAL(defined_type) << "Unrecognized type.";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700201 }
202 });
203}
204static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
205 const AidlDefinedType& /*defined_type*/) {
Steven Moreland8769f932019-10-30 15:38:10 -0700206 out << "#include <android/binder_parcel_utils.h>\n";
207
Steven Moreland2bea13b2018-10-03 15:12:33 -0700208 types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
209 if (a_defined_type.AsInterface() != nullptr) {
Steven Moreland7c933372018-10-11 15:20:04 -0700210 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700211 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700212 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700213 << ">\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900214 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/)
215 << ">\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700216 }
217 });
218}
219
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700220static void GenerateConstantDeclarations(CodeWriter& out, const AidlInterface& interface) {
221 for (const auto& constant : interface.GetConstantDeclarations()) {
222 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700223 CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
224 value.GetType() != AidlConstantValue::Type::BINARY);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700225 if (value.GetType() == AidlConstantValue::Type::STRING) {
226 out << "static const char* " << constant->GetName() << ";\n";
227 }
228 }
229 out << "\n";
230
231 bool hasIntegralConstant = false;
232 for (const auto& constant : interface.GetConstantDeclarations()) {
233 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700234 CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
235 value.GetType() != AidlConstantValue::Type::BINARY);
236 if (value.GetType() == AidlConstantValue::Type::BOOLEAN ||
237 value.GetType() == AidlConstantValue::Type::INT8 ||
238 value.GetType() == AidlConstantValue::Type::INT32) {
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700239 hasIntegralConstant = true;
240 break;
241 }
242 }
243
244 if (hasIntegralConstant) {
245 out << "enum : int32_t {\n";
246 out.Indent();
247 for (const auto& constant : interface.GetConstantDeclarations()) {
248 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700249 if (value.GetType() == AidlConstantValue::Type::BOOLEAN ||
250 value.GetType() == AidlConstantValue::Type::INT8 ||
251 value.GetType() == AidlConstantValue::Type::INT32) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700252 out << constant->GetName() << " = " << constant->ValueString(ConstantValueDecorator)
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700253 << ",\n";
254 }
255 }
256 out.Dedent();
257 out << "};\n";
258 }
259}
260static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) {
261 const std::string clazz = ClassName(interface, ClassNames::INTERFACE);
262
263 for (const auto& constant : interface.GetConstantDeclarations()) {
264 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700265 CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
266 value.GetType() != AidlConstantValue::Type::BINARY);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700267 if (value.GetType() == AidlConstantValue::Type::STRING) {
268 out << "const char* " << clazz << "::" << constant->GetName() << " = "
Daniel Norman37d43dd2019-09-09 17:22:34 -0700269 << constant->ValueString(ConstantValueDecorator) << ";\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700270 }
271 }
272}
273
Steven Morelandb0057e72018-08-27 01:44:11 -0700274void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
275 const Options& options) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700276 GenerateSourceIncludes(out, types, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700277 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700278
Steven Morelandb0057e72018-08-27 01:44:11 -0700279 EnterNdkNamespace(out, defined_type);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700280 GenerateClassSource(out, types, defined_type, options);
Steven Morelandb0057e72018-08-27 01:44:11 -0700281 GenerateClientSource(out, types, defined_type, options);
282 GenerateServerSource(out, types, defined_type, options);
283 GenerateInterfaceSource(out, types, defined_type, options);
284 LeaveNdkNamespace(out, defined_type);
285}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700286
Steven Morelandaada3422018-09-20 15:55:33 -0700287static std::string MethodId(const AidlMethod& m) {
288 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
289}
290
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900291static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
292 const AidlInterface& defined_type,
293 const AidlMethod& method,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900294 const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700295 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
296
Steven Moreland2bea13b2018-10-03 15:12:33 -0700297 out << NdkMethodDecl(types, method, clazz) << " {\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700298 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700299 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
Steven Moreland63404532018-10-08 14:31:00 -0700300 out << "::ndk::ScopedAStatus _aidl_status;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900301
Paul Trautrimb77048c2020-01-21 16:39:32 +0900302 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
303 out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
304 out << "if (" << kCachedHash << " != \"-1\") {\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900305 out.Indent();
Paul Trautrimb77048c2020-01-21 16:39:32 +0900306 out << "*_aidl_return = " << kCachedHash << ";\n"
307 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
308 << "return _aidl_status;\n";
309 out.Dedent();
310 out << "}\n";
311 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
312 out << "if (" << kCachedVersion << " != -1) {\n";
313 out.Indent();
314 out << "*_aidl_return = " << kCachedVersion << ";\n"
Jeongik Chac9972922019-02-11 12:41:16 +0900315 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
316 << "return _aidl_status;\n";
317 out.Dedent();
318 out << "}\n";
319 }
320 out << "::ndk::ScopedAParcel _aidl_in;\n";
321 out << "::ndk::ScopedAParcel _aidl_out;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700322 out << "\n";
323
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900324 if (options.GenLog()) {
325 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
326 false /* isServer */, true /* isNdk */);
327 }
328
Steven Morelandaada3422018-09-20 15:55:33 -0700329 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
330 StatusCheckGoto(out);
331
Steven Morelandeb38ee72018-10-15 14:20:04 -0700332 for (const auto& arg : method.GetArguments()) {
333 const std::string var_name = cpp::BuildVarName(*arg);
334
335 if (arg->IsIn()) {
336 out << "_aidl_ret_status = ";
337 const std::string prefix = (arg->IsOut() ? "*" : "");
338 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
339 out << ";\n";
340 StatusCheckGoto(out);
341 } else if (arg->IsOut() && arg->GetType().IsArray()) {
342 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
343 << ");\n";
344 }
Steven Morelandaada3422018-09-20 15:55:33 -0700345 }
346 out << "_aidl_ret_status = AIBinder_transact(\n";
347 out.Indent();
348 out << "asBinder().get(),\n";
349 out << MethodId(method) << ",\n";
350 out << "_aidl_in.getR(),\n";
351 out << "_aidl_out.getR(),\n";
Steven Morelandb72a1e72019-10-15 11:23:26 -0700352 out << (method.IsOneway() ? "FLAG_ONEWAY" : "0") << "\n";
353 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
354 out << "| FLAG_PRIVATE_LOCAL\n";
355 out << "#endif // BINDER_STABILITY_SUPPORT\n";
356 out << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700357 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900358
359 // If the method is not implmented in the server side but the client has
360 // provided the default implementation, call it instead of failing hard.
361 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
362 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
363 out << iface << "::getDefaultImpl()) {\n";
364 out.Indent();
365 out << "return " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
366 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
367 out.Dedent();
368 out << "}\n";
369
Steven Morelandaada3422018-09-20 15:55:33 -0700370 StatusCheckGoto(out);
371
372 if (!method.IsOneway()) {
373 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
374 StatusCheckGoto(out);
375
376 out << "if (!AStatus_isOk(_aidl_status.get())) return _aidl_status;\n\n";
377 }
378
Steven Morelandaada3422018-09-20 15:55:33 -0700379 if (method.GetType().GetName() != "void") {
380 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700381 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700382 out << ";\n";
383 StatusCheckGoto(out);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900384 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
385 out << kCachedHash << " = *_aidl_return;\n";
386 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
387 out << kCachedVersion << " = *_aidl_return;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900388 }
Steven Morelandaada3422018-09-20 15:55:33 -0700389 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700390 for (const AidlArgument* arg : method.GetOutArguments()) {
391 out << "_aidl_ret_status = ";
392 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
393 out << ";\n";
394 StatusCheckGoto(out);
395 }
Steven Morelandaada3422018-09-20 15:55:33 -0700396
397 out << "_aidl_error:\n";
398 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900399 if (options.GenLog()) {
400 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
401 method, "_aidl_status", "_aidl_return", false /* isServer */,
402 true /* isNdk */);
403 }
Steven Morelandaada3422018-09-20 15:55:33 -0700404 out << "return _aidl_status;\n";
405 out.Dedent();
406 out << "}\n";
407}
408
Steven Moreland2bea13b2018-10-03 15:12:33 -0700409static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900410 const AidlInterface& defined_type,
411 const AidlMethod& method, const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700412 out << "case " << MethodId(method) << ": {\n";
413 out.Indent();
414 for (const auto& arg : method.GetArguments()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700415 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
416 << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700417 }
418 if (method.GetType().GetName() != "void") {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700419 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700420 }
421 out << "\n";
422
Steven Morelandeb38ee72018-10-15 14:20:04 -0700423 for (const auto& arg : method.GetArguments()) {
424 const std::string var_name = cpp::BuildVarName(*arg);
425
426 if (arg->IsIn()) {
427 out << "_aidl_ret_status = ";
428 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
429 out << ";\n";
430 StatusCheckBreak(out);
431 } else if (arg->IsOut() && arg->GetType().IsArray()) {
432 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
433 }
Steven Morelandaada3422018-09-20 15:55:33 -0700434 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900435 if (options.GenLog()) {
436 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
437 true /* isServer */, true /* isNdk */);
438 }
Steven Moreland63404532018-10-08 14:31:00 -0700439 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
Jiyong Park965c5b92018-11-21 13:37:15 +0900440 << NdkArgList(types, method, FormatArgForCall) << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700441
Jeongik Chaeaf978e2019-05-04 00:32:35 +0900442 if (options.GenLog()) {
443 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
444 method, "_aidl_status", "_aidl_return", true /* isServer */,
445 true /* isNdk */);
446 }
Steven Morelandaada3422018-09-20 15:55:33 -0700447 if (method.IsOneway()) {
448 // For a oneway transaction, the kernel will have already returned a result. This is for the
449 // in-process case when a oneway transaction is parceled/unparceled in the same process.
450 out << "_aidl_ret_status = STATUS_OK;\n";
451 } else {
452 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
453 StatusCheckBreak(out);
454
455 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
456
Steven Morelandaada3422018-09-20 15:55:33 -0700457 if (method.GetType().GetName() != "void") {
458 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700459 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700460 out << ";\n";
461 StatusCheckBreak(out);
462 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700463 for (const AidlArgument* arg : method.GetOutArguments()) {
464 out << "_aidl_ret_status = ";
465 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
466 out << ";\n";
467 StatusCheckBreak(out);
468 }
Steven Morelandaada3422018-09-20 15:55:33 -0700469 }
Steven Morelandaada3422018-09-20 15:55:33 -0700470 out << "break;\n";
471 out.Dedent();
472 out << "}\n";
473}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700474
Steven Moreland2bea13b2018-10-03 15:12:33 -0700475void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900476 const AidlInterface& defined_type, const Options& options) {
Steven Moreland0cf3f082018-09-20 19:09:46 -0700477 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
478 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700479
Steven Moreland15b3ba72019-03-06 13:17:08 -0800480 out << "static binder_status_t "
481 << "_aidl_onTransact"
Steven Morelandaada3422018-09-20 15:55:33 -0700482 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
483 "AParcel* _aidl_out) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700484 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700485 out << "(void)_aidl_in;\n";
486 out << "(void)_aidl_out;\n";
487 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
488 if (!defined_type.GetMethods().empty()) {
Steven Moreland15b3ba72019-03-06 13:17:08 -0800489 // we know this cast is valid because this method is only called by the ICInterface
490 // AIBinder_Class object which is associated with this class.
491 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = std::static_pointer_cast<" << bn_clazz
492 << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700493 out << "switch (_aidl_code) {\n";
494 out.Indent();
495 for (const auto& method : defined_type.GetMethods()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900496 GenerateServerCaseDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700497 }
498 out.Dedent();
499 out << "}\n";
500 } else {
501 out << "(void)_aidl_binder;\n";
502 out << "(void)_aidl_code;\n";
503 }
504 out << "return _aidl_ret_status;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700505 out.Dedent();
Steven Moreland73d66242019-09-26 16:03:54 -0700506 out << "}\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700507
Steven Moreland15b3ba72019-03-06 13:17:08 -0800508 out << "static AIBinder_Class* " << kClazz << " = ::ndk::ICInterface::defineClass(" << clazz
509 << "::" << kDescriptor << ", _aidl_onTransact);\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700510}
Steven Morelandb0057e72018-08-27 01:44:11 -0700511void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900512 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700513 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700514
Steven Moreland63404532018-10-08 14:31:00 -0700515 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700516 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900517 if (options.GenLog()) {
518 out << "std::function<void(const Json::Value&)> " << clazz << "::logFunc;\n";
519 }
Steven Morelandaada3422018-09-20 15:55:33 -0700520 out << "\n";
521 for (const auto& method : defined_type.GetMethods()) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900522 GenerateClientMethodDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700523 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700524}
Jiyong Park965c5b92018-11-21 13:37:15 +0900525void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
526 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700527 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900528 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700529
530 out << "// Source for " << clazz << "\n";
531 out << clazz << "::" << clazz << "() {}\n";
532 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900533 if (options.GenLog()) {
534 out << "std::function<void(const Json::Value&)> " << clazz << "::logFunc;\n";
535 }
Steven Moreland63404532018-10-08 14:31:00 -0700536 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700537 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800538 out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700539
Steven Moreland88378b12019-10-11 13:13:24 -0700540 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700541 if (defined_type.IsVintfStability()) {
542 out << "AIBinder_markVintfStability(binder);\n";
543 } else {
544 out << "AIBinder_markCompilationUnitStability(binder);\n";
545 }
Steven Moreland88378b12019-10-11 13:13:24 -0700546 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700547
Steven Moreland63404532018-10-08 14:31:00 -0700548 out << "return ::ndk::SpAIBinder(binder);\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700549 out.Dedent();
550 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900551
552 // Implement the meta methods
553 for (const auto& method : defined_type.GetMethods()) {
554 if (method->IsUserDefined()) {
555 continue;
556 }
557 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
558 out << NdkMethodDecl(types, *method, clazz) << " {\n";
559 out.Indent();
560 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
561 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
562 out.Dedent();
563 out << "}\n";
564 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900565 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
566 out << NdkMethodDecl(types, *method, clazz) << " {\n";
567 out.Indent();
568 out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
569 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
570 out.Dedent();
571 out << "}\n";
572 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900573 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700574}
Jiyong Park965c5b92018-11-21 13:37:15 +0900575void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
576 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700577 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland15b3ba72019-03-06 13:17:08 -0800578 const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -0700579
580 out << "// Source for " << clazz << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900581 out << "const char* " << clazz << "::" << kDescriptor << " = \""
582 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700583 out << clazz << "::" << clazz << "() {}\n";
584 out << clazz << "::~" << clazz << "() {}\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700585 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700586 GenerateConstantDefinitions(out, defined_type);
587 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700588
Steven Moreland3c316ed2019-01-17 09:39:37 -0800589 out << "std::shared_ptr<" << clazz << "> " << clazz
590 << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800591 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800592 out << "if (!AIBinder_associateClass(binder.get(), " << kClazz << ")) { return nullptr; }\n";
593 out << "std::shared_ptr<::ndk::ICInterface> interface = "
594 "::ndk::ICInterface::asInterface(binder.get());\n";
595 out << "if (interface) {\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800596 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800597 out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800598 out.Dedent();
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800599 out << "}\n";
Steven Morelandc09d34c2020-02-13 09:42:49 -0800600 out << "return ::ndk::SharedRefBase::make<" << bp_clazz << ">(binder);\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800601 out.Dedent();
Steven Moreland3c316ed2019-01-17 09:39:37 -0800602 out << "}\n\n";
603
Steven Moreland2bea13b2018-10-03 15:12:33 -0700604 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
605 << clazz << ">& instance) {\n";
606 out.Indent();
607 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
608 "nullptr);\n";
609 out.Dedent();
610 out << "}\n";
611
612 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
613 << clazz << ">* instance) {\n";
614 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700615 out << "::ndk::SpAIBinder binder;\n";
Steven Moreland055d8792018-11-14 12:48:42 -0800616 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700617 out << "if (status != STATUS_OK) return status;\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800618 out << "*instance = " << clazz << "::fromBinder(binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700619 out << "return STATUS_OK;\n";
620 out.Dedent();
621 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900622
623 // defintion for static member setDefaultImpl
624 out << "bool " << clazz << "::setDefaultImpl(std::shared_ptr<" << clazz << "> impl) {\n";
625 out.Indent();
Jooyung Hand4d65342020-05-13 17:17:07 +0900626 out << "// Only one user of this interface can use this function\n";
627 out << "// at a time. This is a heuristic to detect if two different\n";
628 out << "// users in the same process use this function.\n";
629 out << "assert(!" << clazz << "::default_impl);\n";
630 out << "if (impl) {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900631 out.Indent();
632 out << clazz << "::default_impl = impl;\n";
633 out << "return true;\n";
634 out.Dedent();
635 out << "}\n";
636 out << "return false;\n";
637 out.Dedent();
638 out << "}\n";
639
640 // definition for static member getDefaultImpl
641 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
642 out.Indent();
643 out << "return " << clazz << "::default_impl;\n";
644 out.Dedent();
645 out << "}\n";
646
647 // definition for the static field default_impl
648 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
649
650 // default implementation for the <Name>Default class members
651 const std::string defaultClazz = clazz + "Default";
652 for (const auto& method : defined_type.GetMethods()) {
653 if (method->IsUserDefined()) {
654 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
655 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
656 out.Indent();
657 out << "::ndk::ScopedAStatus _aidl_status;\n";
658 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
659 out << "return _aidl_status;\n";
660 out.Dedent();
661 out << "}\n";
662 } else {
663 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
664 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
665 << "int32_t* _aidl_return) {\n";
666 out.Indent();
667 out << "*_aidl_return = 0;\n";
668 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
669 out.Dedent();
670 out << "}\n";
671 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900672 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
673 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
674 << "std::string* _aidl_return) {\n";
675 out.Indent();
676 out << "*_aidl_return = \"\";\n";
677 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
678 out.Dedent();
679 out << "}\n";
680 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900681 }
682 }
683
684 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
685 out.Indent();
686 out << "return ::ndk::SpAIBinder();\n";
687 out.Dedent();
688 out << "}\n";
689
690 out << "bool " << defaultClazz << "::isRemote() {\n";
691 out.Indent();
692 out << "return false;\n";
693 out.Dedent();
694 out << "}\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700695}
Jiyong Park965c5b92018-11-21 13:37:15 +0900696
Steven Morelandb0057e72018-08-27 01:44:11 -0700697void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900698 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700699 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
700
701 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900702 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700703 << "\"\n";
704 out << "\n";
705 out << "#include <android/binder_ibinder.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900706 if (options.GenLog()) {
707 out << "#include <json/value.h>\n";
708 out << "#include <functional>\n";
709 out << "#include <chrono>\n";
710 out << "#include <sstream>\n";
711 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700712 out << "\n";
713 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700714 out << "class " << clazz << " : public ::ndk::BpCInterface<"
Steven Morelandb0057e72018-08-27 01:44:11 -0700715 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
716 out << "public:\n";
717 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800718 out << clazz << "(const ::ndk::SpAIBinder& binder);\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700719 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700720 out << "\n";
721 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700722 out << NdkMethodDecl(types, *method) << " override;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700723 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900724
725 if (options.Version() > 0) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900726 out << "int32_t " << kCachedVersion << " = -1;\n";
727 }
728
729 if (!options.Hash().empty()) {
730 out << "std::string " << kCachedHash << " = \"-1\";\n";
731 out << "std::mutex " << kCachedHashMutex << ";\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900732 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900733 if (options.GenLog()) {
734 out << "static std::function<void(const Json::Value&)> logFunc;\n";
735 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700736 out.Dedent();
737 out << "};\n";
738 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700739}
Jiyong Park965c5b92018-11-21 13:37:15 +0900740void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
741 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700742 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900743 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700744
745 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900746 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700747 << "\"\n";
748 out << "\n";
749 out << "#include <android/binder_ibinder.h>\n";
750 out << "\n";
751 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900752 out << "class " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700753 out << "public:\n";
754 out.Indent();
755 out << clazz << "();\n";
756 out << "virtual ~" << clazz << "();\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900757
758 // Declare the meta methods
759 for (const auto& method : defined_type.GetMethods()) {
760 if (method->IsUserDefined()) {
761 continue;
762 }
763 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
764 out << NdkMethodDecl(types, *method) << " final override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900765 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
766 out << NdkMethodDecl(types, *method) << " final override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900767 } else {
768 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
769 }
770 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900771 if (options.GenLog()) {
772 out << "static std::function<void(const Json::Value&)> logFunc;\n";
773 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700774 out.Dedent();
Steven Moreland0cf3f082018-09-20 19:09:46 -0700775 out << "protected:\n";
776 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700777 out << "::ndk::SpAIBinder createBinder() override;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700778 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700779 out << "private:\n";
780 out.Indent();
781 out.Dedent();
782 out << "};\n";
783 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700784}
785void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900786 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700787 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
788
789 out << "#pragma once\n\n";
790 out << "#include <android/binder_interface_utils.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900791 if (options.GenLog()) {
792 out << "#include <json/value.h>\n";
793 out << "#include <functional>\n";
794 out << "#include <chrono>\n";
795 out << "#include <sstream>\n";
796 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700797 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700798
799 GenerateHeaderIncludes(out, types, defined_type);
800 out << "\n";
801
Steven Morelandb0057e72018-08-27 01:44:11 -0700802 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700803 out << "class " << clazz << " : public ::ndk::ICInterface {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700804 out << "public:\n";
805 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900806 out << "static const char* " << kDescriptor << ";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700807 out << clazz << "();\n";
808 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700809 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700810 GenerateConstantDeclarations(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900811 if (options.Version() > 0) {
812 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
813 << ";\n";
814 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900815 if (!options.Hash().empty()) {
816 out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
817 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700818 out << "\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800819 out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700820 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
821 << ">& instance);";
Jiyong Park1b88cce2018-11-19 19:53:44 +0900822 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700823 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
824 << ">* instance);";
825 out << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900826 out << "static bool setDefaultImpl(std::shared_ptr<" << clazz << "> impl);";
827 out << "\n";
828 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
829 out << "\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700830 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700831 out << "virtual " << NdkMethodDecl(types, *method) << " = 0;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700832 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700833 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900834 out << "private:\n";
835 out.Indent();
836 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
837 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700838 out << "};\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900839
840 const std::string defaultClazz = clazz + "Default";
841
842 out << "class " << defaultClazz << " : public " << clazz << " {\n";
843 out << "public:\n";
844 out.Indent();
845 for (const auto& method : defined_type.GetMethods()) {
846 if (method->IsUserDefined()) {
847 out << NdkMethodDecl(types, *method) << " override;\n";
848 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
849 out << NdkMethodDecl(types, *method) << " override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900850 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
851 out << NdkMethodDecl(types, *method) << " override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900852 }
853 }
854 out << "::ndk::SpAIBinder asBinder() override;\n";
855 out << "bool isRemote() override;\n";
856 out.Dedent();
857 out << "};\n";
858
Steven Morelandb0057e72018-08-27 01:44:11 -0700859 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700860}
861void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700862 const AidlStructuredParcelable& defined_type,
863 const Options& /*options*/) {
Steven Morelandb8df37d2019-11-21 12:33:24 -0800864 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700865
Steven Morelandb0057e72018-08-27 01:44:11 -0700866 out << "#pragma once\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700867 out << "#include <android/binder_interface_utils.h>\n";
868 out << "\n";
869
870 GenerateHeaderIncludes(out, types, defined_type);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700871
Steven Morelandb0057e72018-08-27 01:44:11 -0700872 EnterNdkNamespace(out, defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700873 out << "class " << clazz << " {\n";
874 out << "public:\n";
875 out.Indent();
876 out << "static const char* descriptor;\n";
877 out << "\n";
878 for (const auto& variable : defined_type.GetFields()) {
879 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << " " << variable->GetName();
880 if (variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700881 out << " = " << variable->ValueString(ConstantValueDecorator);
Jeongik Chadb561c92021-09-25 01:19:56 +0900882 } else if (auto type = types.TryGetDefinedType(variable->GetType().GetName()); type) {
883 if (auto enum_type = type->AsEnumDeclaration(); enum_type) {
884 if (!variable->GetType().IsArray()) {
885 // if an enum doesn't have explicit default value, do zero-initialization
886 out << " = " << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << "(0)";
887 }
888 }
Jooyung Hana2dafff2022-03-25 22:03:56 +0900889 } else if (AidlTypenames::IsPrimitiveTypename(variable->GetType().GetName()) &&
890 !variable->GetType().IsArray()) {
891 out << " = {}";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700892 }
893 out << ";\n";
894 }
895 out << "\n";
896 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
897 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
898 out.Dedent();
899 out << "};\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700900 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700901}
902void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700903 const AidlStructuredParcelable& defined_type,
904 const Options& /*options*/) {
Steven Morelandb8df37d2019-11-21 12:33:24 -0800905 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700906
Jiyong Park5b7e5322019-04-03 20:05:01 +0900907 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700908 << "\"\n";
909 out << "\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700910 GenerateSourceIncludes(out, types, defined_type);
911 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700912 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900913 out << "const char* " << clazz << "::" << kDescriptor << " = \""
914 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700915 out << "\n";
916
917 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
918 out.Indent();
Jeongik Cha95eba572018-11-22 09:14:52 +0900919 out << "int32_t _aidl_parcelable_size;\n";
Steven Moreland4348f9a2019-12-16 16:33:01 -0800920 out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
921 out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900922 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
923 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700924
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700925 for (const auto& variable : defined_type.GetFields()) {
926 out << "_aidl_ret_status = ";
927 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
928 out << ";\n";
929 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900930 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
931 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
932 << " return _aidl_ret_status;\n"
933 << "}\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700934 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900935 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
936 << "return _aidl_ret_status;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700937 out.Dedent();
938 out << "}\n";
939
940 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
941 out.Indent();
942 out << "binder_status_t _aidl_ret_status;\n";
943
Jeongik Cha95eba572018-11-22 09:14:52 +0900944 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
945 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
946 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700947
948 for (const auto& variable : defined_type.GetFields()) {
949 out << "_aidl_ret_status = ";
950 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
951 out << ";\n";
952 StatusCheckReturn(out);
953 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900954 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
955 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
956 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
957 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
958
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700959 out << "return _aidl_ret_status;\n";
960 out.Dedent();
961 out << "}\n";
962 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700963 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700964}
Daniel Norman37d43dd2019-09-09 17:22:34 -0700965
Daniel Norman455d95c2019-11-19 09:55:39 -0800966std::string GenerateEnumToString(const AidlTypenames& typenames,
967 const AidlEnumDeclaration& enum_decl) {
968 std::ostringstream code;
969 code << "static inline std::string toString(" << enum_decl.GetName() << " val) {\n";
970 code << " switch(val) {\n";
971 std::set<std::string> unique_cases;
972 for (const auto& enumerator : enum_decl.GetEnumerators()) {
973 std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
974 // Only add a case if its value has not yet been used in the switch
975 // statement. C++ does not allow multiple cases with the same value, but
976 // enums does allow this. In this scenario, the first declared
977 // enumerator with the given value is printed.
978 if (unique_cases.count(c) == 0) {
979 unique_cases.insert(c);
980 code << " case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
981 code << " return \"" << enumerator->GetName() << "\";\n";
982 }
983 }
984 code << " default:\n";
985 code << " return std::to_string(static_cast<"
986 << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
987 code << " }\n";
988 code << "}\n";
989 return code.str();
990}
991
Daniel Norman37d43dd2019-09-09 17:22:34 -0700992void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
993 const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
994 out << "#pragma once\n";
995 out << "\n";
996
997 GenerateHeaderIncludes(out, types, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +0000998 // enum specific headers
999 out << "#include <array>\n";
1000 out << "#include <android/binder_enums.h>\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001001
1002 EnterNdkNamespace(out, enum_decl);
1003 out << "enum class " << enum_decl.GetName() << " : "
1004 << NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK) << " {\n";
1005 out.Indent();
1006 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1007 out << enumerator->GetName() << " = "
1008 << enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator) << ",\n";
1009 }
1010 out.Dedent();
1011 out << "};\n";
Daniel Norman455d95c2019-11-19 09:55:39 -08001012 out << "\n";
1013 out << GenerateEnumToString(types, enum_decl);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001014 LeaveNdkNamespace(out, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001015
1016 out << "namespace ndk {\n";
1017 out << "namespace internal {\n";
1018 out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
1019 out << "} // namespace internal\n";
1020 out << "} // namespace android\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001021}
1022
Steven Morelandb0057e72018-08-27 01:44:11 -07001023} // namespace internals
1024} // namespace ndk
1025} // namespace aidl
1026} // namespace android