blob: e3f9eb2aef30f41e11da80cdcd17212e8349b470 [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
89void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
90 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
91 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
92 if (parcelable != nullptr) {
93 GenerateNdkParcel(output_file, options, types, *parcelable, io_delegate);
94 return;
95 }
96
97 const AidlInterface* interface = defined_type.AsInterface();
98 if (interface != nullptr) {
99 GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
100 return;
101 }
102
103 CHECK(false) << "Unrecognized type sent for cpp generation.";
104}
105namespace internals {
106
107void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
108 out << "namespace aidl {\n";
109 cpp::EnterNamespace(out, defined_type);
110}
111void LeaveNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
112 cpp::LeaveNamespace(out, defined_type);
113 out << "} // namespace aidl\n";
114}
115
Steven Morelandaada3422018-09-20 15:55:33 -0700116static void StatusCheckGoto(CodeWriter& out) {
117 out << "if (_aidl_ret_status != STATUS_OK) goto _aidl_error;\n\n";
118}
119static void StatusCheckBreak(CodeWriter& out) {
120 out << "if (_aidl_ret_status != STATUS_OK) break;\n\n";
121}
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700122static void StatusCheckReturn(CodeWriter& out) {
123 out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
124}
Steven Morelandaada3422018-09-20 15:55:33 -0700125
Steven Moreland2bea13b2018-10-03 15:12:33 -0700126static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
127 const AidlDefinedType& defined_type) {
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700128 out << "#include <android/binder_parcel_utils.h>\n";
129
Steven Moreland2bea13b2018-10-03 15:12:33 -0700130 types.IterateTypes([&](const AidlDefinedType& other_defined_type) {
131 if (&other_defined_type == &defined_type) return;
132
133 if (other_defined_type.AsInterface() != nullptr) {
134 out << "#include <"
Steven Moreland7c933372018-10-11 15:20:04 -0700135 << NdkHeaderFile(other_defined_type, ClassNames::INTERFACE, false /*use_os_sep*/)
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700136 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700137 } else if (other_defined_type.AsStructuredParcelable() != nullptr) {
138 out << "#include <"
139 << NdkHeaderFile(other_defined_type, ClassNames::BASE, false /*use_os_sep*/) << ">\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700140 } else if (other_defined_type.AsParcelable() != nullptr) {
141 out << "#include \"" << other_defined_type.AsParcelable()->GetCppHeader() << "\"\n";
142 } else {
143 AIDL_FATAL(defined_type) << "Unrecognized type.";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700144 }
145 });
146}
147static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
148 const AidlDefinedType& /*defined_type*/) {
149 types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
150 if (a_defined_type.AsInterface() != nullptr) {
Steven Moreland7c933372018-10-11 15:20:04 -0700151 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700152 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700153 out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
Steven Moreland2bea13b2018-10-03 15:12:33 -0700154 << ">\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700155 out << "#include <"
156 << NdkHeaderFile(a_defined_type, ClassNames::INTERFACE, false /*use_os_sep*/) << ">\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700157 }
158 });
159}
160
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700161static void GenerateConstantDeclarations(CodeWriter& out, const AidlInterface& interface) {
162 for (const auto& constant : interface.GetConstantDeclarations()) {
163 const AidlConstantValue& value = constant->GetValue();
164 if (value.GetType() == AidlConstantValue::Type::STRING) {
165 out << "static const char* " << constant->GetName() << ";\n";
166 }
167 }
168 out << "\n";
169
170 bool hasIntegralConstant = false;
171 for (const auto& constant : interface.GetConstantDeclarations()) {
172 const AidlConstantValue& value = constant->GetValue();
173 if (value.GetType() == AidlConstantValue::Type::HEXIDECIMAL ||
174 value.GetType() == AidlConstantValue::Type::INTEGRAL) {
175 hasIntegralConstant = true;
176 break;
177 }
178 }
179
180 if (hasIntegralConstant) {
181 out << "enum : int32_t {\n";
182 out.Indent();
183 for (const auto& constant : interface.GetConstantDeclarations()) {
184 const AidlConstantValue& value = constant->GetValue();
185 if (value.GetType() == AidlConstantValue::Type::HEXIDECIMAL ||
186 value.GetType() == AidlConstantValue::Type::INTEGRAL) {
187 out << constant->GetName() << " = " << constant->ValueString(AidlConstantValueDecorator)
188 << ",\n";
189 }
190 }
191 out.Dedent();
192 out << "};\n";
193 }
194}
195static void GenerateConstantDefinitions(CodeWriter& out, const AidlInterface& interface) {
196 const std::string clazz = ClassName(interface, ClassNames::INTERFACE);
197
198 for (const auto& constant : interface.GetConstantDeclarations()) {
199 const AidlConstantValue& value = constant->GetValue();
200 if (value.GetType() == AidlConstantValue::Type::STRING) {
201 out << "const char* " << clazz << "::" << constant->GetName() << " = "
202 << constant->ValueString(AidlConstantValueDecorator) << ";\n";
203 }
204 }
205}
206
Steven Morelandb0057e72018-08-27 01:44:11 -0700207void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
208 const Options& options) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700209 GenerateSourceIncludes(out, types, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700210 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700211
Steven Morelandb0057e72018-08-27 01:44:11 -0700212 EnterNdkNamespace(out, defined_type);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700213 GenerateClassSource(out, types, defined_type, options);
Steven Morelandb0057e72018-08-27 01:44:11 -0700214 GenerateClientSource(out, types, defined_type, options);
215 GenerateServerSource(out, types, defined_type, options);
216 GenerateInterfaceSource(out, types, defined_type, options);
217 LeaveNdkNamespace(out, defined_type);
218}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700219
220static std::string DataClassFor(const AidlInterface& defined_type) {
221 return "AidlClassData_" + ClassName(defined_type, ClassNames::INTERFACE);
222}
Steven Morelandaada3422018-09-20 15:55:33 -0700223static std::string MethodId(const AidlMethod& m) {
224 return "(FIRST_CALL_TRANSACTION + " + std::to_string(m.GetId()) + " /*" + m.GetName() + "*/)";
225}
226
Steven Moreland2bea13b2018-10-03 15:12:33 -0700227static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
228 const AidlInterface& defined_type,
Steven Morelandaada3422018-09-20 15:55:33 -0700229 const AidlMethod& method) {
230 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
231
Steven Moreland2bea13b2018-10-03 15:12:33 -0700232 out << NdkMethodDecl(types, method, clazz) << " {\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700233 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700234 out << "::ndk::ScopedAParcel _aidl_in;\n";
235 out << "::ndk::ScopedAParcel _aidl_out;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700236 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
Steven Moreland63404532018-10-08 14:31:00 -0700237 out << "::ndk::ScopedAStatus _aidl_status;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700238 out << "\n";
239
240 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
241 StatusCheckGoto(out);
242
Steven Morelandeb38ee72018-10-15 14:20:04 -0700243 for (const auto& arg : method.GetArguments()) {
244 const std::string var_name = cpp::BuildVarName(*arg);
245
246 if (arg->IsIn()) {
247 out << "_aidl_ret_status = ";
248 const std::string prefix = (arg->IsOut() ? "*" : "");
249 WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
250 out << ";\n";
251 StatusCheckGoto(out);
252 } else if (arg->IsOut() && arg->GetType().IsArray()) {
253 out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
254 << ");\n";
255 }
Steven Morelandaada3422018-09-20 15:55:33 -0700256 }
257 out << "_aidl_ret_status = AIBinder_transact(\n";
258 out.Indent();
259 out << "asBinder().get(),\n";
260 out << MethodId(method) << ",\n";
261 out << "_aidl_in.getR(),\n";
262 out << "_aidl_out.getR(),\n";
263 out << (method.IsOneway() ? "FLAG_ONEWAY" : "0") << ");\n";
264 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900265
266 // If the method is not implmented in the server side but the client has
267 // provided the default implementation, call it instead of failing hard.
268 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
269 out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
270 out << iface << "::getDefaultImpl()) {\n";
271 out.Indent();
272 out << "return " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
273 out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
274 out.Dedent();
275 out << "}\n";
276
Steven Morelandaada3422018-09-20 15:55:33 -0700277 StatusCheckGoto(out);
278
279 if (!method.IsOneway()) {
280 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
281 StatusCheckGoto(out);
282
283 out << "if (!AStatus_isOk(_aidl_status.get())) return _aidl_status;\n\n";
284 }
285
Steven Morelandaada3422018-09-20 15:55:33 -0700286 if (method.GetType().GetName() != "void") {
287 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700288 ReadFromParcelFor({out, types, method.GetType(), "_aidl_out.get()", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700289 out << ";\n";
290 StatusCheckGoto(out);
291 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700292 for (const AidlArgument* arg : method.GetOutArguments()) {
293 out << "_aidl_ret_status = ";
294 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_out.get()", cpp::BuildVarName(*arg)});
295 out << ";\n";
296 StatusCheckGoto(out);
297 }
Steven Morelandaada3422018-09-20 15:55:33 -0700298
299 out << "_aidl_error:\n";
300 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
301 out << "return _aidl_status;\n";
302 out.Dedent();
303 out << "}\n";
304}
305
Jiyong Park965c5b92018-11-21 13:37:15 +0900306static void GenerateClientMetaMethodDefinition(CodeWriter& out, const AidlTypenames& types,
307 const AidlInterface& defined_type,
308 const AidlMethod& method, const Options& options) {
309 CHECK(!method.IsUserDefined());
310 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
311 // Client-side implementation for getInterfaceVersion. The version is cached
312 // in the proxy object.
313 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
314
315 out << NdkMethodDecl(types, method, clazz) << " {\n";
316 out.Indent();
317 out << "::ndk::ScopedAStatus _aidl_status;\n";
318 out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
319 out << "if (cached_version_ == -1) {\n";
320 out.Indent();
321 out << "::ndk::ScopedAParcel _aidl_in;\n";
322 out << "::ndk::ScopedAParcel _aidl_out;\n";
323 out << "\n";
324
325 out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
326 StatusCheckGoto(out);
327
328 out << "_aidl_ret_status = AIBinder_transact(\n";
329 out.Indent();
330 out << "asBinder().get(),\n";
331 out << MethodId(method) << ",\n";
332 out << "_aidl_in.getR(),\n";
333 out << "_aidl_out.getR(),\n";
334 out << "0);\n";
335 out.Dedent();
336 StatusCheckGoto(out);
337
338 out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
339 StatusCheckGoto(out);
340
341 out << "if (!AStatus_isOk(_aidl_status.get())) return _aidl_status;\n\n";
342
343 out << "_aidl_ret_status = AParcel_readInt32(_aidl_out.get(), _aidl_return);\n";
344 StatusCheckGoto(out);
345
346 out << "cached_version_ = *_aidl_return;\n";
347 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
348 out << "return _aidl_status;\n";
349
350 out.Dedent();
351 out << "}\n";
352
353 // Shortcut. If cached, just return it without doing the transaction.
354 out << "*_aidl_return = cached_version_;\n";
355 out << "_aidl_error:\n";
356 out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
357 out << "return _aidl_status;\n";
358 out.Dedent();
359 out << "}\n";
360 }
361}
362
Steven Moreland2bea13b2018-10-03 15:12:33 -0700363static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
364 const AidlInterface& /*defined_type*/,
Steven Morelandaada3422018-09-20 15:55:33 -0700365 const AidlMethod& method) {
366 out << "case " << MethodId(method) << ": {\n";
367 out.Indent();
368 for (const auto& arg : method.GetArguments()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700369 out << NdkNameOf(types, arg->GetType(), StorageMode::STACK) << " " << cpp::BuildVarName(*arg)
370 << ";\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700371 }
372 if (method.GetType().GetName() != "void") {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700373 out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700374 }
375 out << "\n";
376
Steven Morelandeb38ee72018-10-15 14:20:04 -0700377 for (const auto& arg : method.GetArguments()) {
378 const std::string var_name = cpp::BuildVarName(*arg);
379
380 if (arg->IsIn()) {
381 out << "_aidl_ret_status = ";
382 ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
383 out << ";\n";
384 StatusCheckBreak(out);
385 } else if (arg->IsOut() && arg->GetType().IsArray()) {
386 out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
387 }
Steven Morelandaada3422018-09-20 15:55:33 -0700388 }
389
Steven Moreland63404532018-10-08 14:31:00 -0700390 out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
Jiyong Park965c5b92018-11-21 13:37:15 +0900391 << NdkArgList(types, method, FormatArgForCall) << ");\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700392
393 if (method.IsOneway()) {
394 // For a oneway transaction, the kernel will have already returned a result. This is for the
395 // in-process case when a oneway transaction is parceled/unparceled in the same process.
396 out << "_aidl_ret_status = STATUS_OK;\n";
397 } else {
398 out << "_aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());\n";
399 StatusCheckBreak(out);
400
401 out << "if (!AStatus_isOk(_aidl_status.get())) break;\n\n";
402
Steven Morelandaada3422018-09-20 15:55:33 -0700403 if (method.GetType().GetName() != "void") {
404 out << "_aidl_ret_status = ";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700405 WriteToParcelFor({out, types, method.GetType(), "_aidl_out", "_aidl_return"});
Steven Morelandaada3422018-09-20 15:55:33 -0700406 out << ";\n";
407 StatusCheckBreak(out);
408 }
Steven Moreland7c78d5d2018-10-15 14:21:11 -0700409 for (const AidlArgument* arg : method.GetOutArguments()) {
410 out << "_aidl_ret_status = ";
411 WriteToParcelFor({out, types, arg->GetType(), "_aidl_out", cpp::BuildVarName(*arg)});
412 out << ";\n";
413 StatusCheckBreak(out);
414 }
Steven Morelandaada3422018-09-20 15:55:33 -0700415 }
416
417 out << "break;\n";
418 out.Dedent();
419 out << "}\n";
420}
Steven Moreland0cf3f082018-09-20 19:09:46 -0700421
Steven Moreland2bea13b2018-10-03 15:12:33 -0700422void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
Steven Moreland0cf3f082018-09-20 19:09:46 -0700423 const AidlInterface& defined_type, const Options& /*options*/) {
424 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
425 const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
426 const std::string data_clazz = DataClassFor(defined_type);
427 const std::string on_create = data_clazz + "_onCreate";
428 const std::string on_destroy = data_clazz + "_onDestory";
429 const std::string on_transact = data_clazz + "_onTransact";
430
431 out << "struct " << data_clazz << " {\n";
432 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900433 out << "static AIBinder_Class* " << kClazz << ";\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700434 out << "std::shared_ptr<" << bn_clazz << "> instance;\n";
435 out.Dedent();
436 out << "};\n\n";
437
438 out << "static void* " << on_create << "(void* args) {\n";
439 out.Indent();
440 out << data_clazz << "* data = new " << data_clazz << "{static_cast<" << bn_clazz
441 << "*>(args)->ref<" << bn_clazz << ">()};\n";
442 out << "return static_cast<void*>(data);\n";
443 out.Dedent();
444 out << "};\n\n";
445
446 out << "static void " << on_destroy << "(void* userData) {\n";
447 out.Indent();
448 out << "delete static_cast<" << data_clazz << "*>(userData);\n";
449 out.Dedent();
450 out << "};\n\n";
451
452 out << "static binder_status_t " << on_transact
Steven Morelandaada3422018-09-20 15:55:33 -0700453 << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
454 "AParcel* _aidl_out) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700455 out.Indent();
Steven Morelandaada3422018-09-20 15:55:33 -0700456 out << "(void)_aidl_in;\n";
457 out << "(void)_aidl_out;\n";
458 out << "binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;\n";
459 if (!defined_type.GetMethods().empty()) {
460 out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = static_cast<" << data_clazz
461 << "*>(AIBinder_getUserData(_aidl_binder))->instance;\n";
462 out << "switch (_aidl_code) {\n";
463 out.Indent();
464 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700465 GenerateServerCaseDefinition(out, types, defined_type, *method);
Steven Morelandaada3422018-09-20 15:55:33 -0700466 }
467 out.Dedent();
468 out << "}\n";
469 } else {
470 out << "(void)_aidl_binder;\n";
471 out << "(void)_aidl_code;\n";
472 }
473 out << "return _aidl_ret_status;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700474 out.Dedent();
475 out << "};\n\n";
476
Jiyong Park965c5b92018-11-21 13:37:15 +0900477 out << "AIBinder_Class* " << data_clazz << ":: " << kClazz << " = AIBinder_Class_define(" << clazz
478 << "::" << kDescriptor << ", " << on_create << ", " << on_destroy << ", " << on_transact
479 << ");\n\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700480}
Steven Morelandb0057e72018-08-27 01:44:11 -0700481void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900482 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700483 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700484 const std::string data_clazz = DataClassFor(defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700485
486 out << "// Source for " << clazz << "\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700487 out << "std::shared_ptr<" << clazz << "> " << clazz
Steven Moreland63404532018-10-08 14:31:00 -0700488 << "::associate(const ::ndk::SpAIBinder& binder) {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700489 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900490 out << "if (!AIBinder_associateClass(binder.get(), " << data_clazz << "::" << kClazz
491 << ")) { return nullptr; }\n";
Steven Moreland1c4b4052018-10-10 12:24:22 -0700492 out << "return (new " << clazz << "(binder))->ref<" << clazz << ">();\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700493 out.Dedent();
494 out << "}\n\n";
495
Steven Moreland63404532018-10-08 14:31:00 -0700496 out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700497 out << clazz << "::~" << clazz << "() {}\n";
498 out << "\n";
499 for (const auto& method : defined_type.GetMethods()) {
Jiyong Park965c5b92018-11-21 13:37:15 +0900500 if (method->IsUserDefined()) {
501 GenerateClientMethodDefinition(out, types, defined_type, *method);
502 } else {
503 GenerateClientMetaMethodDefinition(out, types, defined_type, *method, options);
504 }
Steven Morelandaada3422018-09-20 15:55:33 -0700505 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700506}
Jiyong Park965c5b92018-11-21 13:37:15 +0900507void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
508 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700509 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900510 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland0cf3f082018-09-20 19:09:46 -0700511 const std::string data_clazz = DataClassFor(defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700512
513 out << "// Source for " << clazz << "\n";
514 out << clazz << "::" << clazz << "() {}\n";
515 out << clazz << "::~" << clazz << "() {}\n";
516
Steven Moreland63404532018-10-08 14:31:00 -0700517 out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700518 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900519 out << "AIBinder* binder = AIBinder_new(" << data_clazz << "::" << kClazz
520 << ", static_cast<void*>(this));\n";
Steven Moreland63404532018-10-08 14:31:00 -0700521 out << "return ::ndk::SpAIBinder(binder);\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700522 out.Dedent();
523 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900524
525 // Implement the meta methods
526 for (const auto& method : defined_type.GetMethods()) {
527 if (method->IsUserDefined()) {
528 continue;
529 }
530 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
531 out << NdkMethodDecl(types, *method, clazz) << " {\n";
532 out.Indent();
533 out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
534 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
535 out.Dedent();
536 out << "}\n";
537 }
538 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700539}
Jiyong Park965c5b92018-11-21 13:37:15 +0900540void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
541 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700542 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700543 const std::string data_clazz = DataClassFor(defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700544
545 out << "// Source for " << clazz << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900546 out << "const char* " << clazz << "::" << kDescriptor << " = \""
547 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700548 out << clazz << "::" << clazz << "() {}\n";
549 out << clazz << "::~" << clazz << "() {}\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700550 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700551 GenerateConstantDefinitions(out, defined_type);
552 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700553
Steven Moreland2bea13b2018-10-03 15:12:33 -0700554 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
555 << clazz << ">& instance) {\n";
556 out.Indent();
557 out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
558 "nullptr);\n";
559 out.Dedent();
560 out << "}\n";
561
562 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
563 << clazz << ">* instance) {\n";
564 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700565 out << "::ndk::SpAIBinder binder;\n";
Steven Moreland055d8792018-11-14 12:48:42 -0800566 out << "binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700567 out << "if (status != STATUS_OK) return status;\n";
568 out << data_clazz << "* data = static_cast<" << data_clazz
569 << "*>(AIBinder_getUserData(binder.get()));\n";
570 out << "if (data) {\n";
571 out.Indent();
572 out << "*instance = data->instance;\n";
573 out.Dedent();
574 out << "} else {\n";
575 out.Indent();
576 out << "*instance = " << NdkFullClassName(defined_type, ClassNames::CLIENT)
577 << "::associate(binder);\n";
578 out.Dedent();
579 out << "}\n";
580 out << "return STATUS_OK;\n";
581 out.Dedent();
582 out << "}\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900583
584 // defintion for static member setDefaultImpl
585 out << "bool " << clazz << "::setDefaultImpl(std::shared_ptr<" << clazz << "> impl) {\n";
586 out.Indent();
587 out << "if (!" << clazz << "::default_impl && impl) {\n";
588 out.Indent();
589 out << clazz << "::default_impl = impl;\n";
590 out << "return true;\n";
591 out.Dedent();
592 out << "}\n";
593 out << "return false;\n";
594 out.Dedent();
595 out << "}\n";
596
597 // definition for static member getDefaultImpl
598 out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
599 out.Indent();
600 out << "return " << clazz << "::default_impl;\n";
601 out.Dedent();
602 out << "}\n";
603
604 // definition for the static field default_impl
605 out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
606
607 // default implementation for the <Name>Default class members
608 const std::string defaultClazz = clazz + "Default";
609 for (const auto& method : defined_type.GetMethods()) {
610 if (method->IsUserDefined()) {
611 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
612 << NdkArgList(types, *method, FormatArgNameUnused) << ") {\n";
613 out.Indent();
614 out << "::ndk::ScopedAStatus _aidl_status;\n";
615 out << "_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));\n";
616 out << "return _aidl_status;\n";
617 out.Dedent();
618 out << "}\n";
619 } else {
620 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
621 out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
622 << "int32_t* _aidl_return) {\n";
623 out.Indent();
624 out << "*_aidl_return = 0;\n";
625 out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
626 out.Dedent();
627 out << "}\n";
628 }
629 }
630 }
631
632 out << "::ndk::SpAIBinder " << defaultClazz << "::asBinder() {\n";
633 out.Indent();
634 out << "return ::ndk::SpAIBinder();\n";
635 out.Dedent();
636 out << "}\n";
637
638 out << "bool " << defaultClazz << "::isRemote() {\n";
639 out.Indent();
640 out << "return false;\n";
641 out.Dedent();
642 out << "}\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700643}
Jiyong Park965c5b92018-11-21 13:37:15 +0900644
Steven Morelandb0057e72018-08-27 01:44:11 -0700645void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900646 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700647 const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
648
649 out << "#pragma once\n\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700650 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::INTERFACE, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700651 << "\"\n";
652 out << "\n";
653 out << "#include <android/binder_ibinder.h>\n";
654 out << "\n";
655 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700656 out << "class " << clazz << " : public ::ndk::BpCInterface<"
Steven Morelandb0057e72018-08-27 01:44:11 -0700657 << ClassName(defined_type, ClassNames::INTERFACE) << "> {\n";
658 out << "public:\n";
659 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700660 out << "static std::shared_ptr<" << clazz << "> associate(const ::ndk::SpAIBinder& binder);\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700661 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700662 out << "\n";
663 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700664 out << NdkMethodDecl(types, *method) << " override;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700665 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700666 out.Dedent();
667 out << "private:\n";
668 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700669 out << clazz << "(const ::ndk::SpAIBinder& binder);\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900670
671 if (options.Version() > 0) {
672 out << "int32_t cached_version_ = -1;\n";
673 }
674
Steven Morelandb0057e72018-08-27 01:44:11 -0700675 out.Dedent();
676 out << "};\n";
677 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700678}
Jiyong Park965c5b92018-11-21 13:37:15 +0900679void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
680 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700681 const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
Jiyong Park965c5b92018-11-21 13:37:15 +0900682 const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
Steven Morelandb0057e72018-08-27 01:44:11 -0700683
684 out << "#pragma once\n\n";
Steven Moreland7c933372018-10-11 15:20:04 -0700685 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::INTERFACE, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700686 << "\"\n";
687 out << "\n";
688 out << "#include <android/binder_ibinder.h>\n";
689 out << "\n";
690 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900691 out << "class " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700692 out << "public:\n";
693 out.Indent();
694 out << clazz << "();\n";
695 out << "virtual ~" << clazz << "();\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900696
697 // Declare the meta methods
698 for (const auto& method : defined_type.GetMethods()) {
699 if (method->IsUserDefined()) {
700 continue;
701 }
702 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
703 out << NdkMethodDecl(types, *method) << " final override;\n";
704 } else {
705 AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
706 }
707 }
708
Steven Morelandb0057e72018-08-27 01:44:11 -0700709 out.Dedent();
Steven Moreland0cf3f082018-09-20 19:09:46 -0700710 out << "protected:\n";
711 out.Indent();
Steven Moreland63404532018-10-08 14:31:00 -0700712 out << "::ndk::SpAIBinder createBinder() override;\n";
Steven Moreland0cf3f082018-09-20 19:09:46 -0700713 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700714 out << "private:\n";
715 out.Indent();
716 out.Dedent();
717 out << "};\n";
718 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700719}
720void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
Jiyong Park965c5b92018-11-21 13:37:15 +0900721 const AidlInterface& defined_type, const Options& options) {
Steven Morelandb0057e72018-08-27 01:44:11 -0700722 const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
723
724 out << "#pragma once\n\n";
725 out << "#include <android/binder_interface_utils.h>\n";
726 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700727
728 GenerateHeaderIncludes(out, types, defined_type);
729 out << "\n";
730
Steven Morelandb0057e72018-08-27 01:44:11 -0700731 EnterNdkNamespace(out, defined_type);
Steven Moreland63404532018-10-08 14:31:00 -0700732 out << "class " << clazz << " : public ::ndk::ICInterface {\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700733 out << "public:\n";
734 out.Indent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900735 out << "static AIBinder_Class* " << kClazz << ";\n";
736 out << "static const char* " << kDescriptor << ";\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700737 out << clazz << "();\n";
738 out << "virtual ~" << clazz << "();\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700739 out << "\n";
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700740 GenerateConstantDeclarations(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900741 if (options.Version() > 0) {
742 out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
743 << ";\n";
744 }
Steven Morelandac8fe7f2018-10-04 09:58:31 -0700745 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700746 out << "static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<" << clazz
747 << ">& instance);";
Jiyong Park1b88cce2018-11-19 19:53:44 +0900748 out << "\n";
Steven Moreland2bea13b2018-10-03 15:12:33 -0700749 out << "static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<" << clazz
750 << ">* instance);";
751 out << "\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900752 out << "static bool setDefaultImpl(std::shared_ptr<" << clazz << "> impl);";
753 out << "\n";
754 out << "static const std::shared_ptr<" << clazz << ">& getDefaultImpl();";
755 out << "\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700756 for (const auto& method : defined_type.GetMethods()) {
Steven Moreland2bea13b2018-10-03 15:12:33 -0700757 out << "virtual " << NdkMethodDecl(types, *method) << " = 0;\n";
Steven Morelandaada3422018-09-20 15:55:33 -0700758 }
Steven Morelandb0057e72018-08-27 01:44:11 -0700759 out.Dedent();
Jiyong Park965c5b92018-11-21 13:37:15 +0900760 out << "private:\n";
761 out.Indent();
762 out << "static std::shared_ptr<" << clazz << "> default_impl;\n";
763 out.Dedent();
Steven Morelandb0057e72018-08-27 01:44:11 -0700764 out << "};\n";
Jiyong Park965c5b92018-11-21 13:37:15 +0900765
766 const std::string defaultClazz = clazz + "Default";
767
768 out << "class " << defaultClazz << " : public " << clazz << " {\n";
769 out << "public:\n";
770 out.Indent();
771 for (const auto& method : defined_type.GetMethods()) {
772 if (method->IsUserDefined()) {
773 out << NdkMethodDecl(types, *method) << " override;\n";
774 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
775 out << NdkMethodDecl(types, *method) << " override;\n";
776 }
777 }
778 out << "::ndk::SpAIBinder asBinder() override;\n";
779 out << "bool isRemote() override;\n";
780 out.Dedent();
781 out << "};\n";
782
Steven Morelandb0057e72018-08-27 01:44:11 -0700783 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700784}
785void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700786 const AidlStructuredParcelable& defined_type,
787 const Options& /*options*/) {
788 const std::string clazz = ClassName(defined_type, ClassNames::BASE);
789
Steven Morelandb0057e72018-08-27 01:44:11 -0700790 out << "#pragma once\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700791 out << "#include <android/binder_interface_utils.h>\n";
792 out << "\n";
793
794 GenerateHeaderIncludes(out, types, defined_type);
Steven Moreland2bea13b2018-10-03 15:12:33 -0700795
Steven Morelandb0057e72018-08-27 01:44:11 -0700796 EnterNdkNamespace(out, defined_type);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700797 out << "class " << clazz << " {\n";
798 out << "public:\n";
799 out.Indent();
800 out << "static const char* descriptor;\n";
801 out << "\n";
802 for (const auto& variable : defined_type.GetFields()) {
803 out << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << " " << variable->GetName();
804 if (variable->GetDefaultValue()) {
805 out << " = " << variable->ValueString(AidlConstantValueDecorator);
806 }
807 out << ";\n";
808 }
809 out << "\n";
810 out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
811 out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
812 out.Dedent();
813 out << "};\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700814 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700815}
816void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700817 const AidlStructuredParcelable& defined_type,
818 const Options& /*options*/) {
819 const std::string clazz = ClassName(defined_type, ClassNames::BASE);
820
Steven Moreland7c933372018-10-11 15:20:04 -0700821 out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::BASE, false /*use_os_sep*/)
Steven Morelandb0057e72018-08-27 01:44:11 -0700822 << "\"\n";
823 out << "\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700824 GenerateSourceIncludes(out, types, defined_type);
825 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700826 EnterNdkNamespace(out, defined_type);
Jiyong Park965c5b92018-11-21 13:37:15 +0900827 out << "const char* " << clazz << "::" << kDescriptor << " = \""
828 << defined_type.GetCanonicalName() << "\";\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700829 out << "\n";
830
831 out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
832 out.Indent();
833 out << "std::string _aidl_descriptor;\n";
834 out << "binder_status_t _aidl_ret_status;\n";
835
836 out << "int32_t _aidl_null;\n";
Jeongik Cha95eba572018-11-22 09:14:52 +0900837 out << "int32_t _aidl_parcelable_size;\n";
838 out << "int32_t _aidl_start_pos;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700839 out << "_aidl_ret_status = AParcel_readInt32(parcel, &_aidl_null);\n";
840 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900841 out << "_aidl_start_pos = AParcel_getDataPosition(parcel);\n";
842 out << "_aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
843 out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
844 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700845
846 // TODO(b/117281836)
847 out << "if (_aidl_null == 0) return STATUS_UNEXPECTED_NULL;\n\n";
848
849 for (const auto& variable : defined_type.GetFields()) {
850 out << "_aidl_ret_status = ";
851 ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
852 out << ";\n";
853 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900854 out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
855 << " AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
856 << " return _aidl_ret_status;\n"
857 << "}\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700858 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900859 out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
860 << "return _aidl_ret_status;\n";
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700861 out.Dedent();
862 out << "}\n";
863
864 out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
865 out.Indent();
866 out << "binder_status_t _aidl_ret_status;\n";
867
868 // non-null
869 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 1);\n";
870 StatusCheckReturn(out);
Jeongik Cha95eba572018-11-22 09:14:52 +0900871 out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
872 out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
873 StatusCheckReturn(out);
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700874
875 for (const auto& variable : defined_type.GetFields()) {
876 out << "_aidl_ret_status = ";
877 WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
878 out << ";\n";
879 StatusCheckReturn(out);
880 }
Jeongik Cha95eba572018-11-22 09:14:52 +0900881 out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
882 out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
883 out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
884 out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
885
Steven Morelandbb8f46c2018-10-03 17:38:00 -0700886 out << "return _aidl_ret_status;\n";
887 out.Dedent();
888 out << "}\n";
889 out << "\n";
Steven Morelandb0057e72018-08-27 01:44:11 -0700890 LeaveNdkNamespace(out, defined_type);
Steven Morelandb0057e72018-08-27 01:44:11 -0700891}
892} // namespace internals
893} // namespace ndk
894} // namespace aidl
895} // namespace android