1 /**
2 * Copyright (C) 2015, 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_cpp.h"
18 #include "aidl.h"
19
20 #include <algorithm>
21 #include <cctype>
22 #include <cstring>
23 #include <format>
24 #include <memory>
25 #include <set>
26 #include <string>
27
28 #include <android-base/stringprintf.h>
29 #include <android-base/strings.h>
30
31 #include "aidl_language.h"
32 #include "aidl_to_common.h"
33 #include "aidl_to_cpp.h"
34
35 #include "aidl_typenames.h"
36 #include "logging.h"
37
38 using android::base::Join;
39 using android::base::StringPrintf;
40 using std::set;
41 using std::string;
42 using std::unique_ptr;
43 using std::vector;
44
45 namespace android {
46 namespace aidl {
47 namespace cpp {
48 namespace internals {
49 namespace {
50
51 const char kAndroidStatusVarName[] = "_aidl_ret_status";
52 const char kCodeVarName[] = "_aidl_code";
53 const char kFlagsVarName[] = "_aidl_flags";
54 const char kDataVarName[] = "_aidl_data";
55 const char kErrorLabel[] = "_aidl_error";
56 const char kImplVarName[] = "_aidl_impl";
57 const char kDelegateImplVarName[] = "_aidl_delegate";
58 const char kParcelVarName[] = "_aidl_parcel";
59 const char kReplyVarName[] = "_aidl_reply";
60 const char kReturnVarName[] = "_aidl_return";
61 const char kStatusVarName[] = "_aidl_status";
62 const char kTraceVarName[] = "_aidl_trace";
63 const char kAndroidParcelLiteral[] = "::android::Parcel";
64 const char kAndroidStatusLiteral[] = "::android::status_t";
65 const char kAndroidStatusOk[] = "::android::OK";
66 const char kAndroidStatusBadValue[] = "::android::BAD_VALUE";
67 const char kBinderStatusLiteral[] = "::android::binder::Status";
68 const char kIBinderHeader[] = "binder/IBinder.h";
69 const char kIInterfaceHeader[] = "binder/IInterface.h";
70 const char kBinderDelegateHeader[] = "binder/Delegate.h";
71 const char kParcelHeader[] = "binder/Parcel.h";
72 const char kStabilityHeader[] = "binder/Stability.h";
73 const char kStatusHeader[] = "binder/Status.h";
74 const char kString16Header[] = "utils/String16.h";
75 const char kTraceHeader[] = "binder/Trace.h";
76 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
77
GenerateBreakOnStatusNotOk(CodeWriter & out)78 void GenerateBreakOnStatusNotOk(CodeWriter& out) {
79 out.Write("if (((%s) != (%s))) {\n", kAndroidStatusVarName, kAndroidStatusOk);
80 out.Write(" break;\n");
81 out.Write("}\n");
82 }
83
GenerateGotoErrorOnBadStatus(CodeWriter & out)84 void GenerateGotoErrorOnBadStatus(CodeWriter& out) {
85 out.Write("if (((%s) != (%s))) {\n", kAndroidStatusVarName, kAndroidStatusOk);
86 out.Write(" goto %s;\n", kErrorLabel);
87 out.Write("}\n");
88 }
89
90 // Format three types of arg list for method.
91 // for_declaration & !type_name_only: int a // for method decl with type and arg
92 // for_declaration & type_name_only: int /*a*/ // for method decl with type
93 // !for_declaration : a // for method call with arg (with direction)
GenerateArgList(const AidlTypenames & typenames,const AidlMethod & method,bool for_declaration,bool type_name_only)94 string GenerateArgList(const AidlTypenames& typenames, const AidlMethod& method,
95 bool for_declaration, bool type_name_only) {
96 vector<string> method_arguments;
97 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
98 string literal;
99 // b/144943748: CppNameOf FileDescriptor is unique_fd. Don't pass it by
100 // const reference but by value to make it easier for the user to keep
101 // it beyond the scope of the call. unique_fd is a thin wrapper for an
102 // int (fd) so passing by value is not expensive.
103 const bool non_copyable = IsNonCopyableType(a->GetType(), typenames);
104 if (for_declaration) {
105 // Method declarations need typenames, pointers to out params, and variable
106 // names that match the .aidl specification.
107 literal = CppNameOf(a->GetType(), typenames);
108
109 if (a->IsOut()) {
110 literal = literal + "*";
111 } else {
112 const auto defined_type = typenames.TryGetDefinedType(a->GetType().GetName());
113
114 const bool is_enum = defined_type && defined_type->AsEnumDeclaration() != nullptr;
115 const bool is_primitive = AidlTypenames::IsPrimitiveTypename(a->GetType().GetName());
116
117 // We pass in parameters that are not primitives by const reference.
118 // Arrays of primitives are not primitives.
119 if (!(is_primitive || is_enum || non_copyable) || a->GetType().IsArray()) {
120 literal = "const " + literal + "&";
121 }
122 }
123 if (type_name_only) {
124 literal += " /*" + a->GetName() + "*/";
125 } else {
126 literal += " " + a->GetName();
127 }
128 } else {
129 std::string var_name = BuildVarName(*a);
130 if (a->IsOut()) {
131 literal = "&" + var_name;
132 } else if (non_copyable) {
133 literal = "std::move(" + var_name + ")";
134 } else {
135 literal = var_name;
136 }
137 }
138 method_arguments.push_back(literal);
139 }
140
141 if (method.GetType().GetName() != "void") {
142 string literal;
143 if (for_declaration) {
144 literal = CppNameOf(method.GetType(), typenames) + "*";
145 if (type_name_only) {
146 literal += " /*" + string(kReturnVarName) + "*/";
147 } else {
148 literal += " " + string(kReturnVarName);
149 }
150 } else {
151 literal = string{"&"} + kReturnVarName;
152 }
153 method_arguments.push_back(literal);
154 }
155
156 return Join(method_arguments, ", ");
157 }
158
GenerateMethodDecl(CodeWriter & out,const AidlTypenames & types,const AidlMethod & method,const string & clazz)159 void GenerateMethodDecl(CodeWriter& out, const AidlTypenames& types, const AidlMethod& method,
160 const string& clazz) {
161 string clazz_prefix = clazz.empty() ? "" : clazz + "::";
162 out << "::android::binder::Status " << clazz_prefix << method.GetName() << "("
163 << GenerateArgList(types, method, /*for_declartion=*/true, /*type_name_only=*/false) << ")";
164 }
165
GenerateClientTransaction(CodeWriter & out,const AidlTypenames & typenames,const AidlInterface & interface,const AidlMethod & method,const Options & options)166 void GenerateClientTransaction(CodeWriter& out, const AidlTypenames& typenames,
167 const AidlInterface& interface, const AidlMethod& method,
168 const Options& options) {
169 const string i_name = ClassName(interface, ClassNames::INTERFACE);
170 const string bp_name = GetQualifiedName(interface, ClassNames::CLIENT);
171 const string bn_name = GetQualifiedName(interface, ClassNames::SERVER);
172
173 GenerateMethodDecl(out, typenames, method, bp_name);
174 out << " {\n";
175 out.Indent();
176
177 // Declare parcels to hold our query and the response.
178 out.Write("%s %s;\n", kAndroidParcelLiteral, kDataVarName);
179 if (interface.IsSensitiveData()) {
180 out.Write("%s.markSensitive();\n", kDataVarName);
181 }
182 out.Write("%s.markForBinder(remoteStrong());\n", kDataVarName);
183
184 if (!method.IsOneway()) {
185 out.Write("%s %s;\n", kAndroidParcelLiteral, kReplyVarName);
186 }
187
188 // Declare the status_t variable we need for error handling.
189 out.Write("%s %s = %s;\n", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk);
190 // We unconditionally return a Status object.
191 out.Write("%s %s;\n", kBinderStatusLiteral, kStatusVarName);
192
193 if (options.GenTraces()) {
194 out.Write(
195 "::android::binder::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppClient\");\n",
196 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str());
197 }
198
199 if (options.GenLog()) {
200 out << GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */);
201 }
202
203 if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
204 out << "if (true) {\n";
205 out.Write(" %s = ::android::UNKNOWN_TRANSACTION;\n", kAndroidStatusVarName);
206 out << "} else {\n";
207 out.Indent();
208 }
209
210 // Add the name of the interface we're hoping to call.
211 out.Write("%s = %s.writeInterfaceToken(getInterfaceDescriptor());\n", kAndroidStatusVarName,
212 kDataVarName);
213 GenerateGotoErrorOnBadStatus(out);
214
215 for (const auto& a : method.GetArguments()) {
216 const string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
217
218 if (a->IsIn()) {
219 // Serialization looks roughly like:
220 // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
221 // if (_aidl_ret_status != ::android::OK) { goto error; }
222 out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kDataVarName,
223 ParcelWriteMethodOf(a->GetType(), typenames).c_str(),
224 ParcelWriteCastOf(a->GetType(), typenames, var_name).c_str());
225 GenerateGotoErrorOnBadStatus(out);
226 } else if (a->IsOut() && a->GetType().IsDynamicArray()) {
227 // Special case, the length of the out array is written into the parcel.
228 // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
229 // if (_aidl_ret_status != ::android::OK) { goto error; }
230 out.Write("%s = %s.writeVectorSize(%s);\n", kAndroidStatusVarName, kDataVarName,
231 var_name.c_str());
232 GenerateGotoErrorOnBadStatus(out);
233 }
234 }
235
236 // Invoke the transaction on the remote binder and confirm status.
237 std::vector<std::string> flags;
238 if (method.IsOneway()) flags.push_back("::android::IBinder::FLAG_ONEWAY");
239 if (interface.IsSensitiveData()) flags.push_back("::android::IBinder::FLAG_CLEAR_BUF");
240
241 out.Write("%s = remote()->transact(%s, %s, %s%s, %s);\n", kAndroidStatusVarName,
242 GetTransactionIdFor(bn_name, method).c_str(), kDataVarName,
243 method.IsOneway() ? "" : "&", method.IsOneway() ? "nullptr" : kReplyVarName,
244 flags.empty() ? "0" : Join(flags, " | ").c_str());
245
246 // If the method is not implemented in the remote side, try to call the
247 // default implementation, if provided.
248 vector<string> arg_names;
249 for (const auto& a : method.GetArguments()) {
250 if (IsNonCopyableType(a->GetType(), typenames)) {
251 arg_names.emplace_back(StringPrintf("std::move(%s)", a->GetName().c_str()));
252 } else {
253 arg_names.emplace_back(a->GetName());
254 }
255 }
256 if (method.GetType().GetName() != "void") {
257 arg_names.emplace_back(kReturnVarName);
258 }
259 if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
260 out.Dedent();
261 out << "}\n";
262 }
263 out.Write("if (%s == ::android::UNKNOWN_TRANSACTION && %s::getDefaultImpl()) [[unlikely]] {\n",
264 kAndroidStatusVarName, i_name.c_str());
265 out.Write(" return %s::getDefaultImpl()->%s(%s);\n", i_name.c_str(), method.GetName().c_str(),
266 Join(arg_names, ", ").c_str());
267 out.Write("}\n");
268 GenerateGotoErrorOnBadStatus(out);
269
270 if (!method.IsOneway()) {
271 // Strip off the exception header and fail if we see a remote exception.
272 // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
273 // if (_aidl_ret_status != ::android::OK) { goto error; }
274 // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
275 out.Write("%s = %s.readFromParcel(%s);\n", kAndroidStatusVarName, kStatusVarName,
276 kReplyVarName);
277 GenerateGotoErrorOnBadStatus(out);
278 out.Write("if (!%s.isOk()) {\n", kStatusVarName);
279 out.Write(" return %s;\n", kStatusVarName);
280 out.Write("}\n");
281 }
282
283 // Type checking should guarantee that nothing below emits code until "return
284 // status" if we are a oneway method, so no more fear of accessing reply.
285
286 // If the method is expected to return something, read it first by convention.
287 if (method.GetType().GetName() != "void") {
288 out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
289 ParcelReadMethodOf(method.GetType(), typenames).c_str(),
290 ParcelReadCastOf(method.GetType(), typenames, kReturnVarName).c_str());
291 GenerateGotoErrorOnBadStatus(out);
292 }
293
294 for (const AidlArgument* a : method.GetOutArguments()) {
295 // Deserialization looks roughly like:
296 // _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
297 // if (_aidl_status != ::android::OK) { goto _aidl_error; }
298 out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
299 ParcelReadMethodOf(a->GetType(), typenames).c_str(),
300 ParcelReadCastOf(a->GetType(), typenames, a->GetName()).c_str());
301 GenerateGotoErrorOnBadStatus(out);
302 }
303
304 // If we've gotten to here, one of two things is true:
305 // 1) We've read some bad status_t
306 // 2) We've only read status_t == OK and there was no exception in the
307 // response.
308 // In both cases, we're free to set Status from the status_t and return.
309 out.Write("%s:\n", kErrorLabel);
310 out.Write("%s.setFromStatusT(%s);\n", kStatusVarName, kAndroidStatusVarName);
311
312 if (options.GenLog()) {
313 out << GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
314 false /* isServer */, false /* isNdk */);
315 }
316
317 out.Write("return %s;\n", kStatusVarName);
318 out.Dedent();
319 out << "}\n";
320 }
321
GenerateClientMetaTransaction(CodeWriter & out,const AidlInterface & interface,const AidlMethod & method,const Options & options)322 void GenerateClientMetaTransaction(CodeWriter& out, const AidlInterface& interface,
323 const AidlMethod& method, const Options& options) {
324 AIDL_FATAL_IF(method.IsUserDefined(), method);
325 const string bp_name = GetQualifiedName(interface, ClassNames::CLIENT);
326 const string bn_name = GetQualifiedName(interface, ClassNames::SERVER);
327 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
328 // Note: race condition can happen here, but no locking is required
329 // because 1) writing an interger is atomic and 2) this transaction
330 // will always return the same value, i.e., competing threads will
331 // give write the same value to cached_version_.
332 out << "int32_t " << bp_name << "::" << kGetInterfaceVersion << "() {\n"
333 << " if (cached_version_ == -1) {\n"
334 << " ::android::Parcel data;\n"
335 << " ::android::Parcel reply;\n"
336 << " data.writeInterfaceToken(getInterfaceDescriptor());\n"
337 << " ::android::status_t err = remote()->transact("
338 << GetTransactionIdFor(bn_name, method) << ", data, &reply);\n"
339 << " if (err == ::android::OK) {\n"
340 << " ::android::binder::Status _aidl_status;\n"
341 << " err = _aidl_status.readFromParcel(reply);\n"
342 << " if (err == ::android::OK && _aidl_status.isOk()) {\n"
343 << " cached_version_ = reply.readInt32();\n"
344 << " }\n"
345 << " }\n"
346 << " }\n"
347 << " return cached_version_;\n"
348 << "}\n";
349 out << "\n";
350 }
351 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
352 out << "std::string " << bp_name << "::" << kGetInterfaceHash << "() {\n"
353 << " std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);\n"
354 << " if (cached_hash_ == \"-1\") {\n"
355 << " ::android::Parcel data;\n"
356 << " ::android::Parcel reply;\n"
357 << " data.writeInterfaceToken(getInterfaceDescriptor());\n"
358 << " ::android::status_t err = remote()->transact("
359 << GetTransactionIdFor(bn_name, method) << ", data, &reply);\n"
360 << " if (err == ::android::OK) {\n"
361 << " ::android::binder::Status _aidl_status;\n"
362 << " err = _aidl_status.readFromParcel(reply);\n"
363 << " if (err == ::android::OK && _aidl_status.isOk()) {\n"
364 << " reply.readUtf8FromUtf16(&cached_hash_);\n"
365 << " }\n"
366 << " }\n"
367 << " }\n"
368 << " return cached_hash_;\n"
369 << "}\n";
370 }
371 }
372
373 } // namespace
374
GenerateClientSource(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)375 void GenerateClientSource(CodeWriter& out, const AidlInterface& interface,
376 const AidlTypenames& typenames, const Options& options) {
377 vector<string> include_list = {
378 HeaderFile(interface, ClassNames::CLIENT, false),
379 HeaderFile(interface, ClassNames::SERVER, false), // for TRANSACTION_* consts
380 kParcelHeader};
381 if (options.GenLog()) {
382 include_list.emplace_back("chrono");
383 include_list.emplace_back("functional");
384 }
385 for (const auto& path : include_list) {
386 out << "#include <" << path << ">\n";
387 }
388 out << "\n";
389
390 const string i_name = ClassName(interface, ClassNames::INTERFACE);
391 const string bp_name = ClassName(interface, ClassNames::CLIENT);
392 const string q_name = GetQualifiedName(interface, ClassNames::CLIENT);
393
394 EnterNamespace(out, interface);
395 out << "\n";
396
397 // The constructor just passes the IBinder instance up to the super
398 // class.
399 out << q_name << "::" << bp_name << "(const ::android::sp<::android::IBinder>& _aidl_impl)\n";
400 out << " : BpInterface<" + i_name + ">(_aidl_impl){\n";
401 out << "}\n";
402 out << "\n";
403
404 if (options.GenLog()) {
405 out << "std::function<void(const " + q_name + "::TransactionLog&)> " << q_name
406 << "::logFunc;\n";
407 out << "\n";
408 }
409
410 // Clients define a method per transaction.
411 for (const auto& method : interface.GetMethods()) {
412 if (method->IsUserDefined()) {
413 GenerateClientTransaction(out, typenames, interface, *method, options);
414 } else {
415 GenerateClientMetaTransaction(out, interface, *method, options);
416 }
417 out << "\n";
418 }
419
420 LeaveNamespace(out, interface);
421 }
422
423 namespace {
424
GenerateConstantDefinitions(CodeWriter & out,const AidlDefinedType & type,const AidlTypenames & typenames,const string & template_decl,const string & q_name)425 void GenerateConstantDefinitions(CodeWriter& out, const AidlDefinedType& type,
426 const AidlTypenames& typenames, const string& template_decl,
427 const string& q_name) {
428 for (const auto& constant : type.GetConstantDeclarations()) {
429 const AidlConstantValue& value = constant->GetValue();
430 if (value.GetType() != AidlConstantValue::Type::STRING) continue;
431
432 std::string cpp_type = CppNameOf(constant->GetType(), typenames);
433 out << template_decl;
434 out << "const " << cpp_type << "& " << q_name << "::" << constant->GetName() << "() {\n";
435 out << " static const " << cpp_type << " value("
436 << constant->ValueString(ConstantValueDecorator) << ");\n";
437 out << " return value;\n";
438 out << "}\n";
439 }
440 }
441
GenerateConstantDeclarations(CodeWriter & out,const AidlDefinedType & type,const AidlTypenames & typenames)442 void GenerateConstantDeclarations(CodeWriter& out, const AidlDefinedType& type,
443 const AidlTypenames& typenames) {
444 for (const auto& constant : type.GetConstantDeclarations()) {
445 const AidlTypeSpecifier& type = constant->GetType();
446 const auto cpp_type = CppNameOf(type, typenames);
447 if (type.Signature() == "String") {
448 out << "static const " << cpp_type << "& " << constant->GetName() << "()";
449 GenerateDeprecated(out, *constant);
450 out << ";\n";
451 } else if (type.Signature() == "float" || type.Signature() == "double") {
452 out << "static constexpr " << cpp_type << " " << constant->GetName();
453 GenerateDeprecated(out, *constant);
454 out << " = " << constant->ValueString(ConstantValueDecorator) << ";\n";
455 } else {
456 out << "enum : " << cpp_type << " { " << constant->GetName();
457 GenerateDeprecated(out, *constant);
458 out << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
459 }
460 }
461 }
462
GenerateServerTransaction(CodeWriter & out,const AidlInterface & interface,const AidlMethod & method,const AidlTypenames & typenames,const Options & options)463 void GenerateServerTransaction(CodeWriter& out, const AidlInterface& interface,
464 const AidlMethod& method, const AidlTypenames& typenames,
465 const Options& options) {
466 const string bn_name = GetQualifiedName(interface, ClassNames::SERVER);
467 if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ)) {
468 out << "if (true) {\n";
469 out << " _aidl_ret_status = ::android::UNKNOWN_TRANSACTION;\n";
470 out << " break;\n";
471 out << "}\n";
472 }
473
474 // Declare all the parameters now. In the common case, we expect no errors
475 // in serialization.
476 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
477 out.Write("%s %s;\n", CppNameOf(a->GetType(), typenames).c_str(), BuildVarName(*a).c_str());
478 }
479
480 // Declare a variable to hold the return value.
481 if (method.GetType().GetName() != "void") {
482 out.Write("%s %s;\n", CppNameOf(method.GetType(), typenames).c_str(), kReturnVarName);
483 }
484
485 // Check that the client is calling the correct interface.
486 out.Write("if (!(%s.checkInterface(this))) {\n", kDataVarName);
487 out.Write(" %s = ::android::BAD_TYPE;\n", kAndroidStatusVarName);
488 out.Write(" break;\n");
489 out.Write("}\n");
490
491 if (options.GenTraces()) {
492 out.Write(
493 "::android::binder::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppServer\");\n",
494 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str());
495 }
496
497 if (interface.EnforceExpression() || method.GetType().EnforceExpression()) {
498 out.Write("#error Permission checks not implemented for the cpp backend\n");
499 }
500
501 // Deserialize each "in" parameter to the transaction.
502 for (const auto& a : method.GetArguments()) {
503 // Deserialization looks roughly like:
504 // _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
505 // if (_aidl_ret_status != ::android::OK) { break; }
506 const string& var_name = "&" + BuildVarName(*a);
507 if (a->IsIn()) {
508 out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kDataVarName,
509 ParcelReadMethodOf(a->GetType(), typenames).c_str(),
510 ParcelReadCastOf(a->GetType(), typenames, var_name).c_str());
511 GenerateBreakOnStatusNotOk(out);
512 } else if (a->IsOut() && a->GetType().IsDynamicArray()) {
513 // Special case, the length of the out array is written into the parcel.
514 // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
515 // if (_aidl_ret_status != ::android::OK) { break; }
516 out.Write("%s = %s.resizeOutVector(%s);\n", kAndroidStatusVarName, kDataVarName,
517 var_name.c_str());
518 GenerateBreakOnStatusNotOk(out);
519 }
520 }
521
522 if (options.GenLog()) {
523 out << GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */);
524 }
525
526 if (!method.GetArguments().empty() && options.GetMinSdkVersion() >= SDK_VERSION_Tiramisu) {
527 out << "if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {\n";
528 out << " _aidl_ret_status = st.writeToParcel(_aidl_reply);\n";
529 out << " break;\n";
530 out << "}\n";
531 }
532
533 // Call the actual method. This is implemented by the subclass.
534 out.Write("%s %s(%s(%s));\n", kBinderStatusLiteral, kStatusVarName, method.GetName().c_str(),
535 GenerateArgList(typenames, method, /*for_declaration=*/false, /*type_name_only=*/false)
536 .c_str());
537
538 if (options.GenLog()) {
539 out << GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
540 true /* isServer */, false /* isNdk */);
541 }
542
543 // Write exceptions during transaction handling to parcel.
544 if (!method.IsOneway()) {
545 out.Write("%s = %s.writeToParcel(%s);\n", kAndroidStatusVarName, kStatusVarName, kReplyVarName);
546 GenerateBreakOnStatusNotOk(out);
547 out.Write("if (!%s.isOk()) {\n", kStatusVarName);
548 out.Write(" break;\n");
549 out.Write("}\n");
550 }
551
552 // If we have a return value, write it first.
553 if (method.GetType().GetName() != "void") {
554 out.Write("%s = %s->%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
555 ParcelWriteMethodOf(method.GetType(), typenames).c_str(),
556 ParcelWriteCastOf(method.GetType(), typenames, kReturnVarName).c_str());
557 GenerateBreakOnStatusNotOk(out);
558 }
559 // Write each out parameter to the reply parcel.
560 for (const AidlArgument* a : method.GetOutArguments()) {
561 // Serialization looks roughly like:
562 // _aidl_ret_status = data.WriteInt32(out_param_name);
563 // if (_aidl_ret_status != ::android::OK) { break; }
564 out.Write("%s = %s->%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
565 ParcelWriteMethodOf(a->GetType(), typenames).c_str(),
566 ParcelWriteCastOf(a->GetType(), typenames, BuildVarName(*a)).c_str());
567 GenerateBreakOnStatusNotOk(out);
568 }
569 }
570
GenerateServerMetaTransaction(CodeWriter & out,const AidlInterface & interface,const AidlMethod & method,const Options & options)571 void GenerateServerMetaTransaction(CodeWriter& out, const AidlInterface& interface,
572 const AidlMethod& method, const Options& options) {
573 AIDL_FATAL_IF(method.IsUserDefined(), method);
574
575 string iface = ClassName(interface, ClassNames::INTERFACE);
576 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
577 out << "_aidl_data.checkInterface(this);\n"
578 << "_aidl_reply->writeNoException();\n";
579 out << "_aidl_reply->writeInt32(" << iface << "::VERSION);\n";
580 }
581 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
582 out << "_aidl_data.checkInterface(this);\n"
583 << "_aidl_reply->writeNoException();\n";
584 out << "_aidl_reply->writeUtf8AsUtf16(" << iface << "::HASH);\n";
585 }
586 }
587
588 } // namespace
589
GenerateServerOnTransact(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)590 void GenerateServerOnTransact(CodeWriter& out, const AidlInterface& interface,
591 const AidlTypenames& typenames, const Options& options) {
592 const string bn_name = ClassName(interface, ClassNames::SERVER);
593 const string q_name = GetQualifiedName(interface, ClassNames::SERVER);
594
595 bool deprecated = interface.IsDeprecated() ||
596 std::any_of(interface.GetMethods().begin(), interface.GetMethods().end(),
597 [](const auto& m) { return m->IsDeprecated(); });
598 if (deprecated) {
599 out << "#pragma clang diagnostic push\n";
600 out << "#pragma clang diagnostic ignored \"-Wdeprecated\"\n";
601 out << "\n";
602 }
603
604 out.Write("%s %s::onTransact(uint32_t %s, const %s& %s, %s* %s, uint32_t %s) {\n",
605 kAndroidStatusLiteral, q_name.c_str(), kCodeVarName, kAndroidParcelLiteral,
606 kDataVarName, kAndroidParcelLiteral, kReplyVarName, kFlagsVarName);
607 out.Indent();
608 // Declare the status_t variable
609 out.Write("%s %s = %s;\n", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk);
610
611 // Add the all important switch statement
612 out.Write("switch (%s) {\n", kCodeVarName);
613
614 // The switch statement has a case statement for each transaction code.
615 for (const auto& method : interface.GetMethods()) {
616 out.Write("case %s:\n", GetTransactionIdFor(bn_name, *method).c_str());
617 out << "{\n";
618 out.Indent();
619 if (method->IsUserDefined()) {
620 GenerateServerTransaction(out, interface, *method, typenames, options);
621 } else {
622 GenerateServerMetaTransaction(out, interface, *method, options);
623 }
624 out.Dedent();
625 out << "}\n";
626 out << "break;\n";
627 }
628
629 // The switch statement has a default case which defers to the super class.
630 // The superclass handles a few pre-defined transactions.
631 out << "default:\n";
632 out << "{\n";
633 out.Write(" %s = ::android::BBinder::onTransact(%s, %s, %s, %s);\n", kAndroidStatusVarName,
634 kCodeVarName, kDataVarName, kReplyVarName, kFlagsVarName);
635 out << "}\n";
636 out << "break;\n";
637 out << "}\n"; // switch
638
639 // If we saw a null reference, we can map that to an appropriate exception.
640 out.Write("if (%s == ::android::UNEXPECTED_NULL) {\n", kAndroidStatusVarName);
641 out.Write(" %s = %s::fromExceptionCode(%s::EX_NULL_POINTER).writeOverParcel(%s);\n",
642 kAndroidStatusVarName, kBinderStatusLiteral, kBinderStatusLiteral, kReplyVarName);
643 out.Write("}\n");
644
645 // Finally, the server's onTransact method just returns a status code.
646 out.Write("return %s;\n", kAndroidStatusVarName);
647
648 out.Dedent();
649 out << "}\n";
650 out << "\n";
651
652 if (deprecated) {
653 out << "#pragma clang diagnostic pop\n";
654 out << "\n";
655 }
656 }
657
GenerateServerSource(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)658 void GenerateServerSource(CodeWriter& out, const AidlInterface& interface,
659 const AidlTypenames& typenames, const Options& options) {
660 vector<string> include_list{
661 HeaderFile(interface, ClassNames::SERVER, false),
662 kParcelHeader,
663 kStabilityHeader,
664 };
665 if (options.GenLog()) {
666 include_list.emplace_back("chrono");
667 include_list.emplace_back("functional");
668 }
669 for (const auto& include : include_list) {
670 out << "#include <" << include << ">\n";
671 }
672 out << "\n";
673
674 const string i_name = ClassName(interface, ClassNames::INTERFACE);
675 const string bn_name = ClassName(interface, ClassNames::SERVER);
676 const string q_name = GetQualifiedName(interface, ClassNames::SERVER);
677
678 EnterNamespace(out, interface);
679 out << "\n";
680
681 // constructor
682 out.Write("%s::%s()\n", q_name.c_str(), bn_name.c_str());
683 out << "{\n";
684 out.Indent();
685 if (interface.IsVintfStability()) {
686 out << "::android::internal::Stability::markVintf(this);\n";
687 } else {
688 out << "::android::internal::Stability::markCompilationUnit(this);\n";
689 }
690 out.Dedent();
691 out << "}\n";
692 out << "\n";
693
694 GenerateServerOnTransact(out, interface, typenames, options);
695
696 if (options.Version() > 0) {
697 out << "int32_t " << q_name << "::" << kGetInterfaceVersion << "() {\n"
698 << " return " << i_name << "::VERSION;\n"
699 << "}\n";
700 }
701 if (!options.Hash().empty()) {
702 out << "std::string " << q_name << "::" << kGetInterfaceHash << "() {\n"
703 << " return " << i_name << "::HASH;\n"
704 << "}\n";
705 }
706 if (options.GenLog()) {
707 out << "std::function<void(const " + q_name + "::TransactionLog&)> " << q_name
708 << "::logFunc;\n";
709 }
710
711 LeaveNamespace(out, interface);
712 }
713
GenerateInterfaceSource(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options &)714 void GenerateInterfaceSource(CodeWriter& out, const AidlInterface& interface,
715 const AidlTypenames& typenames, const Options&) {
716 out << "#include <" << HeaderFile(interface, ClassNames::RAW, false) << ">\n";
717 out << "#include <" << HeaderFile(interface, ClassNames::CLIENT, false) << ">\n";
718
719 EnterNamespace(out, interface);
720
721 if (auto parent = interface.GetParentType(); parent) {
722 out << std::format("DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE({}, {}, \"{}\")\n",
723 GetQualifiedName(*parent, ClassNames::MAYBE_INTERFACE),
724 ClassName(interface, ClassNames::BASE), interface.GetDescriptor());
725 } else {
726 out << std::format("DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE({}, \"{}\")\n",
727 ClassName(interface, ClassNames::BASE), interface.GetDescriptor());
728 }
729
730 GenerateConstantDefinitions(out, interface, typenames, /*template_decl=*/"",
731 ClassName(interface, ClassNames::INTERFACE));
732
733 LeaveNamespace(out, interface);
734 }
735
GenerateClientClassDecl(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)736 void GenerateClientClassDecl(CodeWriter& out, const AidlInterface& interface,
737 const AidlTypenames& typenames, const Options& options) {
738 const string bp_name = ClassName(interface, ClassNames::CLIENT);
739 const string iface = ClassName(interface, ClassNames::INTERFACE);
740
741 out << "class LIBBINDER_EXPORTED";
742 GenerateDeprecated(out, interface);
743 out << " " << bp_name << " : public ::android::BpInterface<" << iface << "> {\n";
744 out << "public:\n";
745 out.Indent();
746 out << "explicit " << bp_name << "(const ::android::sp<::android::IBinder>& " << kImplVarName
747 << ");\n";
748 out << "virtual ~" << bp_name << "() = default;\n";
749
750 for (const auto& method : interface.GetMethods()) {
751 if (method->IsUserDefined()) {
752 GenerateMethodDecl(out, typenames, *method, /*clazz=*/"");
753 out << " override";
754 GenerateDeprecated(out, *method);
755 out << ";\n";
756 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
757 out << "int32_t " << method->GetName() << "() override;\n";
758 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
759 out << "std::string " << method->GetName() << "() override;\n";
760 }
761 }
762
763 if (options.GenLog()) {
764 out << kTransactionLogStruct;
765 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
766 }
767 out.Dedent();
768
769 if (options.Version() > 0 || !options.Hash().empty()) {
770 out << "private:\n";
771 out.Indent();
772 if (options.Version() > 0) {
773 out << "int32_t cached_version_ = -1;\n";
774 }
775 if (!options.Hash().empty()) {
776 out << "std::string cached_hash_ = \"-1\";\n";
777 out << "std::mutex cached_hash_mutex_;\n";
778 }
779 out.Dedent();
780 }
781
782 out << "}; // class " << bp_name << "\n";
783 }
784
GenerateClientHeader(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)785 void GenerateClientHeader(CodeWriter& out, const AidlInterface& interface,
786 const AidlTypenames& typenames, const Options& options) {
787 out << "#pragma once\n\n";
788 if (!options.Hash().empty()) {
789 out << "#include <mutex>\n";
790 }
791 out << "#include <" << kIBinderHeader << ">\n";
792 out << "#include <" << kIInterfaceHeader << ">\n";
793 out << "#include <utils/Errors.h>\n";
794 out << "#include <" << HeaderFile(interface, ClassNames::RAW, false) << ">\n";
795 if (options.GenLog()) {
796 out << "#include <functional>\n"; // for std::function
797 out << "#include <android/binder_to_string.h>\n";
798 }
799 out << "\n";
800 EnterNamespace(out, interface);
801 GenerateClientClassDecl(out, interface, typenames, options);
802 LeaveNamespace(out, interface);
803 }
804
805 // Some interfaces are declared in .aidl files, but defined elsewhere.
806 // These interfaces can not have Delegators and need to be avoided.
807 // TODO(b/242920522) These should all be defined in .aidl files.
isKnownUndefinedInterface(const std::string & canonicalName)808 bool isKnownUndefinedInterface(const std::string& canonicalName) {
809 static const auto* kKnownUndefinedInterfaces = new std::set<std::string>{
810 "android.hardware.ICamera", "android.hardware.ICameraClient",
811 "android.IOMXNode", "android.IMediaExtractor",
812 "android.IDataSource",
813 };
814 return kKnownUndefinedInterfaces->find(canonicalName) != kKnownUndefinedInterfaces->end();
815 };
816
isDelegateable(const AidlTypeSpecifier & type)817 bool isDelegateable(const AidlTypeSpecifier& type) {
818 return type.GetDefinedType() && type.GetDefinedType()->AsInterface() &&
819 !isKnownUndefinedInterface(type.GetDefinedType()->GetCanonicalName()) && !type.IsArray();
820 }
821
wrapDelegate(CodeWriter & out,const std::string & argName,const AidlTypeSpecifier & type,bool in)822 void wrapDelegate(CodeWriter& out, const std::string& argName, const AidlTypeSpecifier& type,
823 bool in) {
824 const std::string argRef = in ? argName : "*" + argName;
825 const std::string targetArgName = in ? "_" + argName : argName;
826 const std::string targetArgRef = in ? targetArgName : "*" + targetArgName;
827 // input binders need local variables for each arg to pass to the delegate
828 // because the parameters are const
829 if (in) {
830 out << "::android::sp<::" << Join(type.GetSplitName(), "::") << "Delegator> " << targetArgName
831 << ";\n";
832 }
833 out << "if (" << argRef << ") {\n";
834 out.Indent();
835 out << targetArgRef << " = ::android::sp<::" << Join(type.GetSplitName(), "::")
836 << "Delegator>::cast(delegate(" << argRef << "));\n";
837 out.Dedent();
838 out << "}\n";
839 }
840
GenerateServerClassDecl(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)841 void GenerateServerClassDecl(CodeWriter& out, const AidlInterface& interface,
842 const AidlTypenames& typenames, const Options& options) {
843 const string bn_name = ClassName(interface, ClassNames::SERVER);
844 const string iface = ClassName(interface, ClassNames::INTERFACE);
845
846 out << "class LIBBINDER_EXPORTED";
847 GenerateDeprecated(out, interface);
848 out << " " << bn_name << " : public "
849 << "::android::BnInterface<" << iface << "> {\n";
850 out << "public:\n";
851 out.Indent();
852 for (const auto& method : interface.GetMethods()) {
853 out << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
854 << "::android::IBinder::FIRST_CALL_TRANSACTION + " << std::to_string(method->GetId())
855 << ";\n";
856 }
857 out << "explicit " << bn_name << "();\n";
858 out << std::format("{} onTransact(uint32_t {}, const {}& {}, {}* {}, uint32_t {}) override;\n",
859 kAndroidStatusLiteral, kCodeVarName, kAndroidParcelLiteral, kDataVarName,
860 kAndroidParcelLiteral, kReplyVarName, kFlagsVarName);
861 if (options.Version() > 0) {
862 out << "int32_t " << kGetInterfaceVersion << "();\n";
863 }
864 if (!options.Hash().empty()) {
865 out << "std::string " << kGetInterfaceHash << "();\n";
866 }
867 if (options.GenLog()) {
868 out << kTransactionLogStruct;
869 out << "static std::function<void(const TransactionLog&)> logFunc;\n";
870 }
871 out.Dedent();
872 out << "}; // class " << bn_name << "\n\n";
873
874 std::string d_name = ClassName(interface, ClassNames::DELEGATOR_IMPL);
875 out << "class LIBBINDER_EXPORTED";
876 GenerateDeprecated(out, interface);
877 out << " " << d_name << " : public " << bn_name << " {\n";
878 out << "public:\n";
879 out.Indent();
880 out << "explicit " << d_name << "("
881 << StringPrintf("const ::android::sp<%s> &impl", iface.c_str()) << ") "
882 << StringPrintf(": %s(impl)", kDelegateImplVarName) << " {}\n\n";
883 out << "::android::sp<" << iface << "> getImpl() { return " << kDelegateImplVarName << "; }\n";
884 for (const auto& method : interface.GetMethods()) {
885 if (method->IsUserDefined()) {
886 GenerateMethodDecl(out, typenames, *method, /*clazz=*/"");
887 out << " override";
888 GenerateDeprecated(out, *method);
889
890 std::vector<std::string> args;
891
892 // arg name, type
893 std::vector<pair<const std::string, const AidlTypeSpecifier&>> outBinders;
894 std::vector<pair<const std::string, const AidlTypeSpecifier&>> inBinders;
895 for (const auto& arg : method->GetArguments()) {
896 if (isDelegateable(arg->GetType())) {
897 if (arg->IsOut()) {
898 outBinders.push_back({arg->GetName(), arg->GetType()});
899 } else if (arg->IsIn()) {
900 inBinders.push_back({arg->GetName(), arg->GetType()});
901 } else {
902 AIDL_FATAL(*arg) << "inout interface?";
903 }
904 AIDL_FATAL_IF(!arg->IsIn() && !arg->IsOut(), *arg) << "Not in or out?";
905 args.push_back("_" + arg->GetName());
906 } else {
907 if (IsNonCopyableType(arg->GetType(), typenames)) {
908 args.push_back(StringPrintf("std::move(%s)", arg->GetName().c_str()));
909 } else {
910 args.push_back(arg->GetName());
911 }
912 }
913 }
914 if (method->GetType().GetName() != "void") {
915 if (isDelegateable(method->GetType())) {
916 outBinders.push_back({kReturnVarName, method->GetType()});
917 }
918 args.push_back(kReturnVarName);
919 }
920 out << " {\n";
921 out.Indent();
922 for (const auto binder : inBinders) {
923 wrapDelegate(out, binder.first, binder.second, true);
924 }
925 if (outBinders.empty()) {
926 out << "return " << kDelegateImplVarName << "->" << method->GetName() << "("
927 << base::Join(args, ", ") << ");\n";
928 } else {
929 out << "auto _status = " << kDelegateImplVarName << "->" << method->GetName() << "("
930 << base::Join(args, ", ") << ");\n";
931 for (const auto& binder : outBinders) {
932 wrapDelegate(out, binder.first, binder.second, false);
933 }
934 out << "return _status;\n";
935 }
936 out.Dedent();
937 out << "}\n";
938 } else if (method->GetName() == kGetInterfaceVersion && options.Version()) {
939 out << "int32_t " << kGetInterfaceVersion << "()"
940 << " override {\n";
941 out.Indent();
942 out << "int32_t _delegator_ver = " << bn_name << "::" << kGetInterfaceVersion << "();\n";
943 out << "int32_t _impl_ver = " << kDelegateImplVarName << "->" << kGetInterfaceVersion
944 << "();\n";
945 out << "return _delegator_ver < _impl_ver ? _delegator_ver : _impl_ver;\n";
946 out.Dedent();
947 out << "}\n";
948 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
949 out << "std::string " << kGetInterfaceHash << "()"
950 << " override {\n";
951 out << " return " << kDelegateImplVarName << "->" << kGetInterfaceHash << "();\n";
952 out << "}\n";
953 }
954 }
955 out.Dedent();
956 out << "private:\n";
957 out.Indent();
958 out << "::android::sp<" << iface << "> " << kDelegateImplVarName << ";\n";
959 out.Dedent();
960 out << "}; // class " << d_name << "\n";
961 }
962
963 // Collect all includes for the type's server header. Nested types are visited as well via
964 // VisitTopDown.
GenerateServerHeaderIncludes(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)965 void GenerateServerHeaderIncludes(CodeWriter& out, const AidlDefinedType& defined_type,
966 const AidlTypenames& typenames, const Options& options) {
967 struct Visitor : AidlVisitor {
968 const AidlTypenames& typenames;
969 const Options& options;
970 std::set<std::string> includes;
971 Visitor(const AidlTypenames& typenames, const Options& options)
972 : typenames(typenames), options(options) {}
973
974 // Collect includes for each type reference
975 void Visit(const AidlTypeSpecifier& type) override {
976 // Add Bn* header files for types used in this header. The *Delegator
977 // definitions require them.
978 const auto defined_type = type.GetDefinedType();
979 if (defined_type && defined_type->AsInterface()) {
980 if (!isKnownUndefinedInterface(defined_type->GetCanonicalName())) {
981 includes.insert(HeaderFile(*defined_type, ClassNames::SERVER, /*use_os_sep=*/false));
982 }
983 }
984 }
985
986 // Collect implementation-specific includes for each type definition
987 void Visit(const AidlInterface& iface) override {
988 includes.insert(HeaderFile(iface, ClassNames::SERVER, false));
989 }
990 } v(typenames, options);
991 VisitTopDown(v, defined_type);
992
993 v.includes.insert(kBinderDelegateHeader);
994 for (const auto& path : v.includes) {
995 out << "#include <" << path << ">\n";
996 }
997 out << "\n";
998 }
999
GenerateServerHeader(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)1000 void GenerateServerHeader(CodeWriter& out, const AidlInterface& interface,
1001 const AidlTypenames& typenames, const Options& options) {
1002 out << "#pragma once\n\n";
1003 out << "#include <binder/IInterface.h>\n";
1004 out << "#include <" << HeaderFile(interface, ClassNames::RAW, false) << ">\n";
1005 if (options.GenLog()) {
1006 out << "#include <functional>\n"; // for std::function
1007 out << "#include <android/binder_to_string.h>\n";
1008 }
1009 GenerateServerHeaderIncludes(out, interface, typenames, options);
1010 out << "\n";
1011 EnterNamespace(out, interface);
1012 GenerateServerClassDecl(out, interface, typenames, options);
1013 LeaveNamespace(out, interface);
1014 }
1015
1016 void GenerateClassDecl(CodeWriter& out, const AidlDefinedType& defined_type,
1017 const AidlTypenames& typenames, const Options& options);
1018
GenerateNestedTypeDecls(CodeWriter & out,const AidlDefinedType & type,const AidlTypenames & typenames,const Options & options)1019 void GenerateNestedTypeDecls(CodeWriter& out, const AidlDefinedType& type,
1020 const AidlTypenames& typenames, const Options& options) {
1021 auto visit = [&](const auto& nested) { GenerateClassDecl(out, nested, typenames, options); };
1022 AIDL_FATAL_IF(!TopologicalVisit(type.GetNestedTypes(), visit), type) << "Cycle detected.";
1023 }
1024
GenerateInterfaceClassDecl(CodeWriter & out,const AidlInterface & interface,const AidlTypenames & typenames,const Options & options)1025 void GenerateInterfaceClassDecl(CodeWriter& out, const AidlInterface& interface,
1026 const AidlTypenames& typenames, const Options& options) {
1027 const string i_name = ClassName(interface, ClassNames::INTERFACE);
1028 out << "class LIBBINDER_EXPORTED " << ClassName(interface, ClassNames::DELEGATOR_IMPL) << ";\n\n";
1029 out << "class LIBBINDER_EXPORTED";
1030 GenerateDeprecated(out, interface);
1031 out << " " << i_name << " : public ::android::IInterface {\n";
1032 out << "public:\n";
1033 out.Indent();
1034 out << "typedef " << ClassName(interface, ClassNames::DELEGATOR_IMPL) << " DefaultDelegator;\n";
1035 out << "DECLARE_META_INTERFACE(" << ClassName(interface, ClassNames::BASE) << ")\n";
1036 if (options.Version() > 0) {
1037 if (options.IsLatestUnfrozenVersion()) {
1038 out << kDowngradeComment;
1039 out << "static inline const int32_t VERSION = true ? "
1040 << std::to_string(options.PreviousVersion()) << " : " << std::to_string(options.Version())
1041 << ";\n";
1042 } else {
1043 out << "static inline const int32_t VERSION = " << std::to_string(options.Version()) << ";\n";
1044 }
1045 }
1046 if (!options.Hash().empty()) {
1047 if (options.IsLatestUnfrozenVersion()) {
1048 out << "static inline const std::string HASH = true ? \"" << options.PreviousHash()
1049 << "\" : \"" << options.Hash() << "\";\n";
1050 } else {
1051 out << "static inline const std::string HASH = \"" << options.Hash() << "\";\n";
1052 }
1053 }
1054 GenerateNestedTypeDecls(out, interface, typenames, options);
1055 GenerateConstantDeclarations(out, interface, typenames);
1056 for (const auto& method : interface.GetMethods()) {
1057 if (method->IsUserDefined()) {
1058 out << "virtual ";
1059 GenerateMethodDecl(out, typenames, *method, /*clazz=*/"");
1060 GenerateDeprecated(out, *method);
1061 out << " = 0;\n";
1062 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1063 out << "virtual int32_t " << method->GetName() << "() = 0;\n";
1064 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1065 out << "virtual std::string " << method->GetName() << "() = 0;\n";
1066 }
1067 }
1068 out.Dedent();
1069 out << "}; // class " << i_name << "\n";
1070 out << "\n";
1071
1072 // Implement the default impl class.
1073 const string default_impl = ClassName(interface, ClassNames::DEFAULT_IMPL);
1074 out << "class LIBBINDER_EXPORTED";
1075 GenerateDeprecated(out, interface);
1076 out << " " << default_impl << " : public " << i_name << " {\n";
1077 out << "public:\n";
1078 out.Indent();
1079 // onAsBinder returns nullptr as this interface is not associated with a
1080 // real binder.
1081 out << "::android::IBinder* onAsBinder() override {\n"
1082 << " return nullptr;\n"
1083 << "}\n";
1084
1085 // Each interface method by default returns UNKNOWN_TRANSACTION with is
1086 // the same status that is returned by transact() when the method is
1087 // not implemented in the server side. In other words, these default
1088 // methods do nothing; they only exist to aid making a real default
1089 // impl class without having to override all methods in an interface.
1090 for (const auto& method : interface.GetMethods()) {
1091 if (method->IsUserDefined()) {
1092 out << "::android::binder::Status " << method->GetName() << "("
1093 << GenerateArgList(typenames, *method, /*for_declaration=*/true, /*type_name_only=*/true)
1094 << ") override";
1095 GenerateDeprecated(out, *method);
1096 out << " {\n"
1097 << " return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
1098 << "}\n";
1099 } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1100 out << "int32_t " << kGetInterfaceVersion << "() override {\n"
1101 << " return 0;\n"
1102 << "}\n";
1103 } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1104 out << "std::string " << kGetInterfaceHash << "() override {\n"
1105 << " return \"\";\n"
1106 << "}\n";
1107 }
1108 }
1109 out.Dedent();
1110 out << "}; // class " << default_impl << "\n";
1111
1112 // When an interface is nested, every class should be defined together here
1113 // because we don't have separate headers for them.
1114 // (e.g. IFoo, IFooDefault, BpFoo, BnFoo, IFooDelegator)
1115 if (interface.GetParentType()) {
1116 GenerateClientClassDecl(out, interface, typenames, options);
1117 GenerateServerClassDecl(out, interface, typenames, options);
1118 }
1119 }
1120
GenerateReadFromParcel(CodeWriter & out,const AidlStructuredParcelable & parcel,const AidlTypenames & typenames)1121 void GenerateReadFromParcel(CodeWriter& out, const AidlStructuredParcelable& parcel,
1122 const AidlTypenames& typenames) {
1123 out << "::android::status_t _aidl_ret_status = ::android::OK;\n";
1124 out << "size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n";
1125 out << "int32_t _aidl_parcelable_raw_size = 0;\n";
1126 out << "_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);\n";
1127 out << "if (((_aidl_ret_status) != (::android::OK))) {\n";
1128 out << " return _aidl_ret_status;\n";
1129 out << "}\n";
1130 out << "if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;\n";
1131 out << "size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);\n";
1132 out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;\n";
1133 for (const auto& variable : parcel.GetFields()) {
1134 string method = ParcelReadMethodOf(variable->GetType(), typenames);
1135 string arg = ParcelReadCastOf(variable->GetType(), typenames, "&" + variable->GetName());
1136 out << "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n";
1137 out << " _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
1138 out << " return _aidl_ret_status;\n";
1139 out << "}\n";
1140 if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ)) {
1141 out << "if (false) {\n";
1142 out.Indent();
1143 }
1144 out << "_aidl_ret_status = _aidl_parcel->" << method << "(" << arg << ");\n";
1145 out << "if (((_aidl_ret_status) != (::android::OK))) {\n";
1146 out << " return _aidl_ret_status;\n";
1147 out << "}\n";
1148 if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ)) {
1149 out.Dedent();
1150 out << "}\n";
1151 }
1152 }
1153 out << "_aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
1154 out << "return _aidl_ret_status;\n";
1155 }
1156
GenerateWriteToParcel(CodeWriter & out,const AidlStructuredParcelable & parcel,const AidlTypenames & typenames)1157 void GenerateWriteToParcel(CodeWriter& out, const AidlStructuredParcelable& parcel,
1158 const AidlTypenames& typenames) {
1159 out << "::android::status_t _aidl_ret_status = ::android::OK;\n";
1160 out << "size_t _aidl_start_pos = " << kParcelVarName << "->dataPosition();\n";
1161 out << kParcelVarName << "->writeInt32(0);\n";
1162 for (const auto& variable : parcel.GetFields()) {
1163 string method = ParcelWriteMethodOf(variable->GetType(), typenames);
1164 string arg = ParcelWriteCastOf(variable->GetType(), typenames, variable->GetName());
1165 if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
1166 out << "if (false) {\n";
1167 out.Indent();
1168 }
1169 out << "_aidl_ret_status = " << kParcelVarName << "->" << method << "(" << arg << ");\n";
1170 out << "if (((_aidl_ret_status) != (::android::OK))) {\n";
1171 out << " return _aidl_ret_status;\n";
1172 out << "}\n";
1173 if (variable->IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
1174 out.Dedent();
1175 out << "}\n";
1176 }
1177 }
1178 out << "size_t _aidl_end_pos = " << kParcelVarName << "->dataPosition();\n";
1179 out << kParcelVarName << "->setDataPosition(_aidl_start_pos);\n";
1180 out << kParcelVarName << "->writeInt32(static_cast<int32_t>(_aidl_end_pos - _aidl_start_pos));\n";
1181 out << kParcelVarName << "->setDataPosition(_aidl_end_pos);\n";
1182 out << "return _aidl_ret_status;\n";
1183 }
1184
GetParcelWriterContext(const AidlTypenames & typenames)1185 ParcelWriterContext GetParcelWriterContext(const AidlTypenames& typenames) {
1186 return ParcelWriterContext{
1187 .status_type = kAndroidStatusLiteral,
1188 .status_ok = kAndroidStatusOk,
1189 .status_bad = kAndroidStatusBadValue,
1190 .read_func =
1191 [&](CodeWriter& out, const string& var, const AidlTypeSpecifier& type) {
1192 out << std::format("{}->{}({})", kParcelVarName, ParcelReadMethodOf(type, typenames),
1193 ParcelReadCastOf(type, typenames, "&" + var));
1194 },
1195 .write_func =
1196 [&](CodeWriter& out, const string& value, const AidlTypeSpecifier& type) {
1197 out << std::format("{}->{}({})", kParcelVarName, ParcelWriteMethodOf(type, typenames),
1198 ParcelWriteCastOf(type, typenames, value));
1199 },
1200 };
1201 }
1202
GenerateReadFromParcel(CodeWriter & out,const AidlUnionDecl & decl,const AidlTypenames & typenames)1203 void GenerateReadFromParcel(CodeWriter& out, const AidlUnionDecl& decl,
1204 const AidlTypenames& typenames) {
1205 UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
1206 uw.ReadFromParcel(out, GetParcelWriterContext(typenames));
1207 }
1208
GenerateWriteToParcel(CodeWriter & out,const AidlUnionDecl & decl,const AidlTypenames & typenames)1209 void GenerateWriteToParcel(CodeWriter& out, const AidlUnionDecl& decl,
1210 const AidlTypenames& typenames) {
1211 UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
1212 uw.WriteToParcel(out, GetParcelWriterContext(typenames));
1213 }
1214
GenerateParcelFields(CodeWriter & out,const AidlStructuredParcelable & decl,const AidlTypenames & typenames)1215 void GenerateParcelFields(CodeWriter& out, const AidlStructuredParcelable& decl,
1216 const AidlTypenames& typenames) {
1217 for (const auto& variable : decl.GetFields()) {
1218 const auto& type = variable->GetType();
1219 std::string cpp_type = CppNameOf(type, typenames);
1220 out << cpp_type;
1221 GenerateDeprecated(out, *variable);
1222 out << " " << variable->GetName();
1223 if (variable->GetDefaultValue()) {
1224 out << " = " << variable->ValueString(ConstantValueDecorator);
1225 } else {
1226 // Some types needs to be explicitly initialized even when no default value is set.
1227 // - ParcelableHolder should be initialized with stability
1228 // - enum should be zero initialized, otherwise the value will be indeterminate
1229 // - fixed-size arrays should be initialized, otherwise the value will be indeterminate
1230 if (type.GetName() == "ParcelableHolder") {
1231 if (decl.IsVintfStability()) {
1232 out << " { ::android::Parcelable::Stability::STABILITY_VINTF }";
1233 } else {
1234 out << " { ::android::Parcelable::Stability::STABILITY_LOCAL }";
1235 }
1236 } else if (typenames.GetEnumDeclaration(type) && !type.IsArray()) {
1237 out << " = " << cpp_type << "(0)";
1238 } else if (type.IsFixedSizeArray() && !type.IsNullable()) {
1239 out << " = {{}}";
1240 }
1241 }
1242 out << ";\n";
1243 }
1244 }
1245
GenerateParcelFields(CodeWriter & out,const AidlUnionDecl & decl,const AidlTypenames & typenames)1246 void GenerateParcelFields(CodeWriter& out, const AidlUnionDecl& decl,
1247 const AidlTypenames& typenames) {
1248 UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
1249 uw.PublicFields(out);
1250 }
1251
1252 template <typename ParcelableType>
GenerateParcelClassDecl(CodeWriter & out,const ParcelableType & parcel,const AidlTypenames & typenames,const Options & options)1253 void GenerateParcelClassDecl(CodeWriter& out, const ParcelableType& parcel,
1254 const AidlTypenames& typenames, const Options& options) {
1255 const string clazz = parcel.GetName();
1256
1257 ClangDiagnosticIgnoreDeprecated guard(out, HasDeprecatedField(parcel));
1258 out << TemplateDecl(parcel);
1259 out << "class LIBBINDER_EXPORTED";
1260 GenerateDeprecated(out, parcel);
1261 out << " " << clazz << " : public ::android::Parcelable {\n";
1262 out << "public:\n";
1263 out.Indent();
1264
1265 GenerateNestedTypeDecls(out, parcel, typenames, options);
1266 GenerateParcelFields(out, parcel, typenames);
1267 GenerateParcelableComparisonOperators(out, parcel);
1268 GenerateConstantDeclarations(out, parcel, typenames);
1269
1270 if (parcel.IsVintfStability()) {
1271 out << "::android::Parcelable::Stability getStability() const override { return "
1272 "::android::Parcelable::Stability::STABILITY_VINTF; }\n";
1273 }
1274
1275 out << kAndroidStatusLiteral << " readFromParcel(const ::android::Parcel* _aidl_parcel) final;\n";
1276 out << kAndroidStatusLiteral << " writeToParcel(::android::Parcel* _aidl_parcel) const final;\n";
1277
1278 const string canonical_name = parcel.GetCanonicalName();
1279 out << "static const ::android::String16& getParcelableDescriptor() {\n"
1280 << " static const ::android::StaticString16 DESCRIPTOR (u\"" << canonical_name << "\");\n"
1281 << " return DESCRIPTOR;\n"
1282 << "}\n";
1283
1284 GenerateToString(out, parcel);
1285
1286 out.Dedent();
1287
1288 if (auto decl = AidlCast<AidlUnionDecl>(parcel); decl) {
1289 out << "private:\n";
1290 out.Indent();
1291 UnionWriter uw{*decl, typenames, &CppNameOf, &ConstantValueDecorator};
1292 uw.PrivateFields(out);
1293 out.Dedent();
1294 }
1295
1296 out << "}; // class " << clazz << "\n";
1297 }
1298
1299 template <typename T>
GenerateParcelSource(CodeWriter & out,const T & parcel,const AidlTypenames & typenames,const Options &)1300 void GenerateParcelSource(CodeWriter& out, const T& parcel, const AidlTypenames& typenames,
1301 const Options&) {
1302 string q_name = GetQualifiedName(parcel);
1303 if (parcel.IsGeneric()) {
1304 q_name += "<" + Join(parcel.GetTypeParameters(), ",") + ">";
1305 }
1306
1307 out << "#include <" << CppHeaderForType(parcel) << ">\n\n";
1308
1309 EnterNamespace(out, parcel);
1310 GenerateConstantDefinitions(out, parcel, typenames, TemplateDecl(parcel), q_name);
1311
1312 {
1313 ClangDiagnosticIgnoreDeprecated guard(out, HasDeprecatedField(parcel));
1314 out << TemplateDecl(parcel);
1315 out << "::android::status_t " << q_name << "::readFromParcel(const ::android::Parcel* "
1316 << kParcelVarName << ") {\n";
1317 out.Indent();
1318 GenerateReadFromParcel(out, parcel, typenames);
1319 out.Dedent();
1320 out << "}\n";
1321
1322 out << TemplateDecl(parcel);
1323 out << "::android::status_t " << q_name << "::writeToParcel(::android::Parcel* "
1324 << kParcelVarName << ") const {\n";
1325 out.Indent();
1326 GenerateWriteToParcel(out, parcel, typenames);
1327 out.Dedent();
1328 out << "}\n";
1329 }
1330 LeaveNamespace(out, parcel);
1331 }
1332
GenerateEnumClassDecl(CodeWriter & out,const AidlEnumDeclaration & enum_decl,const AidlTypenames & typenames)1333 void GenerateEnumClassDecl(CodeWriter& out, const AidlEnumDeclaration& enum_decl,
1334 const AidlTypenames& typenames) {
1335 cpp::GenerateEnumClassDecl(out, enum_decl, CppNameOf(enum_decl.GetBackingType(), typenames),
1336 ConstantValueDecorator);
1337 }
1338
GenerateClassDecl(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1339 void GenerateClassDecl(CodeWriter& out, const AidlDefinedType& defined_type,
1340 const AidlTypenames& typenames, const Options& options) {
1341 if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
1342 GenerateInterfaceClassDecl(out, *iface, typenames, options);
1343 } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
1344 GenerateParcelClassDecl(out, *parcelable, typenames, options);
1345 } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
1346 GenerateParcelClassDecl(out, *union_decl, typenames, options);
1347 } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
1348 GenerateEnumClassDecl(out, *enum_decl, typenames);
1349 } else {
1350 AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
1351 }
1352 }
1353
1354 } // namespace internals
1355
1356 using namespace internals;
1357
1358 // Collect all includes for the type's header. Nested types are visited as well via VisitTopDown.
GenerateHeaderIncludes(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1359 void GenerateHeaderIncludes(CodeWriter& out, const AidlDefinedType& defined_type,
1360 const AidlTypenames& typenames, const Options& options) {
1361 struct Visitor : AidlVisitor {
1362 const AidlTypenames& typenames;
1363 const Options& options;
1364 std::set<std::string> includes;
1365 Visitor(const AidlTypenames& typenames, const Options& options)
1366 : typenames(typenames), options(options) {}
1367
1368 // Collect includes for each type reference including built-in type
1369 void Visit(const AidlTypeSpecifier& type) override {
1370 cpp::AddHeaders(type, typenames, &includes);
1371 }
1372
1373 // Collect implementation-specific includes for each type definition
1374 void Visit(const AidlInterface& iface) override {
1375 includes.insert(kIBinderHeader); // IBinder
1376 includes.insert(kIInterfaceHeader); // IInterface
1377 includes.insert(kStatusHeader); // Status
1378 includes.insert(kStrongPointerHeader); // sp<>
1379
1380 if (options.GenTraces()) {
1381 includes.insert(kTraceHeader);
1382 }
1383
1384 // For a nested interface, client/server classes are declared the same header as well.
1385 if (iface.GetParentType()) {
1386 includes.insert(kBinderDelegateHeader); // Delegate.h
1387 // client/server class provides logFunc when gen_log is on
1388 if (options.GenLog()) {
1389 includes.insert("functional"); // std::function for logFunc
1390 includes.insert("android/binder_to_string.h"); // Generic ToString helper
1391 }
1392 }
1393 }
1394
1395 void Visit(const AidlStructuredParcelable&) override {
1396 AddParcelableCommonHeaders();
1397 includes.insert("tuple"); // std::tie in comparison operators
1398 }
1399
1400 void Visit(const AidlUnionDecl& union_decl) override {
1401 AddParcelableCommonHeaders();
1402 auto union_headers = cpp::UnionWriter::GetHeaders(union_decl);
1403 includes.insert(std::begin(union_headers), std::end(union_headers));
1404 }
1405
1406 void Visit(const AidlEnumDeclaration&) override {
1407 includes.insert("array"); // used in enum_values
1408 includes.insert("binder/Enums.h"); // provides enum_range
1409 includes.insert("string"); // toString() returns std::string
1410 }
1411
1412 void AddParcelableCommonHeaders() {
1413 includes.insert(kParcelHeader); // Parcel in readFromParcel/writeToParcel
1414 includes.insert(kStatusHeader); // Status
1415 includes.insert(kString16Header); // String16 in getParcelableDescriptor
1416 includes.insert("android/binder_to_string.h"); // toString()
1417 }
1418 } v(typenames, options);
1419 VisitTopDown(v, defined_type);
1420
1421 for (const auto& path : v.includes) {
1422 out << "#include <" << path << ">\n";
1423 }
1424 out << "\n";
1425 if (v.includes.count("cassert")) {
1426 // TODO(b/31559095) bionic on host should define __assert2
1427 out << "#ifndef __BIONIC__\n#define __assert2(a,b,c,d) ((void)0)\n#endif\n\n";
1428 }
1429 }
1430
1431 // Generic parcelables and enum utilities should be defined in header.
GenerateHeaderDefinitions(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1432 void GenerateHeaderDefinitions(CodeWriter& out, const AidlDefinedType& defined_type,
1433 const AidlTypenames& typenames, const Options& options) {
1434 struct Visitor : AidlVisitor {
1435 CodeWriter& out;
1436 const AidlTypenames& typenames;
1437 const Options& options;
1438 Visitor(CodeWriter& out, const AidlTypenames& typenames, const Options& options)
1439 : out(out), typenames(typenames), options(options) {}
1440
1441 void Visit(const AidlEnumDeclaration& enum_decl) override {
1442 const auto backing_type = CppNameOf(enum_decl.GetBackingType(), typenames);
1443 EnterNamespace(out, enum_decl);
1444 out << GenerateEnumToString(enum_decl, backing_type);
1445 LeaveNamespace(out, enum_decl);
1446
1447 out << "namespace android {\n";
1448 out << "namespace internal {\n";
1449 out << GenerateEnumValues(enum_decl, {""});
1450 out << "} // namespace internal\n";
1451 out << "} // namespace android\n";
1452 }
1453
1454 void Visit(const AidlStructuredParcelable& parcelable) override {
1455 if (parcelable.IsGeneric()) {
1456 GenerateParcelSource(out, parcelable, typenames, options);
1457 }
1458 }
1459
1460 void Visit(const AidlUnionDecl& union_decl) override {
1461 if (union_decl.IsGeneric()) {
1462 GenerateParcelSource(out, union_decl, typenames, options);
1463 }
1464 }
1465
1466 } v(out, typenames, options);
1467 VisitTopDown(v, defined_type);
1468 }
1469
GenerateHeader(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1470 void GenerateHeader(CodeWriter& out, const AidlDefinedType& defined_type,
1471 const AidlTypenames& typenames, const Options& options) {
1472 if (auto parcelable = AidlCast<AidlParcelable>(defined_type); parcelable) {
1473 out << "#error TODO(b/111362593) parcelables do not have headers";
1474 return;
1475 }
1476 out << "#pragma once\n\n";
1477 GenerateHeaderIncludes(out, defined_type, typenames, options);
1478 GenerateForwardDecls(out, defined_type, false);
1479 EnterNamespace(out, defined_type);
1480 // Each class decl contains its own nested types' class decls
1481 GenerateClassDecl(out, defined_type, typenames, options);
1482 LeaveNamespace(out, defined_type);
1483 GenerateHeaderDefinitions(out, defined_type, typenames, options);
1484 }
1485
GenerateClientHeader(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1486 void GenerateClientHeader(CodeWriter& out, const AidlDefinedType& defined_type,
1487 const AidlTypenames& typenames, const Options& options) {
1488 if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
1489 GenerateClientHeader(out, *iface, typenames, options);
1490 } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
1491 out << "#error TODO(b/111362593) parcelables do not have bp classes";
1492 } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
1493 out << "#error TODO(b/111362593) parcelables do not have bp classes";
1494 } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
1495 out << "#error TODO(b/111362593) enums do not have bp classes";
1496 } else if (auto parcelable = AidlCast<AidlParcelable>(defined_type); parcelable) {
1497 out << "#error TODO(b/111362593) parcelables do not have bp classes";
1498 } else {
1499 AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
1500 }
1501 }
1502
GenerateServerHeader(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1503 void GenerateServerHeader(CodeWriter& out, const AidlDefinedType& defined_type,
1504 const AidlTypenames& typenames, const Options& options) {
1505 if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
1506 GenerateServerHeader(out, *iface, typenames, options);
1507 } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
1508 out << "#error TODO(b/111362593) parcelables do not have bn classes";
1509 } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
1510 out << "#error TODO(b/111362593) parcelables do not have bn classes";
1511 } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
1512 out << "#error TODO(b/111362593) enums do not have bn classes";
1513 } else if (auto parcelable = AidlCast<AidlParcelable>(defined_type); parcelable) {
1514 out << "#error TODO(b/111362593) parcelables do not have bn classes";
1515 } else {
1516 AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
1517 }
1518 }
1519
GenerateSource(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)1520 void GenerateSource(CodeWriter& out, const AidlDefinedType& defined_type,
1521 const AidlTypenames& typenames, const Options& options) {
1522 struct Visitor : AidlVisitor {
1523 CodeWriter& out;
1524 const AidlTypenames& typenames;
1525 const Options& options;
1526 Visitor(CodeWriter& out, const AidlTypenames& typenames, const Options& options)
1527 : out(out), typenames(typenames), options(options) {}
1528
1529 void Visit(const AidlInterface& interface) override {
1530 GenerateInterfaceSource(out, interface, typenames, options);
1531 GenerateClientSource(out, interface, typenames, options);
1532 GenerateServerSource(out, interface, typenames, options);
1533 }
1534
1535 void Visit(const AidlStructuredParcelable& parcelable) override {
1536 if (!parcelable.IsGeneric()) {
1537 GenerateParcelSource(out, parcelable, typenames, options);
1538 } else {
1539 out << "\n";
1540 }
1541 }
1542
1543 void Visit(const AidlUnionDecl& union_decl) override {
1544 if (!union_decl.IsGeneric()) {
1545 GenerateParcelSource(out, union_decl, typenames, options);
1546 } else {
1547 out << "\n";
1548 }
1549 }
1550
1551 void Visit(const AidlEnumDeclaration& enum_decl) override {
1552 if (!enum_decl.GetParentType()) {
1553 out << "// This file is intentionally left blank as placeholder for enum declaration.\n";
1554 }
1555 }
1556
1557 void Visit(const AidlParcelable& parcelable) override {
1558 AIDL_FATAL_IF(parcelable.GetParentType(), parcelable)
1559 << "Unstructured parcelable can't be nested.";
1560 out << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
1561 }
1562 } v(out, typenames, options);
1563 VisitTopDown(v, defined_type);
1564 }
1565
GenerateCpp(const string & output_file,const Options & options,const AidlTypenames & typenames,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)1566 bool GenerateCpp(const string& output_file, const Options& options, const AidlTypenames& typenames,
1567 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
1568 if (!ValidateOutputFilePath(output_file, options, defined_type)) {
1569 return false;
1570 }
1571
1572 using GenFn = void (*)(CodeWriter& out, const AidlDefinedType& defined_type,
1573 const AidlTypenames& typenames, const Options& options);
1574 // Wrap Generate* function to handle CodeWriter for a file.
1575 auto gen = [&](auto file, GenFn fn) {
1576 unique_ptr<CodeWriter> writer(io_delegate.GetCodeWriter(file));
1577
1578 GenerateAutoGenHeader(*writer, options);
1579
1580 fn(*writer, defined_type, typenames, options);
1581 AIDL_FATAL_IF(!writer->Close(), defined_type) << "I/O Error!";
1582 return true;
1583 };
1584
1585 return gen(options.OutputHeaderDir() + HeaderFile(defined_type, ClassNames::RAW),
1586 &GenerateHeader) &&
1587 gen(options.OutputHeaderDir() + HeaderFile(defined_type, ClassNames::CLIENT),
1588 &GenerateClientHeader) &&
1589 gen(options.OutputHeaderDir() + HeaderFile(defined_type, ClassNames::SERVER),
1590 &GenerateServerHeader) &&
1591 gen(output_file, &GenerateSource);
1592 }
1593
1594 } // namespace cpp
1595 } // namespace aidl
1596 } // namespace android
1597