blob: 779de7e265efed85a6096aa4fcc7d6b5257336f8 [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;
40using cpp::ClassNames;
41
42void GenerateNdkInterface(const string& output_file, const Options& options,
43 const AidlTypenames& types, const AidlInterface& defined_type,
44 const IoDelegate& io_delegate) {
Jiyong Park5b7e5322019-04-03 20:05:01 +090045 const string i_header = options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
Steven Morelandb0057e72018-08-27 01:44:11 -070046 unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
47 GenerateInterfaceHeader(*i_writer, types, defined_type, options);
48 CHECK(i_writer->Close());
49
Steven Moreland7c933372018-10-11 15:20:04 -070050 const string bp_header =
51 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070052 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
53 GenerateClientHeader(*bp_writer, types, defined_type, options);
54 CHECK(bp_writer->Close());
55
Steven Moreland7c933372018-10-11 15:20:04 -070056 const string bn_header =
57 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070058 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
59 GenerateServerHeader(*bn_writer, types, defined_type, options);
60 CHECK(bn_writer->Close());
61
62 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
63 GenerateSource(*source_writer, types, defined_type, options);
64 CHECK(source_writer->Close());
65}
66
67void GenerateNdkParcel(const string& output_file, const Options& options,
68 const AidlTypenames& types, const AidlStructuredParcelable& defined_type,
69 const IoDelegate& io_delegate) {
Steven Moreland7c933372018-10-11 15:20:04 -070070 const string header_path =
Jiyong Park5b7e5322019-04-03 20:05:01 +090071 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
Steven Morelandb0057e72018-08-27 01:44:11 -070072 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
73 GenerateParcelHeader(*header_writer, types, defined_type, options);
Devin Moore53fc99c2020-08-12 08:07:52 -070074
75 unique_ptr<CodeWriter> source_writer(io_delegate.GetCodeWriter(output_file));
76 if (defined_type.IsGeneric()) {
77 // Need to write source to header if this is a template
78 GenerateParcelSource(*header_writer, types, defined_type, options);
79 } else {
80 GenerateParcelSource(*source_writer, types, defined_type, options);
81 }
82 CHECK(source_writer->Close());
Steven Morelandb0057e72018-08-27 01:44:11 -070083 CHECK(header_writer->Close());
84
Steven Moreland7c933372018-10-11 15:20:04 -070085 const string bp_header =
86 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070087 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
88 *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
89 CHECK(bp_writer->Close());
90
Steven Moreland7c933372018-10-11 15:20:04 -070091 const string bn_header =
92 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070093 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
94 *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
95 CHECK(bn_writer->Close());
Steven Morelandb0057e72018-08-27 01:44:11 -070096}
97
Steven Moreland2a9a7d62019-02-05 16:11:54 -080098void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
99 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
100 *code_writer
101 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
102 CHECK(code_writer->Close());
103}
104
Daniel Norman37d43dd2019-09-09 17:22:34 -0700105void GenerateNdkEnumDeclaration(const string& output_file, const Options& options,
106 const AidlTypenames& types, const AidlEnumDeclaration& defined_type,
107 const IoDelegate& io_delegate) {
108 const string header_path =
109 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
110 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
111 GenerateEnumHeader(*header_writer, types, defined_type, options);
112 CHECK(header_writer->Close());
113
114 const string bp_header =
115 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
116 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
117 *bp_writer << "#error TODO(b/111362593) enums do not have bp classes\n";
118 CHECK(bp_writer->Close());
119
120 const string bn_header =
121 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
122 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
123 *bn_writer << "#error TODO(b/111362593) enums do not have bn classes\n";
124 CHECK(bn_writer->Close());
125
126 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
127 *source_writer
128 << "// This file is intentionally left blank as placeholder for enum declaration.\n";
129 CHECK(source_writer->Close());
130}
131
Steven Morelandb0057e72018-08-27 01:44:11 -0700132void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
133 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700134 if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
135 parcelable != nullptr) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700136 GenerateNdkParcel(output_file, options, types, *parcelable, io_delegate);
137 return;
138 }
139
Daniel Norman37d43dd2019-09-09 17:22:34 -0700140 if (const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
141 parcelable_decl != nullptr) {
Steven Moreland2a9a7d62019-02-05 16:11:54 -0800142 GenerateNdkParcelDeclaration(output_file, io_delegate);
143 return;
144 }
145
Daniel Norman37d43dd2019-09-09 17:22:34 -0700146 if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
147 enum_decl != nullptr) {
148 GenerateNdkEnumDeclaration(output_file, options, types, *enum_decl, io_delegate);
149 return;
150 }
151
152 if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700153 GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
154 return;
155 }
156
Daniel Norman85aed542019-08-21 12:01:14 -0700157 CHECK(false) << "Unrecognized type sent for NDK cpp generation.";
Steven Morelandb0057e72018-08-27 01:44:11 -0700158}
159namespace internals {
160
161void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
162 out << "namespace aidl {\n";
163 cpp::EnterNamespace(out, defined_type);
164}
165void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
166 cpp::LeaveNamespace(out, defined_type);
167 out << "} // namespace aidl\n";
168}
169
Steven Morelandaada3422018-09-20 15:55:33 -0700170static void StatusCheckGoto(CodeWriter& out) {
171 out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
172}
173static void StatusCheckBreak(CodeWriter& out) {
174 out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
175}
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700176static void StatusCheckReturn(CodeWriter& out) {
177 out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
178}
Steven Morelandaada3422018-09-20 15:55:33 -0700179
Steven Moreland2bea13b2018-10-03 15:12:33 -0700180static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
181 const AidlDefinedType& defined_type) {
Steven Moreland8769f932019-10-30 15:38:10 -0700182 out << "#include <cstdint>\n";
183 out << "#include <memory>\n";
184 out << "#include <optional>\n";
185 out << "#include <string>\n";
186 out << "#include <vector>\n";
Steven Moreland88378b12019-10-11 13:13:24 -0700187 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700188 out << "#include <android/binder_stability.h>\n";
Steven Moreland88378b12019-10-11 13:13:24 -0700189 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700190
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900191 auto headerFilePath = [&types](const AidlTypeSpecifier& typespec) -> std::string {
192 const AidlDefinedType* type = types.TryGetDefinedType(typespec.GetName());
193 if (type == nullptr) {
194 // could be a primitive type.
195 return "";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700196 }
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900197
198 if (type->AsInterface() != nullptr) {
199 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
200 } else if (type->AsStructuredParcelable() != nullptr) {
201 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
202 } else if (type->AsParcelable() != nullptr) {
203 return type->AsParcelable()->GetCppHeader();
204 } else if (type->AsEnumDeclaration() != nullptr) {
205 return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
206 } else {
207 AIDL_FATAL(*type) << "Unrecognized type.";
208 return "";
209 }
210 };
211
212 std::set<std::string> includes;
213
214 const AidlInterface* interface = defined_type.AsInterface();
215 if (interface != nullptr) {
216 for (const auto& method : interface->GetMethods()) {
217 includes.insert(headerFilePath(method->GetType()));
218 for (const auto& argument : method->GetArguments()) {
219 includes.insert(headerFilePath(argument->GetType()));
Devin Moore53fc99c2020-08-12 08:07:52 -0700220 // Check the method arguments for generic type arguments
221 if (argument->GetType().IsGeneric()) {
222 for (const auto& type_argument : argument->GetType().GetTypeParameters()) {
223 includes.insert(headerFilePath(*type_argument));
224 }
225 }
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900226 }
227 }
228 }
229
230 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
231 if (parcelable != nullptr) {
232 for (const auto& field : parcelable->GetFields()) {
233 includes.insert(headerFilePath(field->GetType()));
Devin Moore53fc99c2020-08-12 08:07:52 -0700234 // Check the fields for generic type arguments
235 if (field->GetType().IsGeneric()) {
236 for (const auto& type_argument : field->GetType().GetTypeParameters()) {
237 includes.insert(headerFilePath(*type_argument));
238 }
239 }
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900240 }
241 }
242
243 const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
244 if (enum_decl != nullptr) {
245 includes.insert(headerFilePath(enum_decl->GetBackingType()));
246 }
247
248 for (const auto& path : includes) {
249 if (path == "") {
250 continue;
251 }
252 out << "#include <" << path << ">\n";
253 }
Steven Moreland2bea13b2018-10-03 15:12:33 -0700254}
Jiyong Parkf1f5c802020-05-19 17:33:00 +0900255
Steven Moreland2bea13b2018-10-03 15:12:33 -0700256static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
257 const AidlDefinedType& /*defined_type*/) {
Steven Moreland8769f932019-10-30 15:38:10 -0700258 out << "#include <android/binder_parcel_utils.h>\n";
259
Steven Moreland2bea13b2018-10-03 15:12:33 -0700260 types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
261 if (a_defined_type.AsInterface() != nullptr) {
Steven Moreland7c933372018-10-11 15:20:04 -0700262 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700263 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700264 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700265 << ">\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900266 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/)
267 << ">\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700268 }
269 });
270}
271
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700272static void GenerateConstantDeclarations(CodeWriter& out, const AidlInterface& interface) {
273 for (const auto& constant : interface.GetConstantDeclarations()) {
274 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700275 CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
276 value.GetType() != AidlConstantValue::Type::BINARY);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700277 if (value.GetType() == AidlConstantValue::Type::STRING) {
278 out << "static const char* " << constant->GetName() << ";\n";
279 }
280 }
281 out << "\n";
282
283 bool hasIntegralConstant = false;
284 for (const auto& constant : interface.GetConstantDeclarations()) {
285 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700286 CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
287 value.GetType() != AidlConstantValue::Type::BINARY);
288 if (value.GetType() == AidlConstantValue::Type::BOOLEAN ||
289 value.GetType() == AidlConstantValue::Type::INT8 ||
290 value.GetType() == AidlConstantValue::Type::INT32) {
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700291 hasIntegralConstant = true;
292 break;
293 }
294 }
295
296 if (hasIntegralConstant) {
297 out << "enum : int32_t {\n";
298 out.Indent();
299 for (const auto& constant : interface.GetConstantDeclarations()) {
300 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700301 if (value.GetType() == AidlConstantValue::Type::BOOLEAN ||
302 value.GetType() == AidlConstantValue::Type::INT8 ||
303 value.GetType() == AidlConstantValue::Type::INT32) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700304 out << constant->GetName() << " = " << constant->ValueString(ConstantValueDecorator)
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700305 << ",\n";
306 }
307 }
308 out.Dedent();
309 out << "};\n";
310 }
311}
312static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) {
313 const std::string clazz = ClassName(interface, ClassNames::INTERFACE);
314
315 for (const auto& constant : interface.GetConstantDeclarations()) {
316 const AidlConstantValue& value = constant->GetValue();
Will McVickerd7d18df2019-09-12 13:40:50 -0700317 CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
318 value.GetType() != AidlConstantValue::Type::BINARY);
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700319 if (value.GetType() == AidlConstantValue::Type::STRING) {
320 out << "const char* " << clazz << "::" << constant->GetName() << " = "
Daniel Norman37d43dd2019-09-09 17:22:34 -0700321 << constant->ValueString(ConstantValueDecorator) << ";\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700322 }
323 }
324}
325
Steven Morelandb0057e72018-08-27 01:44:11 -0700326void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
327 const Options& options) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700328 GenerateSourceIncludes(out, types, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700329 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700330
Steven Morelandb0057e72018-08-27 01:44:11 -0700331 EnterNdkNamespace(out, defined_type);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700332 GenerateClassSource(out, types, defined_type, options);
Steven Morelandb0057e72018-08-27 01:44:11 -0700333 GenerateClientSource(out, types, defined_type, options);
334 GenerateServerSource(out, types, defined_type, options);
335 GenerateInterfaceSource(out, types, defined_type, options);
336 LeaveNdkNamespace(out, defined_type);
337}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700338
Steven Morelandaada3422018-09-20 15:55:33 -0700339static std::string MethodId(const AidlMethod& m) {
340 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
341}
342
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900343static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
344 const AidlInterface& defined_type,
345 const AidlMethod& method,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900346 const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700347 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
348
Steven Moreland2bea13b2018-10-03 15:12:33 -0700349 out << NdkMethodDecl(types, method, clazz) << " {\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700350 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700351 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
Steven Moreland63404532018-10-08 14:31:00 -0700352 out << "::ndk::ScopedAStatus _aidl_status;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900353
Paul Trautrimb77048c2020-01-21 16:39:32 +0900354 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
355 out << "const std::lock_guard<std::mutex> lock(" << kCachedHashMutex << ");\n";
356 out << "if (" << kCachedHash << " != \"-1\") {\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900357 out.Indent();
Paul Trautrimb77048c2020-01-21 16:39:32 +0900358 out << "*_aidl_return = " << kCachedHash << ";\n"
359 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
360 << "return _aidl_status;\n";
361 out.Dedent();
362 out << "}\n";
363 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
364 out << "if (" << kCachedVersion << " != -1) {\n";
365 out.Indent();
366 out << "*_aidl_return = " << kCachedVersion << ";\n"
Jeongik Chac9972922019-02-11 12:41:16 +0900367 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
368 << "return _aidl_status;\n";
369 out.Dedent();
370 out << "}\n";
371 }
372 out << "::ndk::ScopedAParcel _aidl_in;\n";
373 out << "::ndk::ScopedAParcel _aidl_out;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700374 out << "\n";
375
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900376 if (options.GenLog()) {
377 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
378 false /* isServer */, true /* isNdk */);
379 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700380 if (options.GenTraces()) {
Devin Mooref7600872020-05-13 15:47:50 -0700381 out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
Devin Moore7d5a4542020-04-29 15:37:25 -0700382 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
383 << "::client\");\n";
384 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900385
Steven Morelandaada3422018-09-20 15:55:33 -0700386 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
387 StatusCheckGoto(out);
388
Steven Morelandeb38ee72018-10-15 14:20:04 -0700389 for (const auto& arg : method.GetArguments()) {
390 const std::string var_name = cpp::BuildVarName(*arg);
391
392 if (arg->IsIn()) {
393 out << "_aidl_ret_status = ";
394 const std::string prefix = (arg->IsOut() ? "*" : "");
395 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
396 out << ";\n";
397 StatusCheckGoto(out);
398 } else if (arg->IsOut() && arg->GetType().IsArray()) {
399 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
400 << ");\n";
401 }
Steven Morelandaada3422018-09-20 15:55:33 -0700402 }
403 out << "_aidl_ret_status = AIBinder_transact(\n";
404 out.Indent();
405 out << "asBinder().get(),\n";
406 out << MethodId(method) << ",\n";
407 out << "_aidl_in.getR(),\n";
408 out << "_aidl_out.getR(),\n";
Steven Morelandb72a1e72019-10-15 11:23:26 -0700409 out << (method.IsOneway() ? "FLAG_ONEWAY" : "0") << "\n";
410 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
411 out << "| FLAG_PRIVATE_LOCAL\n";
412 out << "#endif // BINDER_STABILITY_SUPPORT\n";
413 out << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700414 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900415
416 // If the method is not implmented in the server side but the client has
417 // provided the default implementation, call it instead of failing hard.
418 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
419 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
420 out << iface << "::getDefaultImpl()) {\n";
421 out.Indent();
Devin Moore7d5a4542020-04-29 15:37:25 -0700422 out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
Jiyong Park965c5b92018-11-21 13:37:15 +0900423 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700424 out << "goto _aidl_status_return;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900425 out.Dedent();
426 out << "}\n";
427
Steven Morelandaada3422018-09-20 15:55:33 -0700428 StatusCheckGoto(out);
429
430 if (!method.IsOneway()) {
431 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
432 StatusCheckGoto(out);
433
Devin Moore7d5a4542020-04-29 15:37:25 -0700434 out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700435 }
436
Steven Morelandaada3422018-09-20 15:55:33 -0700437 if (method.GetType().GetName() != "void") {
438 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700439 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700440 out << ";\n";
441 StatusCheckGoto(out);
Paul Trautrimb77048c2020-01-21 16:39:32 +0900442 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
443 out << kCachedHash << " = *_aidl_return;\n";
444 } else if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
445 out << kCachedVersion << " = *_aidl_return;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900446 }
Steven Morelandaada3422018-09-20 15:55:33 -0700447 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700448 for (const AidlArgument* arg : method.GetOutArguments()) {
449 out << "_aidl_ret_status = ";
450 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
451 out << ";\n";
452 StatusCheckGoto(out);
453 }
Steven Morelandaada3422018-09-20 15:55:33 -0700454
455 out << "_aidl_error:\n";
456 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700457 out << "_aidl_status_return:\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900458 if (options.GenLog()) {
459 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
460 method, "_aidl_status", "_aidl_return", false /* isServer */,
461 true /* isNdk */);
462 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700463
Steven Morelandaada3422018-09-20 15:55:33 -0700464 out << "return _aidl_status;\n";
465 out.Dedent();
466 out << "}\n";
467}
468
Steven Moreland2bea13b2018-10-03 15:12:33 -0700469static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900470 const AidlInterface& defined_type,
471 const AidlMethod& method, const Options& options) {
Steven Morelandaada3422018-09-20 15:55:33 -0700472 out << "case " << MethodId(method) << ": {\n";
473 out.Indent();
474 for (const auto& arg : method.GetArguments()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700475 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
476 << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700477 }
478 if (method.GetType().GetName() != "void") {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700479 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700480 }
481 out << "\n";
Devin Moore7d5a4542020-04-29 15:37:25 -0700482 if (options.GenTraces()) {
Devin Mooref7600872020-05-13 15:47:50 -0700483 out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
Devin Moore7d5a4542020-04-29 15:37:25 -0700484 << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
485 << "::server\");\n";
486 }
Steven Morelandaada3422018-09-20 15:55:33 -0700487
Steven Morelandeb38ee72018-10-15 14:20:04 -0700488 for (const auto& arg : method.GetArguments()) {
489 const std::string var_name = cpp::BuildVarName(*arg);
490
491 if (arg->IsIn()) {
492 out << "_aidl_ret_status = ";
493 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
494 out << ";\n";
495 StatusCheckBreak(out);
496 } else if (arg->IsOut() && arg->GetType().IsArray()) {
497 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
498 }
Steven Morelandaada3422018-09-20 15:55:33 -0700499 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900500 if (options.GenLog()) {
501 out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
502 true /* isServer */, true /* isNdk */);
503 }
Steven Moreland63404532018-10-08 14:31:00 -0700504 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
Jiyong Park965c5b92018-11-21 13:37:15 +0900505 << NdkArgList(types, method, FormatArgForCall) << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700506
Jeongik Chaeaf978e2019-05-04 00:32:35 +0900507 if (options.GenLog()) {
508 out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
509 method, "_aidl_status", "_aidl_return", true /* isServer */,
510 true /* isNdk */);
511 }
Steven Morelandaada3422018-09-20 15:55:33 -0700512 if (method.IsOneway()) {
513 // For a oneway transaction, the kernel will have already returned a result. This is for the
514 // in-process case when a oneway transaction is parceled/unparceled in the same process.
515 out << "_aidl_ret_status = STATUS_OK;\n";
516 } else {
517 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
518 StatusCheckBreak(out);
519
520 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
521
Steven Morelandaada3422018-09-20 15:55:33 -0700522 if (method.GetType().GetName() != "void") {
523 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700524 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700525 out << ";\n";
526 StatusCheckBreak(out);
527 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700528 for (const AidlArgument* arg : method.GetOutArguments()) {
529 out << "_aidl_ret_status = ";
530 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
531 out << ";\n";
532 StatusCheckBreak(out);
533 }
Steven Morelandaada3422018-09-20 15:55:33 -0700534 }
Steven Morelandaada3422018-09-20 15:55:33 -0700535 out << "break;\n";
536 out.Dedent();
537 out << "}\n";
538}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700539
Steven Moreland2bea13b2018-10-03 15:12:33 -0700540void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900541 const AidlInterface& defined_type, const Options& options) {
Steven Moreland0cf3f082018-09-20 19:09:46 -0700542 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
543 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
Devin Mooref7600872020-05-13 15:47:50 -0700544 if (options.GenTraces()) {
545 out << "class ScopedTrace {\n";
546 out.Indent();
547 out << "public:\n"
548 << "inline ScopedTrace(const char* name) {\n"
549 << "ATrace_beginSection(name);\n"
550 << "}\n"
551 << "inline ~ScopedTrace() {\n"
552 << "ATrace_endSection();\n"
553 << "}\n";
554 out.Dedent();
555 out << "};\n";
556 }
Steven Moreland15b3ba72019-03-06 13:17:08 -0800557 out << "static binder_status_t "
558 << "_aidl_onTransact"
Steven Morelandaada3422018-09-20 15:55:33 -0700559 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
560 "AParcel* _aidl_out) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700561 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700562 out << "(void)_aidl_in;\n";
563 out << "(void)_aidl_out;\n";
564 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
565 if (!defined_type.GetMethods().empty()) {
Steven Moreland15b3ba72019-03-06 13:17:08 -0800566 // we know this cast is valid because this method is only called by the ICInterface
567 // AIBinder_Class object which is associated with this class.
568 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = std::static_pointer_cast<" << bn_clazz
569 << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700570 out << "switch (_aidl_code) {\n";
571 out.Indent();
572 for (const auto& method : defined_type.GetMethods()) {
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900573 GenerateServerCaseDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700574 }
575 out.Dedent();
576 out << "}\n";
577 } else {
578 out << "(void)_aidl_binder;\n";
579 out << "(void)_aidl_code;\n";
580 }
581 out << "return _aidl_ret_status;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700582 out.Dedent();
Steven Moreland73d66242019-09-26 16:03:54 -0700583 out << "}\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700584
Steven Moreland15b3ba72019-03-06 13:17:08 -0800585 out << "static AIBinder_Class* " << kClazz << " = ::ndk::ICInterface::defineClass(" << clazz
586 << "::" << kDescriptor << ", _aidl_onTransact);\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700587}
Steven Morelandb0057e72018-08-27 01:44:11 -0700588void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900589 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700590 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700591
Steven Moreland63404532018-10-08 14:31:00 -0700592 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700593 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900594 if (options.GenLog()) {
595 out << "std::function<void(const Json::Value&)> " << clazz << "::logFunc;\n";
596 }
Steven Morelandaada3422018-09-20 15:55:33 -0700597 out << "\n";
598 for (const auto& method : defined_type.GetMethods()) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900599 GenerateClientMethodDefinition(out, types, defined_type, *method, options);
Steven Morelandaada3422018-09-20 15:55:33 -0700600 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700601}
Jiyong Park965c5b92018-11-21 13:37:15 +0900602void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
603 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700604 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900605 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700606
607 out << "// Source for " << clazz << "\n";
608 out << clazz << "::" << clazz << "() {}\n";
609 out << clazz << "::~" << clazz << "() {}\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900610 if (options.GenLog()) {
611 out << "std::function<void(const Json::Value&)> " << clazz << "::logFunc;\n";
612 }
Steven Moreland63404532018-10-08 14:31:00 -0700613 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700614 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800615 out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700616
Steven Moreland88378b12019-10-11 13:13:24 -0700617 out << "#ifdef BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700618 if (defined_type.IsVintfStability()) {
619 out << "AIBinder_markVintfStability(binder);\n";
620 } else {
621 out << "AIBinder_markCompilationUnitStability(binder);\n";
622 }
Steven Moreland88378b12019-10-11 13:13:24 -0700623 out << "#endif // BINDER_STABILITY_SUPPORT\n";
Steven Morelanda57d0a62019-07-30 09:41:14 -0700624
Steven Moreland63404532018-10-08 14:31:00 -0700625 out << "return ::ndk::SpAIBinder(binder);\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700626 out.Dedent();
627 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900628
629 // Implement the meta methods
630 for (const auto& method : defined_type.GetMethods()) {
631 if (method->IsUserDefined()) {
632 continue;
633 }
634 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
635 out << NdkMethodDecl(types, *method, clazz) << " {\n";
636 out.Indent();
637 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
638 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
639 out.Dedent();
640 out << "}\n";
641 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900642 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
643 out << NdkMethodDecl(types, *method, clazz) << " {\n";
644 out.Indent();
645 out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
646 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
647 out.Dedent();
648 out << "}\n";
649 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900650 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700651}
Jiyong Park965c5b92018-11-21 13:37:15 +0900652void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
653 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700654 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland15b3ba72019-03-06 13:17:08 -0800655 const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -0700656
657 out << "// Source for " << clazz << "\n";
Jiyong Park27fd7fd2020-08-27 16:25:09 +0900658 out << "const char* " << clazz << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
659 << "\";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700660 out << clazz << "::" << clazz << "() {}\n";
661 out << clazz << "::~" << clazz << "() {}\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700662 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700663 GenerateConstantDefinitions(out, defined_type);
664 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700665
Steven Moreland3c316ed2019-01-17 09:39:37 -0800666 out << "std::shared_ptr<" << clazz << "> " << clazz
667 << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800668 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800669 out << "if (!AIBinder_associateClass(binder.get(), " << kClazz << ")) { return nullptr; }\n";
670 out << "std::shared_ptr<::ndk::ICInterface> interface = "
671 "::ndk::ICInterface::asInterface(binder.get());\n";
672 out << "if (interface) {\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800673 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800674 out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800675 out.Dedent();
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800676 out << "}\n";
Steven Morelandc09d34c2020-02-13 09:42:49 -0800677 out << "return ::ndk::SharedRefBase::make<" << bp_clazz << ">(binder);\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800678 out.Dedent();
Steven Moreland3c316ed2019-01-17 09:39:37 -0800679 out << "}\n\n";
680
Steven Moreland2bea13b2018-10-03 15:12:33 -0700681 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
682 << clazz << ">& instance) {\n";
683 out.Indent();
684 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
685 "nullptr);\n";
686 out.Dedent();
687 out << "}\n";
688
689 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
690 << clazz << ">* instance) {\n";
691 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700692 out << "::ndk::SpAIBinder binder;\n";
Steven Moreland055d8792018-11-14 12:48:42 -0800693 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700694 out << "if (status != STATUS_OK) return status;\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800695 out << "*instance = " << clazz << "::fromBinder(binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700696 out << "return STATUS_OK;\n";
697 out.Dedent();
698 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900699
700 // defintion for static member setDefaultImpl
701 out << "bool " << clazz << "::setDefaultImpl(std::shared_ptr<" << clazz << "> impl) {\n";
702 out.Indent();
Jooyung Han4a044662020-05-13 17:17:07 +0900703 out << "// Only one user of this interface can use this function\n";
704 out << "// at a time. This is a heuristic to detect if two different\n";
705 out << "// users in the same process use this function.\n";
706 out << "assert(!" << clazz << "::default_impl);\n";
707 out << "if (impl) {\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900708 out.Indent();
709 out << clazz << "::default_impl = impl;\n";
710 out << "return true;\n";
711 out.Dedent();
712 out << "}\n";
713 out << "return false;\n";
714 out.Dedent();
715 out << "}\n";
716
717 // definition for static member getDefaultImpl
718 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
719 out.Indent();
720 out << "return " << clazz << "::default_impl;\n";
721 out.Dedent();
722 out << "}\n";
723
724 // definition for the static field default_impl
725 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
726
727 // default implementation for the <Name>Default class members
728 const std::string defaultClazz = clazz + "Default";
729 for (const auto& method : defined_type.GetMethods()) {
730 if (method->IsUserDefined()) {
731 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
732 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
733 out.Indent();
734 out << "::ndk::ScopedAStatus _aidl_status;\n";
735 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
736 out << "return _aidl_status;\n";
737 out.Dedent();
738 out << "}\n";
739 } else {
740 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
741 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
742 << "int32_t* _aidl_return) {\n";
743 out.Indent();
744 out << "*_aidl_return = 0;\n";
745 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
746 out.Dedent();
747 out << "}\n";
748 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900749 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
750 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
751 << "std::string* _aidl_return) {\n";
752 out.Indent();
753 out << "*_aidl_return = \"\";\n";
754 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
755 out.Dedent();
756 out << "}\n";
757 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900758 }
759 }
760
761 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
762 out.Indent();
763 out << "return ::ndk::SpAIBinder();\n";
764 out.Dedent();
765 out << "}\n";
766
767 out << "bool " << defaultClazz << "::isRemote() {\n";
768 out.Indent();
769 out << "return false;\n";
770 out.Dedent();
771 out << "}\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700772}
Jiyong Park965c5b92018-11-21 13:37:15 +0900773
Steven Morelandb0057e72018-08-27 01:44:11 -0700774void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900775 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700776 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
777
778 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900779 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700780 << "\"\n";
781 out << "\n";
782 out << "#include <android/binder_ibinder.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900783 if (options.GenLog()) {
784 out << "#include <json/value.h>\n";
785 out << "#include <functional>\n";
786 out << "#include <chrono>\n";
787 out << "#include <sstream>\n";
788 }
Devin Moore7d5a4542020-04-29 15:37:25 -0700789 if (options.GenTraces()) {
790 out << "#include <android/trace.h>\n";
791 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700792 out << "\n";
793 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700794 out << "class " << clazz << " : public ::ndk::BpCInterface<"
Steven Morelandb0057e72018-08-27 01:44:11 -0700795 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
796 out << "public:\n";
797 out.Indent();
Steven Moreland15b3ba72019-03-06 13:17:08 -0800798 out << clazz << "(const ::ndk::SpAIBinder& binder);\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700799 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700800 out << "\n";
801 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700802 out << NdkMethodDecl(types, *method) << " override;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700803 }
Jiyong Park965c5b92018-11-21 13:37:15 +0900804
805 if (options.Version() > 0) {
Paul Trautrimb77048c2020-01-21 16:39:32 +0900806 out << "int32_t " << kCachedVersion << " = -1;\n";
807 }
808
809 if (!options.Hash().empty()) {
810 out << "std::string " << kCachedHash << " = \"-1\";\n";
811 out << "std::mutex " << kCachedHashMutex << ";\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900812 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900813 if (options.GenLog()) {
814 out << "static std::function<void(const Json::Value&)> logFunc;\n";
815 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700816 out.Dedent();
817 out << "};\n";
818 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700819}
Jiyong Park965c5b92018-11-21 13:37:15 +0900820void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
821 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700822 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900823 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700824
825 out << "#pragma once\n\n";
Jiyong Park5b7e5322019-04-03 20:05:01 +0900826 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700827 << "\"\n";
828 out << "\n";
829 out << "#include <android/binder_ibinder.h>\n";
830 out << "\n";
831 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900832 out << "class " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700833 out << "public:\n";
834 out.Indent();
835 out << clazz << "();\n";
836 out << "virtual ~" << clazz << "();\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900837
838 // Declare the meta methods
839 for (const auto& method : defined_type.GetMethods()) {
840 if (method->IsUserDefined()) {
841 continue;
842 }
843 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
844 out << NdkMethodDecl(types, *method) << " final override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900845 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
846 out << NdkMethodDecl(types, *method) << " final override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900847 } else {
848 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
849 }
850 }
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900851 if (options.GenLog()) {
852 out << "static std::function<void(const Json::Value&)> logFunc;\n";
853 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700854 out.Dedent();
Steven Moreland0cf3f082018-09-20 19:09:46 -0700855 out << "protected:\n";
856 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700857 out << "::ndk::SpAIBinder createBinder() override;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700858 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700859 out << "private:\n";
860 out.Indent();
861 out.Dedent();
862 out << "};\n";
863 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700864}
865void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900866 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700867 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
868
869 out << "#pragma once\n\n";
870 out << "#include <android/binder_interface_utils.h>\n";
Jeongik Cha37e2ad52019-04-18 13:44:26 +0900871 if (options.GenLog()) {
872 out << "#include <json/value.h>\n";
873 out << "#include <functional>\n";
874 out << "#include <chrono>\n";
875 out << "#include <sstream>\n";
876 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700877 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700878
879 GenerateHeaderIncludes(out, types, defined_type);
880 out << "\n";
881
Steven Morelandb0057e72018-08-27 01:44:11 -0700882 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700883 out << "class " << clazz << " : public ::ndk::ICInterface {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700884 out << "public:\n";
885 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900886 out << "static const char* " << kDescriptor << ";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700887 out << clazz << "();\n";
888 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700889 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700890 GenerateConstantDeclarations(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900891 if (options.Version() > 0) {
892 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
893 << ";\n";
894 }
Paul Trautrimb77048c2020-01-21 16:39:32 +0900895 if (!options.Hash().empty()) {
896 out << "static inline const std::string " << kHash << " = \"" << options.Hash() << "\";\n";
897 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700898 out << "\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800899 out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700900 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
901 << ">& instance);";
Jiyong Park1b88cce2018-11-19 19:53:44 +0900902 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700903 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
904 << ">* instance);";
905 out << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900906 out << "static bool setDefaultImpl(std::shared_ptr<" << clazz << "> impl);";
907 out << "\n";
908 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
909 out << "\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700910 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700911 out << "virtual " << NdkMethodDecl(types, *method) << " = 0;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700912 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700913 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900914 out << "private:\n";
915 out.Indent();
916 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
917 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700918 out << "};\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900919
920 const std::string defaultClazz = clazz + "Default";
921
922 out << "class " << defaultClazz << " : public " << clazz << " {\n";
923 out << "public:\n";
924 out.Indent();
925 for (const auto& method : defined_type.GetMethods()) {
926 if (method->IsUserDefined()) {
927 out << NdkMethodDecl(types, *method) << " override;\n";
928 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
929 out << NdkMethodDecl(types, *method) << " override;\n";
Paul Trautrimb77048c2020-01-21 16:39:32 +0900930 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
931 out << NdkMethodDecl(types, *method) << " override;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900932 }
933 }
934 out << "::ndk::SpAIBinder asBinder() override;\n";
935 out << "bool isRemote() override;\n";
936 out.Dedent();
937 out << "};\n";
938
Steven Morelandb0057e72018-08-27 01:44:11 -0700939 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700940}
941void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700942 const AidlStructuredParcelable& defined_type,
943 const Options& /*options*/) {
Steven Morelandb8df37d2019-11-21 12:33:24 -0800944 const std::string clazz = ClassName(defined_type, ClassNames::RAW);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700945
Steven Morelandb0057e72018-08-27 01:44:11 -0700946 out << "#pragma once\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700947 out << "#include <android/binder_interface_utils.h>\n";
948 out << "\n";
949
950 GenerateHeaderIncludes(out, types, defined_type);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700951
Steven Morelandb0057e72018-08-27 01:44:11 -0700952 EnterNdkNamespace(out, defined_type);
Devin Moore53fc99c2020-08-12 08:07:52 -0700953 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700954 out << "class " << clazz << " {\n";
955 out << "public:\n";
956 out.Indent();
957 out << "static const char* descriptor;\n";
958 out << "\n";
959 for (const auto& variable : defined_type.GetFields()) {
960 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << " " << variable->GetName();
961 if (variable->GetDefaultValue()) {
Daniel Norman37d43dd2019-09-09 17:22:34 -0700962 out << " = " << variable->ValueString(ConstantValueDecorator);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700963 }
964 out << ";\n";
965 }
966 out << "\n";
967 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
968 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
Jeongik Cha92d33d02020-05-14 00:53:57 +0900969
970 out << "static const bool _aidl_is_stable = "
971 << (defined_type.IsVintfStability() ? "true" : "false") << ";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700972 out.Dedent();
973 out << "};\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700974 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700975}
976void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700977 const AidlStructuredParcelable& defined_type,
978 const Options& /*options*/) {
Devin Moore53fc99c2020-08-12 08:07:52 -0700979 std::string clazz = ClassName(defined_type, ClassNames::RAW);
980 if (defined_type.IsGeneric()) {
981 std::vector<std::string> template_params;
982 for (const auto& parameter : defined_type.GetTypeParameters()) {
983 template_params.push_back(parameter);
984 }
985 clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
986 }
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700987
Jiyong Park5b7e5322019-04-03 20:05:01 +0900988 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700989 << "\"\n";
990 out << "\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700991 GenerateSourceIncludes(out, types, defined_type);
992 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700993 EnterNdkNamespace(out, defined_type);
Devin Moore53fc99c2020-08-12 08:07:52 -0700994 out << cpp::TemplateDecl(defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900995 out << "const char* " << clazz << "::" << kDescriptor << " = \""
996 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700997 out << "\n";
998
Devin Moore53fc99c2020-08-12 08:07:52 -0700999 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001000 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
1001 out.Indent();
Jeongik Cha95eba572018-11-22 09:14:52 +09001002 out << "int32_t _aidl_parcelable_size;\n";
Steven Moreland4348f9a2019-12-16 16:33:01 -08001003 out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1004 out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
Jeongik Cha8b329982020-09-01 20:59:36 +09001005 out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
Jeongik Cha95eba572018-11-22 09:14:52 +09001006 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
1007 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001008
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001009 for (const auto& variable : defined_type.GetFields()) {
1010 out << "_aidl_ret_status = ";
1011 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
1012 out << ";\n";
1013 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +09001014 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1015 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1016 << " return _aidl_ret_status;\n"
1017 << "}\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001018 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001019 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
1020 << "return _aidl_ret_status;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001021 out.Dedent();
1022 out << "}\n";
1023
Devin Moore53fc99c2020-08-12 08:07:52 -07001024 out << cpp::TemplateDecl(defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001025 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
1026 out.Indent();
1027 out << "binder_status_t _aidl_ret_status;\n";
1028
Jeongik Cha95eba572018-11-22 09:14:52 +09001029 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
1030 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
1031 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001032
1033 for (const auto& variable : defined_type.GetFields()) {
1034 out << "_aidl_ret_status = ";
1035 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
1036 out << ";\n";
1037 StatusCheckReturn(out);
1038 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001039 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
1040 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
1041 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
1042 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
1043
Steven Morelandbb8f46c2018-10-03 17:38:00 -07001044 out << "return _aidl_ret_status;\n";
1045 out.Dedent();
1046 out << "}\n";
1047 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -07001048 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -07001049}
Daniel Norman37d43dd2019-09-09 17:22:34 -07001050
Daniel Norman455d95c2019-11-19 09:55:39 -08001051std::string GenerateEnumToString(const AidlTypenames& typenames,
1052 const AidlEnumDeclaration& enum_decl) {
1053 std::ostringstream code;
1054 code << "static inline std::string toString(" << enum_decl.GetName() << " val) {\n";
1055 code << " switch(val) {\n";
1056 std::set<std::string> unique_cases;
1057 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1058 std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
1059 // Only add a case if its value has not yet been used in the switch
1060 // statement. C++ does not allow multiple cases with the same value, but
1061 // enums does allow this. In this scenario, the first declared
1062 // enumerator with the given value is printed.
1063 if (unique_cases.count(c) == 0) {
1064 unique_cases.insert(c);
1065 code << " case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
1066 code << " return \"" << enumerator->GetName() << "\";\n";
1067 }
1068 }
1069 code << " default:\n";
1070 code << " return std::to_string(static_cast<"
1071 << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
1072 code << " }\n";
1073 code << "}\n";
1074 return code.str();
1075}
1076
Daniel Norman37d43dd2019-09-09 17:22:34 -07001077void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
1078 const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
1079 out << "#pragma once\n";
1080 out << "\n";
1081
1082 GenerateHeaderIncludes(out, types, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001083 // enum specific headers
1084 out << "#include <array>\n";
1085 out << "#include <android/binder_enums.h>\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001086
1087 EnterNdkNamespace(out, enum_decl);
1088 out << "enum class " << enum_decl.GetName() << " : "
1089 << NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK) << " {\n";
1090 out.Indent();
1091 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1092 out << enumerator->GetName() << " = "
1093 << enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator) << ",\n";
1094 }
1095 out.Dedent();
1096 out << "};\n";
Daniel Norman455d95c2019-11-19 09:55:39 -08001097 out << "\n";
1098 out << GenerateEnumToString(types, enum_decl);
Daniel Norman37d43dd2019-09-09 17:22:34 -07001099 LeaveNdkNamespace(out, enum_decl);
Jooyung Han7a9aceb2019-12-17 14:18:15 +00001100
1101 out << "namespace ndk {\n";
1102 out << "namespace internal {\n";
1103 out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
1104 out << "} // namespace internal\n";
1105 out << "} // namespace android\n";
Daniel Norman37d43dd2019-09-09 17:22:34 -07001106}
1107
Steven Morelandb0057e72018-08-27 01:44:11 -07001108} // namespace internals
1109} // namespace ndk
1110} // namespace aidl
1111} // namespace android