blob: f7e90cfa607ec158e692f6074da3edb202fa085c [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
Christopher Wileye3550c62015-09-29 13:26:10 -070034using android::base::StringPrintf;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070035using std::string;
Casey Dahlin082f1d12015-09-21 14:06:25 -070036using std::unique_ptr;
Casey Dahlina834dd42015-09-23 11:52:15 -070037using std::vector;
Casey Dahlince776cf2015-10-15 18:45:54 -070038using std::set;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070039
Christopher Wileyeb1acc12015-09-16 11:25:13 -070040namespace android {
41namespace aidl {
Christopher Wileyf944e792015-09-29 10:00:46 -070042namespace cpp {
Casey Dahlina834dd42015-09-23 11:52:15 -070043namespace internals {
Christopher Wiley0c732db2015-09-29 14:36:44 -070044namespace {
Christopher Wiley36570f42015-10-08 17:20:11 -070045
Casey Dahlinb8d9e882015-11-24 10:57:23 -080046const char kAndroidStatusVarName[] = "_aidl_ret_status";
47const char kCodeVarName[] = "_aidl_code";
48const char kFlagsVarName[] = "_aidl_flags";
49const char kDataVarName[] = "_aidl_data";
50const char kErrorLabel[] = "_aidl_error";
51const char kImplVarName[] = "_aidl_impl";
52const char kReplyVarName[] = "_aidl_reply";
Christopher Wileyad339272015-10-05 19:11:58 -070053const char kReturnVarName[] = "_aidl_return";
Casey Dahlinb8d9e882015-11-24 10:57:23 -080054const char kStatusVarName[] = "_aidl_status";
Martijn Coenenf1b50782018-02-21 21:06:23 +010055const char kTraceVarName[] = "_aidl_trace";
Casey Dahlinb8d9e882015-11-24 10:57:23 -080056const char kAndroidParcelLiteral[] = "::android::Parcel";
57const char kAndroidStatusLiteral[] = "::android::status_t";
58const char kAndroidStatusOk[] = "::android::OK";
59const char kBinderStatusLiteral[] = "::android::binder::Status";
Christopher Wiley0c732db2015-09-29 14:36:44 -070060const char kIBinderHeader[] = "binder/IBinder.h";
61const char kIInterfaceHeader[] = "binder/IInterface.h";
Christopher Wileyad339272015-10-05 19:11:58 -070062const char kParcelHeader[] = "binder/Parcel.h";
Christopher Wiley433c8bb2015-11-12 14:20:46 -080063const char kStatusHeader[] = "binder/Status.h";
Christopher Wiley69b44cf2016-05-03 13:43:33 -070064const char kString16Header[] = "utils/String16.h";
Martijn Coenenf1b50782018-02-21 21:06:23 +010065const char kTraceHeader[] = "utils/Trace.h";
Casey Dahlin389781f2015-10-22 13:13:21 -070066const char kStrongPointerHeader[] = "utils/StrongPointer.h";
Casey Dahlin082f1d12015-09-21 14:06:25 -070067
Christopher Wiley0eb903e2015-10-20 17:07:08 -070068unique_ptr<AstNode> BreakOnStatusNotOk() {
69 IfStatement* ret = new IfStatement(new Comparison(
Casey Dahlinb8d9e882015-11-24 10:57:23 -080070 new LiteralExpression(kAndroidStatusVarName), "!=",
71 new LiteralExpression(kAndroidStatusOk)));
Christopher Wiley0eb903e2015-10-20 17:07:08 -070072 ret->OnTrue()->AddLiteral("break");
73 return unique_ptr<AstNode>(ret);
74}
75
Christopher Wiley433c8bb2015-11-12 14:20:46 -080076unique_ptr<AstNode> GotoErrorOnBadStatus() {
77 IfStatement* ret = new IfStatement(new Comparison(
Casey Dahlinb8d9e882015-11-24 10:57:23 -080078 new LiteralExpression(kAndroidStatusVarName), "!=",
79 new LiteralExpression(kAndroidStatusOk)));
80 ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
Christopher Wiley433c8bb2015-11-12 14:20:46 -080081 return unique_ptr<AstNode>(ret);
82}
83
Steven Moreland5557f1c2018-07-02 13:50:23 -070084unique_ptr<AstNode> ReturnOnStatusNotOk() {
85 IfStatement* ret = new IfStatement(new Comparison(new LiteralExpression(kAndroidStatusVarName),
86 "!=", new LiteralExpression(kAndroidStatusOk)));
87 ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
88 return unique_ptr<AstNode>(ret);
89}
90
Christopher Wiley0c732db2015-09-29 14:36:44 -070091string UpperCase(const std::string& s) {
92 string result = s;
93 for (char& c : result)
94 c = toupper(c);
95 return result;
Casey Dahlina834dd42015-09-23 11:52:15 -070096}
Casey Dahlin082f1d12015-09-21 14:06:25 -070097
Christopher Wileyad339272015-10-05 19:11:58 -070098string BuildVarName(const AidlArgument& a) {
99 string prefix = "out_";
100 if (a.GetDirection() & AidlArgument::IN_DIR) {
101 prefix = "in_";
Christopher Wileye3550c62015-09-29 13:26:10 -0700102 }
Christopher Wileyad339272015-10-05 19:11:58 -0700103 return prefix + a.GetName();
104}
105
Christopher Wileyade4b452015-10-10 11:06:03 -0700106ArgList BuildArgList(const TypeNamespace& types,
107 const AidlMethod& method,
108 bool for_declaration) {
Christopher Wileyad339272015-10-05 19:11:58 -0700109 // Build up the argument list for the server method call.
110 vector<string> method_arguments;
111 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
112 string literal;
113 if (for_declaration) {
114 // Method declarations need types, pointers to out params, and variable
115 // names that match the .aidl specification.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800116 const Type* type = a->GetType().GetLanguageType<Type>();
Casey Dahlince776cf2015-10-15 18:45:54 -0700117
Casey Dahlina2f77c42015-12-01 18:26:02 -0800118 literal = type->CppType();
Casey Dahlinb0966612015-10-19 16:35:26 -0700119
Christopher Wileyb8e49a42015-10-27 12:55:18 -0700120 if (a->IsOut()) {
121 literal = literal + "*";
122 } else {
123 // We pass in parameters that are not primitives by const reference.
124 // Arrays of primitives are not primitives.
125 if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
126 literal = "const " + literal + "&";
127 }
128 }
Casey Dahlinb0966612015-10-19 16:35:26 -0700129
130 literal += " " + a->GetName();
Christopher Wileyad339272015-10-05 19:11:58 -0700131 } else {
132 if (a->IsOut()) { literal = "&"; }
133 literal += BuildVarName(*a);
134 }
135 method_arguments.push_back(literal);
136 }
137
Casey Dahlina2f77c42015-12-01 18:26:02 -0800138 const Type* return_type = method.GetType().GetLanguageType<Type>();
Casey Dahlince776cf2015-10-15 18:45:54 -0700139
Christopher Wileyad339272015-10-05 19:11:58 -0700140 if (return_type != types.VoidType()) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700141 string literal;
Christopher Wileyad339272015-10-05 19:11:58 -0700142 if (for_declaration) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700143 literal = StringPrintf(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800144 "%s* %s", return_type->CppType().c_str(),
Casey Dahlinb0966612015-10-19 16:35:26 -0700145 kReturnVarName);
Christopher Wileyad339272015-10-05 19:11:58 -0700146 } else {
Christopher Wileyade4b452015-10-10 11:06:03 -0700147 literal = string{"&"} + kReturnVarName;
Christopher Wileyad339272015-10-05 19:11:58 -0700148 }
Christopher Wileyade4b452015-10-10 11:06:03 -0700149 method_arguments.push_back(literal);
Christopher Wileyad339272015-10-05 19:11:58 -0700150 }
151
Christopher Wileyade4b452015-10-10 11:06:03 -0700152 return ArgList(method_arguments);
Casey Dahlina834dd42015-09-23 11:52:15 -0700153}
154
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700155unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
Christopher Wiley0c732db2015-09-29 14:36:44 -0700156 const TypeNamespace& types,
157 bool for_interface) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700158 uint32_t modifiers = 0;
159 if (for_interface) {
160 modifiers |= MethodDecl::IS_VIRTUAL;
161 modifiers |= MethodDecl::IS_PURE_VIRTUAL;
162 } else {
163 modifiers |= MethodDecl::IS_OVERRIDE;
164 }
165
166 return unique_ptr<Declaration>{
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800167 new MethodDecl{kBinderStatusLiteral,
Casey Dahlinf4a93112015-10-05 16:58:09 -0700168 method.GetName(),
Christopher Wileyad339272015-10-05 19:11:58 -0700169 BuildArgList(types, method, true /* for method decl */),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700170 modifiers}};
171}
172
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700173unique_ptr<CppNamespace> NestInNamespaces(
174 vector<unique_ptr<Declaration>> decls,
175 const vector<string>& package) {
176 if (package.empty()) {
177 // We should also be checking this before we get this far, but do it again
178 // for the sake of unit tests and meaningful errors.
179 LOG(FATAL) << "C++ generation requires a package declaration "
180 "for namespacing";
181 }
182 auto it = package.crbegin(); // Iterate over the namespaces inner to outer
183 unique_ptr<CppNamespace> inner{new CppNamespace{*it, std::move(decls)}};
184 ++it;
185 for (; it != package.crend(); ++it) {
186 inner.reset(new CppNamespace{*it, std::move(inner)});
187 }
188 return inner;
Christopher Wiley0c732db2015-09-29 14:36:44 -0700189}
190
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700191unique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl,
192 const vector<string>& package) {
193 vector<unique_ptr<Declaration>> decls;
194 decls.push_back(std::move(decl));
195 return NestInNamespaces(std::move(decls), package);
Christopher Wiley36570f42015-10-08 17:20:11 -0700196}
197
Christopher Wileyad339272015-10-05 19:11:58 -0700198bool DeclareLocalVariable(const TypeNamespace& types, const AidlArgument& a,
199 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;
225 case ClassNames::BASE:
226 break;
227 }
228 return c_name;
229}
230
Steven Moreland5557f1c2018-07-02 13:50:23 -0700231string BuildHeaderGuard(const AidlDefinedType& defined_type, ClassNames header_type) {
232 string class_name = ClassName(defined_type, header_type);
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700233 for (size_t i = 1; i < class_name.size(); ++i) {
234 if (isupper(class_name[i])) {
235 class_name.insert(i, "_");
236 ++i;
237 }
238 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700239 string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_", defined_type.GetPackage().c_str(),
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700240 class_name.c_str());
241 for (char& c : ret) {
242 if (c == '.') {
243 c = '_';
244 }
245 c = toupper(c);
246 }
247 return ret;
248}
Christopher Wiley36570f42015-10-08 17:20:11 -0700249
250unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
251 const AidlInterface& interface,
252 const AidlMethod& method) {
253 const string i_name = ClassName(interface, ClassNames::INTERFACE);
254 const string bp_name = ClassName(interface, ClassNames::CLIENT);
255 unique_ptr<MethodImpl> ret{new MethodImpl{
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800256 kBinderStatusLiteral, bp_name, method.GetName(),
Christopher Wiley36570f42015-10-08 17:20:11 -0700257 ArgList{BuildArgList(types, method, true /* for method decl */)}}};
258 StatementBlock* b = ret->GetStatementBlock();
259
260 // Declare parcels to hold our query and the response.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800261 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
Christopher Wiley1227d612015-10-26 16:59:20 -0700262 // Even if we're oneway, the transact method still takes a parcel.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800263 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700264
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800265 // Declare the status_t variable we need for error handling.
Christopher Wiley10957122015-12-04 14:35:38 -0800266 b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
267 kAndroidStatusVarName,
268 kAndroidStatusOk));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800269 // We unconditionally return a Status object.
270 b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
Christopher Wiley36570f42015-10-08 17:20:11 -0700271
Martijn Coenenf1b50782018-02-21 21:06:23 +0100272 if (interface.ShouldGenerateTraces()) {
273 b->AddLiteral(
274 StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
275 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
276 }
277
Christopher Wiley8993cb52015-10-21 09:53:24 -0700278 // Add the name of the interface we're hoping to call.
279 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800280 kAndroidStatusVarName,
281 new MethodCall(StringPrintf("%s.writeInterfaceToken",
282 kDataVarName),
283 "getInterfaceDescriptor()")));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800284 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley8993cb52015-10-21 09:53:24 -0700285
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700286 for (const auto& a: method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800287 const Type* type = a->GetType().GetLanguageType<Type>();
Christopher Wiley36570f42015-10-08 17:20:11 -0700288 string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
Casey Dahlin389781f2015-10-22 13:13:21 -0700289 var_name = type->WriteCast(var_name);
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700290
291 if (a->IsIn()) {
292 // Serialization looks roughly like:
293 // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
294 // if (_aidl_ret_status != ::android::OK) { goto error; }
295 const string& method = type->WriteToParcelMethod();
296 b->AddStatement(new Assignment(
297 kAndroidStatusVarName,
298 new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
299 ArgList(var_name))));
300 b->AddStatement(GotoErrorOnBadStatus());
301 } else if (a->IsOut() && a->GetType().IsArray()) {
302 // Special case, the length of the out array is written into the parcel.
303 // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
304 // if (_aidl_ret_status != ::android::OK) { goto error; }
305 b->AddStatement(new Assignment(
306 kAndroidStatusVarName,
307 new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
308 ArgList(var_name))));
309 b->AddStatement(GotoErrorOnBadStatus());
310 }
Christopher Wiley36570f42015-10-08 17:20:11 -0700311 }
312
313 // Invoke the transaction on the remote binder and confirm status.
314 string transaction_code = StringPrintf(
315 "%s::%s", i_name.c_str(), UpperCase(method.GetName()).c_str());
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700316
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800317 vector<string> args = {transaction_code, kDataVarName,
318 StringPrintf("&%s", kReplyVarName)};
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700319
320 if (interface.IsOneway() || method.IsOneway()) {
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800321 args.push_back("::android::IBinder::FLAG_ONEWAY");
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700322 }
323
Christopher Wiley36570f42015-10-08 17:20:11 -0700324 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800325 kAndroidStatusVarName,
Christopher Wiley36570f42015-10-08 17:20:11 -0700326 new MethodCall("remote()->transact",
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700327 ArgList(args))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800328 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700329
Christopher Wiley1227d612015-10-26 16:59:20 -0700330 if (!interface.IsOneway() && !method.IsOneway()) {
331 // Strip off the exception header and fail if we see a remote exception.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800332 // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
333 // if (_aidl_ret_status != ::android::OK) { goto error; }
334 // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800335 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800336 kAndroidStatusVarName,
337 StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800338 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley1227d612015-10-26 16:59:20 -0700339 IfStatement* exception_check = new IfStatement(
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800340 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
Christopher Wiley1227d612015-10-26 16:59:20 -0700341 b->AddStatement(exception_check);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800342 exception_check->OnTrue()->AddLiteral(
343 StringPrintf("return %s", kStatusVarName));
Christopher Wiley1227d612015-10-26 16:59:20 -0700344 }
345
346 // Type checking should guarantee that nothing below emits code until "return
347 // status" if we are a oneway method, so no more fear of accessing reply.
Christopher Wiley2aaeda82015-10-19 15:16:49 -0700348
Christopher Wiley36570f42015-10-08 17:20:11 -0700349 // If the method is expected to return something, read it first by convention.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800350 const Type* return_type = method.GetType().GetLanguageType<Type>();
Christopher Wiley36570f42015-10-08 17:20:11 -0700351 if (return_type != types.VoidType()) {
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700352 const string& method_call = return_type->ReadFromParcelMethod();
Christopher Wiley36570f42015-10-08 17:20:11 -0700353 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800354 kAndroidStatusVarName,
355 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
356 method_call.c_str()),
357 ArgList(kReturnVarName))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800358 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700359 }
360
361 for (const AidlArgument* a : method.GetOutArguments()) {
362 // Deserialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800363 // _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
364 // if (_aidl_status != ::android::OK) { goto _aidl_error; }
Casey Dahlinb0966612015-10-19 16:35:26 -0700365 string method =
Casey Dahlina2f77c42015-12-01 18:26:02 -0800366 a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700367
Christopher Wiley36570f42015-10-08 17:20:11 -0700368 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800369 kAndroidStatusVarName,
370 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
371 method.c_str()),
372 ArgList(a->GetName()))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800373 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700374 }
375
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800376 // If we've gotten to here, one of two things is true:
377 // 1) We've read some bad status_t
378 // 2) We've only read status_t == OK and there was no exception in the
379 // response.
380 // In both cases, we're free to set Status from the status_t and return.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800381 b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800382 b->AddLiteral(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800383 StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
384 kAndroidStatusVarName));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100385
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800386 b->AddLiteral(StringPrintf("return %s", kStatusVarName));
Christopher Wiley36570f42015-10-08 17:20:11 -0700387
388 return unique_ptr<Declaration>(ret.release());
389}
390
391} // namespace
392
Christopher Wileye3550c62015-09-29 13:26:10 -0700393unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
Christopher Wiley36570f42015-10-08 17:20:11 -0700394 const AidlInterface& interface) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700395 vector<string> include_list = {
396 HeaderFile(interface, ClassNames::CLIENT, false),
397 kParcelHeader
398 };
Christopher Wiley36570f42015-10-08 17:20:11 -0700399 vector<unique_ptr<Declaration>> file_decls;
400
401 // The constructor just passes the IBinder instance up to the super
402 // class.
Christopher Wiley1db03482015-10-22 11:42:02 -0700403 const string i_name = ClassName(interface, ClassNames::INTERFACE);
Christopher Wiley36570f42015-10-08 17:20:11 -0700404 file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
Christopher Wiley054afbd2015-10-16 17:08:43 -0700405 ClassName(interface, ClassNames::CLIENT),
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800406 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
407 kImplVarName)},
408 { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
Christopher Wiley36570f42015-10-08 17:20:11 -0700409
410 // Clients define a method per transaction.
411 for (const auto& method : interface.GetMethods()) {
412 unique_ptr<Declaration> m = DefineClientTransaction(
413 types, interface, *method);
414 if (!m) { return nullptr; }
415 file_decls.push_back(std::move(m));
416 }
417 return unique_ptr<Document>{new CppSource{
418 include_list,
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700419 NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700420}
421
Christopher Wileyad339272015-10-05 19:11:58 -0700422namespace {
423
424bool HandleServerTransaction(const TypeNamespace& types,
Martijn Coenenf1b50782018-02-21 21:06:23 +0100425 const AidlInterface& interface,
Christopher Wileyad339272015-10-05 19:11:58 -0700426 const AidlMethod& method,
427 StatementBlock* b) {
428 // Declare all the parameters now. In the common case, we expect no errors
429 // in serialization.
430 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
431 if (!DeclareLocalVariable(types, *a, b)) { return false; }
432 }
433
434 // Declare a variable to hold the return value.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800435 const Type* return_type = method.GetType().GetLanguageType<Type>();
Christopher Wileyad339272015-10-05 19:11:58 -0700436 if (return_type != types.VoidType()) {
437 b->AddLiteral(StringPrintf(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800438 "%s %s", return_type->CppType().c_str(),
Casey Dahlinb0966612015-10-19 16:35:26 -0700439 kReturnVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700440 }
441
Christopher Wiley8993cb52015-10-21 09:53:24 -0700442 // Check that the client is calling the correct interface.
443 IfStatement* interface_check = new IfStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800444 new MethodCall(StringPrintf("%s.checkInterface",
445 kDataVarName), "this"),
Christopher Wiley8993cb52015-10-21 09:53:24 -0700446 true /* invert the check */);
447 b->AddStatement(interface_check);
448 interface_check->OnTrue()->AddStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800449 new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
Christopher Wiley8993cb52015-10-21 09:53:24 -0700450 interface_check->OnTrue()->AddLiteral("break");
451
Christopher Wileyad339272015-10-05 19:11:58 -0700452 // Deserialize each "in" parameter to the transaction.
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700453 for (const auto& a: method.GetArguments()) {
Christopher Wileyad339272015-10-05 19:11:58 -0700454 // Deserialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800455 // _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
456 // if (_aidl_ret_status != ::android::OK) { break; }
Casey Dahlina2f77c42015-12-01 18:26:02 -0800457 const Type* type = a->GetType().GetLanguageType<Type>();
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700458 const string& readMethod = type->ReadFromParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700459
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700460 if (a->IsIn()) {
461 b->AddStatement(new Assignment{
462 kAndroidStatusVarName,
463 new MethodCall{string(kDataVarName) + "." + readMethod,
464 "&" + BuildVarName(*a)}});
465 b->AddStatement(BreakOnStatusNotOk());
466 } else if (a->IsOut() && a->GetType().IsArray()) {
467 // Special case, the length of the out array is written into the parcel.
468 // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
469 // if (_aidl_ret_status != ::android::OK) { break; }
470 b->AddStatement(new Assignment{
471 kAndroidStatusVarName,
472 new MethodCall{string(kDataVarName) + ".resizeOutVector",
473 "&" + BuildVarName(*a)}});
474 b->AddStatement(BreakOnStatusNotOk());
475 }
Christopher Wileyad339272015-10-05 19:11:58 -0700476 }
477
Martijn Coenenf1b50782018-02-21 21:06:23 +0100478 if (interface.ShouldGenerateTraces()) {
479 b->AddStatement(new Statement(new MethodCall("atrace_begin",
480 ArgList{{"ATRACE_TAG_AIDL",
481 StringPrintf("\"%s::%s::cppServer\"",
482 interface.GetName().c_str(),
483 method.GetName().c_str())}})));
484 }
485
Christopher Wileyad339272015-10-05 19:11:58 -0700486 // Call the actual method. This is implemented by the subclass.
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800487 vector<unique_ptr<AstNode>> status_args;
488 status_args.emplace_back(new MethodCall(
Christopher Wileyad339272015-10-05 19:11:58 -0700489 method.GetName(),
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800490 BuildArgList(types, method, false /* not for method decl */)));
491 b->AddStatement(new Statement(new MethodCall(
492 StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
493 ArgList(std::move(status_args)))));
Christopher Wileyad339272015-10-05 19:11:58 -0700494
Martijn Coenenf1b50782018-02-21 21:06:23 +0100495 if (interface.ShouldGenerateTraces()) {
496 b->AddStatement(new Statement(new MethodCall("atrace_end",
497 "ATRACE_TAG_AIDL")));
498 }
499
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800500 // Write exceptions during transaction handling to parcel.
501 if (!method.IsOneway()) {
502 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800503 kAndroidStatusVarName,
504 StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800505 b->AddStatement(BreakOnStatusNotOk());
506 IfStatement* exception_check = new IfStatement(
507 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
508 b->AddStatement(exception_check);
509 exception_check->OnTrue()->AddLiteral("break");
510 }
Casey Dahlinb0966612015-10-19 16:35:26 -0700511
Christopher Wiley36570f42015-10-08 17:20:11 -0700512 // If we have a return value, write it first.
513 if (return_type != types.VoidType()) {
Christopher Wiley2aaeda82015-10-19 15:16:49 -0700514 string writeMethod =
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800515 string(kReplyVarName) + "->" +
Casey Dahlina2f77c42015-12-01 18:26:02 -0800516 return_type->WriteToParcelMethod();
Christopher Wiley36570f42015-10-08 17:20:11 -0700517 b->AddStatement(new Assignment{
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800518 kAndroidStatusVarName, new MethodCall{writeMethod,
Casey Dahlin389781f2015-10-22 13:13:21 -0700519 ArgList{return_type->WriteCast(kReturnVarName)}}});
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700520 b->AddStatement(BreakOnStatusNotOk());
Christopher Wiley36570f42015-10-08 17:20:11 -0700521 }
522
Christopher Wileyad339272015-10-05 19:11:58 -0700523 // Write each out parameter to the reply parcel.
524 for (const AidlArgument* a : method.GetOutArguments()) {
525 // Serialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800526 // _aidl_ret_status = data.WriteInt32(out_param_name);
527 // if (_aidl_ret_status != ::android::OK) { break; }
Casey Dahlina2f77c42015-12-01 18:26:02 -0800528 const Type* type = a->GetType().GetLanguageType<Type>();
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700529 const string& writeMethod = type->WriteToParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700530
Christopher Wileyad339272015-10-05 19:11:58 -0700531 b->AddStatement(new Assignment{
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800532 kAndroidStatusVarName,
533 new MethodCall{string(kReplyVarName) + "->" + writeMethod,
Casey Dahlin389781f2015-10-22 13:13:21 -0700534 type->WriteCast(BuildVarName(*a))}});
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700535 b->AddStatement(BreakOnStatusNotOk());
Christopher Wileyad339272015-10-05 19:11:58 -0700536 }
537
538 return true;
539}
540
541} // namespace
542
Christopher Wileye3550c62015-09-29 13:26:10 -0700543unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
Christopher Wiley054afbd2015-10-16 17:08:43 -0700544 const AidlInterface& interface) {
545 const string bn_name = ClassName(interface, ClassNames::SERVER);
546 vector<string> include_list{
547 HeaderFile(interface, ClassNames::SERVER, false),
548 kParcelHeader
549 };
Christopher Wileyad339272015-10-05 19:11:58 -0700550 unique_ptr<MethodImpl> on_transact{new MethodImpl{
551 kAndroidStatusLiteral, bn_name, "onTransact",
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800552 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
553 StringPrintf("const %s& %s", kAndroidParcelLiteral,
554 kDataVarName),
555 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
556 StringPrintf("uint32_t %s", kFlagsVarName)}}
Christopher Wiley36570f42015-10-08 17:20:11 -0700557 }};
Christopher Wileyad339272015-10-05 19:11:58 -0700558
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800559 // Declare the status_t variable
Christopher Wiley05f4f892015-10-14 13:30:43 -0700560 on_transact->GetStatementBlock()->AddLiteral(
Christopher Wiley10957122015-12-04 14:35:38 -0800561 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
562 kAndroidStatusOk));
Christopher Wiley05f4f892015-10-14 13:30:43 -0700563
Christopher Wileyad339272015-10-05 19:11:58 -0700564 // Add the all important switch statement, but retain a pointer to it.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800565 SwitchStatement* s = new SwitchStatement{kCodeVarName};
Christopher Wileyf9688b02015-10-08 17:17:50 -0700566 on_transact->GetStatementBlock()->AddStatement(s);
Christopher Wileyad339272015-10-05 19:11:58 -0700567
568 // The switch statement has a case statement for each transaction code.
Christopher Wiley054afbd2015-10-16 17:08:43 -0700569 for (const auto& method : interface.GetMethods()) {
Christopher Wileyad339272015-10-05 19:11:58 -0700570 StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
571 if (!b) { return nullptr; }
572
Martijn Coenenf1b50782018-02-21 21:06:23 +0100573 if (!HandleServerTransaction(types, interface, *method, b)) { return nullptr; }
Christopher Wileyad339272015-10-05 19:11:58 -0700574 }
575
576 // The switch statement has a default case which defers to the super class.
577 // The superclass handles a few pre-defined transactions.
578 StatementBlock* b = s->AddCase("");
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800579 b->AddLiteral(StringPrintf(
580 "%s = ::android::BBinder::onTransact(%s, %s, "
581 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
582 kDataVarName, kReplyVarName, kFlagsVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700583
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800584 // If we saw a null reference, we can map that to an appropriate exception.
585 IfStatement* null_check = new IfStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800586 new LiteralExpression(string(kAndroidStatusVarName) +
587 " == ::android::UNEXPECTED_NULL"));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800588 on_transact->GetStatementBlock()->AddStatement(null_check);
589 null_check->OnTrue()->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800590 kAndroidStatusVarName,
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800591 StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800592 ".writeToParcel(%s)",
593 kBinderStatusLiteral, kBinderStatusLiteral,
594 kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800595
Christopher Wileyad339272015-10-05 19:11:58 -0700596 // Finally, the server's onTransact method just returns a status code.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800597 on_transact->GetStatementBlock()->AddLiteral(
598 StringPrintf("return %s", kAndroidStatusVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700599
600 return unique_ptr<Document>{new CppSource{
601 include_list,
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700602 NestInNamespaces(std::move(on_transact), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700603}
604
Christopher Wileyf59c4992015-10-08 13:12:44 -0700605unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& /* types */,
Christopher Wiley054afbd2015-10-16 17:08:43 -0700606 const AidlInterface& interface) {
607 vector<string> include_list{
608 HeaderFile(interface, ClassNames::INTERFACE, false),
609 HeaderFile(interface, ClassNames::CLIENT, false),
610 };
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700611
Christopher Wiley054afbd2015-10-16 17:08:43 -0700612 string fq_name = ClassName(interface, ClassNames::INTERFACE);
613 if (!interface.GetPackage().empty()) {
614 fq_name = interface.GetPackage() + "." + fq_name;
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700615 }
616
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700617 vector<unique_ptr<Declaration>> decls;
618
Christopher Wiley11a9d792016-02-24 17:20:33 -0800619 unique_ptr<MacroDecl> meta_if{new MacroDecl{
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700620 "IMPLEMENT_META_INTERFACE",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700621 ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
Christopher Wileyade4b452015-10-10 11:06:03 -0700622 '"' + fq_name + '"'}}}};
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700623 decls.push_back(std::move(meta_if));
624
625 for (const auto& constant: interface.GetStringConstants()) {
626 unique_ptr<MethodImpl> getter(new MethodImpl(
627 "const ::android::String16&",
628 ClassName(interface, ClassNames::INTERFACE),
629 constant->GetName(),
630 {}));
631 getter->GetStatementBlock()->AddLiteral(
632 StringPrintf("static const ::android::String16 value(%s)",
633 constant->GetValue().c_str()));
634 getter->GetStatementBlock()->AddLiteral("return value");
635 decls.push_back(std::move(getter));
636 }
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700637
638 return unique_ptr<Document>{new CppSource{
639 include_list,
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700640 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700641}
642
Christopher Wileye3550c62015-09-29 13:26:10 -0700643unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700644 const AidlInterface& interface) {
645 const string i_name = ClassName(interface, ClassNames::INTERFACE);
646 const string bp_name = ClassName(interface, ClassNames::CLIENT);
Casey Dahlina834dd42015-09-23 11:52:15 -0700647
Christopher Wileyb23149d2015-10-14 13:52:21 -0700648 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
649 bp_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800650 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
651 kImplVarName)},
Christopher Wileyb23149d2015-10-14 13:52:21 -0700652 ConstructorDecl::IS_EXPLICIT
653 }};
654 unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
655 "~" + bp_name,
656 ArgList{},
657 ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
Casey Dahlina834dd42015-09-23 11:52:15 -0700658
Christopher Wileyf944e792015-09-29 10:00:46 -0700659 vector<unique_ptr<Declaration>> publics;
Casey Dahlina834dd42015-09-23 11:52:15 -0700660 publics.push_back(std::move(constructor));
661 publics.push_back(std::move(destructor));
662
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700663 for (const auto& method: interface.GetMethods()) {
Christopher Wiley36570f42015-10-08 17:20:11 -0700664 publics.push_back(BuildMethodDecl(*method, types, false));
Casey Dahlina834dd42015-09-23 11:52:15 -0700665 }
666
Christopher Wileyf944e792015-09-29 10:00:46 -0700667 unique_ptr<ClassDecl> bp_class{
668 new ClassDecl{bp_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800669 "::android::BpInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700670 std::move(publics),
671 {}
Casey Dahlina834dd42015-09-23 11:52:15 -0700672 }};
673
Christopher Wiley0c732db2015-09-29 14:36:44 -0700674 return unique_ptr<Document>{new CppHeader{
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700675 BuildHeaderGuard(interface, ClassNames::CLIENT),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700676 {kIBinderHeader,
677 kIInterfaceHeader,
678 "utils/Errors.h",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700679 HeaderFile(interface, ClassNames::INTERFACE, false)},
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700680 NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700681}
682
Christopher Wileyf59c4992015-10-08 13:12:44 -0700683unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
Christopher Wileyfd51d602015-10-14 13:04:48 -0700684 const AidlInterface& interface) {
685 const string i_name = ClassName(interface, ClassNames::INTERFACE);
686 const string bn_name = ClassName(interface, ClassNames::SERVER);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700687
Christopher Wileyfd51d602015-10-14 13:04:48 -0700688 unique_ptr<Declaration> on_transact{new MethodDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700689 kAndroidStatusLiteral, "onTransact",
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800690 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
691 StringPrintf("const %s& %s", kAndroidParcelLiteral,
692 kDataVarName),
693 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
694 StringPrintf("uint32_t %s = 0", kFlagsVarName)}},
Christopher Wileyfd51d602015-10-14 13:04:48 -0700695 MethodDecl::IS_OVERRIDE
696 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700697
Christopher Wileyf944e792015-09-29 10:00:46 -0700698 std::vector<unique_ptr<Declaration>> publics;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700699 publics.push_back(std::move(on_transact));
700
Christopher Wileyf944e792015-09-29 10:00:46 -0700701 unique_ptr<ClassDecl> bn_class{
702 new ClassDecl{bn_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800703 "::android::BnInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700704 std::move(publics),
705 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700706 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700707
Christopher Wiley0c732db2015-09-29 14:36:44 -0700708 return unique_ptr<Document>{new CppHeader{
Christopher Wileyfd51d602015-10-14 13:04:48 -0700709 BuildHeaderGuard(interface, ClassNames::SERVER),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700710 {"binder/IInterface.h",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700711 HeaderFile(interface, ClassNames::INTERFACE, false)},
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700712 NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700713}
714
Christopher Wileye3550c62015-09-29 13:26:10 -0700715unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700716 const AidlInterface& interface) {
Casey Dahlin389781f2015-10-22 13:13:21 -0700717 set<string> includes = { kIBinderHeader, kIInterfaceHeader,
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800718 kStatusHeader, kStrongPointerHeader };
Casey Dahlince776cf2015-10-15 18:45:54 -0700719
720 for (const auto& method : interface.GetMethods()) {
721 for (const auto& argument : method->GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800722 const Type* type = argument->GetType().GetLanguageType<Type>();
723 type->GetHeaders(&includes);
Casey Dahlince776cf2015-10-15 18:45:54 -0700724 }
725
Casey Dahlina2f77c42015-12-01 18:26:02 -0800726 const Type* return_type = method->GetType().GetLanguageType<Type>();
727 return_type->GetHeaders(&includes);
Casey Dahlince776cf2015-10-15 18:45:54 -0700728 }
729
Christopher Wiley0c732db2015-09-29 14:36:44 -0700730 unique_ptr<ClassDecl> if_class{
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700731 new ClassDecl{ClassName(interface, ClassNames::INTERFACE),
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800732 "::android::IInterface"}};
Christopher Wiley11a9d792016-02-24 17:20:33 -0800733 if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700734 "DECLARE_META_INTERFACE",
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700735 ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
Christopher Wiley0c732db2015-09-29 14:36:44 -0700736
Christopher Wileyfd7dc032016-02-02 17:58:39 -0800737 unique_ptr<Enum> constant_enum{new Enum{"", "int32_t"}};
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700738 for (const auto& constant : interface.GetIntConstants()) {
Christopher Wileyfd7dc032016-02-02 17:58:39 -0800739 constant_enum->AddValue(
740 constant->GetName(), std::to_string(constant->GetValue()));
741 }
742 if (constant_enum->HasValues()) {
743 if_class->AddPublic(std::move(constant_enum));
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800744 }
745
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700746 if (!interface.GetStringConstants().empty()) {
747 includes.insert(kString16Header);
748 }
Martijn Coenenf1b50782018-02-21 21:06:23 +0100749
750 if (interface.ShouldGenerateTraces()) {
751 includes.insert(kTraceHeader);
752 }
753
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700754 for (const auto& constant : interface.GetStringConstants()) {
755 unique_ptr<MethodDecl> getter(new MethodDecl(
756 "const ::android::String16&", constant->GetName(),
757 {}, MethodDecl::IS_STATIC));
758 if_class->AddPublic(std::move(getter));
759 }
760
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700761 if (!interface.GetMethods().empty()) {
762 unique_ptr<Enum> call_enum{new Enum{"Call"}};
763 for (const auto& method : interface.GetMethods()) {
764 // Each method gets an enum entry and pure virtual declaration.
765 if_class->AddPublic(BuildMethodDecl(*method, types, true));
766 call_enum->AddValue(
767 UpperCase(method->GetName()),
768 StringPrintf("::android::IBinder::FIRST_CALL_TRANSACTION + %d",
769 method->GetId()));
770 }
771 if_class->AddPublic(std::move(call_enum));
Christopher Wiley0c732db2015-09-29 14:36:44 -0700772 }
Christopher Wiley0c732db2015-09-29 14:36:44 -0700773
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700774 return unique_ptr<Document>{new CppHeader{
775 BuildHeaderGuard(interface, ClassNames::INTERFACE),
Casey Dahlince776cf2015-10-15 18:45:54 -0700776 vector<string>(includes.begin(), includes.end()),
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700777 NestInNamespaces(std::move(if_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700778}
779
Steven Moreland5557f1c2018-07-02 13:50:23 -0700780std::unique_ptr<Document> BuildParcelHeader(const TypeNamespace& /*types*/,
781 const AidlStructuredParcelable& parcel) {
782 unique_ptr<ClassDecl> parcel_class{new ClassDecl{parcel.GetName(), "::android::Parcelable"}};
783
784 set<string> includes = {kStatusHeader, kParcelHeader};
785 for (const auto& variable : parcel.GetFields()) {
786 const Type* type = variable->GetType().GetLanguageType<Type>();
787 type->GetHeaders(&includes);
788 }
789
790 for (const auto& variable : parcel.GetFields()) {
791 const Type* type = variable->GetType().GetLanguageType<Type>();
792
793 parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(
794 StringPrintf("%s %s;\n", type->CppType().c_str(), variable->GetName().c_str()))));
795 }
796
797 unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
798 ArgList("const Parcel* _aidl_parcel"),
799 MethodDecl::IS_OVERRIDE));
800 parcel_class->AddPublic(std::move(read));
801 unique_ptr<MethodDecl> write(new MethodDecl(kAndroidStatusLiteral, "writeToParcel",
802 ArgList("Parcel* _aidl_parcel"),
803 MethodDecl::IS_OVERRIDE | MethodDecl::IS_CONST));
804 parcel_class->AddPublic(std::move(write));
805
806 return unique_ptr<Document>{new CppHeader{
807 BuildHeaderGuard(parcel, ClassNames::BASE), vector<string>(includes.begin(), includes.end()),
808 NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage())}};
809}
810std::unique_ptr<Document> BuildParcelSource(const TypeNamespace& types,
811 const AidlStructuredParcelable& parcel) {
812 unique_ptr<MethodImpl> read{new MethodImpl{kAndroidStatusLiteral, parcel.GetName(),
813 "readFromParcel",
814 ArgList("const Parcel* _aidl_parcel")}};
815 StatementBlock* read_block = read->GetStatementBlock();
816 read_block->AddLiteral(
817 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
818 for (const auto& variable : parcel.GetFields()) {
819 string method = variable->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
820
821 read_block->AddStatement(new Assignment(
822 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
823 ArgList("&" + variable->GetName()))));
824 read_block->AddStatement(ReturnOnStatusNotOk());
825 }
826 read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
827
828 unique_ptr<MethodImpl> write{new MethodImpl{kAndroidStatusLiteral, parcel.GetName(),
829 "writeToParcel", ArgList("Parcel* _aidl_parcel"),
830 true /*const*/}};
831 StatementBlock* write_block = write->GetStatementBlock();
832 write_block->AddLiteral(
833 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
834 for (const auto& variable : parcel.GetFields()) {
835 string method = variable->GetType().GetLanguageType<Type>()->WriteToParcelMethod();
836
837 write_block->AddStatement(new Assignment(
838 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
839 ArgList(variable->GetName()))));
840 write_block->AddStatement(ReturnOnStatusNotOk());
841 }
842 write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
843
844 vector<unique_ptr<Declaration>> file_decls;
845 file_decls.push_back(std::move(read));
846 file_decls.push_back(std::move(write));
847
848 set<string> includes = {};
849 parcel.GetLanguageType<Type>()->GetHeaders(&includes);
850
851 return unique_ptr<Document>{
852 new CppSource{vector<string>(includes.begin(), includes.end()),
853 NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
854}
855
Christopher Wiley054afbd2015-10-16 17:08:43 -0700856bool WriteHeader(const CppOptions& options,
857 const TypeNamespace& types,
858 const AidlInterface& interface,
859 const IoDelegate& io_delegate,
860 ClassNames header_type) {
861 unique_ptr<Document> header;
862 switch (header_type) {
863 case ClassNames::INTERFACE:
864 header = BuildInterfaceHeader(types, interface);
865 break;
866 case ClassNames::CLIENT:
867 header = BuildClientHeader(types, interface);
868 break;
869 case ClassNames::SERVER:
870 header = BuildServerHeader(types, interface);
871 break;
872 default:
873 LOG(FATAL) << "aidl internal error";
874 }
875 if (!header) {
876 LOG(ERROR) << "aidl internal error: Failed to generate header.";
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700877 return false;
878 }
Christopher Wiley054afbd2015-10-16 17:08:43 -0700879
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800880 const string header_path = options.OutputHeaderDir() + OS_PATH_SEPARATOR +
881 HeaderFile(interface, header_type);
882 unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
883 header->Write(code_writer.get());
Christopher Wiley054afbd2015-10-16 17:08:43 -0700884
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800885 const bool success = code_writer->Close();
886 if (!success) {
887 io_delegate.RemovePath(header_path);
888 }
889
890 return success;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700891}
892
Casey Dahlina834dd42015-09-23 11:52:15 -0700893} // namespace internals
894
895using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700896
Steven Moreland5557f1c2018-07-02 13:50:23 -0700897string HeaderFile(const AidlDefinedType& defined_type, ClassNames class_type, bool use_os_sep) {
898 string file_path = defined_type.GetPackage();
Christopher Wiley3a9911c2016-01-19 12:59:09 -0800899 for (char& c: file_path) {
900 if (c == '.') {
901 c = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
902 }
903 }
904 if (!file_path.empty()) {
905 file_path += (use_os_sep) ? OS_PATH_SEPARATOR : '/';
906 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700907 file_path += ClassName(defined_type, class_type);
Christopher Wiley3a9911c2016-01-19 12:59:09 -0800908 file_path += ".h";
909
910 return file_path;
911}
912
Steven Moreland5557f1c2018-07-02 13:50:23 -0700913bool GenerateCppInterface(const CppOptions& options, const TypeNamespace& types,
914 const AidlInterface& interface, const IoDelegate& io_delegate) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700915 auto interface_src = BuildInterfaceSource(types, interface);
916 auto client_src = BuildClientSource(types, interface);
917 auto server_src = BuildServerSource(types, interface);
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700918
Christopher Wiley054afbd2015-10-16 17:08:43 -0700919 if (!interface_src || !client_src || !server_src) {
920 return false;
921 }
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700922
Christopher Wiley054afbd2015-10-16 17:08:43 -0700923 if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(),
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700924 interface.GetSplitPackage())) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700925 LOG(ERROR) << "Failed to create directory structure for headers.";
926 return false;
927 }
928
929 if (!WriteHeader(options, types, interface, io_delegate,
930 ClassNames::INTERFACE) ||
931 !WriteHeader(options, types, interface, io_delegate,
932 ClassNames::CLIENT) ||
933 !WriteHeader(options, types, interface, io_delegate,
934 ClassNames::SERVER)) {
935 return false;
936 }
937
Christopher Wiley054afbd2015-10-16 17:08:43 -0700938 unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(
939 options.OutputCppFilePath());
940 interface_src->Write(writer.get());
941 client_src->Write(writer.get());
942 server_src->Write(writer.get());
943
Christopher Wiley9d6e0b22015-11-13 12:18:16 -0800944 const bool success = writer->Close();
945 if (!success) {
946 io_delegate.RemovePath(options.OutputCppFilePath());
947 }
948
949 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700950}
951
Steven Moreland5557f1c2018-07-02 13:50:23 -0700952bool GenerateCppParcel(const CppOptions& options, const cpp::TypeNamespace& types,
953 const AidlStructuredParcelable& parcelable, const IoDelegate& io_delegate) {
954 auto header = BuildParcelHeader(types, parcelable);
955 auto source = BuildParcelSource(types, parcelable);
956
957 if (!header || !source) {
958 return false;
959 }
960
961 if (!io_delegate.CreatedNestedDirs(options.OutputHeaderDir(), parcelable.GetSplitPackage())) {
962 LOG(ERROR) << "Failed to create directory structure for headers.";
963 }
964
965 const string header_path =
966 options.OutputHeaderDir() + OS_PATH_SEPARATOR + HeaderFile(parcelable, ClassNames::BASE);
967 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
968 header->Write(header_writer.get());
969 CHECK(header_writer->Close());
970
971 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(options.OutputCppFilePath());
972 source->Write(source_writer.get());
973 CHECK(source_writer->Close());
974
975 return true;
976}
977
978bool GenerateCpp(const CppOptions& options, const TypeNamespace& types,
979 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
980 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
981 if (parcelable != nullptr) {
982 return GenerateCppParcel(options, types, *parcelable, io_delegate);
983 }
984
985 const AidlInterface* interface = defined_type.AsInterface();
986 if (interface != nullptr) {
987 return GenerateCppInterface(options, types, *interface, io_delegate);
988 }
989
990 CHECK(false) << "Unrecognized type sent for cpp generation.";
991 return false;
992}
993
Christopher Wileyf944e792015-09-29 10:00:46 -0700994} // namespace cpp
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700995} // namespace aidl
Christopher Wileyf944e792015-09-29 10:00:46 -0700996} // namespace android