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