• 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 
19 #include <cctype>
20 #include <cstring>
21 #include <memory>
22 #include <random>
23 #include <set>
24 #include <string>
25 
26 #include <android-base/stringprintf.h>
27 
28 #include "aidl_language.h"
29 #include "ast_cpp.h"
30 #include "code_writer.h"
31 #include "logging.h"
32 #include "os.h"
33 
34 using android::base::StringPrintf;
35 using std::string;
36 using std::unique_ptr;
37 using std::vector;
38 using std::set;
39 
40 namespace android {
41 namespace aidl {
42 namespace cpp {
43 namespace internals {
44 namespace {
45 
46 const char kAndroidStatusVarName[] = "_aidl_ret_status";
47 const char kCodeVarName[] = "_aidl_code";
48 const char kFlagsVarName[] = "_aidl_flags";
49 const char kDataVarName[] = "_aidl_data";
50 const char kErrorLabel[] = "_aidl_error";
51 const char kImplVarName[] = "_aidl_impl";
52 const char kReplyVarName[] = "_aidl_reply";
53 const char kReturnVarName[] = "_aidl_return";
54 const char kStatusVarName[] = "_aidl_status";
55 const char kAndroidParcelLiteral[] = "::android::Parcel";
56 const char kAndroidStatusLiteral[] = "::android::status_t";
57 const char kAndroidStatusOk[] = "::android::OK";
58 const char kBinderStatusLiteral[] = "::android::binder::Status";
59 const char kIBinderHeader[] = "binder/IBinder.h";
60 const char kIInterfaceHeader[] = "binder/IInterface.h";
61 const char kParcelHeader[] = "binder/Parcel.h";
62 const char kStatusHeader[] = "binder/Status.h";
63 const char kString16Header[] = "utils/String16.h";
64 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
65 
BreakOnStatusNotOk()66 unique_ptr<AstNode> BreakOnStatusNotOk() {
67   IfStatement* ret = new IfStatement(new Comparison(
68       new LiteralExpression(kAndroidStatusVarName), "!=",
69       new LiteralExpression(kAndroidStatusOk)));
70   ret->OnTrue()->AddLiteral("break");
71   return unique_ptr<AstNode>(ret);
72 }
73 
GotoErrorOnBadStatus()74 unique_ptr<AstNode> GotoErrorOnBadStatus() {
75   IfStatement* ret = new IfStatement(new Comparison(
76       new LiteralExpression(kAndroidStatusVarName), "!=",
77       new LiteralExpression(kAndroidStatusOk)));
78   ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
79   return unique_ptr<AstNode>(ret);
80 }
81 
82 
ReturnOnStatusNotOk()83 unique_ptr<AstNode> ReturnOnStatusNotOk() {
84   IfStatement* ret = new IfStatement(new Comparison(
85       new LiteralExpression(kAndroidStatusVarName), "!=",
86       new LiteralExpression(kAndroidStatusOk)));
87   ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
88   return unique_ptr<AstNode>(ret);
89 }
90 
UpperCase(const std::string & s)91 string UpperCase(const std::string& s) {
92   string result = s;
93   for (char& c : result)
94     c = toupper(c);
95   return result;
96 }
97 
BuildVarName(const AidlArgument & a)98 string BuildVarName(const AidlArgument& a) {
99   string prefix = "out_";
100   if (a.GetDirection() & AidlArgument::IN_DIR) {
101     prefix = "in_";
102   }
103   return prefix + a.GetName();
104 }
105 
BuildArgList(const TypeNamespace & types,const AidlMethod & method,bool for_declaration)106 ArgList BuildArgList(const TypeNamespace& types,
107                      const AidlMethod& method,
108                      bool for_declaration) {
109   // Build up the argument list for the server method call.
110   vector<string> method_arguments;
111   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
112     string literal;
113     if (for_declaration) {
114       // Method declarations need types, pointers to out params, and variable
115       // names that match the .aidl specification.
116       const Type* type = a->GetType().GetLanguageType<Type>();
117 
118       literal = type->CppType();
119 
120       if (a->IsOut()) {
121         literal = literal + "*";
122       } else {
123         // We pass in parameters that are not primitives by const reference.
124         // Arrays of primitives are not primitives.
125         if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
126           literal = "const " + literal + "&";
127         }
128       }
129 
130       literal += " " + a->GetName();
131     } else {
132       if (a->IsOut()) { literal = "&"; }
133       literal += BuildVarName(*a);
134     }
135     method_arguments.push_back(literal);
136   }
137 
138   const Type* return_type = method.GetType().GetLanguageType<Type>();
139 
140   if (return_type != types.VoidType()) {
141     string literal;
142     if (for_declaration) {
143       literal = StringPrintf(
144           "%s* %s", return_type->CppType().c_str(),
145           kReturnVarName);
146     } else {
147       literal = string{"&"} + kReturnVarName;
148     }
149     method_arguments.push_back(literal);
150   }
151 
152   return ArgList(method_arguments);
153 }
154 
BuildMethodDecl(const AidlMethod & method,const TypeNamespace & types,bool for_interface)155 unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
156                                         const TypeNamespace& types,
157                                         bool for_interface) {
158   uint32_t modifiers = 0;
159   if (for_interface) {
160     modifiers |= MethodDecl::IS_VIRTUAL;
161     modifiers |= MethodDecl::IS_PURE_VIRTUAL;
162   } else {
163     modifiers |= MethodDecl::IS_OVERRIDE;
164   }
165 
166   return unique_ptr<Declaration>{
167       new MethodDecl{kBinderStatusLiteral,
168                      method.GetName(),
169                      BuildArgList(types, method, true /* for method decl */),
170                      modifiers}};
171 }
172 
NestInNamespaces(vector<unique_ptr<Declaration>> decls,const vector<string> & package)173 unique_ptr<CppNamespace> NestInNamespaces(
174     vector<unique_ptr<Declaration>> decls,
175     const vector<string>& package) {
176   if (package.empty()) {
177     // We should also be checking this before we get this far, but do it again
178     // for the sake of unit tests and meaningful errors.
179     LOG(FATAL) << "C++ generation requires a package declaration "
180                   "for namespacing";
181   }
182   auto it = package.crbegin();  // Iterate over the namespaces inner to outer
183   unique_ptr<CppNamespace> inner{new CppNamespace{*it, std::move(decls)}};
184   ++it;
185   for (; it != package.crend(); ++it) {
186     inner.reset(new CppNamespace{*it, std::move(inner)});
187   }
188   return inner;
189 }
190 
NestInNamespaces(unique_ptr<Declaration> decl,const vector<string> & package)191 unique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl,
192                                           const vector<string>& package) {
193   vector<unique_ptr<Declaration>> decls;
194   decls.push_back(std::move(decl));
195   return NestInNamespaces(std::move(decls), package);
196 }
197 
DeclareLocalVariable(const TypeNamespace & types,const AidlArgument & a,StatementBlock * b)198 bool DeclareLocalVariable(const TypeNamespace& types, const AidlArgument& a,
199                           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 
ClassName(const AidlInterface & interface,ClassNames type)209 string ClassName(const AidlInterface& interface, ClassNames type) {
210   string c_name = interface.GetName();
211 
212   if (c_name.length() >= 2 && c_name[0] == 'I' && isupper(c_name[1]))
213     c_name = c_name.substr(1);
214 
215   switch (type) {
216     case ClassNames::CLIENT:
217       c_name = "Bp" + c_name;
218       break;
219     case ClassNames::SERVER:
220       c_name = "Bn" + c_name;
221       break;
222     case ClassNames::INTERFACE:
223       c_name = "I" + c_name;
224       break;
225     case ClassNames::BASE:
226       break;
227   }
228   return c_name;
229 }
230 
BuildHeaderGuard(const AidlInterface & interface,ClassNames header_type)231 string BuildHeaderGuard(const AidlInterface& interface,
232                         ClassNames header_type) {
233   string class_name = ClassName(interface, header_type);
234   for (size_t i = 1; i < class_name.size(); ++i) {
235     if (isupper(class_name[i])) {
236       class_name.insert(i, "_");
237       ++i;
238     }
239   }
240   string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_",
241                             interface.GetPackage().c_str(),
242                             class_name.c_str());
243   for (char& c : ret) {
244     if (c == '.') {
245       c = '_';
246     }
247     c = toupper(c);
248   }
249   return ret;
250 }
251 
DefineClientTransaction(const TypeNamespace & types,const AidlInterface & interface,const AidlMethod & method)252 unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
253                                                 const AidlInterface& interface,
254                                                 const AidlMethod& method) {
255   const string i_name = ClassName(interface, ClassNames::INTERFACE);
256   const string bp_name = ClassName(interface, ClassNames::CLIENT);
257   unique_ptr<MethodImpl> ret{new MethodImpl{
258       kBinderStatusLiteral, bp_name, method.GetName(),
259       ArgList{BuildArgList(types, method, true /* for method decl */)}}};
260   StatementBlock* b = ret->GetStatementBlock();
261 
262   // Declare parcels to hold our query and the response.
263   b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
264   // Even if we're oneway, the transact method still takes a parcel.
265   b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
266 
267   // Declare the status_t variable we need for error handling.
268   b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
269                              kAndroidStatusVarName,
270                              kAndroidStatusOk));
271   // We unconditionally return a Status object.
272   b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
273 
274   // Add the name of the interface we're hoping to call.
275   b->AddStatement(new Assignment(
276       kAndroidStatusVarName,
277       new MethodCall(StringPrintf("%s.writeInterfaceToken",
278                                   kDataVarName),
279                      "getInterfaceDescriptor()")));
280   b->AddStatement(GotoErrorOnBadStatus());
281 
282   for (const auto& a: method.GetArguments()) {
283     const Type* type = a->GetType().GetLanguageType<Type>();
284     string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
285     var_name = type->WriteCast(var_name);
286 
287     if (a->IsIn()) {
288       // Serialization looks roughly like:
289       //     _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
290       //     if (_aidl_ret_status != ::android::OK) { goto error; }
291       const string& method = type->WriteToParcelMethod();
292       b->AddStatement(new Assignment(
293           kAndroidStatusVarName,
294           new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
295                          ArgList(var_name))));
296       b->AddStatement(GotoErrorOnBadStatus());
297     } else if (a->IsOut() && a->GetType().IsArray()) {
298       // Special case, the length of the out array is written into the parcel.
299       //     _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
300       //     if (_aidl_ret_status != ::android::OK) { goto error; }
301       b->AddStatement(new Assignment(
302           kAndroidStatusVarName,
303           new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
304                          ArgList(var_name))));
305       b->AddStatement(GotoErrorOnBadStatus());
306     }
307   }
308 
309   // Invoke the transaction on the remote binder and confirm status.
310   string transaction_code = StringPrintf(
311       "%s::%s", i_name.c_str(), UpperCase(method.GetName()).c_str());
312 
313   vector<string> args = {transaction_code, kDataVarName,
314                          StringPrintf("&%s", kReplyVarName)};
315 
316   if (interface.IsOneway() || method.IsOneway()) {
317     args.push_back("::android::IBinder::FLAG_ONEWAY");
318   }
319 
320   b->AddStatement(new Assignment(
321       kAndroidStatusVarName,
322       new MethodCall("remote()->transact",
323                      ArgList(args))));
324   b->AddStatement(GotoErrorOnBadStatus());
325 
326   if (!interface.IsOneway() && !method.IsOneway()) {
327     // Strip off the exception header and fail if we see a remote exception.
328     // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
329     // if (_aidl_ret_status != ::android::OK) { goto error; }
330     // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
331     b->AddStatement(new Assignment(
332         kAndroidStatusVarName,
333         StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
334     b->AddStatement(GotoErrorOnBadStatus());
335     IfStatement* exception_check = new IfStatement(
336         new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
337     b->AddStatement(exception_check);
338     exception_check->OnTrue()->AddLiteral(
339         StringPrintf("return %s", kStatusVarName));
340   }
341 
342   // Type checking should guarantee that nothing below emits code until "return
343   // status" if we are a oneway method, so no more fear of accessing reply.
344 
345   // If the method is expected to return something, read it first by convention.
346   const Type* return_type = method.GetType().GetLanguageType<Type>();
347   if (return_type != types.VoidType()) {
348     const string& method_call = return_type->ReadFromParcelMethod();
349     b->AddStatement(new Assignment(
350         kAndroidStatusVarName,
351         new MethodCall(StringPrintf("%s.%s", kReplyVarName,
352                                     method_call.c_str()),
353                        ArgList(kReturnVarName))));
354     b->AddStatement(GotoErrorOnBadStatus());
355   }
356 
357   for (const AidlArgument* a : method.GetOutArguments()) {
358     // Deserialization looks roughly like:
359     //     _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
360     //     if (_aidl_status != ::android::OK) { goto _aidl_error; }
361     string method =
362       a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
363 
364     b->AddStatement(new Assignment(
365         kAndroidStatusVarName,
366         new MethodCall(StringPrintf("%s.%s", kReplyVarName,
367                                     method.c_str()),
368                        ArgList(a->GetName()))));
369     b->AddStatement(GotoErrorOnBadStatus());
370   }
371 
372   // If we've gotten to here, one of two things is true:
373   //   1) We've read some bad status_t
374   //   2) We've only read status_t == OK and there was no exception in the
375   //      response.
376   // In both cases, we're free to set Status from the status_t and return.
377   b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
378   b->AddLiteral(
379       StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
380                    kAndroidStatusVarName));
381   b->AddLiteral(StringPrintf("return %s", kStatusVarName));
382 
383   return unique_ptr<Declaration>(ret.release());
384 }
385 
386 }  // namespace
387 
BuildClientSource(const TypeNamespace & types,const AidlInterface & interface)388 unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
389                                        const AidlInterface& interface) {
390   vector<string> include_list = {
391       HeaderFile(interface, ClassNames::CLIENT, false),
392       kParcelHeader
393   };
394   vector<unique_ptr<Declaration>> file_decls;
395 
396   // The constructor just passes the IBinder instance up to the super
397   // class.
398   const string i_name = ClassName(interface, ClassNames::INTERFACE);
399   file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
400       ClassName(interface, ClassNames::CLIENT),
401       ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
402                            kImplVarName)},
403       { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
404 
405   // Clients define a method per transaction.
406   for (const auto& method : interface.GetMethods()) {
407     unique_ptr<Declaration> m = DefineClientTransaction(
408         types, interface, *method);
409     if (!m) { return nullptr; }
410     file_decls.push_back(std::move(m));
411   }
412   return unique_ptr<Document>{new CppSource{
413       include_list,
414       NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
415 }
416 
417 namespace {
418 
HandleServerTransaction(const TypeNamespace & types,const AidlMethod & method,StatementBlock * b)419 bool HandleServerTransaction(const TypeNamespace& types,
420                              const AidlMethod& method,
421                              StatementBlock* b) {
422   // Declare all the parameters now.  In the common case, we expect no errors
423   // in serialization.
424   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
425     if (!DeclareLocalVariable(types, *a, b)) { return false; }
426   }
427 
428   // Declare a variable to hold the return value.
429   const Type* return_type = method.GetType().GetLanguageType<Type>();
430   if (return_type != types.VoidType()) {
431     b->AddLiteral(StringPrintf(
432         "%s %s", return_type->CppType().c_str(),
433         kReturnVarName));
434   }
435 
436   // Check that the client is calling the correct interface.
437   IfStatement* interface_check = new IfStatement(
438       new MethodCall(StringPrintf("%s.checkInterface",
439                                   kDataVarName), "this"),
440       true /* invert the check */);
441   b->AddStatement(interface_check);
442   interface_check->OnTrue()->AddStatement(
443       new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
444   interface_check->OnTrue()->AddLiteral("break");
445 
446   // Deserialize each "in" parameter to the transaction.
447   for (const auto& a: method.GetArguments()) {
448     // Deserialization looks roughly like:
449     //     _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
450     //     if (_aidl_ret_status != ::android::OK) { break; }
451     const Type* type = a->GetType().GetLanguageType<Type>();
452     const string& readMethod = type->ReadFromParcelMethod();
453 
454     if (a->IsIn()) {
455       b->AddStatement(new Assignment{
456           kAndroidStatusVarName,
457           new MethodCall{string(kDataVarName) + "." + readMethod,
458                          "&" + BuildVarName(*a)}});
459       b->AddStatement(BreakOnStatusNotOk());
460     } else if (a->IsOut() && a->GetType().IsArray()) {
461       // Special case, the length of the out array is written into the parcel.
462       //     _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
463       //     if (_aidl_ret_status != ::android::OK) { break; }
464       b->AddStatement(new Assignment{
465           kAndroidStatusVarName,
466           new MethodCall{string(kDataVarName) + ".resizeOutVector",
467                          "&" + BuildVarName(*a)}});
468       b->AddStatement(BreakOnStatusNotOk());
469     }
470   }
471 
472   // Call the actual method.  This is implemented by the subclass.
473   vector<unique_ptr<AstNode>> status_args;
474   status_args.emplace_back(new MethodCall(
475           method.GetName(),
476           BuildArgList(types, method, false /* not for method decl */)));
477   b->AddStatement(new Statement(new MethodCall(
478       StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
479       ArgList(std::move(status_args)))));
480 
481   // Write exceptions during transaction handling to parcel.
482   if (!method.IsOneway()) {
483     b->AddStatement(new Assignment(
484         kAndroidStatusVarName,
485         StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
486     b->AddStatement(BreakOnStatusNotOk());
487     IfStatement* exception_check = new IfStatement(
488         new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
489     b->AddStatement(exception_check);
490     exception_check->OnTrue()->AddLiteral("break");
491   }
492 
493   // If we have a return value, write it first.
494   if (return_type != types.VoidType()) {
495     string writeMethod =
496         string(kReplyVarName) + "->" +
497         return_type->WriteToParcelMethod();
498     b->AddStatement(new Assignment{
499         kAndroidStatusVarName, new MethodCall{writeMethod,
500         ArgList{return_type->WriteCast(kReturnVarName)}}});
501     b->AddStatement(BreakOnStatusNotOk());
502   }
503 
504   // Write each out parameter to the reply parcel.
505   for (const AidlArgument* a : method.GetOutArguments()) {
506     // Serialization looks roughly like:
507     //     _aidl_ret_status = data.WriteInt32(out_param_name);
508     //     if (_aidl_ret_status != ::android::OK) { break; }
509     const Type* type = a->GetType().GetLanguageType<Type>();
510     const string& writeMethod = type->WriteToParcelMethod();
511 
512     b->AddStatement(new Assignment{
513         kAndroidStatusVarName,
514         new MethodCall{string(kReplyVarName) + "->" + writeMethod,
515                        type->WriteCast(BuildVarName(*a))}});
516     b->AddStatement(BreakOnStatusNotOk());
517   }
518 
519   return true;
520 }
521 
522 }  // namespace
523 
BuildServerSource(const TypeNamespace & types,const AidlInterface & interface)524 unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
525                                        const AidlInterface& interface) {
526   const string bn_name = ClassName(interface, ClassNames::SERVER);
527   vector<string> include_list{
528       HeaderFile(interface, ClassNames::SERVER, false),
529       kParcelHeader
530   };
531   unique_ptr<MethodImpl> on_transact{new MethodImpl{
532       kAndroidStatusLiteral, bn_name, "onTransact",
533       ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
534                StringPrintf("const %s& %s", kAndroidParcelLiteral,
535                             kDataVarName),
536                StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
537                StringPrintf("uint32_t %s", kFlagsVarName)}}
538       }};
539 
540   // Declare the status_t variable
541   on_transact->GetStatementBlock()->AddLiteral(
542       StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
543                    kAndroidStatusOk));
544 
545   // Add the all important switch statement, but retain a pointer to it.
546   SwitchStatement* s = new SwitchStatement{kCodeVarName};
547   on_transact->GetStatementBlock()->AddStatement(s);
548 
549   // The switch statement has a case statement for each transaction code.
550   for (const auto& method : interface.GetMethods()) {
551     StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
552     if (!b) { return nullptr; }
553 
554     if (!HandleServerTransaction(types, *method, b)) { return nullptr; }
555   }
556 
557   // The switch statement has a default case which defers to the super class.
558   // The superclass handles a few pre-defined transactions.
559   StatementBlock* b = s->AddCase("");
560   b->AddLiteral(StringPrintf(
561                 "%s = ::android::BBinder::onTransact(%s, %s, "
562                 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
563                 kDataVarName, kReplyVarName, kFlagsVarName));
564 
565   // If we saw a null reference, we can map that to an appropriate exception.
566   IfStatement* null_check = new IfStatement(
567       new LiteralExpression(string(kAndroidStatusVarName) +
568                             " == ::android::UNEXPECTED_NULL"));
569   on_transact->GetStatementBlock()->AddStatement(null_check);
570   null_check->OnTrue()->AddStatement(new Assignment(
571       kAndroidStatusVarName,
572       StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
573                    ".writeToParcel(%s)",
574                    kBinderStatusLiteral, kBinderStatusLiteral,
575                    kReplyVarName)));
576 
577   // Finally, the server's onTransact method just returns a status code.
578   on_transact->GetStatementBlock()->AddLiteral(
579       StringPrintf("return %s", kAndroidStatusVarName));
580 
581   return unique_ptr<Document>{new CppSource{
582       include_list,
583       NestInNamespaces(std::move(on_transact), interface.GetSplitPackage())}};
584 }
585 
BuildInterfaceSource(const TypeNamespace &,const AidlInterface & interface)586 unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& /* types */,
587                                           const AidlInterface& interface) {
588   vector<string> include_list{
589       HeaderFile(interface, ClassNames::INTERFACE, false),
590       HeaderFile(interface, ClassNames::CLIENT, false),
591   };
592 
593   string fq_name = ClassName(interface, ClassNames::INTERFACE);
594   if (!interface.GetPackage().empty()) {
595     fq_name = interface.GetPackage() + "." + fq_name;
596   }
597 
598   vector<unique_ptr<Declaration>> decls;
599 
600   unique_ptr<MacroDecl> meta_if{new MacroDecl{
601       "IMPLEMENT_META_INTERFACE",
602       ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
603                              '"' + fq_name + '"'}}}};
604   decls.push_back(std::move(meta_if));
605 
606   for (const auto& constant: interface.GetStringConstants()) {
607     unique_ptr<MethodImpl> getter(new MethodImpl(
608         "const ::android::String16&",
609         ClassName(interface, ClassNames::INTERFACE),
610         constant->GetName(),
611         {}));
612     getter->GetStatementBlock()->AddLiteral(
613         StringPrintf("static const ::android::String16 value(%s)",
614                      constant->GetValue().c_str()));
615     getter->GetStatementBlock()->AddLiteral("return value");
616     decls.push_back(std::move(getter));
617   }
618 
619   return unique_ptr<Document>{new CppSource{
620       include_list,
621       NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
622 }
623 
BuildClientHeader(const TypeNamespace & types,const AidlInterface & interface)624 unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
625                                        const AidlInterface& interface) {
626   const string i_name = ClassName(interface, ClassNames::INTERFACE);
627   const string bp_name = ClassName(interface, ClassNames::CLIENT);
628 
629   unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
630       bp_name,
631       ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
632                            kImplVarName)},
633       ConstructorDecl::IS_EXPLICIT
634   }};
635   unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
636       "~" + bp_name,
637       ArgList{},
638       ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
639 
640   vector<unique_ptr<Declaration>> publics;
641   publics.push_back(std::move(constructor));
642   publics.push_back(std::move(destructor));
643 
644   for (const auto& method: interface.GetMethods()) {
645     publics.push_back(BuildMethodDecl(*method, types, false));
646   }
647 
648   unique_ptr<ClassDecl> bp_class{
649       new ClassDecl{bp_name,
650                     "::android::BpInterface<" + i_name + ">",
651                     std::move(publics),
652                     {}
653       }};
654 
655   return unique_ptr<Document>{new CppHeader{
656       BuildHeaderGuard(interface, ClassNames::CLIENT),
657       {kIBinderHeader,
658        kIInterfaceHeader,
659        "utils/Errors.h",
660        HeaderFile(interface, ClassNames::INTERFACE, false)},
661       NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
662 }
663 
BuildServerHeader(const TypeNamespace &,const AidlInterface & interface)664 unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
665                                        const AidlInterface& interface) {
666   const string i_name = ClassName(interface, ClassNames::INTERFACE);
667   const string bn_name = ClassName(interface, ClassNames::SERVER);
668 
669   unique_ptr<Declaration> on_transact{new MethodDecl{
670       kAndroidStatusLiteral, "onTransact",
671       ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
672                StringPrintf("const %s& %s", kAndroidParcelLiteral,
673                             kDataVarName),
674                StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
675                StringPrintf("uint32_t %s = 0", kFlagsVarName)}},
676       MethodDecl::IS_OVERRIDE
677   }};
678 
679   std::vector<unique_ptr<Declaration>> publics;
680   publics.push_back(std::move(on_transact));
681 
682   unique_ptr<ClassDecl> bn_class{
683       new ClassDecl{bn_name,
684                     "::android::BnInterface<" + i_name + ">",
685                     std::move(publics),
686                     {}
687       }};
688 
689   return unique_ptr<Document>{new CppHeader{
690       BuildHeaderGuard(interface, ClassNames::SERVER),
691       {"binder/IInterface.h",
692        HeaderFile(interface, ClassNames::INTERFACE, false)},
693       NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
694 }
695 
BuildInterfaceHeader(const TypeNamespace & types,const AidlInterface & interface)696 unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
697                                           const AidlInterface& interface) {
698   set<string> includes = { kIBinderHeader, kIInterfaceHeader,
699                            kStatusHeader, kStrongPointerHeader };
700 
701   for (const auto& method : interface.GetMethods()) {
702     for (const auto& argument : method->GetArguments()) {
703       const Type* type = argument->GetType().GetLanguageType<Type>();
704       type->GetHeaders(&includes);
705     }
706 
707     const Type* return_type = method->GetType().GetLanguageType<Type>();
708     return_type->GetHeaders(&includes);
709   }
710 
711   unique_ptr<ClassDecl> if_class{
712       new ClassDecl{ClassName(interface, ClassNames::INTERFACE),
713                     "::android::IInterface"}};
714   if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
715       "DECLARE_META_INTERFACE",
716       ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
717 
718   unique_ptr<Enum> constant_enum{new Enum{"", "int32_t"}};
719   for (const auto& constant : interface.GetIntConstants()) {
720     constant_enum->AddValue(
721         constant->GetName(), std::to_string(constant->GetValue()));
722   }
723   if (constant_enum->HasValues()) {
724     if_class->AddPublic(std::move(constant_enum));
725   }
726 
727   if (!interface.GetStringConstants().empty()) {
728     includes.insert(kString16Header);
729   }
730   for (const auto& constant : interface.GetStringConstants()) {
731     unique_ptr<MethodDecl> getter(new MethodDecl(
732           "const ::android::String16&", constant->GetName(),
733           {}, MethodDecl::IS_STATIC));
734     if_class->AddPublic(std::move(getter));
735   }
736 
737   if (!interface.GetMethods().empty()) {
738     unique_ptr<Enum> call_enum{new Enum{"Call"}};
739     for (const auto& method : interface.GetMethods()) {
740       // Each method gets an enum entry and pure virtual declaration.
741       if_class->AddPublic(BuildMethodDecl(*method, types, true));
742       call_enum->AddValue(
743           UpperCase(method->GetName()),
744           StringPrintf("::android::IBinder::FIRST_CALL_TRANSACTION + %d",
745                        method->GetId()));
746     }
747     if_class->AddPublic(std::move(call_enum));
748   }
749 
750   return unique_ptr<Document>{new CppHeader{
751       BuildHeaderGuard(interface, ClassNames::INTERFACE),
752       vector<string>(includes.begin(), includes.end()),
753       NestInNamespaces(std::move(if_class), interface.GetSplitPackage())}};
754 }
755 
WriteHeader(const CppOptions & options,const TypeNamespace & types,const AidlInterface & interface,const IoDelegate & io_delegate,ClassNames header_type)756 bool WriteHeader(const CppOptions& options,
757                  const TypeNamespace& types,
758                  const AidlInterface& interface,
759                  const IoDelegate& io_delegate,
760                  ClassNames header_type) {
761   unique_ptr<Document> header;
762   switch (header_type) {
763     case ClassNames::INTERFACE:
764       header = BuildInterfaceHeader(types, interface);
765       break;
766     case ClassNames::CLIENT:
767       header = BuildClientHeader(types, interface);
768       break;
769     case ClassNames::SERVER:
770       header = BuildServerHeader(types, interface);
771       break;
772     default:
773       LOG(FATAL) << "aidl internal error";
774   }
775   if (!header) {
776     LOG(ERROR) << "aidl internal error: Failed to generate header.";
777     return false;
778   }
779 
780   const string header_path = options.OutputHeaderDir() + OS_PATH_SEPARATOR +
781                              HeaderFile(interface, header_type);
782   unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
783   header->Write(code_writer.get());
784 
785   const bool success = code_writer->Close();
786   if (!success) {
787     io_delegate.RemovePath(header_path);
788   }
789 
790   return success;
791 }
792 
793 }  // namespace internals
794 
795 using namespace internals;
796 
HeaderFile(const AidlInterface & interface,ClassNames class_type,bool use_os_sep)797 string HeaderFile(const AidlInterface& interface,
798                   ClassNames class_type,
799                   bool use_os_sep) {
800   string file_path = interface.GetPackage();
801   for (char& c: file_path) {
802     if (c == '.') {
803       c = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
804     }
805   }
806   if (!file_path.empty()) {
807     file_path += (use_os_sep) ? OS_PATH_SEPARATOR : '/';
808   }
809   file_path += ClassName(interface, class_type);
810   file_path += ".h";
811 
812   return file_path;
813 }
814 
GenerateCpp(const CppOptions & options,const TypeNamespace & types,const AidlInterface & interface,const IoDelegate & io_delegate)815 bool GenerateCpp(const CppOptions& options,
816                  const TypeNamespace& types,
817                  const AidlInterface& interface,
818                  const IoDelegate& io_delegate) {
819   auto interface_src = BuildInterfaceSource(types, interface);
820   auto client_src = BuildClientSource(types, interface);
821   auto server_src = BuildServerSource(types, interface);
822 
823   if (!interface_src || !client_src || !server_src) {
824     return false;
825   }
826 
827   if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(),
828                                      interface.GetSplitPackage())) {
829     LOG(ERROR) << "Failed to create directory structure for headers.";
830     return false;
831   }
832 
833   if (!WriteHeader(options, types, interface, io_delegate,
834                    ClassNames::INTERFACE) ||
835       !WriteHeader(options, types, interface, io_delegate,
836                    ClassNames::CLIENT) ||
837       !WriteHeader(options, types, interface, io_delegate,
838                    ClassNames::SERVER)) {
839     return false;
840   }
841 
842   unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(
843       options.OutputCppFilePath());
844   interface_src->Write(writer.get());
845   client_src->Write(writer.get());
846   server_src->Write(writer.get());
847 
848   const bool success = writer->Close();
849   if (!success) {
850     io_delegate.RemovePath(options.OutputCppFilePath());
851   }
852 
853   return success;
854 }
855 
856 }  // namespace cpp
857 }  // namespace aidl
858 }  // namespace android
859