blob: effc8bed686632a403e4dad3d2c049df092740d3 [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
Jiyong Park965c5b92018-11-21 13:37:15 +090030static constexpr const char* kClazz = "clazz";
31static constexpr const char* kDescriptor = "descriptor";
32static constexpr const char* kVersion = "version";
33
Steven Morelandb0057e72018-08-27 01:44:11 -070034using namespace internals;
35using cpp::ClassNames;
36
37void GenerateNdkInterface(const string& output_file, const Options& options,
38 const AidlTypenames& types, const AidlInterface& defined_type,
39 const IoDelegate& io_delegate) {
Steven Morelandb0057e72018-08-27 01:44:11 -070040 const string i_header =
Steven Moreland7c933372018-10-11 15:20:04 -070041 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -070042 unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
43 GenerateInterfaceHeader(*i_writer, types, defined_type, options);
44 CHECK(i_writer->Close());
45
Steven Moreland7c933372018-10-11 15:20:04 -070046 const string bp_header =
47 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070048 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
49 GenerateClientHeader(*bp_writer, types, defined_type, options);
50 CHECK(bp_writer->Close());
51
Steven Moreland7c933372018-10-11 15:20:04 -070052 const string bn_header =
53 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070054 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
55 GenerateServerHeader(*bn_writer, types, defined_type, options);
56 CHECK(bn_writer->Close());
57
58 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
59 GenerateSource(*source_writer, types, defined_type, options);
60 CHECK(source_writer->Close());
61}
62
63void GenerateNdkParcel(const string& output_file, const Options& options,
64 const AidlTypenames& types, const AidlStructuredParcelable& defined_type,
65 const IoDelegate& io_delegate) {
Steven Moreland7c933372018-10-11 15:20:04 -070066 const string header_path =
67 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::BASE);
Steven Morelandb0057e72018-08-27 01:44:11 -070068 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
69 GenerateParcelHeader(*header_writer, types, defined_type, options);
70 CHECK(header_writer->Close());
71
Steven Moreland7c933372018-10-11 15:20:04 -070072 const string bp_header =
73 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
Steven Morelandb0057e72018-08-27 01:44:11 -070074 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
75 *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
76 CHECK(bp_writer->Close());
77
Steven Moreland7c933372018-10-11 15:20:04 -070078 const string bn_header =
79 options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
Steven Morelandb0057e72018-08-27 01:44:11 -070080 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
81 *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
82 CHECK(bn_writer->Close());
83
84 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
85 GenerateParcelSource(*source_writer, types, defined_type, options);
86 CHECK(source_writer->Close());
87}
88
Steven Moreland2a9a7d62019-02-05 16:11:54 -080089void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
90 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
91 *code_writer
92 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
93 CHECK(code_writer->Close());
94}
95
Steven Morelandb0057e72018-08-27 01:44:11 -070096void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
97 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
98 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
99 if (parcelable != nullptr) {
100 GenerateNdkParcel(output_file, options, types, *parcelable, io_delegate);
101 return;
102 }
103
Steven Moreland2a9a7d62019-02-05 16:11:54 -0800104 const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
105 if (parcelable_decl != nullptr) {
106 GenerateNdkParcelDeclaration(output_file, io_delegate);
107 return;
108 }
109
Steven Morelandb0057e72018-08-27 01:44:11 -0700110 const AidlInterface* interface = defined_type.AsInterface();
111 if (interface != nullptr) {
112 GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
113 return;
114 }
115
116 CHECK(false) << "Unrecognized type sent for cpp generation.";
117}
118namespace internals {
119
120void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
121 out << "namespace aidl {\n";
122 cpp::EnterNamespace(out, defined_type);
123}
124void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
125 cpp::LeaveNamespace(out, defined_type);
126 out << "} // namespace aidl\n";
127}
128
Steven Morelandaada3422018-09-20 15:55:33 -0700129static void StatusCheckGoto(CodeWriter& out) {
130 out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
131}
132static void StatusCheckBreak(CodeWriter& out) {
133 out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
134}
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700135static void StatusCheckReturn(CodeWriter& out) {
136 out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
137}
Steven Morelandaada3422018-09-20 15:55:33 -0700138
Steven Moreland2bea13b2018-10-03 15:12:33 -0700139static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
140 const AidlDefinedType& defined_type) {
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700141 out << "#include <android/binder_parcel_utils.h>\n";
142
Steven Moreland2bea13b2018-10-03 15:12:33 -0700143 types.IterateTypes([&](const AidlDefinedType& other_defined_type) {
144 if (&other_defined_type == &defined_type) return;
145
146 if (other_defined_type.AsInterface() != nullptr) {
147 out << "#include <"
Steven Moreland7c933372018-10-11 15:20:04 -0700148 << NdkHeaderFile(other_defined_type, ClassNames::INTERFACE, false /*use_os_sep*/)
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700149 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700150 } else if (other_defined_type.AsStructuredParcelable() != nullptr) {
151 out << "#include <"
152 << NdkHeaderFile(other_defined_type, ClassNames::BASE, false /*use_os_sep*/) << ">\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700153 } else if (other_defined_type.AsParcelable() != nullptr) {
154 out << "#include \"" << other_defined_type.AsParcelable()->GetCppHeader() << "\"\n";
155 } else {
156 AIDL_FATAL(defined_type) << "Unrecognized type.";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700157 }
158 });
159}
160static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
161 const AidlDefinedType& /*defined_type*/) {
162 types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
163 if (a_defined_type.AsInterface() != nullptr) {
Steven Moreland7c933372018-10-11 15:20:04 -0700164 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700165 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700166 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700167 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700168 out << "#include <"
169 << NdkHeaderFile(a_defined_type, ClassNames::INTERFACE, false /*use_os_sep*/) << ">\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700170 }
171 });
172}
173
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700174static void GenerateConstantDeclarations(CodeWriter& out, const AidlInterface& interface) {
175 for (const auto& constant : interface.GetConstantDeclarations()) {
176 const AidlConstantValue& value = constant->GetValue();
177 if (value.GetType() == AidlConstantValue::Type::STRING) {
178 out << "static const char* " << constant->GetName() << ";\n";
179 }
180 }
181 out << "\n";
182
183 bool hasIntegralConstant = false;
184 for (const auto& constant : interface.GetConstantDeclarations()) {
185 const AidlConstantValue& value = constant->GetValue();
186 if (value.GetType() == AidlConstantValue::Type::HEXIDECIMAL ||
187 value.GetType() == AidlConstantValue::Type::INTEGRAL) {
188 hasIntegralConstant = true;
189 break;
190 }
191 }
192
193 if (hasIntegralConstant) {
194 out << "enum : int32_t {\n";
195 out.Indent();
196 for (const auto& constant : interface.GetConstantDeclarations()) {
197 const AidlConstantValue& value = constant->GetValue();
198 if (value.GetType() == AidlConstantValue::Type::HEXIDECIMAL ||
199 value.GetType() == AidlConstantValue::Type::INTEGRAL) {
200 out << constant->GetName() << " = " << constant->ValueString(AidlConstantValueDecorator)
201 << ",\n";
202 }
203 }
204 out.Dedent();
205 out << "};\n";
206 }
207}
208static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) {
209 const std::string clazz = ClassName(interface, ClassNames::INTERFACE);
210
211 for (const auto& constant : interface.GetConstantDeclarations()) {
212 const AidlConstantValue& value = constant->GetValue();
213 if (value.GetType() == AidlConstantValue::Type::STRING) {
214 out << "const char* " << clazz << "::" << constant->GetName() << " = "
215 << constant->ValueString(AidlConstantValueDecorator) << ";\n";
216 }
217 }
218}
219
Steven Morelandb0057e72018-08-27 01:44:11 -0700220void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
221 const Options& options) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700222 GenerateSourceIncludes(out, types, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700223 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700224
Steven Morelandb0057e72018-08-27 01:44:11 -0700225 EnterNdkNamespace(out, defined_type);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700226 GenerateClassSource(out, types, defined_type, options);
Steven Morelandb0057e72018-08-27 01:44:11 -0700227 GenerateClientSource(out, types, defined_type, options);
228 GenerateServerSource(out, types, defined_type, options);
229 GenerateInterfaceSource(out, types, defined_type, options);
230 LeaveNdkNamespace(out, defined_type);
231}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700232
233static std::string DataClassFor(const AidlInterface& defined_type) {
234 return "AidlClassData_" + ClassName(defined_type, ClassNames::INTERFACE);
235}
Steven Morelandaada3422018-09-20 15:55:33 -0700236static std::string MethodId(const AidlMethod& m) {
237 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
238}
239
Steven Moreland2bea13b2018-10-03 15:12:33 -0700240static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
241 const AidlInterface& defined_type,
Jeongik Chac9972922019-02-11 12:41:16 +0900242 const AidlMethod& method, const bool cacheable) {
Steven Morelandaada3422018-09-20 15:55:33 -0700243 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
244
Steven Moreland2bea13b2018-10-03 15:12:33 -0700245 out << NdkMethodDecl(types, method, clazz) << " {\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700246 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700247 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
Steven Moreland63404532018-10-08 14:31:00 -0700248 out << "::ndk::ScopedAStatus _aidl_status;\n";
Jeongik Chac9972922019-02-11 12:41:16 +0900249
250 if (cacheable) {
251 out << "if (_aidl_cached_value != -1) {\n";
252 out.Indent();
253 out << "*_aidl_return = _aidl_cached_value;\n"
254 << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n"
255 << "return _aidl_status;\n";
256 out.Dedent();
257 out << "}\n";
258 }
259 out << "::ndk::ScopedAParcel _aidl_in;\n";
260 out << "::ndk::ScopedAParcel _aidl_out;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700261 out << "\n";
262
263 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
264 StatusCheckGoto(out);
265
Steven Morelandeb38ee72018-10-15 14:20:04 -0700266 for (const auto& arg : method.GetArguments()) {
267 const std::string var_name = cpp::BuildVarName(*arg);
268
269 if (arg->IsIn()) {
270 out << "_aidl_ret_status = ";
271 const std::string prefix = (arg->IsOut() ? "*" : "");
272 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
273 out << ";\n";
274 StatusCheckGoto(out);
275 } else if (arg->IsOut() && arg->GetType().IsArray()) {
276 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
277 << ");\n";
278 }
Steven Morelandaada3422018-09-20 15:55:33 -0700279 }
280 out << "_aidl_ret_status = AIBinder_transact(\n";
281 out.Indent();
282 out << "asBinder().get(),\n";
283 out << MethodId(method) << ",\n";
284 out << "_aidl_in.getR(),\n";
285 out << "_aidl_out.getR(),\n";
286 out << (method.IsOneway() ? "FLAG_ONEWAY" : "0") << ");\n";
287 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900288
289 // If the method is not implmented in the server side but the client has
290 // provided the default implementation, call it instead of failing hard.
291 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
292 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
293 out << iface << "::getDefaultImpl()) {\n";
294 out.Indent();
295 out << "return " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
296 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
297 out.Dedent();
298 out << "}\n";
299
Steven Morelandaada3422018-09-20 15:55:33 -0700300 StatusCheckGoto(out);
301
302 if (!method.IsOneway()) {
303 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
304 StatusCheckGoto(out);
305
306 out << "if (!AStatus_isOk(_aidl_status.get())) return _aidl_status;\n\n";
307 }
308
Steven Morelandaada3422018-09-20 15:55:33 -0700309 if (method.GetType().GetName() != "void") {
310 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700311 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700312 out << ";\n";
313 StatusCheckGoto(out);
Jeongik Chac9972922019-02-11 12:41:16 +0900314 if (cacheable) {
315 out << "_aidl_cached_value = *_aidl_return;\n";
316 }
Steven Morelandaada3422018-09-20 15:55:33 -0700317 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700318 for (const AidlArgument* arg : method.GetOutArguments()) {
319 out << "_aidl_ret_status = ";
320 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
321 out << ";\n";
322 StatusCheckGoto(out);
323 }
Steven Morelandaada3422018-09-20 15:55:33 -0700324
325 out << "_aidl_error:\n";
326 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
327 out << "return _aidl_status;\n";
328 out.Dedent();
329 out << "}\n";
330}
331
Steven Moreland2bea13b2018-10-03 15:12:33 -0700332static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
333 const AidlInterface& /*defined_type*/,
Steven Morelandaada3422018-09-20 15:55:33 -0700334 const AidlMethod& method) {
335 out << "case " << MethodId(method) << ": {\n";
336 out.Indent();
337 for (const auto& arg : method.GetArguments()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700338 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
339 << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700340 }
341 if (method.GetType().GetName() != "void") {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700342 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700343 }
344 out << "\n";
345
Steven Morelandeb38ee72018-10-15 14:20:04 -0700346 for (const auto& arg : method.GetArguments()) {
347 const std::string var_name = cpp::BuildVarName(*arg);
348
349 if (arg->IsIn()) {
350 out << "_aidl_ret_status = ";
351 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
352 out << ";\n";
353 StatusCheckBreak(out);
354 } else if (arg->IsOut() && arg->GetType().IsArray()) {
355 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
356 }
Steven Morelandaada3422018-09-20 15:55:33 -0700357 }
358
Steven Moreland63404532018-10-08 14:31:00 -0700359 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
Jiyong Park965c5b92018-11-21 13:37:15 +0900360 << NdkArgList(types, method, FormatArgForCall) << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700361
362 if (method.IsOneway()) {
363 // For a oneway transaction, the kernel will have already returned a result. This is for the
364 // in-process case when a oneway transaction is parceled/unparceled in the same process.
365 out << "_aidl_ret_status = STATUS_OK;\n";
366 } else {
367 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
368 StatusCheckBreak(out);
369
370 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
371
Steven Morelandaada3422018-09-20 15:55:33 -0700372 if (method.GetType().GetName() != "void") {
373 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700374 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700375 out << ";\n";
376 StatusCheckBreak(out);
377 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700378 for (const AidlArgument* arg : method.GetOutArguments()) {
379 out << "_aidl_ret_status = ";
380 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
381 out << ";\n";
382 StatusCheckBreak(out);
383 }
Steven Morelandaada3422018-09-20 15:55:33 -0700384 }
385
386 out << "break;\n";
387 out.Dedent();
388 out << "}\n";
389}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700390
Steven Moreland2bea13b2018-10-03 15:12:33 -0700391void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
Steven Moreland0cf3f082018-09-20 19:09:46 -0700392 const AidlInterface& defined_type, const Options& /*options*/) {
393 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
394 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
395 const std::string data_clazz = DataClassFor(defined_type);
396 const std::string on_create = data_clazz + "_onCreate";
397 const std::string on_destroy = data_clazz + "_onDestory";
398 const std::string on_transact = data_clazz + "_onTransact";
399
400 out << "struct " << data_clazz << " {\n";
401 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900402 out << "static AIBinder_Class* " << kClazz << ";\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700403 out << "std::shared_ptr<" << bn_clazz << "> instance;\n";
404 out.Dedent();
405 out << "};\n\n";
406
407 out << "static void* " << on_create << "(void* args) {\n";
408 out.Indent();
409 out << data_clazz << "* data = new " << data_clazz << "{static_cast<" << bn_clazz
410 << "*>(args)->ref<" << bn_clazz << ">()};\n";
411 out << "return static_cast<void*>(data);\n";
412 out.Dedent();
413 out << "};\n\n";
414
415 out << "static void " << on_destroy << "(void* userData) {\n";
416 out.Indent();
417 out << "delete static_cast<" << data_clazz << "*>(userData);\n";
418 out.Dedent();
419 out << "};\n\n";
420
421 out << "static binder_status_t " << on_transact
Steven Morelandaada3422018-09-20 15:55:33 -0700422 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
423 "AParcel* _aidl_out) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700424 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700425 out << "(void)_aidl_in;\n";
426 out << "(void)_aidl_out;\n";
427 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
428 if (!defined_type.GetMethods().empty()) {
429 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = static_cast<" << data_clazz
430 << "*>(AIBinder_getUserData(_aidl_binder))->instance;\n";
431 out << "switch (_aidl_code) {\n";
432 out.Indent();
433 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700434 GenerateServerCaseDefinition(out, types, defined_type, *method);
Steven Morelandaada3422018-09-20 15:55:33 -0700435 }
436 out.Dedent();
437 out << "}\n";
438 } else {
439 out << "(void)_aidl_binder;\n";
440 out << "(void)_aidl_code;\n";
441 }
442 out << "return _aidl_ret_status;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700443 out.Dedent();
444 out << "};\n\n";
445
Jiyong Park965c5b92018-11-21 13:37:15 +0900446 out << "AIBinder_Class* " << data_clazz << ":: " << kClazz << " = AIBinder_Class_define(" << clazz
447 << "::" << kDescriptor << ", " << on_create << ", " << on_destroy << ", " << on_transact
448 << ");\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700449}
Steven Morelandb0057e72018-08-27 01:44:11 -0700450void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900451 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700452 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700453 const std::string data_clazz = DataClassFor(defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700454
455 out << "// Source for " << clazz << "\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700456 out << "std::shared_ptr<" << clazz << "> " << clazz
Steven Moreland63404532018-10-08 14:31:00 -0700457 << "::associate(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700458 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900459 out << "if (!AIBinder_associateClass(binder.get(), " << data_clazz << "::" << kClazz
460 << ")) { return nullptr; }\n";
Steven Moreland1c4b4052018-10-10 12:24:22 -0700461 out << "return (new " << clazz << "(binder))->ref<" << clazz << ">();\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700462 out.Dedent();
463 out << "}\n\n";
464
Steven Moreland63404532018-10-08 14:31:00 -0700465 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700466 out << clazz << "::~" << clazz << "() {}\n";
467 out << "\n";
468 for (const auto& method : defined_type.GetMethods()) {
Jeongik Chac9972922019-02-11 12:41:16 +0900469 // Only getInterfaceVersion can use cache.
470 const bool cacheable = !method->IsUserDefined() && method->GetName() == kGetInterfaceVersion &&
471 options.Version() > 0;
472 GenerateClientMethodDefinition(out, types, defined_type, *method, cacheable);
Steven Morelandaada3422018-09-20 15:55:33 -0700473 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700474}
Jiyong Park965c5b92018-11-21 13:37:15 +0900475void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
476 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700477 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900478 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700479 const std::string data_clazz = DataClassFor(defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700480
481 out << "// Source for " << clazz << "\n";
482 out << clazz << "::" << clazz << "() {}\n";
483 out << clazz << "::~" << clazz << "() {}\n";
484
Steven Moreland63404532018-10-08 14:31:00 -0700485 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700486 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900487 out << "AIBinder* binder = AIBinder_new(" << data_clazz << "::" << kClazz
488 << ", static_cast<void*>(this));\n";
Steven Moreland63404532018-10-08 14:31:00 -0700489 out << "return ::ndk::SpAIBinder(binder);\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700490 out.Dedent();
491 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900492
493 // Implement the meta methods
494 for (const auto& method : defined_type.GetMethods()) {
495 if (method->IsUserDefined()) {
496 continue;
497 }
498 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
499 out << NdkMethodDecl(types, *method, clazz) << " {\n";
500 out.Indent();
501 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
502 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
503 out.Dedent();
504 out << "}\n";
505 }
506 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700507}
Jiyong Park965c5b92018-11-21 13:37:15 +0900508void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
509 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700510 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700511 const std::string data_clazz = DataClassFor(defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700512
513 out << "// Source for " << clazz << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900514 out << "const char* " << clazz << "::" << kDescriptor << " = \""
515 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700516 out << clazz << "::" << clazz << "() {}\n";
517 out << clazz << "::~" << clazz << "() {}\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700518 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700519 GenerateConstantDefinitions(out, defined_type);
520 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700521
Steven Moreland3c316ed2019-01-17 09:39:37 -0800522 out << "std::shared_ptr<" << clazz << "> " << clazz
523 << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800524 out.Indent();
Steven Moreland3c316ed2019-01-17 09:39:37 -0800525 out << data_clazz << "* data = static_cast<" << data_clazz
526 << "*>(AIBinder_getUserData(binder.get()));\n";
527 out << "if (data) {\n";
528 out.Indent();
529 out << "return data->instance;\n";
530 out.Dedent();
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800531 out << "}\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800532 // If it is local, it is not an 'ndk' instance, and parceling will happen locally.
533 out << "return " << NdkFullClassName(defined_type, ClassNames::CLIENT)
534 << "::associate(binder);\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800535 out.Dedent();
Steven Moreland3c316ed2019-01-17 09:39:37 -0800536 out << "}\n\n";
537
Steven Moreland2bea13b2018-10-03 15:12:33 -0700538 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
539 << clazz << ">& instance) {\n";
540 out.Indent();
541 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
542 "nullptr);\n";
543 out.Dedent();
544 out << "}\n";
545
546 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
547 << clazz << ">* instance) {\n";
548 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700549 out << "::ndk::SpAIBinder binder;\n";
Steven Moreland055d8792018-11-14 12:48:42 -0800550 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700551 out << "if (status != STATUS_OK) return status;\n";
Steven Moreland3c316ed2019-01-17 09:39:37 -0800552 out << "*instance = " << clazz << "::fromBinder(binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700553 out << "return STATUS_OK;\n";
554 out.Dedent();
555 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900556
557 // defintion for static member setDefaultImpl
558 out << "bool " << clazz << "::setDefaultImpl(std::shared_ptr<" << clazz << "> impl) {\n";
559 out.Indent();
560 out << "if (!" << clazz << "::default_impl && impl) {\n";
561 out.Indent();
562 out << clazz << "::default_impl = impl;\n";
563 out << "return true;\n";
564 out.Dedent();
565 out << "}\n";
566 out << "return false;\n";
567 out.Dedent();
568 out << "}\n";
569
570 // definition for static member getDefaultImpl
571 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
572 out.Indent();
573 out << "return " << clazz << "::default_impl;\n";
574 out.Dedent();
575 out << "}\n";
576
577 // definition for the static field default_impl
578 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
579
580 // default implementation for the <Name>Default class members
581 const std::string defaultClazz = clazz + "Default";
582 for (const auto& method : defined_type.GetMethods()) {
583 if (method->IsUserDefined()) {
584 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
585 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
586 out.Indent();
587 out << "::ndk::ScopedAStatus _aidl_status;\n";
588 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
589 out << "return _aidl_status;\n";
590 out.Dedent();
591 out << "}\n";
592 } else {
593 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
594 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
595 << "int32_t* _aidl_return) {\n";
596 out.Indent();
597 out << "*_aidl_return = 0;\n";
598 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
599 out.Dedent();
600 out << "}\n";
601 }
602 }
603 }
604
605 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
606 out.Indent();
607 out << "return ::ndk::SpAIBinder();\n";
608 out.Dedent();
609 out << "}\n";
610
611 out << "bool " << defaultClazz << "::isRemote() {\n";
612 out.Indent();
613 out << "return false;\n";
614 out.Dedent();
615 out << "}\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700616}
Jiyong Park965c5b92018-11-21 13:37:15 +0900617
Steven Morelandb0057e72018-08-27 01:44:11 -0700618void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900619 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700620 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
621
622 out << "#pragma once\n\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700623 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::INTERFACE, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700624 << "\"\n";
625 out << "\n";
626 out << "#include <android/binder_ibinder.h>\n";
627 out << "\n";
628 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700629 out << "class " << clazz << " : public ::ndk::BpCInterface<"
Steven Morelandb0057e72018-08-27 01:44:11 -0700630 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
631 out << "public:\n";
632 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700633 out << "static std::shared_ptr<" << clazz << "> associate(const ::ndk::SpAIBinder& binder);\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700634 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700635 out << "\n";
636 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700637 out << NdkMethodDecl(types, *method) << " override;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700638 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700639 out.Dedent();
640 out << "private:\n";
641 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700642 out << clazz << "(const ::ndk::SpAIBinder& binder);\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900643
644 if (options.Version() > 0) {
Jeongik Chac9972922019-02-11 12:41:16 +0900645 out << "int32_t _aidl_cached_value = -1;\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900646 }
647
Steven Morelandb0057e72018-08-27 01:44:11 -0700648 out.Dedent();
649 out << "};\n";
650 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700651}
Jiyong Park965c5b92018-11-21 13:37:15 +0900652void GenerateServerHeader(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::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900655 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700656
657 out << "#pragma once\n\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700658 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::INTERFACE, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700659 << "\"\n";
660 out << "\n";
661 out << "#include <android/binder_ibinder.h>\n";
662 out << "\n";
663 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900664 out << "class " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700665 out << "public:\n";
666 out.Indent();
667 out << clazz << "();\n";
668 out << "virtual ~" << clazz << "();\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900669
670 // Declare the meta methods
671 for (const auto& method : defined_type.GetMethods()) {
672 if (method->IsUserDefined()) {
673 continue;
674 }
675 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
676 out << NdkMethodDecl(types, *method) << " final override;\n";
677 } else {
678 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
679 }
680 }
681
Steven Morelandb0057e72018-08-27 01:44:11 -0700682 out.Dedent();
Steven Moreland0cf3f082018-09-20 19:09:46 -0700683 out << "protected:\n";
684 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700685 out << "::ndk::SpAIBinder createBinder() override;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700686 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700687 out << "private:\n";
688 out.Indent();
689 out.Dedent();
690 out << "};\n";
691 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700692}
693void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900694 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700695 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
696
697 out << "#pragma once\n\n";
698 out << "#include <android/binder_interface_utils.h>\n";
699 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700700
701 GenerateHeaderIncludes(out, types, defined_type);
702 out << "\n";
703
Steven Morelandb0057e72018-08-27 01:44:11 -0700704 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700705 out << "class " << clazz << " : public ::ndk::ICInterface {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700706 out << "public:\n";
707 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900708 out << "static AIBinder_Class* " << kClazz << ";\n";
709 out << "static const char* " << kDescriptor << ";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700710 out << clazz << "();\n";
711 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700712 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700713 GenerateConstantDeclarations(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900714 if (options.Version() > 0) {
715 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
716 << ";\n";
717 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700718 out << "\n";
Steven Moreland4cb2e6d2019-01-18 14:03:43 -0800719 out << "static std::shared_ptr<" << clazz << "> fromBinder(const ::ndk::SpAIBinder& binder);\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700720 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
721 << ">& instance);";
Jiyong Park1b88cce2018-11-19 19:53:44 +0900722 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700723 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
724 << ">* instance);";
725 out << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900726 out << "static bool setDefaultImpl(std::shared_ptr<" << clazz << "> impl);";
727 out << "\n";
728 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
729 out << "\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700730 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700731 out << "virtual " << NdkMethodDecl(types, *method) << " = 0;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700732 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700733 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900734 out << "private:\n";
735 out.Indent();
736 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
737 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700738 out << "};\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900739
740 const std::string defaultClazz = clazz + "Default";
741
742 out << "class " << defaultClazz << " : public " << clazz << " {\n";
743 out << "public:\n";
744 out.Indent();
745 for (const auto& method : defined_type.GetMethods()) {
746 if (method->IsUserDefined()) {
747 out << NdkMethodDecl(types, *method) << " override;\n";
748 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
749 out << NdkMethodDecl(types, *method) << " override;\n";
750 }
751 }
752 out << "::ndk::SpAIBinder asBinder() override;\n";
753 out << "bool isRemote() override;\n";
754 out.Dedent();
755 out << "};\n";
756
Steven Morelandb0057e72018-08-27 01:44:11 -0700757 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700758}
759void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700760 const AidlStructuredParcelable& defined_type,
761 const Options& /*options*/) {
762 const std::string clazz = ClassName(defined_type, ClassNames::BASE);
763
Steven Morelandb0057e72018-08-27 01:44:11 -0700764 out << "#pragma once\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700765 out << "#include <android/binder_interface_utils.h>\n";
766 out << "\n";
767
768 GenerateHeaderIncludes(out, types, defined_type);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700769
Steven Morelandb0057e72018-08-27 01:44:11 -0700770 EnterNdkNamespace(out, defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700771 out << "class " << clazz << " {\n";
772 out << "public:\n";
773 out.Indent();
774 out << "static const char* descriptor;\n";
775 out << "\n";
776 for (const auto& variable : defined_type.GetFields()) {
777 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << " " << variable->GetName();
778 if (variable->GetDefaultValue()) {
779 out << " = " << variable->ValueString(AidlConstantValueDecorator);
780 }
781 out << ";\n";
782 }
783 out << "\n";
784 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
785 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
786 out.Dedent();
787 out << "};\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700788 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700789}
790void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700791 const AidlStructuredParcelable& defined_type,
792 const Options& /*options*/) {
793 const std::string clazz = ClassName(defined_type, ClassNames::BASE);
794
Steven Moreland7c933372018-10-11 15:20:04 -0700795 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::BASE, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700796 << "\"\n";
797 out << "\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700798 GenerateSourceIncludes(out, types, defined_type);
799 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700800 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900801 out << "const char* " << clazz << "::" << kDescriptor << " = \""
802 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700803 out << "\n";
804
805 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
806 out.Indent();
807 out << "std::string _aidl_descriptor;\n";
808 out << "binder_status_t _aidl_ret_status;\n";
809
810 out << "int32_t _aidl_null;\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900811 out << "int32_t _aidl_parcelable_size;\n";
812 out << "int32_t _aidl_start_pos;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700813 out << "_aidl_ret_status = AParcel_readInt32(parcel, &_aidl_null);\n";
814 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900815 out << "_aidl_start_pos = AParcel_getDataPosition(parcel);\n";
816 out << "_aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
817 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
818 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700819
820 // TODO(b/117281836)
821 out << "if (_aidl_null == 0) return STATUS_UNEXPECTED_NULL;\n\n";
822
823 for (const auto& variable : defined_type.GetFields()) {
824 out << "_aidl_ret_status = ";
825 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
826 out << ";\n";
827 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900828 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
829 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
830 << " return _aidl_ret_status;\n"
831 << "}\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700832 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900833 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
834 << "return _aidl_ret_status;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700835 out.Dedent();
836 out << "}\n";
837
838 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
839 out.Indent();
840 out << "binder_status_t _aidl_ret_status;\n";
841
842 // non-null
843 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 1);\n";
844 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900845 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
846 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
847 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700848
849 for (const auto& variable : defined_type.GetFields()) {
850 out << "_aidl_ret_status = ";
851 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
852 out << ";\n";
853 StatusCheckReturn(out);
854 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900855 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
856 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
857 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
858 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
859
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700860 out << "return _aidl_ret_status;\n";
861 out.Dedent();
862 out << "}\n";
863 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700864 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700865}
866} // namespace internals
867} // namespace ndk
868} // namespace aidl
869} // namespace android