blob: e74ec40d085b0035ecae1aed2910cf5e45d0aa2d [file] [log] [blame]
Christopher Wileyeb1acc12015-09-16 11:25:13 -07001/*
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"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070018
Casey Dahlin082f1d12015-09-21 14:06:25 -070019#include <cctype>
Christopher Wileyad339272015-10-05 19:11:58 -070020#include <cstring>
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070021#include <memory>
Casey Dahlin082f1d12015-09-21 14:06:25 -070022#include <random>
Casey Dahlince776cf2015-10-15 18:45:54 -070023#include <set>
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070024#include <string>
25
Elliott Hughes0a620672015-12-04 13:53:18 -080026#include <android-base/stringprintf.h>
Christopher Wileye3550c62015-09-29 13:26:10 -070027
Casey Dahlina834dd42015-09-23 11:52:15 -070028#include "aidl_language.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070029#include "ast_cpp.h"
30#include "code_writer.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070031#include "logging.h"
Christopher Wiley054afbd2015-10-16 17:08:43 -070032#include "os.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070033
Jiyong Park75e1a742018-07-04 12:31:23 +090034using android::base::Join;
Christopher Wileye3550c62015-09-29 13:26:10 -070035using android::base::StringPrintf;
Jiyong Park75e1a742018-07-04 12:31:23 +090036using std::set;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070037using std::string;
Casey Dahlin082f1d12015-09-21 14:06:25 -070038using std::unique_ptr;
Casey Dahlina834dd42015-09-23 11:52:15 -070039using std::vector;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070040
Christopher Wileyeb1acc12015-09-16 11:25:13 -070041namespace android {
42namespace aidl {
Christopher Wileyf944e792015-09-29 10:00:46 -070043namespace cpp {
Casey Dahlina834dd42015-09-23 11:52:15 -070044namespace internals {
Christopher Wiley0c732db2015-09-29 14:36:44 -070045namespace {
Christopher Wiley36570f42015-10-08 17:20:11 -070046
Casey Dahlinb8d9e882015-11-24 10:57:23 -080047const char kAndroidStatusVarName[] = "_aidl_ret_status";
48const char kCodeVarName[] = "_aidl_code";
49const char kFlagsVarName[] = "_aidl_flags";
50const char kDataVarName[] = "_aidl_data";
51const char kErrorLabel[] = "_aidl_error";
52const char kImplVarName[] = "_aidl_impl";
53const char kReplyVarName[] = "_aidl_reply";
Christopher Wileyad339272015-10-05 19:11:58 -070054const char kReturnVarName[] = "_aidl_return";
Casey Dahlinb8d9e882015-11-24 10:57:23 -080055const char kStatusVarName[] = "_aidl_status";
Martijn Coenenf1b50782018-02-21 21:06:23 +010056const char kTraceVarName[] = "_aidl_trace";
Casey Dahlinb8d9e882015-11-24 10:57:23 -080057const char kAndroidParcelLiteral[] = "::android::Parcel";
58const char kAndroidStatusLiteral[] = "::android::status_t";
59const char kAndroidStatusOk[] = "::android::OK";
60const char kBinderStatusLiteral[] = "::android::binder::Status";
Christopher Wiley0c732db2015-09-29 14:36:44 -070061const char kIBinderHeader[] = "binder/IBinder.h";
62const char kIInterfaceHeader[] = "binder/IInterface.h";
Christopher Wileyad339272015-10-05 19:11:58 -070063const char kParcelHeader[] = "binder/Parcel.h";
Christopher Wiley433c8bb2015-11-12 14:20:46 -080064const char kStatusHeader[] = "binder/Status.h";
Christopher Wiley69b44cf2016-05-03 13:43:33 -070065const char kString16Header[] = "utils/String16.h";
Martijn Coenenf1b50782018-02-21 21:06:23 +010066const char kTraceHeader[] = "utils/Trace.h";
Casey Dahlin389781f2015-10-22 13:13:21 -070067const char kStrongPointerHeader[] = "utils/StrongPointer.h";
Jiyong Park75e1a742018-07-04 12:31:23 +090068const char kAndroidBaseMacrosHeader[] = "android-base/macros.h";
Casey Dahlin082f1d12015-09-21 14:06:25 -070069
Christopher Wiley0eb903e2015-10-20 17:07:08 -070070unique_ptr<AstNode> BreakOnStatusNotOk() {
71 IfStatement* ret = new IfStatement(new Comparison(
Casey Dahlinb8d9e882015-11-24 10:57:23 -080072 new LiteralExpression(kAndroidStatusVarName), "!=",
73 new LiteralExpression(kAndroidStatusOk)));
Christopher Wiley0eb903e2015-10-20 17:07:08 -070074 ret->OnTrue()->AddLiteral("break");
75 return unique_ptr<AstNode>(ret);
76}
77
Christopher Wiley433c8bb2015-11-12 14:20:46 -080078unique_ptr<AstNode> GotoErrorOnBadStatus() {
79 IfStatement* ret = new IfStatement(new Comparison(
Casey Dahlinb8d9e882015-11-24 10:57:23 -080080 new LiteralExpression(kAndroidStatusVarName), "!=",
81 new LiteralExpression(kAndroidStatusOk)));
82 ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
Christopher Wiley433c8bb2015-11-12 14:20:46 -080083 return unique_ptr<AstNode>(ret);
84}
85
Steven Moreland5557f1c2018-07-02 13:50:23 -070086unique_ptr<AstNode> ReturnOnStatusNotOk() {
87 IfStatement* ret = new IfStatement(new Comparison(new LiteralExpression(kAndroidStatusVarName),
88 "!=", new LiteralExpression(kAndroidStatusOk)));
89 ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
90 return unique_ptr<AstNode>(ret);
91}
92
Christopher Wiley0c732db2015-09-29 14:36:44 -070093string UpperCase(const std::string& s) {
94 string result = s;
95 for (char& c : result)
96 c = toupper(c);
97 return result;
Casey Dahlina834dd42015-09-23 11:52:15 -070098}
Casey Dahlin082f1d12015-09-21 14:06:25 -070099
Christopher Wileyad339272015-10-05 19:11:58 -0700100string BuildVarName(const AidlArgument& a) {
101 string prefix = "out_";
102 if (a.GetDirection() & AidlArgument::IN_DIR) {
103 prefix = "in_";
Christopher Wileye3550c62015-09-29 13:26:10 -0700104 }
Christopher Wileyad339272015-10-05 19:11:58 -0700105 return prefix + a.GetName();
106}
107
Jiyong Park75e1a742018-07-04 12:31:23 +0900108ArgList BuildArgList(const TypeNamespace& types, const AidlMethod& method, bool for_declaration,
109 bool type_name_only = false) {
Christopher Wileyad339272015-10-05 19:11:58 -0700110 // Build up the argument list for the server method call.
111 vector<string> method_arguments;
112 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
113 string literal;
114 if (for_declaration) {
115 // Method declarations need types, pointers to out params, and variable
116 // names that match the .aidl specification.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800117 const Type* type = a->GetType().GetLanguageType<Type>();
Casey Dahlince776cf2015-10-15 18:45:54 -0700118
Casey Dahlina2f77c42015-12-01 18:26:02 -0800119 literal = type->CppType();
Casey Dahlinb0966612015-10-19 16:35:26 -0700120
Christopher Wileyb8e49a42015-10-27 12:55:18 -0700121 if (a->IsOut()) {
122 literal = literal + "*";
123 } else {
124 // We pass in parameters that are not primitives by const reference.
125 // Arrays of primitives are not primitives.
126 if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
127 literal = "const " + literal + "&";
128 }
129 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900130 if (!type_name_only) {
131 literal += " " + a->GetName();
132 }
Christopher Wileyad339272015-10-05 19:11:58 -0700133 } else {
134 if (a->IsOut()) { literal = "&"; }
135 literal += BuildVarName(*a);
136 }
137 method_arguments.push_back(literal);
138 }
139
Casey Dahlina2f77c42015-12-01 18:26:02 -0800140 const Type* return_type = method.GetType().GetLanguageType<Type>();
Casey Dahlince776cf2015-10-15 18:45:54 -0700141
Christopher Wileyad339272015-10-05 19:11:58 -0700142 if (return_type != types.VoidType()) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700143 string literal;
Christopher Wileyad339272015-10-05 19:11:58 -0700144 if (for_declaration) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900145 literal = StringPrintf("%s* %s", return_type->CppType().c_str(),
146 type_name_only ? "" : kReturnVarName);
Christopher Wileyad339272015-10-05 19:11:58 -0700147 } else {
Christopher Wileyade4b452015-10-10 11:06:03 -0700148 literal = string{"&"} + kReturnVarName;
Christopher Wileyad339272015-10-05 19:11:58 -0700149 }
Christopher Wileyade4b452015-10-10 11:06:03 -0700150 method_arguments.push_back(literal);
Christopher Wileyad339272015-10-05 19:11:58 -0700151 }
152
Christopher Wileyade4b452015-10-10 11:06:03 -0700153 return ArgList(method_arguments);
Casey Dahlina834dd42015-09-23 11:52:15 -0700154}
155
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700156unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
Christopher Wiley0c732db2015-09-29 14:36:44 -0700157 const TypeNamespace& types,
158 bool for_interface) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700159 uint32_t modifiers = 0;
160 if (for_interface) {
161 modifiers |= MethodDecl::IS_VIRTUAL;
162 modifiers |= MethodDecl::IS_PURE_VIRTUAL;
163 } else {
164 modifiers |= MethodDecl::IS_OVERRIDE;
165 }
166
167 return unique_ptr<Declaration>{
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800168 new MethodDecl{kBinderStatusLiteral,
Casey Dahlinf4a93112015-10-05 16:58:09 -0700169 method.GetName(),
Christopher Wileyad339272015-10-05 19:11:58 -0700170 BuildArgList(types, method, true /* for method decl */),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700171 modifiers}};
172}
173
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700174unique_ptr<CppNamespace> NestInNamespaces(
175 vector<unique_ptr<Declaration>> decls,
176 const vector<string>& package) {
177 if (package.empty()) {
178 // We should also be checking this before we get this far, but do it again
179 // for the sake of unit tests and meaningful errors.
180 LOG(FATAL) << "C++ generation requires a package declaration "
181 "for namespacing";
182 }
183 auto it = package.crbegin(); // Iterate over the namespaces inner to outer
184 unique_ptr<CppNamespace> inner{new CppNamespace{*it, std::move(decls)}};
185 ++it;
186 for (; it != package.crend(); ++it) {
187 inner.reset(new CppNamespace{*it, std::move(inner)});
188 }
189 return inner;
Christopher Wiley0c732db2015-09-29 14:36:44 -0700190}
191
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700192unique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl,
193 const vector<string>& package) {
194 vector<unique_ptr<Declaration>> decls;
195 decls.push_back(std::move(decl));
196 return NestInNamespaces(std::move(decls), package);
Christopher Wiley36570f42015-10-08 17:20:11 -0700197}
198
Steven Moreland1c41e972018-07-09 16:07:00 -0700199bool DeclareLocalVariable(const AidlArgument& a, StatementBlock* b) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800200 const Type* cpp_type = a.GetType().GetLanguageType<Type>();
Christopher Wileyad339272015-10-05 19:11:58 -0700201 if (!cpp_type) { return false; }
202
Casey Dahlina2f77c42015-12-01 18:26:02 -0800203 string type = cpp_type->CppType();
Casey Dahlinb0966612015-10-19 16:35:26 -0700204
205 b->AddLiteral(type + " " + BuildVarName(a));
Christopher Wileyad339272015-10-05 19:11:58 -0700206 return true;
207}
208
Steven Moreland5557f1c2018-07-02 13:50:23 -0700209string ClassName(const AidlDefinedType& defined_type, ClassNames type) {
210 string c_name = defined_type.GetName();
Christopher Wiley0c732db2015-09-29 14:36:44 -0700211
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;
Jiyong Park75e1a742018-07-04 12:31:23 +0900225 case ClassNames::DEFAULT_IMPL:
226 c_name = "I" + c_name + "Default";
227 break;
Christopher Wiley0c732db2015-09-29 14:36:44 -0700228 case ClassNames::BASE:
229 break;
230 }
231 return c_name;
232}
233
Steven Moreland5557f1c2018-07-02 13:50:23 -0700234string BuildHeaderGuard(const AidlDefinedType& defined_type, ClassNames header_type) {
235 string class_name = ClassName(defined_type, header_type);
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700236 for (size_t i = 1; i < class_name.size(); ++i) {
237 if (isupper(class_name[i])) {
238 class_name.insert(i, "_");
239 ++i;
240 }
241 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700242 string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_", defined_type.GetPackage().c_str(),
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700243 class_name.c_str());
244 for (char& c : ret) {
245 if (c == '.') {
246 c = '_';
247 }
248 c = toupper(c);
249 }
250 return ret;
251}
Christopher Wiley36570f42015-10-08 17:20:11 -0700252
253unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
254 const AidlInterface& interface,
255 const AidlMethod& method) {
256 const string i_name = ClassName(interface, ClassNames::INTERFACE);
257 const string bp_name = ClassName(interface, ClassNames::CLIENT);
258 unique_ptr<MethodImpl> ret{new MethodImpl{
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800259 kBinderStatusLiteral, bp_name, method.GetName(),
Christopher Wiley36570f42015-10-08 17:20:11 -0700260 ArgList{BuildArgList(types, method, true /* for method decl */)}}};
261 StatementBlock* b = ret->GetStatementBlock();
262
263 // Declare parcels to hold our query and the response.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800264 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
Christopher Wiley1227d612015-10-26 16:59:20 -0700265 // Even if we're oneway, the transact method still takes a parcel.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800266 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700267
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800268 // Declare the status_t variable we need for error handling.
Christopher Wiley10957122015-12-04 14:35:38 -0800269 b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
270 kAndroidStatusVarName,
271 kAndroidStatusOk));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800272 // We unconditionally return a Status object.
273 b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
Christopher Wiley36570f42015-10-08 17:20:11 -0700274
Martijn Coenenf1b50782018-02-21 21:06:23 +0100275 if (interface.ShouldGenerateTraces()) {
276 b->AddLiteral(
277 StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
278 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
279 }
280
Christopher Wiley8993cb52015-10-21 09:53:24 -0700281 // Add the name of the interface we're hoping to call.
282 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800283 kAndroidStatusVarName,
284 new MethodCall(StringPrintf("%s.writeInterfaceToken",
285 kDataVarName),
286 "getInterfaceDescriptor()")));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800287 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley8993cb52015-10-21 09:53:24 -0700288
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700289 for (const auto& a: method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800290 const Type* type = a->GetType().GetLanguageType<Type>();
Christopher Wiley36570f42015-10-08 17:20:11 -0700291 string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
Casey Dahlin389781f2015-10-22 13:13:21 -0700292 var_name = type->WriteCast(var_name);
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700293
294 if (a->IsIn()) {
295 // Serialization looks roughly like:
296 // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
297 // if (_aidl_ret_status != ::android::OK) { goto error; }
298 const string& method = type->WriteToParcelMethod();
299 b->AddStatement(new Assignment(
300 kAndroidStatusVarName,
301 new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
302 ArgList(var_name))));
303 b->AddStatement(GotoErrorOnBadStatus());
304 } else if (a->IsOut() && a->GetType().IsArray()) {
305 // Special case, the length of the out array is written into the parcel.
306 // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
307 // if (_aidl_ret_status != ::android::OK) { goto error; }
308 b->AddStatement(new Assignment(
309 kAndroidStatusVarName,
310 new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
311 ArgList(var_name))));
312 b->AddStatement(GotoErrorOnBadStatus());
313 }
Christopher Wiley36570f42015-10-08 17:20:11 -0700314 }
315
316 // Invoke the transaction on the remote binder and confirm status.
317 string transaction_code = StringPrintf(
318 "%s::%s", i_name.c_str(), UpperCase(method.GetName()).c_str());
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700319
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800320 vector<string> args = {transaction_code, kDataVarName,
321 StringPrintf("&%s", kReplyVarName)};
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700322
323 if (interface.IsOneway() || method.IsOneway()) {
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800324 args.push_back("::android::IBinder::FLAG_ONEWAY");
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700325 }
326
Christopher Wiley36570f42015-10-08 17:20:11 -0700327 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800328 kAndroidStatusVarName,
Christopher Wiley36570f42015-10-08 17:20:11 -0700329 new MethodCall("remote()->transact",
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700330 ArgList(args))));
Jiyong Park75e1a742018-07-04 12:31:23 +0900331
332 // If the method is not implemented in the remote side, try to call the
333 // default implementation, if provided.
334 vector<string> arg_names;
335 for (const auto& a : method.GetArguments()) {
336 arg_names.emplace_back(a->GetName());
337 }
338 if (method.GetType().GetLanguageType<Type>() != types.VoidType()) {
339 arg_names.emplace_back(kReturnVarName);
340 }
341 b->AddLiteral(StringPrintf("if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && "
342 "%s::getDefaultImpl())) {\n"
343 " return %s::getDefaultImpl()->%s(%s);\n"
344 "}\n",
345 i_name.c_str(), i_name.c_str(), method.GetName().c_str(),
346 Join(arg_names, ", ").c_str()),
347 false /* no semicolon */);
348
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800349 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700350
Christopher Wiley1227d612015-10-26 16:59:20 -0700351 if (!interface.IsOneway() && !method.IsOneway()) {
352 // Strip off the exception header and fail if we see a remote exception.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800353 // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
354 // if (_aidl_ret_status != ::android::OK) { goto error; }
355 // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800356 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800357 kAndroidStatusVarName,
358 StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800359 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley1227d612015-10-26 16:59:20 -0700360 IfStatement* exception_check = new IfStatement(
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800361 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
Christopher Wiley1227d612015-10-26 16:59:20 -0700362 b->AddStatement(exception_check);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800363 exception_check->OnTrue()->AddLiteral(
364 StringPrintf("return %s", kStatusVarName));
Christopher Wiley1227d612015-10-26 16:59:20 -0700365 }
366
367 // Type checking should guarantee that nothing below emits code until "return
368 // status" if we are a oneway method, so no more fear of accessing reply.
Christopher Wiley2aaeda82015-10-19 15:16:49 -0700369
Christopher Wiley36570f42015-10-08 17:20:11 -0700370 // If the method is expected to return something, read it first by convention.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800371 const Type* return_type = method.GetType().GetLanguageType<Type>();
Christopher Wiley36570f42015-10-08 17:20:11 -0700372 if (return_type != types.VoidType()) {
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700373 const string& method_call = return_type->ReadFromParcelMethod();
Christopher Wiley36570f42015-10-08 17:20:11 -0700374 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800375 kAndroidStatusVarName,
376 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
377 method_call.c_str()),
378 ArgList(kReturnVarName))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800379 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700380 }
381
382 for (const AidlArgument* a : method.GetOutArguments()) {
383 // Deserialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800384 // _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
385 // if (_aidl_status != ::android::OK) { goto _aidl_error; }
Casey Dahlinb0966612015-10-19 16:35:26 -0700386 string method =
Casey Dahlina2f77c42015-12-01 18:26:02 -0800387 a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700388
Christopher Wiley36570f42015-10-08 17:20:11 -0700389 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800390 kAndroidStatusVarName,
391 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
392 method.c_str()),
393 ArgList(a->GetName()))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800394 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700395 }
396
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800397 // If we've gotten to here, one of two things is true:
398 // 1) We've read some bad status_t
399 // 2) We've only read status_t == OK and there was no exception in the
400 // response.
401 // In both cases, we're free to set Status from the status_t and return.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800402 b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800403 b->AddLiteral(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800404 StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
405 kAndroidStatusVarName));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100406
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800407 b->AddLiteral(StringPrintf("return %s", kStatusVarName));
Christopher Wiley36570f42015-10-08 17:20:11 -0700408
409 return unique_ptr<Declaration>(ret.release());
410}
411
412} // namespace
413
Christopher Wileye3550c62015-09-29 13:26:10 -0700414unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
Christopher Wiley36570f42015-10-08 17:20:11 -0700415 const AidlInterface& interface) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700416 vector<string> include_list = {
417 HeaderFile(interface, ClassNames::CLIENT, false),
Jiyong Park75e1a742018-07-04 12:31:23 +0900418 kParcelHeader,
419 kAndroidBaseMacrosHeader
Christopher Wiley054afbd2015-10-16 17:08:43 -0700420 };
Christopher Wiley36570f42015-10-08 17:20:11 -0700421 vector<unique_ptr<Declaration>> file_decls;
422
423 // The constructor just passes the IBinder instance up to the super
424 // class.
Christopher Wiley1db03482015-10-22 11:42:02 -0700425 const string i_name = ClassName(interface, ClassNames::INTERFACE);
Christopher Wiley36570f42015-10-08 17:20:11 -0700426 file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
Christopher Wiley054afbd2015-10-16 17:08:43 -0700427 ClassName(interface, ClassNames::CLIENT),
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800428 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
429 kImplVarName)},
430 { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
Christopher Wiley36570f42015-10-08 17:20:11 -0700431
432 // Clients define a method per transaction.
433 for (const auto& method : interface.GetMethods()) {
434 unique_ptr<Declaration> m = DefineClientTransaction(
435 types, interface, *method);
436 if (!m) { return nullptr; }
437 file_decls.push_back(std::move(m));
438 }
439 return unique_ptr<Document>{new CppSource{
440 include_list,
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700441 NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700442}
443
Christopher Wileyad339272015-10-05 19:11:58 -0700444namespace {
445
446bool HandleServerTransaction(const TypeNamespace& types,
Martijn Coenenf1b50782018-02-21 21:06:23 +0100447 const AidlInterface& interface,
Christopher Wileyad339272015-10-05 19:11:58 -0700448 const AidlMethod& method,
449 StatementBlock* b) {
450 // Declare all the parameters now. In the common case, we expect no errors
451 // in serialization.
452 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
Steven Moreland1c41e972018-07-09 16:07:00 -0700453 if (!DeclareLocalVariable(*a, b)) {
454 return false;
455 }
Christopher Wileyad339272015-10-05 19:11:58 -0700456 }
457
458 // Declare a variable to hold the return value.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800459 const Type* return_type = method.GetType().GetLanguageType<Type>();
Christopher Wileyad339272015-10-05 19:11:58 -0700460 if (return_type != types.VoidType()) {
461 b->AddLiteral(StringPrintf(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800462 "%s %s", return_type->CppType().c_str(),
Casey Dahlinb0966612015-10-19 16:35:26 -0700463 kReturnVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700464 }
465
Christopher Wiley8993cb52015-10-21 09:53:24 -0700466 // Check that the client is calling the correct interface.
467 IfStatement* interface_check = new IfStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800468 new MethodCall(StringPrintf("%s.checkInterface",
469 kDataVarName), "this"),
Christopher Wiley8993cb52015-10-21 09:53:24 -0700470 true /* invert the check */);
471 b->AddStatement(interface_check);
472 interface_check->OnTrue()->AddStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800473 new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
Christopher Wiley8993cb52015-10-21 09:53:24 -0700474 interface_check->OnTrue()->AddLiteral("break");
475
Christopher Wileyad339272015-10-05 19:11:58 -0700476 // Deserialize each "in" parameter to the transaction.
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700477 for (const auto& a: method.GetArguments()) {
Christopher Wileyad339272015-10-05 19:11:58 -0700478 // Deserialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800479 // _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
480 // if (_aidl_ret_status != ::android::OK) { break; }
Casey Dahlina2f77c42015-12-01 18:26:02 -0800481 const Type* type = a->GetType().GetLanguageType<Type>();
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700482 const string& readMethod = type->ReadFromParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700483
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700484 if (a->IsIn()) {
485 b->AddStatement(new Assignment{
486 kAndroidStatusVarName,
487 new MethodCall{string(kDataVarName) + "." + readMethod,
488 "&" + BuildVarName(*a)}});
489 b->AddStatement(BreakOnStatusNotOk());
490 } else if (a->IsOut() && a->GetType().IsArray()) {
491 // Special case, the length of the out array is written into the parcel.
492 // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
493 // if (_aidl_ret_status != ::android::OK) { break; }
494 b->AddStatement(new Assignment{
495 kAndroidStatusVarName,
496 new MethodCall{string(kDataVarName) + ".resizeOutVector",
497 "&" + BuildVarName(*a)}});
498 b->AddStatement(BreakOnStatusNotOk());
499 }
Christopher Wileyad339272015-10-05 19:11:58 -0700500 }
501
Martijn Coenenf1b50782018-02-21 21:06:23 +0100502 if (interface.ShouldGenerateTraces()) {
503 b->AddStatement(new Statement(new MethodCall("atrace_begin",
504 ArgList{{"ATRACE_TAG_AIDL",
505 StringPrintf("\"%s::%s::cppServer\"",
506 interface.GetName().c_str(),
507 method.GetName().c_str())}})));
508 }
509
Christopher Wileyad339272015-10-05 19:11:58 -0700510 // Call the actual method. This is implemented by the subclass.
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800511 vector<unique_ptr<AstNode>> status_args;
512 status_args.emplace_back(new MethodCall(
Christopher Wileyad339272015-10-05 19:11:58 -0700513 method.GetName(),
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800514 BuildArgList(types, method, false /* not for method decl */)));
515 b->AddStatement(new Statement(new MethodCall(
516 StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
517 ArgList(std::move(status_args)))));
Christopher Wileyad339272015-10-05 19:11:58 -0700518
Martijn Coenenf1b50782018-02-21 21:06:23 +0100519 if (interface.ShouldGenerateTraces()) {
520 b->AddStatement(new Statement(new MethodCall("atrace_end",
521 "ATRACE_TAG_AIDL")));
522 }
523
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800524 // Write exceptions during transaction handling to parcel.
525 if (!method.IsOneway()) {
526 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800527 kAndroidStatusVarName,
528 StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800529 b->AddStatement(BreakOnStatusNotOk());
530 IfStatement* exception_check = new IfStatement(
531 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
532 b->AddStatement(exception_check);
533 exception_check->OnTrue()->AddLiteral("break");
534 }
Casey Dahlinb0966612015-10-19 16:35:26 -0700535
Christopher Wiley36570f42015-10-08 17:20:11 -0700536 // If we have a return value, write it first.
537 if (return_type != types.VoidType()) {
Christopher Wiley2aaeda82015-10-19 15:16:49 -0700538 string writeMethod =
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800539 string(kReplyVarName) + "->" +
Casey Dahlina2f77c42015-12-01 18:26:02 -0800540 return_type->WriteToParcelMethod();
Christopher Wiley36570f42015-10-08 17:20:11 -0700541 b->AddStatement(new Assignment{
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800542 kAndroidStatusVarName, new MethodCall{writeMethod,
Casey Dahlin389781f2015-10-22 13:13:21 -0700543 ArgList{return_type->WriteCast(kReturnVarName)}}});
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700544 b->AddStatement(BreakOnStatusNotOk());
Christopher Wiley36570f42015-10-08 17:20:11 -0700545 }
546
Christopher Wileyad339272015-10-05 19:11:58 -0700547 // Write each out parameter to the reply parcel.
548 for (const AidlArgument* a : method.GetOutArguments()) {
549 // Serialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800550 // _aidl_ret_status = data.WriteInt32(out_param_name);
551 // if (_aidl_ret_status != ::android::OK) { break; }
Casey Dahlina2f77c42015-12-01 18:26:02 -0800552 const Type* type = a->GetType().GetLanguageType<Type>();
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700553 const string& writeMethod = type->WriteToParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700554
Christopher Wileyad339272015-10-05 19:11:58 -0700555 b->AddStatement(new Assignment{
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800556 kAndroidStatusVarName,
557 new MethodCall{string(kReplyVarName) + "->" + writeMethod,
Casey Dahlin389781f2015-10-22 13:13:21 -0700558 type->WriteCast(BuildVarName(*a))}});
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700559 b->AddStatement(BreakOnStatusNotOk());
Christopher Wileyad339272015-10-05 19:11:58 -0700560 }
561
562 return true;
563}
564
565} // namespace
566
Christopher Wileye3550c62015-09-29 13:26:10 -0700567unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
Christopher Wiley054afbd2015-10-16 17:08:43 -0700568 const AidlInterface& interface) {
569 const string bn_name = ClassName(interface, ClassNames::SERVER);
570 vector<string> include_list{
571 HeaderFile(interface, ClassNames::SERVER, false),
572 kParcelHeader
573 };
Christopher Wileyad339272015-10-05 19:11:58 -0700574 unique_ptr<MethodImpl> on_transact{new MethodImpl{
575 kAndroidStatusLiteral, bn_name, "onTransact",
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800576 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
577 StringPrintf("const %s& %s", kAndroidParcelLiteral,
578 kDataVarName),
579 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
580 StringPrintf("uint32_t %s", kFlagsVarName)}}
Christopher Wiley36570f42015-10-08 17:20:11 -0700581 }};
Christopher Wileyad339272015-10-05 19:11:58 -0700582
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800583 // Declare the status_t variable
Christopher Wiley05f4f892015-10-14 13:30:43 -0700584 on_transact->GetStatementBlock()->AddLiteral(
Christopher Wiley10957122015-12-04 14:35:38 -0800585 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
586 kAndroidStatusOk));
Christopher Wiley05f4f892015-10-14 13:30:43 -0700587
Christopher Wileyad339272015-10-05 19:11:58 -0700588 // Add the all important switch statement, but retain a pointer to it.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800589 SwitchStatement* s = new SwitchStatement{kCodeVarName};
Christopher Wileyf9688b02015-10-08 17:17:50 -0700590 on_transact->GetStatementBlock()->AddStatement(s);
Christopher Wileyad339272015-10-05 19:11:58 -0700591
592 // The switch statement has a case statement for each transaction code.
Christopher Wiley054afbd2015-10-16 17:08:43 -0700593 for (const auto& method : interface.GetMethods()) {
Christopher Wileyad339272015-10-05 19:11:58 -0700594 StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
595 if (!b) { return nullptr; }
596
Martijn Coenenf1b50782018-02-21 21:06:23 +0100597 if (!HandleServerTransaction(types, interface, *method, b)) { return nullptr; }
Christopher Wileyad339272015-10-05 19:11:58 -0700598 }
599
600 // The switch statement has a default case which defers to the super class.
601 // The superclass handles a few pre-defined transactions.
602 StatementBlock* b = s->AddCase("");
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800603 b->AddLiteral(StringPrintf(
604 "%s = ::android::BBinder::onTransact(%s, %s, "
605 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
606 kDataVarName, kReplyVarName, kFlagsVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700607
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800608 // If we saw a null reference, we can map that to an appropriate exception.
609 IfStatement* null_check = new IfStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800610 new LiteralExpression(string(kAndroidStatusVarName) +
611 " == ::android::UNEXPECTED_NULL"));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800612 on_transact->GetStatementBlock()->AddStatement(null_check);
613 null_check->OnTrue()->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800614 kAndroidStatusVarName,
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800615 StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800616 ".writeToParcel(%s)",
617 kBinderStatusLiteral, kBinderStatusLiteral,
618 kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800619
Christopher Wileyad339272015-10-05 19:11:58 -0700620 // Finally, the server's onTransact method just returns a status code.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800621 on_transact->GetStatementBlock()->AddLiteral(
622 StringPrintf("return %s", kAndroidStatusVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700623
624 return unique_ptr<Document>{new CppSource{
625 include_list,
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700626 NestInNamespaces(std::move(on_transact), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700627}
628
Jiyong Park75e1a742018-07-04 12:31:23 +0900629unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& types,
Christopher Wiley054afbd2015-10-16 17:08:43 -0700630 const AidlInterface& interface) {
631 vector<string> include_list{
632 HeaderFile(interface, ClassNames::INTERFACE, false),
633 HeaderFile(interface, ClassNames::CLIENT, false),
634 };
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700635
Christopher Wiley054afbd2015-10-16 17:08:43 -0700636 string fq_name = ClassName(interface, ClassNames::INTERFACE);
637 if (!interface.GetPackage().empty()) {
638 fq_name = interface.GetPackage() + "." + fq_name;
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700639 }
640
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700641 vector<unique_ptr<Declaration>> decls;
642
Christopher Wiley11a9d792016-02-24 17:20:33 -0800643 unique_ptr<MacroDecl> meta_if{new MacroDecl{
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700644 "IMPLEMENT_META_INTERFACE",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700645 ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
Christopher Wileyade4b452015-10-10 11:06:03 -0700646 '"' + fq_name + '"'}}}};
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700647 decls.push_back(std::move(meta_if));
648
Steven Moreland693640b2018-07-19 13:46:27 -0700649 for (const auto& constant : interface.GetConstantDeclarations()) {
650 const AidlConstantValue& value = constant->GetValue();
651 if (value.GetType() != AidlConstantValue::Type::STRING) continue;
652
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700653 unique_ptr<MethodImpl> getter(new MethodImpl(
654 "const ::android::String16&",
655 ClassName(interface, ClassNames::INTERFACE),
656 constant->GetName(),
657 {}));
658 getter->GetStatementBlock()->AddLiteral(
Steven Moreland693640b2018-07-19 13:46:27 -0700659 StringPrintf("static const ::android::String16 value(%s)", value.ToString().c_str()));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700660 getter->GetStatementBlock()->AddLiteral("return value");
661 decls.push_back(std::move(getter));
662 }
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700663
Jiyong Park75e1a742018-07-04 12:31:23 +0900664 // Implement the default impl class.
665 // onAsBinder returns nullptr as this interface is not associated with a
666 // real binder.
667 const string default_impl(ClassName(interface, ClassNames::DEFAULT_IMPL));
668 decls.emplace_back(
669 new LiteralDecl(StringPrintf("::android::IBinder* %s::onAsBinder() {\n"
670 " return nullptr;\n"
671 "}\n",
672 default_impl.c_str())));
673 // Each interface method by default returns UNKNOWN_TRANSACTION with is
674 // the same status that is returned by transact() when the method is
675 // not implemented in the server side. In other words, these default
676 // methods do nothing; they only exist to aid making a real default
677 // impl class without having to override all methods in an interface.
678 for (const auto& method : interface.GetMethods()) {
679 decls.emplace_back(new LiteralDecl(StringPrintf(
680 "::android::binder::Status %s::%s%s {\n"
681 " return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
682 "}\n",
683 default_impl.c_str(), method->GetName().c_str(),
684 BuildArgList(types, *method, true, true).ToString().c_str())));
685 }
686
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700687 return unique_ptr<Document>{new CppSource{
688 include_list,
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700689 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700690}
691
Christopher Wileye3550c62015-09-29 13:26:10 -0700692unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700693 const AidlInterface& interface) {
694 const string i_name = ClassName(interface, ClassNames::INTERFACE);
695 const string bp_name = ClassName(interface, ClassNames::CLIENT);
Casey Dahlina834dd42015-09-23 11:52:15 -0700696
Christopher Wileyb23149d2015-10-14 13:52:21 -0700697 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
698 bp_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800699 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
700 kImplVarName)},
Christopher Wileyb23149d2015-10-14 13:52:21 -0700701 ConstructorDecl::IS_EXPLICIT
702 }};
703 unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
704 "~" + bp_name,
705 ArgList{},
706 ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
Casey Dahlina834dd42015-09-23 11:52:15 -0700707
Christopher Wileyf944e792015-09-29 10:00:46 -0700708 vector<unique_ptr<Declaration>> publics;
Casey Dahlina834dd42015-09-23 11:52:15 -0700709 publics.push_back(std::move(constructor));
710 publics.push_back(std::move(destructor));
711
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700712 for (const auto& method: interface.GetMethods()) {
Christopher Wiley36570f42015-10-08 17:20:11 -0700713 publics.push_back(BuildMethodDecl(*method, types, false));
Casey Dahlina834dd42015-09-23 11:52:15 -0700714 }
715
Christopher Wileyf944e792015-09-29 10:00:46 -0700716 unique_ptr<ClassDecl> bp_class{
717 new ClassDecl{bp_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800718 "::android::BpInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700719 std::move(publics),
720 {}
Casey Dahlina834dd42015-09-23 11:52:15 -0700721 }};
722
Christopher Wiley0c732db2015-09-29 14:36:44 -0700723 return unique_ptr<Document>{new CppHeader{
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700724 BuildHeaderGuard(interface, ClassNames::CLIENT),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700725 {kIBinderHeader,
726 kIInterfaceHeader,
727 "utils/Errors.h",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700728 HeaderFile(interface, ClassNames::INTERFACE, false)},
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700729 NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700730}
731
Christopher Wileyf59c4992015-10-08 13:12:44 -0700732unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
Christopher Wileyfd51d602015-10-14 13:04:48 -0700733 const AidlInterface& interface) {
734 const string i_name = ClassName(interface, ClassNames::INTERFACE);
735 const string bn_name = ClassName(interface, ClassNames::SERVER);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700736
Christopher Wileyfd51d602015-10-14 13:04:48 -0700737 unique_ptr<Declaration> on_transact{new MethodDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700738 kAndroidStatusLiteral, "onTransact",
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800739 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
740 StringPrintf("const %s& %s", kAndroidParcelLiteral,
741 kDataVarName),
742 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
743 StringPrintf("uint32_t %s = 0", kFlagsVarName)}},
Christopher Wileyfd51d602015-10-14 13:04:48 -0700744 MethodDecl::IS_OVERRIDE
745 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700746
Christopher Wileyf944e792015-09-29 10:00:46 -0700747 std::vector<unique_ptr<Declaration>> publics;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700748 publics.push_back(std::move(on_transact));
749
Christopher Wileyf944e792015-09-29 10:00:46 -0700750 unique_ptr<ClassDecl> bn_class{
751 new ClassDecl{bn_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800752 "::android::BnInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700753 std::move(publics),
754 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700755 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700756
Christopher Wiley0c732db2015-09-29 14:36:44 -0700757 return unique_ptr<Document>{new CppHeader{
Christopher Wileyfd51d602015-10-14 13:04:48 -0700758 BuildHeaderGuard(interface, ClassNames::SERVER),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700759 {"binder/IInterface.h",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700760 HeaderFile(interface, ClassNames::INTERFACE, false)},
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700761 NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700762}
763
Christopher Wileye3550c62015-09-29 13:26:10 -0700764unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700765 const AidlInterface& interface) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900766 set<string> includes = {kIBinderHeader, kIInterfaceHeader, kStatusHeader, kStrongPointerHeader};
Casey Dahlince776cf2015-10-15 18:45:54 -0700767
768 for (const auto& method : interface.GetMethods()) {
769 for (const auto& argument : method->GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800770 const Type* type = argument->GetType().GetLanguageType<Type>();
771 type->GetHeaders(&includes);
Casey Dahlince776cf2015-10-15 18:45:54 -0700772 }
773
Casey Dahlina2f77c42015-12-01 18:26:02 -0800774 const Type* return_type = method->GetType().GetLanguageType<Type>();
775 return_type->GetHeaders(&includes);
Casey Dahlince776cf2015-10-15 18:45:54 -0700776 }
777
Jiyong Park75e1a742018-07-04 12:31:23 +0900778 const string i_name = ClassName(interface, ClassNames::INTERFACE);
779 unique_ptr<ClassDecl> if_class{new ClassDecl{i_name, "::android::IInterface"}};
Christopher Wiley11a9d792016-02-24 17:20:33 -0800780 if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700781 "DECLARE_META_INTERFACE",
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700782 ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
Christopher Wiley0c732db2015-09-29 14:36:44 -0700783
Steven Moreland693640b2018-07-19 13:46:27 -0700784 std::vector<std::unique_ptr<Declaration>> string_constants;
785 unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t"}};
786 for (const auto& constant : interface.GetConstantDeclarations()) {
787 const AidlConstantValue& value = constant->GetValue();
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800788
Steven Moreland693640b2018-07-19 13:46:27 -0700789 switch (value.GetType()) {
790 case AidlConstantValue::Type::STRING: {
791 unique_ptr<Declaration> getter(new MethodDecl(
792 "const ::android::String16&", constant->GetName(), {}, MethodDecl::IS_STATIC));
793 string_constants.push_back(std::move(getter));
794 break;
795 }
796 case AidlConstantValue::Type::INTEGER: {
797 int_constant_enum->AddValue(constant->GetName(), value.ToString());
798 break;
799 }
800 default: {
801 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
802 }
803 }
804 }
805 if (int_constant_enum->HasValues()) {
806 if_class->AddPublic(std::move(int_constant_enum));
807 }
808 if (!string_constants.empty()) {
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700809 includes.insert(kString16Header);
Steven Moreland693640b2018-07-19 13:46:27 -0700810
811 for (auto& string_constant : string_constants) {
812 if_class->AddPublic(std::move(string_constant));
813 }
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700814 }
Martijn Coenenf1b50782018-02-21 21:06:23 +0100815
816 if (interface.ShouldGenerateTraces()) {
817 includes.insert(kTraceHeader);
818 }
819
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700820 if (!interface.GetMethods().empty()) {
821 unique_ptr<Enum> call_enum{new Enum{"Call"}};
822 for (const auto& method : interface.GetMethods()) {
823 // Each method gets an enum entry and pure virtual declaration.
824 if_class->AddPublic(BuildMethodDecl(*method, types, true));
825 call_enum->AddValue(
826 UpperCase(method->GetName()),
827 StringPrintf("::android::IBinder::FIRST_CALL_TRANSACTION + %d",
828 method->GetId()));
829 }
830 if_class->AddPublic(std::move(call_enum));
Christopher Wiley0c732db2015-09-29 14:36:44 -0700831 }
Christopher Wiley0c732db2015-09-29 14:36:44 -0700832
Jiyong Park75e1a742018-07-04 12:31:23 +0900833 vector<unique_ptr<Declaration>> decls;
834 decls.emplace_back(std::move(if_class));
835
836 // Base class for the default implementation.
837 vector<string> method_decls;
838 for (const auto& method : interface.GetMethods()) {
839 method_decls.emplace_back(BuildMethodDecl(*method, types, false)->ToString());
840 }
841 decls.emplace_back(new LiteralDecl(
842 android::base::StringPrintf("class %s : public %s {\n"
843 "public:\n"
844 " ::android::IBinder* onAsBinder() override;\n"
845 " %s\n"
846 "};\n",
847 ClassName(interface, ClassNames::DEFAULT_IMPL).c_str(),
848 i_name.c_str(), Join(method_decls, " ").c_str())));
849
850 return unique_ptr<Document>{
851 new CppHeader{BuildHeaderGuard(interface, ClassNames::INTERFACE),
852 vector<string>(includes.begin(), includes.end()),
853 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700854}
855
Steven Moreland5557f1c2018-07-02 13:50:23 -0700856std::unique_ptr<Document> BuildParcelHeader(const TypeNamespace& /*types*/,
857 const AidlStructuredParcelable& parcel) {
858 unique_ptr<ClassDecl> parcel_class{new ClassDecl{parcel.GetName(), "::android::Parcelable"}};
859
860 set<string> includes = {kStatusHeader, kParcelHeader};
861 for (const auto& variable : parcel.GetFields()) {
862 const Type* type = variable->GetType().GetLanguageType<Type>();
863 type->GetHeaders(&includes);
864 }
865
866 for (const auto& variable : parcel.GetFields()) {
867 const Type* type = variable->GetType().GetLanguageType<Type>();
Steven Moreland9ea10e32018-07-19 15:26:09 -0700868 const AidlConstantValue* default_value = variable->GetDefaultValue();
Steven Moreland5557f1c2018-07-02 13:50:23 -0700869
Steven Moreland9ea10e32018-07-19 15:26:09 -0700870 std::ostringstream out;
871 out << type->CppType().c_str() << " " << variable->GetName().c_str();
872 if (default_value) {
873 out << " = " << type->CppType().c_str() << "(" << default_value->ToString() << ")";
874 }
875 out << ";\n";
876
877 parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
Steven Moreland5557f1c2018-07-02 13:50:23 -0700878 }
879
880 unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
Steven Morelandce39c532018-07-11 16:59:50 -0700881 ArgList("const ::android::Parcel* _aidl_parcel"),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700882 MethodDecl::IS_OVERRIDE));
883 parcel_class->AddPublic(std::move(read));
884 unique_ptr<MethodDecl> write(new MethodDecl(kAndroidStatusLiteral, "writeToParcel",
Steven Morelandce39c532018-07-11 16:59:50 -0700885 ArgList("::android::Parcel* _aidl_parcel"),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700886 MethodDecl::IS_OVERRIDE | MethodDecl::IS_CONST));
887 parcel_class->AddPublic(std::move(write));
888
889 return unique_ptr<Document>{new CppHeader{
890 BuildHeaderGuard(parcel, ClassNames::BASE), vector<string>(includes.begin(), includes.end()),
891 NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage())}};
892}
Steven Moreland1c41e972018-07-09 16:07:00 -0700893std::unique_ptr<Document> BuildParcelSource(const TypeNamespace& /*types*/,
Steven Moreland5557f1c2018-07-02 13:50:23 -0700894 const AidlStructuredParcelable& parcel) {
895 unique_ptr<MethodImpl> read{new MethodImpl{kAndroidStatusLiteral, parcel.GetName(),
896 "readFromParcel",
Steven Morelandce39c532018-07-11 16:59:50 -0700897 ArgList("const ::android::Parcel* _aidl_parcel")}};
Steven Moreland5557f1c2018-07-02 13:50:23 -0700898 StatementBlock* read_block = read->GetStatementBlock();
899 read_block->AddLiteral(
900 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
901 for (const auto& variable : parcel.GetFields()) {
902 string method = variable->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
903
904 read_block->AddStatement(new Assignment(
905 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
906 ArgList("&" + variable->GetName()))));
907 read_block->AddStatement(ReturnOnStatusNotOk());
908 }
909 read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
910
Steven Morelandce39c532018-07-11 16:59:50 -0700911 unique_ptr<MethodImpl> write{
912 new MethodImpl{kAndroidStatusLiteral, parcel.GetName(), "writeToParcel",
913 ArgList("::android::Parcel* _aidl_parcel"), true /*const*/}};
Steven Moreland5557f1c2018-07-02 13:50:23 -0700914 StatementBlock* write_block = write->GetStatementBlock();
915 write_block->AddLiteral(
916 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
917 for (const auto& variable : parcel.GetFields()) {
918 string method = variable->GetType().GetLanguageType<Type>()->WriteToParcelMethod();
919
920 write_block->AddStatement(new Assignment(
921 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
922 ArgList(variable->GetName()))));
923 write_block->AddStatement(ReturnOnStatusNotOk());
924 }
925 write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
926
927 vector<unique_ptr<Declaration>> file_decls;
928 file_decls.push_back(std::move(read));
929 file_decls.push_back(std::move(write));
930
931 set<string> includes = {};
932 parcel.GetLanguageType<Type>()->GetHeaders(&includes);
933
934 return unique_ptr<Document>{
935 new CppSource{vector<string>(includes.begin(), includes.end()),
936 NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
937}
938
Christopher Wiley054afbd2015-10-16 17:08:43 -0700939bool WriteHeader(const CppOptions& options,
940 const TypeNamespace& types,
941 const AidlInterface& interface,
942 const IoDelegate& io_delegate,
943 ClassNames header_type) {
944 unique_ptr<Document> header;
945 switch (header_type) {
946 case ClassNames::INTERFACE:
947 header = BuildInterfaceHeader(types, interface);
948 break;
949 case ClassNames::CLIENT:
950 header = BuildClientHeader(types, interface);
951 break;
952 case ClassNames::SERVER:
953 header = BuildServerHeader(types, interface);
954 break;
955 default:
956 LOG(FATAL) << "aidl internal error";
957 }
958 if (!header) {
959 LOG(ERROR) << "aidl internal error: Failed to generate header.";
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700960 return false;
961 }
Christopher Wiley054afbd2015-10-16 17:08:43 -0700962
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800963 const string header_path = options.OutputHeaderDir() + OS_PATH_SEPARATOR +
964 HeaderFile(interface, header_type);
965 unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
966 header->Write(code_writer.get());
Christopher Wiley054afbd2015-10-16 17:08:43 -0700967
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800968 const bool success = code_writer->Close();
969 if (!success) {
970 io_delegate.RemovePath(header_path);
971 }
972
973 return success;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700974}
975
Casey Dahlina834dd42015-09-23 11:52:15 -0700976} // namespace internals
977
978using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700979
Steven Moreland5557f1c2018-07-02 13:50:23 -0700980string HeaderFile(const AidlDefinedType& defined_type, ClassNames class_type, bool use_os_sep) {
981 string file_path = defined_type.GetPackage();
Christopher Wiley3a9911c2016-01-19 12:59:09 -0800982 for (char& c: file_path) {
983 if (c == '.') {
984 c = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
985 }
986 }
987 if (!file_path.empty()) {
988 file_path += (use_os_sep) ? OS_PATH_SEPARATOR : '/';
989 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700990 file_path += ClassName(defined_type, class_type);
Christopher Wiley3a9911c2016-01-19 12:59:09 -0800991 file_path += ".h";
992
993 return file_path;
994}
995
Steven Moreland5557f1c2018-07-02 13:50:23 -0700996bool GenerateCppInterface(const CppOptions& options, const TypeNamespace& types,
997 const AidlInterface& interface, const IoDelegate& io_delegate) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700998 auto interface_src = BuildInterfaceSource(types, interface);
999 auto client_src = BuildClientSource(types, interface);
1000 auto server_src = BuildServerSource(types, interface);
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001001
Christopher Wiley054afbd2015-10-16 17:08:43 -07001002 if (!interface_src || !client_src || !server_src) {
1003 return false;
1004 }
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001005
Christopher Wiley054afbd2015-10-16 17:08:43 -07001006 if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(),
Christopher Wileyb656a3b2015-10-16 11:11:09 -07001007 interface.GetSplitPackage())) {
Christopher Wiley054afbd2015-10-16 17:08:43 -07001008 LOG(ERROR) << "Failed to create directory structure for headers.";
1009 return false;
1010 }
1011
1012 if (!WriteHeader(options, types, interface, io_delegate,
1013 ClassNames::INTERFACE) ||
1014 !WriteHeader(options, types, interface, io_delegate,
1015 ClassNames::CLIENT) ||
1016 !WriteHeader(options, types, interface, io_delegate,
1017 ClassNames::SERVER)) {
1018 return false;
1019 }
1020
Christopher Wiley054afbd2015-10-16 17:08:43 -07001021 unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(
1022 options.OutputCppFilePath());
1023 interface_src->Write(writer.get());
1024 client_src->Write(writer.get());
1025 server_src->Write(writer.get());
1026
Christopher Wiley9d6e0b22015-11-13 12:18:16 -08001027 const bool success = writer->Close();
1028 if (!success) {
1029 io_delegate.RemovePath(options.OutputCppFilePath());
1030 }
1031
1032 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -07001033}
1034
Steven Moreland5557f1c2018-07-02 13:50:23 -07001035bool GenerateCppParcel(const CppOptions& options, const cpp::TypeNamespace& types,
1036 const AidlStructuredParcelable& parcelable, const IoDelegate& io_delegate) {
1037 auto header = BuildParcelHeader(types, parcelable);
1038 auto source = BuildParcelSource(types, parcelable);
1039
1040 if (!header || !source) {
1041 return false;
1042 }
1043
1044 if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(), parcelable.GetSplitPackage())) {
1045 LOG(ERROR) << "Failed to create directory structure for headers.";
1046 }
1047
1048 const string header_path =
1049 options.OutputHeaderDir() + OS_PATH_SEPARATOR + HeaderFile(parcelable, ClassNames::BASE);
1050 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1051 header->Write(header_writer.get());
1052 CHECK(header_writer->Close());
1053
Steven Moreland81079f92018-07-06 16:15:53 -07001054 // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
1055 const string bp_header =
1056 options.OutputHeaderDir() + OS_PATH_SEPARATOR + HeaderFile(parcelable, ClassNames::CLIENT);
1057 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1058 bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
1059 CHECK(bp_writer->Close());
1060 const string bn_header =
1061 options.OutputHeaderDir() + OS_PATH_SEPARATOR + HeaderFile(parcelable, ClassNames::SERVER);
1062 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1063 bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
1064 CHECK(bn_writer->Close());
1065
Steven Moreland5557f1c2018-07-02 13:50:23 -07001066 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(options.OutputCppFilePath());
1067 source->Write(source_writer.get());
1068 CHECK(source_writer->Close());
1069
1070 return true;
1071}
1072
1073bool GenerateCpp(const CppOptions& options, const TypeNamespace& types,
1074 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
1075 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
1076 if (parcelable != nullptr) {
1077 return GenerateCppParcel(options, types, *parcelable, io_delegate);
1078 }
1079
1080 const AidlInterface* interface = defined_type.AsInterface();
1081 if (interface != nullptr) {
1082 return GenerateCppInterface(options, types, *interface, io_delegate);
1083 }
1084
1085 CHECK(false) << "Unrecognized type sent for cpp generation.";
1086 return false;
1087}
1088
Christopher Wileyf944e792015-09-29 10:00:46 -07001089} // namespace cpp
Christopher Wileyeb1acc12015-09-16 11:25:13 -07001090} // namespace aidl
Christopher Wileyf944e792015-09-29 10:00:46 -07001091} // namespace android