1eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley/*
2eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * Copyright (C) 2015, The Android Open Source Project
3eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley *
4eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * Licensed under the Apache License, Version 2.0 (the "License");
5eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * you may not use this file except in compliance with the License.
6eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * You may obtain a copy of the License at
7eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley *
8eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley *     http://www.apache.org/licenses/LICENSE-2.0
9eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley *
10eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * Unless required by applicable law or agreed to in writing, software
11eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * distributed under the License is distributed on an "AS IS" BASIS,
12eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * See the License for the specific language governing permissions and
14eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley * limitations under the License.
15eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley */
16eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley
17eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley#include "generate_cpp.h"
189a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
19082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin#include <cctype>
20ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley#include <cstring>
219a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley#include <memory>
22082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin#include <random>
23ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin#include <set>
249a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley#include <string>
259a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
260a62067f35e957493bc37c4b42dfdcfc16353831Elliott Hughes#include <android-base/stringprintf.h>
27e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wiley
28a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin#include "aidl_language.h"
299a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley#include "ast_cpp.h"
309a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley#include "code_writer.h"
31eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley#include "logging.h"
32054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley#include "os.h"
33eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley
34e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wileyusing android::base::StringPrintf;
359a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wileyusing std::string;
36082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlinusing std::unique_ptr;
37a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlinusing std::vector;
38ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlinusing std::set;
399a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
40eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wileynamespace android {
41eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wileynamespace aidl {
42f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wileynamespace cpp {
43a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlinnamespace internals {
440c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wileynamespace {
4536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
46b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kAndroidStatusVarName[] = "_aidl_ret_status";
47b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kCodeVarName[] = "_aidl_code";
48b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kFlagsVarName[] = "_aidl_flags";
49b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kDataVarName[] = "_aidl_data";
50b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kErrorLabel[] = "_aidl_error";
51b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kImplVarName[] = "_aidl_impl";
52b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kReplyVarName[] = "_aidl_reply";
53ad3392747003a30928da6cd206e41f66398c2062Christopher Wileyconst char kReturnVarName[] = "_aidl_return";
54b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kStatusVarName[] = "_aidl_status";
55b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kAndroidParcelLiteral[] = "::android::Parcel";
56b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kAndroidStatusLiteral[] = "::android::status_t";
57b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kAndroidStatusOk[] = "::android::OK";
58b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlinconst char kBinderStatusLiteral[] = "::android::binder::Status";
590c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wileyconst char kIBinderHeader[] = "binder/IBinder.h";
600c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wileyconst char kIInterfaceHeader[] = "binder/IInterface.h";
61ad3392747003a30928da6cd206e41f66398c2062Christopher Wileyconst char kParcelHeader[] = "binder/Parcel.h";
62433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wileyconst char kStatusHeader[] = "binder/Status.h";
6369b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wileyconst char kString16Header[] = "utils/String16.h";
64389781f56bb6b4363e9eb03acf915ba297f607d5Casey Dahlinconst char kStrongPointerHeader[] = "utils/StrongPointer.h";
65082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin
660eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wileyunique_ptr<AstNode> BreakOnStatusNotOk() {
670eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley  IfStatement* ret = new IfStatement(new Comparison(
68b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(kAndroidStatusVarName), "!=",
69b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(kAndroidStatusOk)));
700eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley  ret->OnTrue()->AddLiteral("break");
710eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley  return unique_ptr<AstNode>(ret);
720eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley}
730eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley
74433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wileyunique_ptr<AstNode> GotoErrorOnBadStatus() {
75433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  IfStatement* ret = new IfStatement(new Comparison(
76b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(kAndroidStatusVarName), "!=",
77b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(kAndroidStatusOk)));
78b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
79433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  return unique_ptr<AstNode>(ret);
80433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley}
81433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley
82433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley
830eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wileyunique_ptr<AstNode> ReturnOnStatusNotOk() {
840eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley  IfStatement* ret = new IfStatement(new Comparison(
85b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(kAndroidStatusVarName), "!=",
86b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(kAndroidStatusOk)));
87b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
880eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley  return unique_ptr<AstNode>(ret);
890eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley}
900eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley
910c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wileystring UpperCase(const std::string& s) {
920c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  string result = s;
930c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  for (char& c : result)
940c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    c = toupper(c);
950c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  return result;
96a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin}
97a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin
98ad3392747003a30928da6cd206e41f66398c2062Christopher Wileystring BuildVarName(const AidlArgument& a) {
99ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  string prefix = "out_";
100ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  if (a.GetDirection() & AidlArgument::IN_DIR) {
101ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    prefix = "in_";
102e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wiley  }
103ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  return prefix + a.GetName();
104082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin}
105082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin
106ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher WileyArgList BuildArgList(const TypeNamespace& types,
107ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley                     const AidlMethod& method,
108ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley                     bool for_declaration) {
109ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Build up the argument list for the server method call.
110ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  vector<string> method_arguments;
111ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
112ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    string literal;
113ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    if (for_declaration) {
114ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley      // Method declarations need types, pointers to out params, and variable
115ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley      // names that match the .aidl specification.
116a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin      const Type* type = a->GetType().GetLanguageType<Type>();
117ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin
118a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin      literal = type->CppType();
119b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
120b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley      if (a->IsOut()) {
121b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley        literal = literal + "*";
122b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley      } else {
123b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley        // We pass in parameters that are not primitives by const reference.
124b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley        // Arrays of primitives are not primitives.
125b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley        if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
126b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley          literal = "const " + literal + "&";
127b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley        }
128b8e49a407e8648afb28ca9bad4bf8434224f0b18Christopher Wiley      }
129b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
130b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin      literal += " " + a->GetName();
131ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    } else {
132ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley      if (a->IsOut()) { literal = "&"; }
133ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley      literal += BuildVarName(*a);
134ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    }
135ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    method_arguments.push_back(literal);
136ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  }
137ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
138a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin  const Type* return_type = method.GetType().GetLanguageType<Type>();
139ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin
140ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  if (return_type != types.VoidType()) {
141ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley    string literal;
142ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    if (for_declaration) {
143ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley      literal = StringPrintf(
144a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin          "%s* %s", return_type->CppType().c_str(),
145b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin          kReturnVarName);
146ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    } else {
147ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley      literal = string{"&"} + kReturnVarName;
148ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    }
149ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley    method_arguments.push_back(literal);
1500c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  }
1510c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
152ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley  return ArgList(method_arguments);
153ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley}
1540c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
155ad3392747003a30928da6cd206e41f66398c2062Christopher Wileyunique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
156ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley                                        const TypeNamespace& types,
157ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley                                        bool for_interface) {
1580c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  uint32_t modifiers = 0;
1590c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  if (for_interface) {
1600c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    modifiers |= MethodDecl::IS_VIRTUAL;
1610c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    modifiers |= MethodDecl::IS_PURE_VIRTUAL;
1620c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  } else {
1630c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    modifiers |= MethodDecl::IS_OVERRIDE;
1640c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  }
1650c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
1660c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  return unique_ptr<Declaration>{
167433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley      new MethodDecl{kBinderStatusLiteral,
168f4a9311fa018c78a7b30a73bd8ebbaa33c701ae4Casey Dahlin                     method.GetName(),
169ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley                     BuildArgList(types, method, true /* for method decl */),
1700c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley                     modifiers}};
1710c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley}
1720c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
173b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wileyunique_ptr<CppNamespace> NestInNamespaces(
174b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley    vector<unique_ptr<Declaration>> decls,
175b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley    const vector<string>& package) {
176b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  if (package.empty()) {
177b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley    // We should also be checking this before we get this far, but do it again
178b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley    // for the sake of unit tests and meaningful errors.
179b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley    LOG(FATAL) << "C++ generation requires a package declaration "
180b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley                  "for namespacing";
181b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  }
182b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  auto it = package.crbegin();  // Iterate over the namespaces inner to outer
183b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  unique_ptr<CppNamespace> inner{new CppNamespace{*it, std::move(decls)}};
184b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  ++it;
185b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  for (; it != package.crend(); ++it) {
186b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley    inner.reset(new CppNamespace{*it, std::move(inner)});
187b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  }
188b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  return inner;
1890c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley}
1900c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
191b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wileyunique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl,
192b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley                                          const vector<string>& package) {
193b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  vector<unique_ptr<Declaration>> decls;
194b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  decls.push_back(std::move(decl));
195b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley  return NestInNamespaces(std::move(decls), package);
19636570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley}
19736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
198ad3392747003a30928da6cd206e41f66398c2062Christopher Wileybool DeclareLocalVariable(const TypeNamespace& types, const AidlArgument& a,
199ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley                          StatementBlock* b) {
200a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin  const Type* cpp_type = a.GetType().GetLanguageType<Type>();
201ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  if (!cpp_type) { return false; }
202ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
203a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin  string type = cpp_type->CppType();
204b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
205b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin  b->AddLiteral(type + " " + BuildVarName(a));
206ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  return true;
207ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley}
208ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
2091ae2bc56d20fe0e19262f2721abc338662fa6e30Casey Dahlinstring ClassName(const AidlInterface& interface, ClassNames type) {
210fb7da2e62fe66b0a57ffbb0304f5884024a68f1cCasey Dahlin  string c_name = interface.GetName();
2110c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
2120c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  if (c_name.length() >= 2 && c_name[0] == 'I' && isupper(c_name[1]))
2130c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    c_name = c_name.substr(1);
2140c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
2150c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  switch (type) {
2160c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    case ClassNames::CLIENT:
2170c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      c_name = "Bp" + c_name;
2180c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      break;
2190c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    case ClassNames::SERVER:
2200c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      c_name = "Bn" + c_name;
2210c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      break;
2220c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    case ClassNames::INTERFACE:
2230c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      c_name = "I" + c_name;
2240c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      break;
2250c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley    case ClassNames::BASE:
2260c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      break;
2270c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  }
2280c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  return c_name;
2290c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley}
2300c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
2313bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wileystring BuildHeaderGuard(const AidlInterface& interface,
2323bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley                        ClassNames header_type) {
2333bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  string class_name = ClassName(interface, header_type);
2343bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  for (size_t i = 1; i < class_name.size(); ++i) {
2353bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley    if (isupper(class_name[i])) {
2363bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      class_name.insert(i, "_");
2373bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      ++i;
2383bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley    }
2393bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  }
2403bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_",
2413bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley                            interface.GetPackage().c_str(),
2423bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley                            class_name.c_str());
2433bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  for (char& c : ret) {
2443bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley    if (c == '.') {
2453bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      c = '_';
2463bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley    }
2473bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley    c = toupper(c);
2483bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  }
2493bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  return ret;
2503bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley}
25136570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
25236570f4779a413ebef9302d1563fd92917ec2e42Christopher Wileyunique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
25336570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley                                                const AidlInterface& interface,
25436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley                                                const AidlMethod& method) {
25536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  const string i_name = ClassName(interface, ClassNames::INTERFACE);
25636570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  const string bp_name = ClassName(interface, ClassNames::CLIENT);
25736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  unique_ptr<MethodImpl> ret{new MethodImpl{
258433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley      kBinderStatusLiteral, bp_name, method.GetName(),
25936570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley      ArgList{BuildArgList(types, method, true /* for method decl */)}}};
26036570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  StatementBlock* b = ret->GetStatementBlock();
26136570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
26236570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // Declare parcels to hold our query and the response.
263b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
2641227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley  // Even if we're oneway, the transact method still takes a parcel.
265b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
2660dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin
267433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // Declare the status_t variable we need for error handling.
2681095712f27931cb64d398d77201036cdcef0a296Christopher Wiley  b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
2691095712f27931cb64d398d77201036cdcef0a296Christopher Wiley                             kAndroidStatusVarName,
2701095712f27931cb64d398d77201036cdcef0a296Christopher Wiley                             kAndroidStatusOk));
271433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // We unconditionally return a Status object.
272433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
27336570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
2748993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  // Add the name of the interface we're hoping to call.
2758993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  b->AddStatement(new Assignment(
276b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      kAndroidStatusVarName,
277b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new MethodCall(StringPrintf("%s.writeInterfaceToken",
278b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                                  kDataVarName),
279b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                     "getInterfaceDescriptor()")));
280433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  b->AddStatement(GotoErrorOnBadStatus());
2818993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley
28274b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley  for (const auto& a: method.GetArguments()) {
283a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin    const Type* type = a->GetType().GetLanguageType<Type>();
28436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
285389781f56bb6b4363e9eb03acf915ba297f607d5Casey Dahlin    var_name = type->WriteCast(var_name);
28674b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley
28774b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley    if (a->IsIn()) {
28874b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      // Serialization looks roughly like:
28974b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      //     _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
29074b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      //     if (_aidl_ret_status != ::android::OK) { goto error; }
29174b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      const string& method = type->WriteToParcelMethod();
29274b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(new Assignment(
29374b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          kAndroidStatusVarName,
29474b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
29574b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley                         ArgList(var_name))));
29674b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(GotoErrorOnBadStatus());
29774b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley    } else if (a->IsOut() && a->GetType().IsArray()) {
29874b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      // Special case, the length of the out array is written into the parcel.
29974b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      //     _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
30074b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      //     if (_aidl_ret_status != ::android::OK) { goto error; }
30174b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(new Assignment(
30274b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          kAndroidStatusVarName,
30374b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
30474b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley                         ArgList(var_name))));
30574b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(GotoErrorOnBadStatus());
30674b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley    }
30736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  }
30836570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
30936570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // Invoke the transaction on the remote binder and confirm status.
31036570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  string transaction_code = StringPrintf(
31136570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley      "%s::%s", i_name.c_str(), UpperCase(method.GetName()).c_str());
3120dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin
313b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  vector<string> args = {transaction_code, kDataVarName,
314b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                         StringPrintf("&%s", kReplyVarName)};
3150dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin
3160dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin  if (interface.IsOneway() || method.IsOneway()) {
317b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    args.push_back("::android::IBinder::FLAG_ONEWAY");
3180dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin  }
3190dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin
32036570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  b->AddStatement(new Assignment(
321b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      kAndroidStatusVarName,
32236570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley      new MethodCall("remote()->transact",
3230dd08af9e6145fb746e96e7ecc5e4c2096de3a6eCasey Dahlin                     ArgList(args))));
324433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  b->AddStatement(GotoErrorOnBadStatus());
32536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
3261227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley  if (!interface.IsOneway() && !method.IsOneway()) {
3271227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley    // Strip off the exception header and fail if we see a remote exception.
328b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
329b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    // if (_aidl_ret_status != ::android::OK) { goto error; }
330b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
331433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(new Assignment(
332b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        kAndroidStatusVarName,
333b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
334433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(GotoErrorOnBadStatus());
3351227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley    IfStatement* exception_check = new IfStatement(
336433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley        new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
3371227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley    b->AddStatement(exception_check);
338433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    exception_check->OnTrue()->AddLiteral(
339433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley        StringPrintf("return %s", kStatusVarName));
3401227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley  }
3411227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley
3421227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley  // Type checking should guarantee that nothing below emits code until "return
3431227d6135418a6a876666adcf4f8d9b498f17647Christopher Wiley  // status" if we are a oneway method, so no more fear of accessing reply.
3442aaeda8b140de83f2cb2d51405ea27ccf1eefc13Christopher Wiley
34536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // If the method is expected to return something, read it first by convention.
346a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin  const Type* return_type = method.GetType().GetLanguageType<Type>();
34736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  if (return_type != types.VoidType()) {
348f05cc26630828c848e46ea0e584dbdd2541ea723Chih-Hung Hsieh    const string& method_call = return_type->ReadFromParcelMethod();
34936570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    b->AddStatement(new Assignment(
350b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        kAndroidStatusVarName,
351b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        new MethodCall(StringPrintf("%s.%s", kReplyVarName,
352b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                                    method_call.c_str()),
353b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                       ArgList(kReturnVarName))));
354433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(GotoErrorOnBadStatus());
35536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  }
35636570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
35736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  for (const AidlArgument* a : method.GetOutArguments()) {
35836570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    // Deserialization looks roughly like:
359b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    //     _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
360b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    //     if (_aidl_status != ::android::OK) { goto _aidl_error; }
361b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin    string method =
362a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin      a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
363b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
36436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    b->AddStatement(new Assignment(
365b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        kAndroidStatusVarName,
366b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        new MethodCall(StringPrintf("%s.%s", kReplyVarName,
367b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                                    method.c_str()),
368b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                       ArgList(a->GetName()))));
369433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(GotoErrorOnBadStatus());
37036570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  }
37136570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
372433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // If we've gotten to here, one of two things is true:
373433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  //   1) We've read some bad status_t
374433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  //   2) We've only read status_t == OK and there was no exception in the
375433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  //      response.
376433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // In both cases, we're free to set Status from the status_t and return.
377b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
378433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  b->AddLiteral(
379b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
380b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                   kAndroidStatusVarName));
381433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  b->AddLiteral(StringPrintf("return %s", kStatusVarName));
38236570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
38336570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  return unique_ptr<Declaration>(ret.release());
38436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley}
38536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
38636570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley}  // namespace
38736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
388e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wileyunique_ptr<Document> BuildClientSource(const TypeNamespace& types,
38936570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley                                       const AidlInterface& interface) {
390054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  vector<string> include_list = {
391054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      HeaderFile(interface, ClassNames::CLIENT, false),
392054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      kParcelHeader
393054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  };
39436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  vector<unique_ptr<Declaration>> file_decls;
39536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
39636570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // The constructor just passes the IBinder instance up to the super
39736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // class.
3981db03482145137749602c830a593494498f5be55Christopher Wiley  const string i_name = ClassName(interface, ClassNames::INTERFACE);
39936570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
400054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      ClassName(interface, ClassNames::CLIENT),
401b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
402b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                           kImplVarName)},
403b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
40436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
40536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // Clients define a method per transaction.
40636570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  for (const auto& method : interface.GetMethods()) {
40736570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    unique_ptr<Declaration> m = DefineClientTransaction(
40836570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley        types, interface, *method);
40936570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    if (!m) { return nullptr; }
41036570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    file_decls.push_back(std::move(m));
41136570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  }
41236570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  return unique_ptr<Document>{new CppSource{
41336570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley      include_list,
414b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley      NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
4159a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley}
4169a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
417ad3392747003a30928da6cd206e41f66398c2062Christopher Wileynamespace {
418ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
419ad3392747003a30928da6cd206e41f66398c2062Christopher Wileybool HandleServerTransaction(const TypeNamespace& types,
420ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley                             const AidlMethod& method,
421ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley                             StatementBlock* b) {
422ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Declare all the parameters now.  In the common case, we expect no errors
423ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // in serialization.
424ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
425ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    if (!DeclareLocalVariable(types, *a, b)) { return false; }
426ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  }
427ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
428ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Declare a variable to hold the return value.
429a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin  const Type* return_type = method.GetType().GetLanguageType<Type>();
430ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  if (return_type != types.VoidType()) {
431ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    b->AddLiteral(StringPrintf(
432a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin        "%s %s", return_type->CppType().c_str(),
433b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin        kReturnVarName));
434ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  }
435ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
4368993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  // Check that the client is calling the correct interface.
4378993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  IfStatement* interface_check = new IfStatement(
438b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new MethodCall(StringPrintf("%s.checkInterface",
439b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                                  kDataVarName), "this"),
4408993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley      true /* invert the check */);
4418993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  b->AddStatement(interface_check);
4428993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  interface_check->OnTrue()->AddStatement(
443b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
4448993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley  interface_check->OnTrue()->AddLiteral("break");
4458993cb5f297f9e329470d75f02a7b3e3a4bc64a5Christopher Wiley
446ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Deserialize each "in" parameter to the transaction.
44774b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley  for (const auto& a: method.GetArguments()) {
448ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    // Deserialization looks roughly like:
449b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    //     _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
450b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    //     if (_aidl_ret_status != ::android::OK) { break; }
451a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin    const Type* type = a->GetType().GetLanguageType<Type>();
452f05cc26630828c848e46ea0e584dbdd2541ea723Chih-Hung Hsieh    const string& readMethod = type->ReadFromParcelMethod();
453b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
45474b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley    if (a->IsIn()) {
45574b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(new Assignment{
45674b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          kAndroidStatusVarName,
45774b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          new MethodCall{string(kDataVarName) + "." + readMethod,
45874b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley                         "&" + BuildVarName(*a)}});
45974b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(BreakOnStatusNotOk());
46074b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley    } else if (a->IsOut() && a->GetType().IsArray()) {
46174b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      // Special case, the length of the out array is written into the parcel.
46274b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      //     _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
46374b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      //     if (_aidl_ret_status != ::android::OK) { break; }
46474b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(new Assignment{
46574b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          kAndroidStatusVarName,
46674b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley          new MethodCall{string(kDataVarName) + ".resizeOutVector",
46774b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley                         "&" + BuildVarName(*a)}});
46874b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley      b->AddStatement(BreakOnStatusNotOk());
46974b7bf1043d1905e6f999f7c47920319029453c0Christopher Wiley    }
470ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  }
471ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
472ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Call the actual method.  This is implemented by the subclass.
473433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  vector<unique_ptr<AstNode>> status_args;
474433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  status_args.emplace_back(new MethodCall(
475ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley          method.GetName(),
476433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley          BuildArgList(types, method, false /* not for method decl */)));
477433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  b->AddStatement(new Statement(new MethodCall(
478433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley      StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
479433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley      ArgList(std::move(status_args)))));
480ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
481433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // Write exceptions during transaction handling to parcel.
482433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  if (!method.IsOneway()) {
483433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(new Assignment(
484b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        kAndroidStatusVarName,
485b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
486433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(BreakOnStatusNotOk());
487433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    IfStatement* exception_check = new IfStatement(
488433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley        new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
489433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    b->AddStatement(exception_check);
490433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley    exception_check->OnTrue()->AddLiteral("break");
491433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  }
492b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
49336570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  // If we have a return value, write it first.
49436570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  if (return_type != types.VoidType()) {
4952aaeda8b140de83f2cb2d51405ea27ccf1eefc13Christopher Wiley    string writeMethod =
496b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        string(kReplyVarName) + "->" +
497a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin        return_type->WriteToParcelMethod();
49836570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    b->AddStatement(new Assignment{
499b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        kAndroidStatusVarName, new MethodCall{writeMethod,
500389781f56bb6b4363e9eb03acf915ba297f607d5Casey Dahlin        ArgList{return_type->WriteCast(kReturnVarName)}}});
5010eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley    b->AddStatement(BreakOnStatusNotOk());
50236570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley  }
50336570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley
504ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Write each out parameter to the reply parcel.
505ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  for (const AidlArgument* a : method.GetOutArguments()) {
506ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    // Serialization looks roughly like:
507b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    //     _aidl_ret_status = data.WriteInt32(out_param_name);
508b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin    //     if (_aidl_ret_status != ::android::OK) { break; }
509a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin    const Type* type = a->GetType().GetLanguageType<Type>();
510f05cc26630828c848e46ea0e584dbdd2541ea723Chih-Hung Hsieh    const string& writeMethod = type->WriteToParcelMethod();
511b0966619850093e117104dc34d8a6ae4c56ea3ffCasey Dahlin
512ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    b->AddStatement(new Assignment{
513b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        kAndroidStatusVarName,
514b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin        new MethodCall{string(kReplyVarName) + "->" + writeMethod,
515389781f56bb6b4363e9eb03acf915ba297f607d5Casey Dahlin                       type->WriteCast(BuildVarName(*a))}});
5160eb903eff2376941ad7e947bd5d3a32e15d89f69Christopher Wiley    b->AddStatement(BreakOnStatusNotOk());
517ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  }
518ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
519ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  return true;
520ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley}
521ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
522ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley}  // namespace
523ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
524e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wileyunique_ptr<Document> BuildServerSource(const TypeNamespace& types,
525054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                                       const AidlInterface& interface) {
526054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  const string bn_name = ClassName(interface, ClassNames::SERVER);
527054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  vector<string> include_list{
528054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      HeaderFile(interface, ClassNames::SERVER, false),
529054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      kParcelHeader
530054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  };
531ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  unique_ptr<MethodImpl> on_transact{new MethodImpl{
532ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley      kAndroidStatusLiteral, bn_name, "onTransact",
533b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
534b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin               StringPrintf("const %s& %s", kAndroidParcelLiteral,
535b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                            kDataVarName),
536b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin               StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
537b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin               StringPrintf("uint32_t %s", kFlagsVarName)}}
53836570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley      }};
539ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
540433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // Declare the status_t variable
54105f4f890cad7b2a510e8e1f80fa5884db1bd8383Christopher Wiley  on_transact->GetStatementBlock()->AddLiteral(
5421095712f27931cb64d398d77201036cdcef0a296Christopher Wiley      StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
5431095712f27931cb64d398d77201036cdcef0a296Christopher Wiley                   kAndroidStatusOk));
54405f4f890cad7b2a510e8e1f80fa5884db1bd8383Christopher Wiley
545ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Add the all important switch statement, but retain a pointer to it.
546b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  SwitchStatement* s = new SwitchStatement{kCodeVarName};
547f9688b04c9e34063e8b2dffab4827e02f4f104faChristopher Wiley  on_transact->GetStatementBlock()->AddStatement(s);
548ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
549ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // The switch statement has a case statement for each transaction code.
550054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  for (const auto& method : interface.GetMethods()) {
551ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
552ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    if (!b) { return nullptr; }
553ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
554ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley    if (!HandleServerTransaction(types, *method, b)) { return nullptr; }
555ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  }
556ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
557ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // The switch statement has a default case which defers to the super class.
558ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // The superclass handles a few pre-defined transactions.
559ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  StatementBlock* b = s->AddCase("");
560b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  b->AddLiteral(StringPrintf(
561b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                "%s = ::android::BBinder::onTransact(%s, %s, "
562b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                "%s, %s)", kAndroidStatusVarName, kCodeVarName,
563b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                kDataVarName, kReplyVarName, kFlagsVarName));
564ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
565433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  // If we saw a null reference, we can map that to an appropriate exception.
566433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  IfStatement* null_check = new IfStatement(
567b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      new LiteralExpression(string(kAndroidStatusVarName) +
568b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                            " == ::android::UNEXPECTED_NULL"));
569433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  on_transact->GetStatementBlock()->AddStatement(null_check);
570433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley  null_check->OnTrue()->AddStatement(new Assignment(
571b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      kAndroidStatusVarName,
572433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley      StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
573b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                   ".writeToParcel(%s)",
574b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                   kBinderStatusLiteral, kBinderStatusLiteral,
575b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                   kReplyVarName)));
576433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley
577ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  // Finally, the server's onTransact method just returns a status code.
578b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin  on_transact->GetStatementBlock()->AddLiteral(
579b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      StringPrintf("return %s", kAndroidStatusVarName));
580ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley
581ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley  return unique_ptr<Document>{new CppSource{
582ad3392747003a30928da6cd206e41f66398c2062Christopher Wiley      include_list,
583b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley      NestInNamespaces(std::move(on_transact), interface.GetSplitPackage())}};
5849a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley}
5859a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
586f59c49950aea9d5d0111a4558b58c336c9091ea6Christopher Wileyunique_ptr<Document> BuildInterfaceSource(const TypeNamespace& /* types */,
587054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                                          const AidlInterface& interface) {
588054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  vector<string> include_list{
589054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      HeaderFile(interface, ClassNames::INTERFACE, false),
590054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      HeaderFile(interface, ClassNames::CLIENT, false),
591054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  };
592054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
593054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  string fq_name = ClassName(interface, ClassNames::INTERFACE);
594054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  if (!interface.GetPackage().empty()) {
595054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    fq_name = interface.GetPackage() + "." + fq_name;
5961dd458d3e3647823acb9554f8ae17631d597a1ecChristopher Wiley  }
5971dd458d3e3647823acb9554f8ae17631d597a1ecChristopher Wiley
59869b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  vector<unique_ptr<Declaration>> decls;
59969b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley
60011a9d79a1189bbfa5b64a77b32f1a947ad91f0ddChristopher Wiley  unique_ptr<MacroDecl> meta_if{new MacroDecl{
6011dd458d3e3647823acb9554f8ae17631d597a1ecChristopher Wiley      "IMPLEMENT_META_INTERFACE",
602054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
603ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley                             '"' + fq_name + '"'}}}};
60469b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  decls.push_back(std::move(meta_if));
60569b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley
60669b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  for (const auto& constant: interface.GetStringConstants()) {
60769b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    unique_ptr<MethodImpl> getter(new MethodImpl(
60869b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley        "const ::android::String16&",
60969b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley        ClassName(interface, ClassNames::INTERFACE),
61069b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley        constant->GetName(),
61169b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley        {}));
61269b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    getter->GetStatementBlock()->AddLiteral(
61369b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley        StringPrintf("static const ::android::String16 value(%s)",
61469b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley                     constant->GetValue().c_str()));
61569b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    getter->GetStatementBlock()->AddLiteral("return value");
61669b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    decls.push_back(std::move(getter));
61769b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  }
6181dd458d3e3647823acb9554f8ae17631d597a1ecChristopher Wiley
6191dd458d3e3647823acb9554f8ae17631d597a1ecChristopher Wiley  return unique_ptr<Document>{new CppSource{
6201dd458d3e3647823acb9554f8ae17631d597a1ecChristopher Wiley      include_list,
62169b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley      NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
6229a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley}
6239a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
624e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wileyunique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
6253bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley                                       const AidlInterface& interface) {
6263bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  const string i_name = ClassName(interface, ClassNames::INTERFACE);
6273bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  const string bp_name = ClassName(interface, ClassNames::CLIENT);
628082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin
629b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley  unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
630b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley      bp_name,
631b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
632b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                           kImplVarName)},
633b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley      ConstructorDecl::IS_EXPLICIT
634b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley  }};
635b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley  unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
636b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley      "~" + bp_name,
637b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley      ArgList{},
638b23149dbc77744864b78edeb9f9cbb2f94f8c06dChristopher Wiley      ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
639a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin
640f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley  vector<unique_ptr<Declaration>> publics;
641a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin  publics.push_back(std::move(constructor));
642a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin  publics.push_back(std::move(destructor));
643082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin
6443bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  for (const auto& method: interface.GetMethods()) {
64536570f4779a413ebef9302d1563fd92917ec2e42Christopher Wiley    publics.push_back(BuildMethodDecl(*method, types, false));
646a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin  }
647a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin
648f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley  unique_ptr<ClassDecl> bp_class{
649f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley      new ClassDecl{bp_name,
650b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                    "::android::BpInterface<" + i_name + ">",
651f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley                    std::move(publics),
652f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley                    {}
653a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin      }};
654a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin
6550c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  return unique_ptr<Document>{new CppHeader{
6563bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      BuildHeaderGuard(interface, ClassNames::CLIENT),
6570c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      {kIBinderHeader,
6580c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley       kIInterfaceHeader,
6590c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley       "utils/Errors.h",
660054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley       HeaderFile(interface, ClassNames::INTERFACE, false)},
661b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley      NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
662a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin}
663a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin
664f59c49950aea9d5d0111a4558b58c336c9091ea6Christopher Wileyunique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
665fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley                                       const AidlInterface& interface) {
666fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley  const string i_name = ClassName(interface, ClassNames::INTERFACE);
667fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley  const string bn_name = ClassName(interface, ClassNames::SERVER);
668082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin
669fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley  unique_ptr<Declaration> on_transact{new MethodDecl{
670ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley      kAndroidStatusLiteral, "onTransact",
671b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin      ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
672b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin               StringPrintf("const %s& %s", kAndroidParcelLiteral,
673b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                            kDataVarName),
674b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin               StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
675b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin               StringPrintf("uint32_t %s = 0", kFlagsVarName)}},
676fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley      MethodDecl::IS_OVERRIDE
677fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley  }};
678082f1d172dbc9de990a04c26b55972faf812771bCasey Dahlin
679f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley  std::vector<unique_ptr<Declaration>> publics;
680b7d0f7f4bb08171e025659d17cd3bb57b35b739aCasey Dahlin  publics.push_back(std::move(on_transact));
681b7d0f7f4bb08171e025659d17cd3bb57b35b739aCasey Dahlin
682f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley  unique_ptr<ClassDecl> bn_class{
683f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley      new ClassDecl{bn_name,
684b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                    "::android::BnInterface<" + i_name + ">",
685f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley                    std::move(publics),
686f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley                    {}
687b7d0f7f4bb08171e025659d17cd3bb57b35b739aCasey Dahlin      }};
688b7d0f7f4bb08171e025659d17cd3bb57b35b739aCasey Dahlin
6890c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  return unique_ptr<Document>{new CppHeader{
690fd51d60f486f1ad514e6f24744ebffab7a3d89bdChristopher Wiley      BuildHeaderGuard(interface, ClassNames::SERVER),
6910c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley      {"binder/IInterface.h",
692054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley       HeaderFile(interface, ClassNames::INTERFACE, false)},
693b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley      NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
6949a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley}
6959a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
696e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wileyunique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
6973bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley                                          const AidlInterface& interface) {
698389781f56bb6b4363e9eb03acf915ba297f607d5Casey Dahlin  set<string> includes = { kIBinderHeader, kIInterfaceHeader,
699433c8bbdfa1ee6db10b7f08d3c50eafd49ad2687Christopher Wiley                           kStatusHeader, kStrongPointerHeader };
700ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin
701ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin  for (const auto& method : interface.GetMethods()) {
702ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin    for (const auto& argument : method->GetArguments()) {
703a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin      const Type* type = argument->GetType().GetLanguageType<Type>();
704a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin      type->GetHeaders(&includes);
705ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin    }
706ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin
707a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin    const Type* return_type = method->GetType().GetLanguageType<Type>();
708a2f77c40fb6287895e2030055c0104eac0a1f73aCasey Dahlin    return_type->GetHeaders(&includes);
709ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin  }
710ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin
7110c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  unique_ptr<ClassDecl> if_class{
7123bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      new ClassDecl{ClassName(interface, ClassNames::INTERFACE),
713b8d9e8898c34da45027e56be88d5c9238ea88203Casey Dahlin                    "::android::IInterface"}};
71411a9d79a1189bbfa5b64a77b32f1a947ad91f0ddChristopher Wiley  if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
715ade4b45d8d9e922aca70d0995f2fb8a170de838bChristopher Wiley      "DECLARE_META_INTERFACE",
7163bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
7170c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
718fd7dc03fdd1e0cd558df43a155ab1644cbe2b553Christopher Wiley  unique_ptr<Enum> constant_enum{new Enum{"", "int32_t"}};
719d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley  for (const auto& constant : interface.GetIntConstants()) {
720fd7dc03fdd1e0cd558df43a155ab1644cbe2b553Christopher Wiley    constant_enum->AddValue(
721fd7dc03fdd1e0cd558df43a155ab1644cbe2b553Christopher Wiley        constant->GetName(), std::to_string(constant->GetValue()));
722fd7dc03fdd1e0cd558df43a155ab1644cbe2b553Christopher Wiley  }
723fd7dc03fdd1e0cd558df43a155ab1644cbe2b553Christopher Wiley  if (constant_enum->HasValues()) {
724fd7dc03fdd1e0cd558df43a155ab1644cbe2b553Christopher Wiley    if_class->AddPublic(std::move(constant_enum));
725d40e2fed2c19850d53f1620322ac5cbca2c0e245Casey Dahlin  }
726d40e2fed2c19850d53f1620322ac5cbca2c0e245Casey Dahlin
72769b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  if (!interface.GetStringConstants().empty()) {
72869b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    includes.insert(kString16Header);
72969b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  }
73069b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  for (const auto& constant : interface.GetStringConstants()) {
73169b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    unique_ptr<MethodDecl> getter(new MethodDecl(
73269b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley          "const ::android::String16&", constant->GetName(),
73369b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley          {}, MethodDecl::IS_STATIC));
73469b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley    if_class->AddPublic(std::move(getter));
73569b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley  }
73669b44cf003bd5bda9dcd97a6fe872630c1b2818fChristopher Wiley
737d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley  if (!interface.GetMethods().empty()) {
738d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley    unique_ptr<Enum> call_enum{new Enum{"Call"}};
739d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley    for (const auto& method : interface.GetMethods()) {
740d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley      // Each method gets an enum entry and pure virtual declaration.
741d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley      if_class->AddPublic(BuildMethodDecl(*method, types, true));
742d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley      call_enum->AddValue(
743d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley          UpperCase(method->GetName()),
744d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley          StringPrintf("::android::IBinder::FIRST_CALL_TRANSACTION + %d",
745d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley                       method->GetId()));
746d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley    }
747d6bdd8d7cfb0a96ccc826cbb005128f0f7ca3446Christopher Wiley    if_class->AddPublic(std::move(call_enum));
7480c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley  }
7490c732dbae2e6b33cde9a266ea091e1459742f1f1Christopher Wiley
7503bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley  return unique_ptr<Document>{new CppHeader{
7513bb6bc1d481459cc9ec93b764d245040b78e6507Christopher Wiley      BuildHeaderGuard(interface, ClassNames::INTERFACE),
752ce776cfc9560ee541464a23fb64ecd74e442b96fCasey Dahlin      vector<string>(includes.begin(), includes.end()),
753b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley      NestInNamespaces(std::move(if_class), interface.GetSplitPackage())}};
7549a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley}
7559a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
756054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wileybool WriteHeader(const CppOptions& options,
757054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                 const TypeNamespace& types,
758054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                 const AidlInterface& interface,
759054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                 const IoDelegate& io_delegate,
760054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                 ClassNames header_type) {
761054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  unique_ptr<Document> header;
762054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  switch (header_type) {
763054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    case ClassNames::INTERFACE:
764054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      header = BuildInterfaceHeader(types, interface);
765054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      break;
766054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    case ClassNames::CLIENT:
767054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      header = BuildClientHeader(types, interface);
768054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      break;
769054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    case ClassNames::SERVER:
770054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      header = BuildServerHeader(types, interface);
771054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      break;
772054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    default:
773054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      LOG(FATAL) << "aidl internal error";
774054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  }
775054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  if (!header) {
776054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    LOG(ERROR) << "aidl internal error: Failed to generate header.";
7779a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley    return false;
7789a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley  }
779054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
7809d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  const string header_path = options.OutputHeaderDir() + OS_PATH_SEPARATOR +
7819d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley                             HeaderFile(interface, header_type);
7829d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
7839d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  header->Write(code_writer.get());
784054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
7859d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  const bool success = code_writer->Close();
7869d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  if (!success) {
7879d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    io_delegate.RemovePath(header_path);
7889d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  }
7899d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley
7909d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  return success;
7919a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley}
7929a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
793a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin}  // namespace internals
794a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlin
795a834dd4650b3196893440ee49c7ff6b303b45a92Casey Dahlinusing namespace internals;
7969a8e1d9ad667faff9272e0e99b37a6aeba2d8d20Christopher Wiley
7973a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wileystring HeaderFile(const AidlInterface& interface,
7983a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley                  ClassNames class_type,
7993a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley                  bool use_os_sep) {
8003a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  string file_path = interface.GetPackage();
8013a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  for (char& c: file_path) {
8023a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley    if (c == '.') {
8033a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley      c = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
8043a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley    }
8053a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  }
8063a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  if (!file_path.empty()) {
8073a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley    file_path += (use_os_sep) ? OS_PATH_SEPARATOR : '/';
8083a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  }
8093a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  file_path += ClassName(interface, class_type);
8103a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  file_path += ".h";
8113a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley
8123a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley  return file_path;
8133a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley}
8143a9911cc8fd881effadbdf51e8f4cf721a1d9601Christopher Wiley
815e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wileybool GenerateCpp(const CppOptions& options,
816e3550c6679939d2bf5f35c540cd83198ab156fb7Christopher Wiley                 const TypeNamespace& types,
817054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                 const AidlInterface& interface,
818054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                 const IoDelegate& io_delegate) {
819054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  auto interface_src = BuildInterfaceSource(types, interface);
820054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  auto client_src = BuildClientSource(types, interface);
821054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  auto server_src = BuildServerSource(types, interface);
822054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
823054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  if (!interface_src || !client_src || !server_src) {
824054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    return false;
825054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  }
826054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
827054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(),
828b656a3b1954bbe4b548a3c11274c833bbca35935Christopher Wiley                                     interface.GetSplitPackage())) {
829054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    LOG(ERROR) << "Failed to create directory structure for headers.";
830054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    return false;
831054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  }
832054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
833054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  if (!WriteHeader(options, types, interface, io_delegate,
834054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                   ClassNames::INTERFACE) ||
835054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      !WriteHeader(options, types, interface, io_delegate,
836054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                   ClassNames::CLIENT) ||
837054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      !WriteHeader(options, types, interface, io_delegate,
838054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley                   ClassNames::SERVER)) {
839054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley    return false;
840054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  }
841054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
842054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(
843054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley      options.OutputCppFilePath());
844054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  interface_src->Write(writer.get());
845054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  client_src->Write(writer.get());
846054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley  server_src->Write(writer.get());
847054afbd3037addb4f2e245ecbc36f31d3040f877Christopher Wiley
8489d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  const bool success = writer->Close();
8499d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  if (!success) {
8509d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley    io_delegate.RemovePath(options.OutputCppFilePath());
8519d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  }
8529d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley
8539d6e0b29add607669e440085f1fc60cd434dc987Christopher Wiley  return success;
854eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley}
855eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley
856f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley}  // namespace cpp
857eb1acc1cf7dbf578d8ab2e596982c4c635aa9865Christopher Wiley}  // namespace aidl
858f944e79bdaf92fffe9ea78314d3636e7e4de8c51Christopher Wiley}  // namespace android
859