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