• 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 <cctype>
21 #include <cstring>
22 #include <memory>
23 #include <random>
24 #include <set>
25 #include <string>
26 
27 #include <android-base/stringprintf.h>
28 
29 #include "aidl_language.h"
30 #include "aidl_to_cpp.h"
31 #include "ast_cpp.h"
32 #include "code_writer.h"
33 #include "logging.h"
34 #include "os.h"
35 
36 using android::base::Join;
37 using android::base::StringPrintf;
38 using std::set;
39 using std::string;
40 using std::unique_ptr;
41 using std::vector;
42 
43 namespace android {
44 namespace aidl {
45 namespace cpp {
46 namespace internals {
47 namespace {
48 
49 const char kAndroidStatusVarName[] = "_aidl_ret_status";
50 const char kCodeVarName[] = "_aidl_code";
51 const char kFlagsVarName[] = "_aidl_flags";
52 const char kDataVarName[] = "_aidl_data";
53 const char kErrorLabel[] = "_aidl_error";
54 const char kImplVarName[] = "_aidl_impl";
55 const char kReplyVarName[] = "_aidl_reply";
56 const char kReturnVarName[] = "_aidl_return";
57 const char kStatusVarName[] = "_aidl_status";
58 const char kTraceVarName[] = "_aidl_trace";
59 const char kAndroidParcelLiteral[] = "::android::Parcel";
60 const char kAndroidStatusLiteral[] = "::android::status_t";
61 const char kAndroidStatusOk[] = "::android::OK";
62 const char kBinderStatusLiteral[] = "::android::binder::Status";
63 const char kIBinderHeader[] = "binder/IBinder.h";
64 const char kIInterfaceHeader[] = "binder/IInterface.h";
65 const char kParcelHeader[] = "binder/Parcel.h";
66 const char kStatusHeader[] = "binder/Status.h";
67 const char kString16Header[] = "utils/String16.h";
68 const char kTraceHeader[] = "utils/Trace.h";
69 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
70 const char kAndroidBaseMacrosHeader[] = "android-base/macros.h";
71 
BreakOnStatusNotOk()72 unique_ptr<AstNode> BreakOnStatusNotOk() {
73   IfStatement* ret = new IfStatement(new Comparison(
74       new LiteralExpression(kAndroidStatusVarName), "!=",
75       new LiteralExpression(kAndroidStatusOk)));
76   ret->OnTrue()->AddLiteral("break");
77   return unique_ptr<AstNode>(ret);
78 }
79 
GotoErrorOnBadStatus()80 unique_ptr<AstNode> GotoErrorOnBadStatus() {
81   IfStatement* ret = new IfStatement(new Comparison(
82       new LiteralExpression(kAndroidStatusVarName), "!=",
83       new LiteralExpression(kAndroidStatusOk)));
84   ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
85   return unique_ptr<AstNode>(ret);
86 }
87 
ReturnOnStatusNotOk()88 unique_ptr<AstNode> ReturnOnStatusNotOk() {
89   IfStatement* ret = new IfStatement(new Comparison(new LiteralExpression(kAndroidStatusVarName),
90                                                     "!=", new LiteralExpression(kAndroidStatusOk)));
91   ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
92   return unique_ptr<AstNode>(ret);
93 }
94 
BuildArgList(const TypeNamespace & types,const AidlMethod & method,bool for_declaration,bool type_name_only=false)95 ArgList BuildArgList(const TypeNamespace& types, const AidlMethod& method, bool for_declaration,
96                      bool type_name_only = false) {
97   // Build up the argument list for the server method call.
98   vector<string> method_arguments;
99   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
100     string literal;
101     if (for_declaration) {
102       // Method declarations need types, pointers to out params, and variable
103       // names that match the .aidl specification.
104       const Type* type = a->GetType().GetLanguageType<Type>();
105 
106       literal = type->CppType();
107 
108       if (a->IsOut()) {
109         literal = literal + "*";
110       } else {
111         // We pass in parameters that are not primitives by const reference.
112         // Arrays of primitives are not primitives.
113         if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
114           literal = "const " + literal + "&";
115         }
116       }
117       if (!type_name_only) {
118         literal += " " + a->GetName();
119       }
120     } else {
121       if (a->IsOut()) { literal = "&"; }
122       literal += BuildVarName(*a);
123     }
124     method_arguments.push_back(literal);
125   }
126 
127   const Type* return_type = method.GetType().GetLanguageType<Type>();
128 
129   if (return_type != types.VoidType()) {
130     string literal;
131     if (for_declaration) {
132       literal = StringPrintf("%s* %s", return_type->CppType().c_str(),
133                              type_name_only ? "" : kReturnVarName);
134     } else {
135       literal = string{"&"} + kReturnVarName;
136     }
137     method_arguments.push_back(literal);
138   }
139 
140   return ArgList(method_arguments);
141 }
142 
BuildMethodDecl(const AidlMethod & method,const TypeNamespace & types,bool for_interface)143 unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
144                                         const TypeNamespace& types,
145                                         bool for_interface) {
146   uint32_t modifiers = 0;
147   if (for_interface) {
148     modifiers |= MethodDecl::IS_VIRTUAL;
149     modifiers |= MethodDecl::IS_PURE_VIRTUAL;
150   } else {
151     modifiers |= MethodDecl::IS_OVERRIDE;
152   }
153 
154   return unique_ptr<Declaration>{
155       new MethodDecl{kBinderStatusLiteral,
156                      method.GetName(),
157                      BuildArgList(types, method, true /* for method decl */),
158                      modifiers}};
159 }
160 
BuildMetaMethodDecl(const AidlMethod & method,const TypeNamespace &,const Options & options,bool for_interface)161 unique_ptr<Declaration> BuildMetaMethodDecl(const AidlMethod& method, const TypeNamespace&,
162                                             const Options& options, bool for_interface) {
163   CHECK(!method.IsUserDefined());
164   if (method.GetName() == kGetInterfaceVersion && options.Version()) {
165     std::ostringstream code;
166     if (for_interface) {
167       code << "virtual ";
168     }
169     code << "int32_t " << kGetInterfaceVersion << "()";
170     if (for_interface) {
171       code << " = 0;\n";
172     } else {
173       code << " override;\n";
174     }
175     return unique_ptr<Declaration>(new LiteralDecl(code.str()));
176   }
177   return nullptr;
178 }
179 
NestInNamespaces(vector<unique_ptr<Declaration>> decls,const vector<string> & package)180 std::vector<unique_ptr<Declaration>> NestInNamespaces(vector<unique_ptr<Declaration>> decls,
181                                                       const vector<string>& package) {
182   auto it = package.crbegin();  // Iterate over the namespaces inner to outer
183   for (; it != package.crend(); ++it) {
184     vector<unique_ptr<Declaration>> inner;
185     inner.emplace_back(unique_ptr<Declaration>{new CppNamespace{*it, std::move(decls)}});
186 
187     decls = std::move(inner);
188   }
189   return decls;
190 }
191 
NestInNamespaces(unique_ptr<Declaration> decl,const vector<string> & package)192 std::vector<unique_ptr<Declaration>> NestInNamespaces(unique_ptr<Declaration> decl,
193                                                       const vector<string>& package) {
194   vector<unique_ptr<Declaration>> decls;
195   decls.push_back(std::move(decl));
196   return NestInNamespaces(std::move(decls), package);
197 }
198 
DeclareLocalVariable(const AidlArgument & a,StatementBlock * b)199 bool DeclareLocalVariable(const AidlArgument& a, StatementBlock* b) {
200   const Type* cpp_type = a.GetType().GetLanguageType<Type>();
201   if (!cpp_type) { return false; }
202 
203   string type = cpp_type->CppType();
204 
205   b->AddLiteral(type + " " + BuildVarName(a));
206   return true;
207 }
208 
BuildHeaderGuard(const AidlDefinedType & defined_type,ClassNames header_type)209 string BuildHeaderGuard(const AidlDefinedType& defined_type, ClassNames header_type) {
210   string class_name = ClassName(defined_type, header_type);
211   for (size_t i = 1; i < class_name.size(); ++i) {
212     if (isupper(class_name[i])) {
213       class_name.insert(i, "_");
214       ++i;
215     }
216   }
217   string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_", defined_type.GetPackage().c_str(),
218                             class_name.c_str());
219   for (char& c : ret) {
220     if (c == '.') {
221       c = '_';
222     }
223     c = toupper(c);
224   }
225   return ret;
226 }
227 
DefineClientTransaction(const TypeNamespace & types,const AidlInterface & interface,const AidlMethod & method,const Options & options)228 unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
229                                                 const AidlInterface& interface,
230                                                 const AidlMethod& method, const Options& options) {
231   const string i_name = ClassName(interface, ClassNames::INTERFACE);
232   const string bp_name = ClassName(interface, ClassNames::CLIENT);
233   unique_ptr<MethodImpl> ret{new MethodImpl{
234       kBinderStatusLiteral, bp_name, method.GetName(),
235       ArgList{BuildArgList(types, method, true /* for method decl */)}}};
236   StatementBlock* b = ret->GetStatementBlock();
237 
238   // Declare parcels to hold our query and the response.
239   b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
240   // Even if we're oneway, the transact method still takes a parcel.
241   b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
242 
243   // Declare the status_t variable we need for error handling.
244   b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
245                              kAndroidStatusVarName,
246                              kAndroidStatusOk));
247   // We unconditionally return a Status object.
248   b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
249 
250   if (options.GenTraces()) {
251     b->AddLiteral(
252         StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
253         kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
254   }
255 
256   if (options.GenLog()) {
257     b->AddLiteral(GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */),
258                   false /* no semicolon */);
259   }
260 
261   // Add the name of the interface we're hoping to call.
262   b->AddStatement(new Assignment(
263       kAndroidStatusVarName,
264       new MethodCall(StringPrintf("%s.writeInterfaceToken",
265                                   kDataVarName),
266                      "getInterfaceDescriptor()")));
267   b->AddStatement(GotoErrorOnBadStatus());
268 
269   for (const auto& a: method.GetArguments()) {
270     const Type* type = a->GetType().GetLanguageType<Type>();
271     string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
272     var_name = type->WriteCast(var_name);
273 
274     if (a->IsIn()) {
275       // Serialization looks roughly like:
276       //     _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
277       //     if (_aidl_ret_status != ::android::OK) { goto error; }
278       const string& method = type->WriteToParcelMethod();
279       b->AddStatement(new Assignment(
280           kAndroidStatusVarName,
281           new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
282                          ArgList(var_name))));
283       b->AddStatement(GotoErrorOnBadStatus());
284     } else if (a->IsOut() && a->GetType().IsArray()) {
285       // Special case, the length of the out array is written into the parcel.
286       //     _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
287       //     if (_aidl_ret_status != ::android::OK) { goto error; }
288       b->AddStatement(new Assignment(
289           kAndroidStatusVarName,
290           new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
291                          ArgList(var_name))));
292       b->AddStatement(GotoErrorOnBadStatus());
293     }
294   }
295 
296   // Invoke the transaction on the remote binder and confirm status.
297   string transaction_code = GetTransactionIdFor(method);
298 
299   vector<string> args = {transaction_code, kDataVarName,
300                          StringPrintf("&%s", kReplyVarName)};
301 
302   if (method.IsOneway()) {
303     args.push_back("::android::IBinder::FLAG_ONEWAY");
304   }
305 
306   b->AddStatement(new Assignment(
307       kAndroidStatusVarName,
308       new MethodCall("remote()->transact",
309                      ArgList(args))));
310 
311   // If the method is not implemented in the remote side, try to call the
312   // default implementation, if provided.
313   vector<string> arg_names;
314   for (const auto& a : method.GetArguments()) {
315     arg_names.emplace_back(a->GetName());
316   }
317   if (method.GetType().GetLanguageType<Type>() != types.VoidType()) {
318     arg_names.emplace_back(kReturnVarName);
319   }
320   b->AddLiteral(StringPrintf("if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && "
321                              "%s::getDefaultImpl())) {\n"
322                              "   return %s::getDefaultImpl()->%s(%s);\n"
323                              "}\n",
324                              i_name.c_str(), i_name.c_str(), method.GetName().c_str(),
325                              Join(arg_names, ", ").c_str()),
326                 false /* no semicolon */);
327 
328   b->AddStatement(GotoErrorOnBadStatus());
329 
330   if (!method.IsOneway()) {
331     // Strip off the exception header and fail if we see a remote exception.
332     // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
333     // if (_aidl_ret_status != ::android::OK) { goto error; }
334     // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
335     b->AddStatement(new Assignment(
336         kAndroidStatusVarName,
337         StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
338     b->AddStatement(GotoErrorOnBadStatus());
339     IfStatement* exception_check = new IfStatement(
340         new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
341     b->AddStatement(exception_check);
342     exception_check->OnTrue()->AddLiteral(
343         StringPrintf("return %s", kStatusVarName));
344   }
345 
346   // Type checking should guarantee that nothing below emits code until "return
347   // status" if we are a oneway method, so no more fear of accessing reply.
348 
349   // If the method is expected to return something, read it first by convention.
350   const Type* return_type = method.GetType().GetLanguageType<Type>();
351   if (return_type != types.VoidType()) {
352     const string& method_call = return_type->ReadFromParcelMethod();
353     b->AddStatement(new Assignment(
354         kAndroidStatusVarName,
355         new MethodCall(StringPrintf("%s.%s", kReplyVarName,
356                                     method_call.c_str()),
357                        ArgList(kReturnVarName))));
358     b->AddStatement(GotoErrorOnBadStatus());
359   }
360 
361   for (const AidlArgument* a : method.GetOutArguments()) {
362     // Deserialization looks roughly like:
363     //     _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
364     //     if (_aidl_status != ::android::OK) { goto _aidl_error; }
365     string method =
366       a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
367 
368     b->AddStatement(new Assignment(
369         kAndroidStatusVarName,
370         new MethodCall(StringPrintf("%s.%s", kReplyVarName,
371                                     method.c_str()),
372                        ArgList(a->GetName()))));
373     b->AddStatement(GotoErrorOnBadStatus());
374   }
375 
376   // If we've gotten to here, one of two things is true:
377   //   1) We've read some bad status_t
378   //   2) We've only read status_t == OK and there was no exception in the
379   //      response.
380   // In both cases, we're free to set Status from the status_t and return.
381   b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
382   b->AddLiteral(
383       StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
384                    kAndroidStatusVarName));
385 
386   if (options.GenLog()) {
387     b->AddLiteral(GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
388                                      false /* isServer */, false /* isNdk */),
389                   false /* no semicolon */);
390   }
391 
392   b->AddLiteral(StringPrintf("return %s", kStatusVarName));
393 
394   return unique_ptr<Declaration>(ret.release());
395 }
396 
DefineClientMetaTransaction(const TypeNamespace &,const AidlInterface & interface,const AidlMethod & method,const Options & options)397 unique_ptr<Declaration> DefineClientMetaTransaction(const TypeNamespace&,
398                                                     const AidlInterface& interface,
399                                                     const AidlMethod& method,
400                                                     const Options& options) {
401   CHECK(!method.IsUserDefined());
402   if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
403     const string iface = ClassName(interface, ClassNames::INTERFACE);
404     const string proxy = ClassName(interface, ClassNames::CLIENT);
405     // Note: race condition can happen here, but no locking is required
406     // because 1) writing an interger is atomic and 2) this transaction
407     // will always return the same value, i.e., competing threads will
408     // give write the same value to cached_version_.
409     std::ostringstream code;
410     code << "int32_t " << proxy << "::" << kGetInterfaceVersion << "() {\n"
411          << "  if (cached_version_ == -1) {\n"
412          << "    ::android::Parcel data;\n"
413          << "    ::android::Parcel reply;\n"
414          << "    data.writeInterfaceToken(getInterfaceDescriptor());\n"
415          << "    ::android::status_t err = remote()->transact(" << GetTransactionIdFor(method)
416          << ", data, &reply);\n"
417          << "    if (err == ::android::OK) {\n"
418          << "      ::android::binder::Status _aidl_status;\n"
419          << "      err = _aidl_status.readFromParcel(reply);\n"
420          << "      if (err == ::android::OK && _aidl_status.isOk()) {\n"
421          << "        cached_version_ = reply.readInt32();\n"
422          << "      }\n"
423          << "    }\n"
424          << "  }\n"
425          << "  return cached_version_;\n"
426          << "}\n";
427     return unique_ptr<Declaration>(new LiteralDecl(code.str()));
428   }
429   return nullptr;
430 }
431 
432 }  // namespace
433 
BuildClientSource(const TypeNamespace & types,const AidlInterface & interface,const Options & options)434 unique_ptr<Document> BuildClientSource(const TypeNamespace& types, const AidlInterface& interface,
435                                        const Options& options) {
436   vector<string> include_list = {
437       HeaderFile(interface, ClassNames::CLIENT, false),
438       kParcelHeader,
439       kAndroidBaseMacrosHeader
440   };
441   if (options.GenLog()) {
442     include_list.emplace_back("chrono");
443     include_list.emplace_back("functional");
444     include_list.emplace_back("json/value.h");
445   }
446   vector<unique_ptr<Declaration>> file_decls;
447 
448   // The constructor just passes the IBinder instance up to the super
449   // class.
450   const string i_name = ClassName(interface, ClassNames::INTERFACE);
451   file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
452       ClassName(interface, ClassNames::CLIENT),
453       ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
454                            kImplVarName)},
455       { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
456 
457   if (options.GenLog()) {
458     string code;
459     ClassName(interface, ClassNames::CLIENT);
460     CodeWriterPtr writer = CodeWriter::ForString(&code);
461     (*writer) << "std::function<void(const Json::Value&)> "
462               << ClassName(interface, ClassNames::CLIENT) << "::logFunc;\n";
463     writer->Close();
464     file_decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
465   }
466 
467   // Clients define a method per transaction.
468   for (const auto& method : interface.GetMethods()) {
469     unique_ptr<Declaration> m;
470     if (method->IsUserDefined()) {
471       m = DefineClientTransaction(types, interface, *method, options);
472     } else {
473       m = DefineClientMetaTransaction(types, interface, *method, options);
474     }
475     if (!m) { return nullptr; }
476     file_decls.push_back(std::move(m));
477   }
478   return unique_ptr<Document>{new CppSource{
479       include_list,
480       NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
481 }
482 
483 namespace {
484 
HandleServerTransaction(const TypeNamespace & types,const AidlInterface & interface,const AidlMethod & method,const Options & options,StatementBlock * b)485 bool HandleServerTransaction(const TypeNamespace& types, const AidlInterface& interface,
486                              const AidlMethod& method, const Options& options, StatementBlock* b) {
487   // Declare all the parameters now.  In the common case, we expect no errors
488   // in serialization.
489   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
490     if (!DeclareLocalVariable(*a, b)) {
491       return false;
492     }
493   }
494 
495   // Declare a variable to hold the return value.
496   const Type* return_type = method.GetType().GetLanguageType<Type>();
497   if (return_type != types.VoidType()) {
498     b->AddLiteral(StringPrintf(
499         "%s %s", return_type->CppType().c_str(),
500         kReturnVarName));
501   }
502 
503   // Check that the client is calling the correct interface.
504   IfStatement* interface_check = new IfStatement(
505       new MethodCall(StringPrintf("%s.checkInterface",
506                                   kDataVarName), "this"),
507       true /* invert the check */);
508   b->AddStatement(interface_check);
509   interface_check->OnTrue()->AddStatement(
510       new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
511   interface_check->OnTrue()->AddLiteral("break");
512 
513   // Deserialize each "in" parameter to the transaction.
514   for (const auto& a: method.GetArguments()) {
515     // Deserialization looks roughly like:
516     //     _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
517     //     if (_aidl_ret_status != ::android::OK) { break; }
518     const Type* type = a->GetType().GetLanguageType<Type>();
519     const string& readMethod = type->ReadFromParcelMethod();
520 
521     if (a->IsIn()) {
522       b->AddStatement(new Assignment{
523           kAndroidStatusVarName,
524           new MethodCall{string(kDataVarName) + "." + readMethod,
525                          "&" + BuildVarName(*a)}});
526       b->AddStatement(BreakOnStatusNotOk());
527     } else if (a->IsOut() && a->GetType().IsArray()) {
528       // Special case, the length of the out array is written into the parcel.
529       //     _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
530       //     if (_aidl_ret_status != ::android::OK) { break; }
531       b->AddStatement(new Assignment{
532           kAndroidStatusVarName,
533           new MethodCall{string(kDataVarName) + ".resizeOutVector",
534                          "&" + BuildVarName(*a)}});
535       b->AddStatement(BreakOnStatusNotOk());
536     }
537   }
538 
539   if (options.GenTraces()) {
540     b->AddStatement(new Statement(new MethodCall("atrace_begin",
541         ArgList{{"ATRACE_TAG_AIDL",
542         StringPrintf("\"%s::%s::cppServer\"",
543                      interface.GetName().c_str(),
544                      method.GetName().c_str())}})));
545   }
546   const string bn_name = ClassName(interface, ClassNames::SERVER);
547   if (options.GenLog()) {
548     b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
549                   false);
550   }
551   // Call the actual method.  This is implemented by the subclass.
552   vector<unique_ptr<AstNode>> status_args;
553   status_args.emplace_back(new MethodCall(
554           method.GetName(),
555           BuildArgList(types, method, false /* not for method decl */)));
556   b->AddStatement(new Statement(new MethodCall(
557       StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
558       ArgList(std::move(status_args)))));
559 
560   if (options.GenTraces()) {
561     b->AddStatement(new Statement(new MethodCall("atrace_end",
562                                                  "ATRACE_TAG_AIDL")));
563   }
564 
565   if (options.GenLog()) {
566     b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
567                                      true /* isServer */, false /* isNdk */),
568                   false);
569   }
570 
571   // Write exceptions during transaction handling to parcel.
572   if (!method.IsOneway()) {
573     b->AddStatement(new Assignment(
574         kAndroidStatusVarName,
575         StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
576     b->AddStatement(BreakOnStatusNotOk());
577     IfStatement* exception_check = new IfStatement(
578         new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
579     b->AddStatement(exception_check);
580     exception_check->OnTrue()->AddLiteral("break");
581   }
582 
583   // If we have a return value, write it first.
584   if (return_type != types.VoidType()) {
585     string writeMethod =
586         string(kReplyVarName) + "->" +
587         return_type->WriteToParcelMethod();
588     b->AddStatement(new Assignment{
589         kAndroidStatusVarName, new MethodCall{writeMethod,
590         ArgList{return_type->WriteCast(kReturnVarName)}}});
591     b->AddStatement(BreakOnStatusNotOk());
592   }
593   // Write each out parameter to the reply parcel.
594   for (const AidlArgument* a : method.GetOutArguments()) {
595     // Serialization looks roughly like:
596     //     _aidl_ret_status = data.WriteInt32(out_param_name);
597     //     if (_aidl_ret_status != ::android::OK) { break; }
598     const Type* type = a->GetType().GetLanguageType<Type>();
599     const string& writeMethod = type->WriteToParcelMethod();
600 
601     b->AddStatement(new Assignment{
602         kAndroidStatusVarName,
603         new MethodCall{string(kReplyVarName) + "->" + writeMethod,
604                        type->WriteCast(BuildVarName(*a))}});
605     b->AddStatement(BreakOnStatusNotOk());
606   }
607 
608   return true;
609 }
610 
HandleServerMetaTransaction(const TypeNamespace &,const AidlInterface & interface,const AidlMethod & method,const Options & options,StatementBlock * b)611 bool HandleServerMetaTransaction(const TypeNamespace&, const AidlInterface& interface,
612                                  const AidlMethod& method, const Options& options,
613                                  StatementBlock* b) {
614   CHECK(!method.IsUserDefined());
615 
616   if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
617     std::ostringstream code;
618     code << "_aidl_data.checkInterface(this);\n"
619          << "_aidl_reply->writeNoException();\n"
620          << "_aidl_reply->writeInt32(" << ClassName(interface, ClassNames::INTERFACE)
621          << "::VERSION)";
622     b->AddLiteral(code.str());
623     return true;
624   }
625   return false;
626 }
627 
628 }  // namespace
629 
BuildServerSource(const TypeNamespace & types,const AidlInterface & interface,const Options & options)630 unique_ptr<Document> BuildServerSource(const TypeNamespace& types, const AidlInterface& interface,
631                                        const Options& options) {
632   const string bn_name = ClassName(interface, ClassNames::SERVER);
633   vector<string> include_list{
634       HeaderFile(interface, ClassNames::SERVER, false),
635       kParcelHeader
636   };
637   if (options.GenLog()) {
638     include_list.emplace_back("chrono");
639     include_list.emplace_back("functional");
640     include_list.emplace_back("json/value.h");
641   }
642   unique_ptr<MethodImpl> on_transact{new MethodImpl{
643       kAndroidStatusLiteral, bn_name, "onTransact",
644       ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
645                StringPrintf("const %s& %s", kAndroidParcelLiteral,
646                             kDataVarName),
647                StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
648                StringPrintf("uint32_t %s", kFlagsVarName)}}
649       }};
650 
651   // Declare the status_t variable
652   on_transact->GetStatementBlock()->AddLiteral(
653       StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
654                    kAndroidStatusOk));
655 
656   // Add the all important switch statement, but retain a pointer to it.
657   SwitchStatement* s = new SwitchStatement{kCodeVarName};
658   on_transact->GetStatementBlock()->AddStatement(s);
659 
660   // The switch statement has a case statement for each transaction code.
661   for (const auto& method : interface.GetMethods()) {
662     StatementBlock* b = s->AddCase(GetTransactionIdFor(*method));
663     if (!b) { return nullptr; }
664 
665     bool success = false;
666     if (method->IsUserDefined()) {
667       success = HandleServerTransaction(types, interface, *method, options, b);
668     } else {
669       success = HandleServerMetaTransaction(types, interface, *method, options, b);
670     }
671     if (!success) {
672       return nullptr;
673     }
674   }
675 
676   // The switch statement has a default case which defers to the super class.
677   // The superclass handles a few pre-defined transactions.
678   StatementBlock* b = s->AddCase("");
679   b->AddLiteral(StringPrintf(
680                 "%s = ::android::BBinder::onTransact(%s, %s, "
681                 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
682                 kDataVarName, kReplyVarName, kFlagsVarName));
683 
684   // If we saw a null reference, we can map that to an appropriate exception.
685   IfStatement* null_check = new IfStatement(
686       new LiteralExpression(string(kAndroidStatusVarName) +
687                             " == ::android::UNEXPECTED_NULL"));
688   on_transact->GetStatementBlock()->AddStatement(null_check);
689   null_check->OnTrue()->AddStatement(new Assignment(
690       kAndroidStatusVarName,
691       StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
692                    ".writeToParcel(%s)",
693                    kBinderStatusLiteral, kBinderStatusLiteral,
694                    kReplyVarName)));
695 
696   // Finally, the server's onTransact method just returns a status code.
697   on_transact->GetStatementBlock()->AddLiteral(
698       StringPrintf("return %s", kAndroidStatusVarName));
699   vector<unique_ptr<Declaration>> decls;
700   decls.push_back(std::move(on_transact));
701 
702   if (options.Version() > 0) {
703     std::ostringstream code;
704     code << "int32_t " << bn_name << "::" << kGetInterfaceVersion << "() {\n"
705          << "  return " << ClassName(interface, ClassNames::INTERFACE) << "::VERSION;\n"
706          << "}\n";
707     decls.emplace_back(new LiteralDecl(code.str()));
708   }
709 
710   if (options.GenLog()) {
711     string code;
712     ClassName(interface, ClassNames::SERVER);
713     CodeWriterPtr writer = CodeWriter::ForString(&code);
714     (*writer) << "std::function<void(const Json::Value&)> "
715               << ClassName(interface, ClassNames::SERVER) << "::logFunc;\n";
716     writer->Close();
717     decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
718   }
719   return unique_ptr<Document>{
720       new CppSource{include_list, NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
721 }
722 
BuildInterfaceSource(const TypeNamespace & types,const AidlInterface & interface,const Options & options)723 unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& types,
724                                           const AidlInterface& interface, const Options& options) {
725   vector<string> include_list{
726       HeaderFile(interface, ClassNames::RAW, false),
727       HeaderFile(interface, ClassNames::CLIENT, false),
728   };
729 
730   string fq_name = ClassName(interface, ClassNames::INTERFACE);
731   if (!interface.GetPackage().empty()) {
732     fq_name = interface.GetPackage() + "." + fq_name;
733   }
734 
735   vector<unique_ptr<Declaration>> decls;
736 
737   unique_ptr<MacroDecl> meta_if{new MacroDecl{
738       "IMPLEMENT_META_INTERFACE",
739       ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
740                              '"' + fq_name + '"'}}}};
741   decls.push_back(std::move(meta_if));
742 
743   for (const auto& constant : interface.GetConstantDeclarations()) {
744     const AidlConstantValue& value = constant->GetValue();
745     if (value.GetType() != AidlConstantValue::Type::STRING) continue;
746 
747     std::string cppType = constant->GetType().GetLanguageType<Type>()->CppType();
748 
749     unique_ptr<MethodImpl> getter(new MethodImpl("const " + cppType + "&",
750                                                  ClassName(interface, ClassNames::INTERFACE),
751                                                  constant->GetName(), {}));
752     getter->GetStatementBlock()->AddLiteral(
753         StringPrintf("static const %s value(%s)", cppType.c_str(),
754                      constant->ValueString(ConstantValueDecorator).c_str()));
755     getter->GetStatementBlock()->AddLiteral("return value");
756     decls.push_back(std::move(getter));
757   }
758 
759   // Implement the default impl class.
760   // onAsBinder returns nullptr as this interface is not associated with a
761   // real binder.
762   const string default_impl(ClassName(interface, ClassNames::DEFAULT_IMPL));
763   decls.emplace_back(
764       new LiteralDecl(StringPrintf("::android::IBinder* %s::onAsBinder() {\n"
765                                    "  return nullptr;\n"
766                                    "}\n",
767                                    default_impl.c_str())));
768   // Each interface method by default returns UNKNOWN_TRANSACTION with is
769   // the same status that is returned by transact() when the method is
770   // not implemented in the server side. In other words, these default
771   // methods do nothing; they only exist to aid making a real default
772   // impl class without having to override all methods in an interface.
773   for (const auto& method : interface.GetMethods()) {
774     if (method->IsUserDefined()) {
775       std::ostringstream code;
776       code << "::android::binder::Status " << default_impl << "::" << method->GetName()
777            << BuildArgList(types, *method, true, true).ToString() << " {\n"
778            << "  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
779            << "}\n";
780       decls.emplace_back(new LiteralDecl(code.str()));
781     } else {
782       if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
783         std::ostringstream code;
784         code << "int32_t " << default_impl << "::" << kGetInterfaceVersion << "() {\n"
785              << "  return 0;\n"
786              << "}\n";
787         decls.emplace_back(new LiteralDecl(code.str()));
788       }
789     }
790   }
791 
792   return unique_ptr<Document>{new CppSource{
793       include_list,
794       NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
795 }
796 
BuildClientHeader(const TypeNamespace & types,const AidlInterface & interface,const Options & options)797 unique_ptr<Document> BuildClientHeader(const TypeNamespace& types, const AidlInterface& interface,
798                                        const Options& options) {
799   const string i_name = ClassName(interface, ClassNames::INTERFACE);
800   const string bp_name = ClassName(interface, ClassNames::CLIENT);
801 
802   vector<string> includes = {kIBinderHeader, kIInterfaceHeader, "utils/Errors.h",
803                              HeaderFile(interface, ClassNames::RAW, false)};
804 
805   unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
806       bp_name,
807       ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
808                            kImplVarName)},
809       ConstructorDecl::IS_EXPLICIT
810   }};
811   unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
812       "~" + bp_name,
813       ArgList{},
814       ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
815 
816   vector<unique_ptr<Declaration>> publics;
817   publics.push_back(std::move(constructor));
818   publics.push_back(std::move(destructor));
819 
820   for (const auto& method: interface.GetMethods()) {
821     if (method->IsUserDefined()) {
822       publics.push_back(BuildMethodDecl(*method, types, false));
823     } else {
824       publics.push_back(BuildMetaMethodDecl(*method, types, options, false));
825     }
826   }
827 
828   if (options.GenLog()) {
829     includes.emplace_back("chrono");      // for std::chrono::steady_clock
830     includes.emplace_back("functional");  // for std::function
831     includes.emplace_back("json/value.h");
832     publics.emplace_back(
833         new LiteralDecl{"static std::function<void(const Json::Value&)> logFunc;\n"});
834   }
835 
836   vector<unique_ptr<Declaration>> privates;
837 
838   if (options.Version() > 0) {
839     privates.emplace_back(new LiteralDecl("int32_t cached_version_ = -1;\n"));
840   }
841 
842   unique_ptr<ClassDecl> bp_class{new ClassDecl{
843       bp_name,
844       "::android::BpInterface<" + i_name + ">",
845       std::move(publics),
846       std::move(privates),
847   }};
848 
849   return unique_ptr<Document>{
850       new CppHeader{BuildHeaderGuard(interface, ClassNames::CLIENT), includes,
851                     NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
852 }
853 
BuildServerHeader(const TypeNamespace &,const AidlInterface & interface,const Options & options)854 unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
855                                        const AidlInterface& interface, const Options& options) {
856   const string i_name = ClassName(interface, ClassNames::INTERFACE);
857   const string bn_name = ClassName(interface, ClassNames::SERVER);
858 
859   unique_ptr<Declaration> on_transact{new MethodDecl{
860       kAndroidStatusLiteral, "onTransact",
861       ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
862                StringPrintf("const %s& %s", kAndroidParcelLiteral,
863                             kDataVarName),
864                StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
865                StringPrintf("uint32_t %s", kFlagsVarName)}},
866       MethodDecl::IS_OVERRIDE
867   }};
868   vector<string> includes = {"binder/IInterface.h", HeaderFile(interface, ClassNames::RAW, false)};
869 
870   vector<unique_ptr<Declaration>> publics;
871   publics.push_back(std::move(on_transact));
872 
873   if (options.Version() > 0) {
874     std::ostringstream code;
875     code << "int32_t " << kGetInterfaceVersion << "() final override;\n";
876     publics.emplace_back(new LiteralDecl(code.str()));
877   }
878 
879   if (options.GenLog()) {
880     includes.emplace_back("chrono");      // for std::chrono::steady_clock
881     includes.emplace_back("functional");  // for std::function
882     includes.emplace_back("json/value.h");
883     publics.emplace_back(
884         new LiteralDecl{"static std::function<void(const Json::Value&)> logFunc;\n"});
885   }
886   unique_ptr<ClassDecl> bn_class{
887       new ClassDecl{bn_name,
888                     "::android::BnInterface<" + i_name + ">",
889                     std::move(publics),
890                     {}
891       }};
892 
893   return unique_ptr<Document>{
894       new CppHeader{BuildHeaderGuard(interface, ClassNames::SERVER), includes,
895                     NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
896 }
897 
BuildInterfaceHeader(const TypeNamespace & types,const AidlInterface & interface,const Options & options)898 unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
899                                           const AidlInterface& interface, const Options& options) {
900   set<string> includes = {kIBinderHeader, kIInterfaceHeader, kStatusHeader, kStrongPointerHeader};
901 
902   for (const auto& method : interface.GetMethods()) {
903     for (const auto& argument : method->GetArguments()) {
904       const Type* type = argument->GetType().GetLanguageType<Type>();
905       type->GetHeaders(&includes);
906     }
907 
908     const Type* return_type = method->GetType().GetLanguageType<Type>();
909     if (return_type != nullptr) {
910       return_type->GetHeaders(&includes);
911     }
912   }
913 
914   const string i_name = ClassName(interface, ClassNames::INTERFACE);
915   unique_ptr<ClassDecl> if_class{new ClassDecl{i_name, "::android::IInterface"}};
916   if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
917       "DECLARE_META_INTERFACE",
918       ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
919 
920   if (options.Version() > 0) {
921     std::ostringstream code;
922     code << "const int32_t VERSION = " << options.Version() << ";\n";
923 
924     if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
925   }
926 
927   std::vector<std::unique_ptr<Declaration>> string_constants;
928   unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t"}};
929   for (const auto& constant : interface.GetConstantDeclarations()) {
930     const AidlConstantValue& value = constant->GetValue();
931 
932     switch (value.GetType()) {
933       case AidlConstantValue::Type::STRING: {
934         std::string cppType = constant->GetType().GetLanguageType<Type>()->CppType();
935         unique_ptr<Declaration> getter(new MethodDecl("const " + cppType + "&", constant->GetName(),
936                                                       {}, MethodDecl::IS_STATIC));
937         string_constants.push_back(std::move(getter));
938         break;
939       }
940       case AidlConstantValue::Type::INTEGRAL:
941       case AidlConstantValue::Type::HEXIDECIMAL: {
942         int_constant_enum->AddValue(constant->GetName(),
943                                     constant->ValueString(ConstantValueDecorator));
944         break;
945       }
946       default: {
947         LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
948       }
949     }
950   }
951   if (int_constant_enum->HasValues()) {
952     if_class->AddPublic(std::move(int_constant_enum));
953   }
954   if (!string_constants.empty()) {
955     includes.insert(kString16Header);
956 
957     for (auto& string_constant : string_constants) {
958       if_class->AddPublic(std::move(string_constant));
959     }
960   }
961 
962   if (options.GenTraces()) {
963     includes.insert(kTraceHeader);
964   }
965 
966   if (!interface.GetMethods().empty()) {
967     for (const auto& method : interface.GetMethods()) {
968       if (method->IsUserDefined()) {
969         // Each method gets an enum entry and pure virtual declaration.
970         if_class->AddPublic(BuildMethodDecl(*method, types, true));
971       } else {
972         if_class->AddPublic(BuildMetaMethodDecl(*method, types, options, true));
973       }
974     }
975   }
976 
977   vector<unique_ptr<Declaration>> decls;
978   decls.emplace_back(std::move(if_class));
979 
980   // Base class for the default implementation.
981   vector<string> method_decls;
982   for (const auto& method : interface.GetMethods()) {
983     if (method->IsUserDefined()) {
984       method_decls.emplace_back(BuildMethodDecl(*method, types, false)->ToString());
985     } else {
986       method_decls.emplace_back(BuildMetaMethodDecl(*method, types, options, false)->ToString());
987     }
988   }
989 
990   decls.emplace_back(new LiteralDecl(
991       android::base::StringPrintf("class %s : public %s {\n"
992                                   "public:\n"
993                                   "  ::android::IBinder* onAsBinder() override;\n"
994                                   "  %s\n"
995                                   "};\n",
996                                   ClassName(interface, ClassNames::DEFAULT_IMPL).c_str(),
997                                   i_name.c_str(), Join(method_decls, "  ").c_str())));
998 
999   return unique_ptr<Document>{
1000       new CppHeader{BuildHeaderGuard(interface, ClassNames::INTERFACE),
1001                     vector<string>(includes.begin(), includes.end()),
1002                     NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
1003 }
1004 
BuildParcelHeader(const TypeNamespace &,const AidlStructuredParcelable & parcel,const Options &)1005 std::unique_ptr<Document> BuildParcelHeader(const TypeNamespace& /*types*/,
1006                                             const AidlStructuredParcelable& parcel,
1007                                             const Options&) {
1008   unique_ptr<ClassDecl> parcel_class{new ClassDecl{parcel.GetName(), "::android::Parcelable"}};
1009 
1010   set<string> includes = {kStatusHeader, kParcelHeader};
1011   for (const auto& variable : parcel.GetFields()) {
1012     const Type* type = variable->GetType().GetLanguageType<Type>();
1013     type->GetHeaders(&includes);
1014   }
1015 
1016   for (const auto& variable : parcel.GetFields()) {
1017     const Type* type = variable->GetType().GetLanguageType<Type>();
1018 
1019     std::ostringstream out;
1020     out << type->CppType().c_str() << " " << variable->GetName().c_str();
1021     if (variable->GetDefaultValue()) {
1022       out << " = " << type->CppType().c_str() << "("
1023           << variable->ValueString(ConstantValueDecorator) << ")";
1024     }
1025     out << ";\n";
1026 
1027     parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
1028   }
1029 
1030   unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
1031                                              ArgList("const ::android::Parcel* _aidl_parcel"),
1032                                              MethodDecl::IS_OVERRIDE | MethodDecl::IS_FINAL));
1033   parcel_class->AddPublic(std::move(read));
1034   unique_ptr<MethodDecl> write(new MethodDecl(
1035       kAndroidStatusLiteral, "writeToParcel", ArgList("::android::Parcel* _aidl_parcel"),
1036       MethodDecl::IS_OVERRIDE | MethodDecl::IS_CONST | MethodDecl::IS_FINAL));
1037   parcel_class->AddPublic(std::move(write));
1038 
1039   return unique_ptr<Document>{new CppHeader{
1040       BuildHeaderGuard(parcel, ClassNames::BASE), vector<string>(includes.begin(), includes.end()),
1041       NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage())}};
1042 }
BuildParcelSource(const TypeNamespace &,const AidlStructuredParcelable & parcel,const Options &)1043 std::unique_ptr<Document> BuildParcelSource(const TypeNamespace& /*types*/,
1044                                             const AidlStructuredParcelable& parcel,
1045                                             const Options&) {
1046   unique_ptr<MethodImpl> read{new MethodImpl{kAndroidStatusLiteral, parcel.GetName(),
1047                                              "readFromParcel",
1048                                              ArgList("const ::android::Parcel* _aidl_parcel")}};
1049   StatementBlock* read_block = read->GetStatementBlock();
1050   read_block->AddLiteral(
1051       StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
1052 
1053   read_block->AddLiteral(
1054       "size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1055       "int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();\n"
1056       "if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;\n"
1057       "size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);\n");
1058 
1059   for (const auto& variable : parcel.GetFields()) {
1060     string method = variable->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
1061 
1062     read_block->AddStatement(new Assignment(
1063         kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1064                                               ArgList("&" + variable->GetName()))));
1065     read_block->AddStatement(ReturnOnStatusNotOk());
1066     read_block->AddLiteral(StringPrintf(
1067         "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1068         "  _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
1069         "  return %s;\n"
1070         "}",
1071         kAndroidStatusVarName));
1072   }
1073   read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1074 
1075   unique_ptr<MethodImpl> write{
1076       new MethodImpl{kAndroidStatusLiteral, parcel.GetName(), "writeToParcel",
1077                      ArgList("::android::Parcel* _aidl_parcel"), true /*const*/}};
1078   StatementBlock* write_block = write->GetStatementBlock();
1079   write_block->AddLiteral(
1080       StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
1081 
1082   write_block->AddLiteral(
1083       "auto _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1084       "_aidl_parcel->writeInt32(0);");
1085 
1086   for (const auto& variable : parcel.GetFields()) {
1087     string method = variable->GetType().GetLanguageType<Type>()->WriteToParcelMethod();
1088 
1089     write_block->AddStatement(new Assignment(
1090         kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1091                                               ArgList(variable->GetName()))));
1092     write_block->AddStatement(ReturnOnStatusNotOk());
1093   }
1094 
1095   write_block->AddLiteral(
1096       "auto _aidl_end_pos = _aidl_parcel->dataPosition();\n"
1097       "_aidl_parcel->setDataPosition(_aidl_start_pos);\n"
1098       "_aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);\n"
1099       "_aidl_parcel->setDataPosition(_aidl_end_pos);");
1100   write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1101 
1102   vector<unique_ptr<Declaration>> file_decls;
1103   file_decls.push_back(std::move(read));
1104   file_decls.push_back(std::move(write));
1105 
1106   set<string> includes = {};
1107   parcel.GetLanguageType<Type>()->GetHeaders(&includes);
1108 
1109   return unique_ptr<Document>{
1110       new CppSource{vector<string>(includes.begin(), includes.end()),
1111                     NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
1112 }
1113 
WriteHeader(const Options & options,const TypeNamespace & types,const AidlInterface & interface,const IoDelegate & io_delegate,ClassNames header_type)1114 bool WriteHeader(const Options& options, const TypeNamespace& types, const AidlInterface& interface,
1115                  const IoDelegate& io_delegate, ClassNames header_type) {
1116   unique_ptr<Document> header;
1117   switch (header_type) {
1118     case ClassNames::INTERFACE:
1119       header = BuildInterfaceHeader(types, interface, options);
1120       header_type = ClassNames::RAW;
1121       break;
1122     case ClassNames::CLIENT:
1123       header = BuildClientHeader(types, interface, options);
1124       break;
1125     case ClassNames::SERVER:
1126       header = BuildServerHeader(types, interface, options);
1127       break;
1128     default:
1129       LOG(FATAL) << "aidl internal error";
1130   }
1131   if (!header) {
1132     LOG(ERROR) << "aidl internal error: Failed to generate header.";
1133     return false;
1134   }
1135 
1136   const string header_path = options.OutputHeaderDir() + HeaderFile(interface, header_type);
1137   unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
1138   header->Write(code_writer.get());
1139 
1140   const bool success = code_writer->Close();
1141   if (!success) {
1142     io_delegate.RemovePath(header_path);
1143   }
1144 
1145   return success;
1146 }
1147 
1148 }  // namespace internals
1149 
1150 using namespace internals;
1151 
GenerateCppInterface(const string & output_file,const Options & options,const TypeNamespace & types,const AidlInterface & interface,const IoDelegate & io_delegate)1152 bool GenerateCppInterface(const string& output_file, const Options& options,
1153                           const TypeNamespace& types, const AidlInterface& interface,
1154                           const IoDelegate& io_delegate) {
1155   auto interface_src = BuildInterfaceSource(types, interface, options);
1156   auto client_src = BuildClientSource(types, interface, options);
1157   auto server_src = BuildServerSource(types, interface, options);
1158 
1159   if (!interface_src || !client_src || !server_src) {
1160     return false;
1161   }
1162 
1163   if (!WriteHeader(options, types, interface, io_delegate,
1164                    ClassNames::INTERFACE) ||
1165       !WriteHeader(options, types, interface, io_delegate,
1166                    ClassNames::CLIENT) ||
1167       !WriteHeader(options, types, interface, io_delegate,
1168                    ClassNames::SERVER)) {
1169     return false;
1170   }
1171 
1172   unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(output_file);
1173   interface_src->Write(writer.get());
1174   client_src->Write(writer.get());
1175   server_src->Write(writer.get());
1176 
1177   const bool success = writer->Close();
1178   if (!success) {
1179     io_delegate.RemovePath(output_file);
1180   }
1181 
1182   return success;
1183 }
1184 
GenerateCppParcel(const string & output_file,const Options & options,const cpp::TypeNamespace & types,const AidlStructuredParcelable & parcelable,const IoDelegate & io_delegate)1185 bool GenerateCppParcel(const string& output_file, const Options& options,
1186                        const cpp::TypeNamespace& types, const AidlStructuredParcelable& parcelable,
1187                        const IoDelegate& io_delegate) {
1188   auto header = BuildParcelHeader(types, parcelable, options);
1189   auto source = BuildParcelSource(types, parcelable, options);
1190 
1191   if (!header || !source) {
1192     return false;
1193   }
1194 
1195   const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
1196   unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1197   header->Write(header_writer.get());
1198   CHECK(header_writer->Close());
1199 
1200   // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
1201   const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
1202   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1203   bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
1204   CHECK(bp_writer->Close());
1205   const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
1206   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1207   bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
1208   CHECK(bn_writer->Close());
1209 
1210   unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
1211   source->Write(source_writer.get());
1212   CHECK(source_writer->Close());
1213 
1214   return true;
1215 }
1216 
GenerateCppParcelDeclaration(const std::string & filename,const IoDelegate & io_delegate)1217 bool GenerateCppParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
1218   CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
1219   *code_writer
1220       << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
1221 
1222   return true;
1223 }
1224 
GenerateCpp(const string & output_file,const Options & options,const TypeNamespace & types,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)1225 bool GenerateCpp(const string& output_file, const Options& options, const TypeNamespace& types,
1226                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
1227   const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
1228   if (parcelable != nullptr) {
1229     return GenerateCppParcel(output_file, options, types, *parcelable, io_delegate);
1230   }
1231 
1232   const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
1233   if (parcelable_decl != nullptr) {
1234     return GenerateCppParcelDeclaration(output_file, io_delegate);
1235   }
1236 
1237   const AidlInterface* interface = defined_type.AsInterface();
1238   if (interface != nullptr) {
1239     return GenerateCppInterface(output_file, options, types, *interface, io_delegate);
1240   }
1241 
1242   CHECK(false) << "Unrecognized type sent for cpp generation.";
1243   return false;
1244 }
1245 
1246 }  // namespace cpp
1247 }  // namespace aidl
1248 }  // namespace android
1249