blob: 76f98062297fdf08b3eeb5ae1a4e4c70b7f47e36 [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"
Jiyong Park309668e2018-07-28 16:55:44 +090018#include "aidl.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070019
Casey Dahlin082f1d12015-09-21 14:06:25 -070020#include <cctype>
Christopher Wileyad339272015-10-05 19:11:58 -070021#include <cstring>
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070022#include <memory>
Casey Dahlin082f1d12015-09-21 14:06:25 -070023#include <random>
Casey Dahlince776cf2015-10-15 18:45:54 -070024#include <set>
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070025#include <string>
26
Elliott Hughes0a620672015-12-04 13:53:18 -080027#include <android-base/stringprintf.h>
Christopher Wileye3550c62015-09-29 13:26:10 -070028
Casey Dahlina834dd42015-09-23 11:52:15 -070029#include "aidl_language.h"
Jiyong Parkce50e262018-10-29 09:54:20 +090030#include "aidl_to_cpp.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070031#include "ast_cpp.h"
32#include "code_writer.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070033#include "logging.h"
Christopher Wiley054afbd2015-10-16 17:08:43 -070034#include "os.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070035
Jiyong Park75e1a742018-07-04 12:31:23 +090036using android::base::Join;
Christopher Wileye3550c62015-09-29 13:26:10 -070037using android::base::StringPrintf;
Jiyong Park75e1a742018-07-04 12:31:23 +090038using std::set;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070039using std::string;
Casey Dahlin082f1d12015-09-21 14:06:25 -070040using std::unique_ptr;
Casey Dahlina834dd42015-09-23 11:52:15 -070041using std::vector;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070042
Christopher Wileyeb1acc12015-09-16 11:25:13 -070043namespace android {
44namespace aidl {
Christopher Wileyf944e792015-09-29 10:00:46 -070045namespace cpp {
Casey Dahlina834dd42015-09-23 11:52:15 -070046namespace internals {
Christopher Wiley0c732db2015-09-29 14:36:44 -070047namespace {
Christopher Wiley36570f42015-10-08 17:20:11 -070048
Casey Dahlinb8d9e882015-11-24 10:57:23 -080049const char kAndroidStatusVarName[] = "_aidl_ret_status";
50const char kCodeVarName[] = "_aidl_code";
51const char kFlagsVarName[] = "_aidl_flags";
52const char kDataVarName[] = "_aidl_data";
53const char kErrorLabel[] = "_aidl_error";
54const char kImplVarName[] = "_aidl_impl";
55const char kReplyVarName[] = "_aidl_reply";
Christopher Wileyad339272015-10-05 19:11:58 -070056const char kReturnVarName[] = "_aidl_return";
Casey Dahlinb8d9e882015-11-24 10:57:23 -080057const char kStatusVarName[] = "_aidl_status";
Martijn Coenenf1b50782018-02-21 21:06:23 +010058const char kTraceVarName[] = "_aidl_trace";
Casey Dahlinb8d9e882015-11-24 10:57:23 -080059const char kAndroidParcelLiteral[] = "::android::Parcel";
60const char kAndroidStatusLiteral[] = "::android::status_t";
61const char kAndroidStatusOk[] = "::android::OK";
62const char kBinderStatusLiteral[] = "::android::binder::Status";
Christopher Wiley0c732db2015-09-29 14:36:44 -070063const char kIBinderHeader[] = "binder/IBinder.h";
64const char kIInterfaceHeader[] = "binder/IInterface.h";
Christopher Wileyad339272015-10-05 19:11:58 -070065const char kParcelHeader[] = "binder/Parcel.h";
Christopher Wiley433c8bb2015-11-12 14:20:46 -080066const char kStatusHeader[] = "binder/Status.h";
Christopher Wiley69b44cf2016-05-03 13:43:33 -070067const char kString16Header[] = "utils/String16.h";
Martijn Coenenf1b50782018-02-21 21:06:23 +010068const char kTraceHeader[] = "utils/Trace.h";
Casey Dahlin389781f2015-10-22 13:13:21 -070069const char kStrongPointerHeader[] = "utils/StrongPointer.h";
Jiyong Park75e1a742018-07-04 12:31:23 +090070const char kAndroidBaseMacrosHeader[] = "android-base/macros.h";
Casey Dahlin082f1d12015-09-21 14:06:25 -070071
Christopher Wiley0eb903e2015-10-20 17:07:08 -070072unique_ptr<AstNode> BreakOnStatusNotOk() {
73 IfStatement* ret = new IfStatement(new Comparison(
Casey Dahlinb8d9e882015-11-24 10:57:23 -080074 new LiteralExpression(kAndroidStatusVarName), "!=",
75 new LiteralExpression(kAndroidStatusOk)));
Christopher Wiley0eb903e2015-10-20 17:07:08 -070076 ret->OnTrue()->AddLiteral("break");
77 return unique_ptr<AstNode>(ret);
78}
79
Christopher Wiley433c8bb2015-11-12 14:20:46 -080080unique_ptr<AstNode> GotoErrorOnBadStatus() {
81 IfStatement* ret = new IfStatement(new Comparison(
Casey Dahlinb8d9e882015-11-24 10:57:23 -080082 new LiteralExpression(kAndroidStatusVarName), "!=",
83 new LiteralExpression(kAndroidStatusOk)));
84 ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
Christopher Wiley433c8bb2015-11-12 14:20:46 -080085 return unique_ptr<AstNode>(ret);
86}
87
Steven Moreland5557f1c2018-07-02 13:50:23 -070088unique_ptr<AstNode> ReturnOnStatusNotOk() {
89 IfStatement* ret = new IfStatement(new Comparison(new LiteralExpression(kAndroidStatusVarName),
90 "!=", new LiteralExpression(kAndroidStatusOk)));
91 ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
92 return unique_ptr<AstNode>(ret);
93}
94
Jiyong Park75e1a742018-07-04 12:31:23 +090095ArgList BuildArgList(const TypeNamespace& types, const AidlMethod& method, bool for_declaration,
96 bool type_name_only = false) {
Christopher Wileyad339272015-10-05 19:11:58 -070097 // Build up the argument list for the server method call.
98 vector<string> method_arguments;
99 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
100 string literal;
101 if (for_declaration) {
102 // Method declarations need types, pointers to out params, and variable
103 // names that match the .aidl specification.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800104 const Type* type = a->GetType().GetLanguageType<Type>();
Casey Dahlince776cf2015-10-15 18:45:54 -0700105
Casey Dahlina2f77c42015-12-01 18:26:02 -0800106 literal = type->CppType();
Casey Dahlinb0966612015-10-19 16:35:26 -0700107
Christopher Wileyb8e49a42015-10-27 12:55:18 -0700108 if (a->IsOut()) {
109 literal = literal + "*";
110 } else {
111 // We pass in parameters that are not primitives by const reference.
112 // Arrays of primitives are not primitives.
113 if (!type->IsCppPrimitive() || a->GetType().IsArray()) {
114 literal = "const " + literal + "&";
115 }
116 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900117 if (!type_name_only) {
118 literal += " " + a->GetName();
119 }
Christopher Wileyad339272015-10-05 19:11:58 -0700120 } else {
121 if (a->IsOut()) { literal = "&"; }
122 literal += BuildVarName(*a);
123 }
124 method_arguments.push_back(literal);
125 }
126
Casey Dahlina2f77c42015-12-01 18:26:02 -0800127 const Type* return_type = method.GetType().GetLanguageType<Type>();
Casey Dahlince776cf2015-10-15 18:45:54 -0700128
Christopher Wileyad339272015-10-05 19:11:58 -0700129 if (return_type != types.VoidType()) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700130 string literal;
Christopher Wileyad339272015-10-05 19:11:58 -0700131 if (for_declaration) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900132 literal = StringPrintf("%s* %s", return_type->CppType().c_str(),
133 type_name_only ? "" : kReturnVarName);
Christopher Wileyad339272015-10-05 19:11:58 -0700134 } else {
Christopher Wileyade4b452015-10-10 11:06:03 -0700135 literal = string{"&"} + kReturnVarName;
Christopher Wileyad339272015-10-05 19:11:58 -0700136 }
Christopher Wileyade4b452015-10-10 11:06:03 -0700137 method_arguments.push_back(literal);
Christopher Wileyad339272015-10-05 19:11:58 -0700138 }
139
Christopher Wileyade4b452015-10-10 11:06:03 -0700140 return ArgList(method_arguments);
Casey Dahlina834dd42015-09-23 11:52:15 -0700141}
142
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700143unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
Christopher Wiley0c732db2015-09-29 14:36:44 -0700144 const TypeNamespace& types,
145 bool for_interface) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700146 uint32_t modifiers = 0;
147 if (for_interface) {
148 modifiers |= MethodDecl::IS_VIRTUAL;
149 modifiers |= MethodDecl::IS_PURE_VIRTUAL;
150 } else {
151 modifiers |= MethodDecl::IS_OVERRIDE;
152 }
153
154 return unique_ptr<Declaration>{
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800155 new MethodDecl{kBinderStatusLiteral,
Casey Dahlinf4a93112015-10-05 16:58:09 -0700156 method.GetName(),
Christopher Wileyad339272015-10-05 19:11:58 -0700157 BuildArgList(types, method, true /* for method decl */),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700158 modifiers}};
159}
160
Jiyong Park309668e2018-07-28 16:55:44 +0900161unique_ptr<Declaration> BuildMetaMethodDecl(const AidlMethod& method, const TypeNamespace&,
162 const Options& options, bool for_interface) {
163 CHECK(!method.IsUserDefined());
164 if (method.GetName() == kGetInterfaceVersion && options.Version()) {
165 std::ostringstream code;
166 if (for_interface) {
167 code << "virtual ";
168 }
169 code << "int32_t " << kGetInterfaceVersion << "()";
170 if (for_interface) {
171 code << " = 0;\n";
172 } else {
173 code << " override;\n";
174 }
175 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
176 }
177 return nullptr;
178}
179
Steven Morelandf3da0892018-10-05 14:52:01 -0700180std::vector<unique_ptr<Declaration>> NestInNamespaces(vector<unique_ptr<Declaration>> decls,
181 const vector<string>& package) {
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700182 auto it = package.crbegin(); // Iterate over the namespaces inner to outer
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700183 for (; it != package.crend(); ++it) {
Steven Morelandf3da0892018-10-05 14:52:01 -0700184 vector<unique_ptr<Declaration>> inner;
185 inner.emplace_back(unique_ptr<Declaration>{new CppNamespace{*it, std::move(decls)}});
186
187 decls = std::move(inner);
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700188 }
Steven Morelandf3da0892018-10-05 14:52:01 -0700189 return decls;
Christopher Wiley0c732db2015-09-29 14:36:44 -0700190}
191
Steven Morelandf3da0892018-10-05 14:52:01 -0700192std::vector<unique_ptr<Declaration>> NestInNamespaces(unique_ptr<Declaration> decl,
193 const vector<string>& package) {
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700194 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 BuildHeaderGuard(const AidlDefinedType& defined_type, ClassNames header_type) {
210 string class_name = ClassName(defined_type, header_type);
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700211 for (size_t i = 1; i < class_name.size(); ++i) {
212 if (isupper(class_name[i])) {
213 class_name.insert(i, "_");
214 ++i;
215 }
216 }
Steven Moreland5557f1c2018-07-02 13:50:23 -0700217 string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_", defined_type.GetPackage().c_str(),
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700218 class_name.c_str());
219 for (char& c : ret) {
220 if (c == '.') {
221 c = '_';
222 }
223 c = toupper(c);
224 }
225 return ret;
226}
Christopher Wiley36570f42015-10-08 17:20:11 -0700227
228unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
229 const AidlInterface& interface,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900230 const AidlMethod& method, const Options& options) {
Christopher Wiley36570f42015-10-08 17:20:11 -0700231 const string i_name = ClassName(interface, ClassNames::INTERFACE);
232 const string bp_name = ClassName(interface, ClassNames::CLIENT);
233 unique_ptr<MethodImpl> ret{new MethodImpl{
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800234 kBinderStatusLiteral, bp_name, method.GetName(),
Christopher Wiley36570f42015-10-08 17:20:11 -0700235 ArgList{BuildArgList(types, method, true /* for method decl */)}}};
236 StatementBlock* b = ret->GetStatementBlock();
237
238 // Declare parcels to hold our query and the response.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800239 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
Christopher Wiley1227d612015-10-26 16:59:20 -0700240 // Even if we're oneway, the transact method still takes a parcel.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800241 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
Casey Dahlin0dd08af2015-10-20 18:45:50 -0700242
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800243 // Declare the status_t variable we need for error handling.
Christopher Wiley10957122015-12-04 14:35:38 -0800244 b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
245 kAndroidStatusVarName,
246 kAndroidStatusOk));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800247 // We unconditionally return a Status object.
248 b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
Christopher Wiley36570f42015-10-08 17:20:11 -0700249
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900250 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100251 b->AddLiteral(
252 StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
253 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
254 }
255
Jiyong Parkce50e262018-10-29 09:54:20 +0900256 if (options.GenLog()) {
257 string code;
258 CodeWriterPtr writer = CodeWriter::ForString(&code);
259 (*writer) << "Json::Value _log_input_args(Json::objectValue);\n";
260
261 (*writer) << "if (" << bp_name << "::logFunc != nullptr) {\n";
262 (*writer).Indent();
263
264 for (const auto& a : method.GetArguments()) {
265 if (a->IsIn()) {
266 WriteLogFor({*(writer.get()), types.typenames_, a->GetType(), a->GetName(), a->IsOut(),
267 "_log_input_args"});
268 }
269 }
270
271 (*writer).Dedent();
272 (*writer) << "}\n";
273
274 (*writer) << "auto _log_start = std::chrono::steady_clock::now();\n";
275 writer->Close();
276 b->AddLiteral(code, false /* no semicolon */);
277 }
278
Christopher Wiley8993cb52015-10-21 09:53:24 -0700279 // Add the name of the interface we're hoping to call.
280 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800281 kAndroidStatusVarName,
282 new MethodCall(StringPrintf("%s.writeInterfaceToken",
283 kDataVarName),
284 "getInterfaceDescriptor()")));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800285 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley8993cb52015-10-21 09:53:24 -0700286
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700287 for (const auto& a: method.GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800288 const Type* type = a->GetType().GetLanguageType<Type>();
Christopher Wiley36570f42015-10-08 17:20:11 -0700289 string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
Casey Dahlin389781f2015-10-22 13:13:21 -0700290 var_name = type->WriteCast(var_name);
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700291
292 if (a->IsIn()) {
293 // Serialization looks roughly like:
294 // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
295 // if (_aidl_ret_status != ::android::OK) { goto error; }
296 const string& method = type->WriteToParcelMethod();
297 b->AddStatement(new Assignment(
298 kAndroidStatusVarName,
299 new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
300 ArgList(var_name))));
301 b->AddStatement(GotoErrorOnBadStatus());
302 } else if (a->IsOut() && a->GetType().IsArray()) {
303 // Special case, the length of the out array is written into the parcel.
304 // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
305 // if (_aidl_ret_status != ::android::OK) { goto error; }
306 b->AddStatement(new Assignment(
307 kAndroidStatusVarName,
308 new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
309 ArgList(var_name))));
310 b->AddStatement(GotoErrorOnBadStatus());
311 }
Christopher Wiley36570f42015-10-08 17:20:11 -0700312 }
313
314 // Invoke the transaction on the remote binder and confirm status.
Jeongik Chab5d962f2018-11-17 09:12:28 +0900315 string transaction_code = GetTransactionIdFor(method);
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))));
Jiyong Park75e1a742018-07-04 12:31:23 +0900328
329 // If the method is not implemented in the remote side, try to call the
330 // default implementation, if provided.
331 vector<string> arg_names;
332 for (const auto& a : method.GetArguments()) {
333 arg_names.emplace_back(a->GetName());
334 }
335 if (method.GetType().GetLanguageType<Type>() != types.VoidType()) {
336 arg_names.emplace_back(kReturnVarName);
337 }
338 b->AddLiteral(StringPrintf("if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && "
339 "%s::getDefaultImpl())) {\n"
340 " return %s::getDefaultImpl()->%s(%s);\n"
341 "}\n",
342 i_name.c_str(), i_name.c_str(), method.GetName().c_str(),
343 Join(arg_names, ", ").c_str()),
344 false /* no semicolon */);
345
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800346 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700347
Christopher Wiley1227d612015-10-26 16:59:20 -0700348 if (!interface.IsOneway() && !method.IsOneway()) {
349 // Strip off the exception header and fail if we see a remote exception.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800350 // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
351 // if (_aidl_ret_status != ::android::OK) { goto error; }
352 // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800353 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800354 kAndroidStatusVarName,
355 StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800356 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley1227d612015-10-26 16:59:20 -0700357 IfStatement* exception_check = new IfStatement(
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800358 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
Christopher Wiley1227d612015-10-26 16:59:20 -0700359 b->AddStatement(exception_check);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800360 exception_check->OnTrue()->AddLiteral(
361 StringPrintf("return %s", kStatusVarName));
Christopher Wiley1227d612015-10-26 16:59:20 -0700362 }
363
364 // Type checking should guarantee that nothing below emits code until "return
365 // status" if we are a oneway method, so no more fear of accessing reply.
Christopher Wiley2aaeda82015-10-19 15:16:49 -0700366
Christopher Wiley36570f42015-10-08 17:20:11 -0700367 // If the method is expected to return something, read it first by convention.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800368 const Type* return_type = method.GetType().GetLanguageType<Type>();
Christopher Wiley36570f42015-10-08 17:20:11 -0700369 if (return_type != types.VoidType()) {
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700370 const string& method_call = return_type->ReadFromParcelMethod();
Christopher Wiley36570f42015-10-08 17:20:11 -0700371 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800372 kAndroidStatusVarName,
373 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
374 method_call.c_str()),
375 ArgList(kReturnVarName))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800376 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700377 }
378
379 for (const AidlArgument* a : method.GetOutArguments()) {
380 // Deserialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800381 // _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
382 // if (_aidl_status != ::android::OK) { goto _aidl_error; }
Casey Dahlinb0966612015-10-19 16:35:26 -0700383 string method =
Casey Dahlina2f77c42015-12-01 18:26:02 -0800384 a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700385
Christopher Wiley36570f42015-10-08 17:20:11 -0700386 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800387 kAndroidStatusVarName,
388 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
389 method.c_str()),
390 ArgList(a->GetName()))));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800391 b->AddStatement(GotoErrorOnBadStatus());
Christopher Wiley36570f42015-10-08 17:20:11 -0700392 }
393
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800394 // If we've gotten to here, one of two things is true:
395 // 1) We've read some bad status_t
396 // 2) We've only read status_t == OK and there was no exception in the
397 // response.
398 // In both cases, we're free to set Status from the status_t and return.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800399 b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800400 b->AddLiteral(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800401 StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
402 kAndroidStatusVarName));
Martijn Coenenf1b50782018-02-21 21:06:23 +0100403
Jiyong Parkce50e262018-10-29 09:54:20 +0900404 if (options.GenLog()) {
405 string code;
406 CodeWriterPtr writer = CodeWriter::ForString(&code);
407
408 (*writer) << "if (" << bp_name << "::logFunc != nullptr) {\n";
409 (*writer).Indent();
410
411 // Write the log as a Json object. For example,
412 //
413 // Json log object for following interface description
414 //
415 // package foo.bar;
416 // interface IFoo {
417 // String TestMethod(int arg1, inout String[] arg2, out double arg3);
418 // }
419 //
420 // would be:
421 //
422 // {
423 // duration_ms: 100,
424 // interface_name: "foo.bar.IFoo",
425 // method_name: "TestMethod",
426 // proxy_address: "0x12345678",
427 // input_args: {
428 // arg1: 30,
429 // arg2: ["apple", "grape"],
430 // },
431 // output_args: {
432 // arg2: ["mango", "banana"],
433 // arg3: "10.5",
434 // },
435 // _aidl_return: "ok",
436 // }
437 (*writer) << "auto _log_end = std::chrono::steady_clock::now();\n";
438 (*writer) << "Json::Value _log_transaction(Json::objectValue);\n";
439 (*writer) << "_log_transaction[\"duration_ms\"] = "
440 << "std::chrono::duration_cast<std::chrono::milliseconds>(_log_end - "
441 "_log_start).count();\n";
442 (*writer) << "_log_transaction[\"interface_name\"] = "
443 << "Json::Value(\"" << interface.GetCanonicalName() << "\");\n";
444 (*writer) << "_log_transaction[\"method_name\"] = "
445 << "Json::Value(\"" << method.GetName() << "\");\n";
446 (*writer) << "_log_transaction[\"proxy_address\"] = "
447 << "Json::Value(android::base::StringPrintf(\"0x%%p\", this));\n";
448 (*writer) << "_log_transaction[\"input_args\"] = _log_input_args;\n";
449 (*writer) << "Json::Value _log_output_args(Json::objectValue);\n";
450
451 for (const auto& a : method.GetOutArguments()) {
452 WriteLogFor({*(writer.get()), types.typenames_, a->GetType(), a->GetName(), true,
453 "_log_output_args"});
454 }
455
456 (*writer) << "_log_transaction[\"output_args\"] = _log_output_args;\n";
457
458 if (method.GetType().GetName() != "void") {
459 WriteLogFor({*(writer.get()), types.typenames_, method.GetType(), kReturnVarName, true,
460 "_log_transaction"});
461 }
462
463 // call the user-provided function with the Json object for the entire
464 // transaction
465 (*writer) << bp_name << "::logFunc(_log_transaction);\n";
466
467 (*writer).Dedent();
468 (*writer) << "}\n";
469
470 writer->Close();
471 b->AddLiteral(code, false /* no semicolon */);
472 }
473
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800474 b->AddLiteral(StringPrintf("return %s", kStatusVarName));
Christopher Wiley36570f42015-10-08 17:20:11 -0700475
476 return unique_ptr<Declaration>(ret.release());
477}
478
Jiyong Park309668e2018-07-28 16:55:44 +0900479unique_ptr<Declaration> DefineClientMetaTransaction(const TypeNamespace&,
480 const AidlInterface& interface,
481 const AidlMethod& method,
482 const Options& options) {
483 CHECK(!method.IsUserDefined());
484 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
485 const string iface = ClassName(interface, ClassNames::INTERFACE);
486 const string proxy = ClassName(interface, ClassNames::CLIENT);
487 // Note: race condition can happen here, but no locking is required
488 // because 1) writing an interger is atomic and 2) this transaction
489 // will always return the same value, i.e., competing threads will
490 // give write the same value to cached_version_.
491 std::ostringstream code;
492 code << "int32_t " << proxy << "::" << kGetInterfaceVersion << "() {\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900493 << " if (cached_version_ == -1) {\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900494 << " ::android::Parcel data;\n"
495 << " ::android::Parcel reply;\n"
Jiyong Park965c5b92018-11-21 13:37:15 +0900496 << " data.writeInterfaceToken(getInterfaceDescriptor());\n"
Jeongik Chab5d962f2018-11-17 09:12:28 +0900497 << " ::android::status_t err = remote()->transact(" << GetTransactionIdFor(method)
498 << ", data, &reply);\n"
Jiyong Park309668e2018-07-28 16:55:44 +0900499 << " if (err == ::android::OK) {\n"
500 << " cached_version_ = reply.readInt32();\n"
501 << " }\n"
502 << " }\n"
503 << " return cached_version_;\n"
504 << "}\n";
505 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
506 }
507 return nullptr;
508}
509
Christopher Wiley36570f42015-10-08 17:20:11 -0700510} // namespace
511
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900512unique_ptr<Document> BuildClientSource(const TypeNamespace& types, const AidlInterface& interface,
513 const Options& options) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700514 vector<string> include_list = {
515 HeaderFile(interface, ClassNames::CLIENT, false),
Jiyong Park75e1a742018-07-04 12:31:23 +0900516 kParcelHeader,
517 kAndroidBaseMacrosHeader
Christopher Wiley054afbd2015-10-16 17:08:43 -0700518 };
Jiyong Parkce50e262018-10-29 09:54:20 +0900519 if (options.GenLog()) {
520 include_list.emplace_back("chrono");
521 include_list.emplace_back("functional");
522 include_list.emplace_back("json/value.h");
523 include_list.emplace_back("android-base/stringprintf.h");
524 }
Christopher Wiley36570f42015-10-08 17:20:11 -0700525 vector<unique_ptr<Declaration>> file_decls;
526
527 // The constructor just passes the IBinder instance up to the super
528 // class.
Christopher Wiley1db03482015-10-22 11:42:02 -0700529 const string i_name = ClassName(interface, ClassNames::INTERFACE);
Christopher Wiley36570f42015-10-08 17:20:11 -0700530 file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
Christopher Wiley054afbd2015-10-16 17:08:43 -0700531 ClassName(interface, ClassNames::CLIENT),
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800532 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
533 kImplVarName)},
534 { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
Christopher Wiley36570f42015-10-08 17:20:11 -0700535
Jiyong Parkce50e262018-10-29 09:54:20 +0900536 if (options.GenLog()) {
537 string code;
538 ClassName(interface, ClassNames::CLIENT);
539 CodeWriterPtr writer = CodeWriter::ForString(&code);
540 (*writer) << "std::function<void(const Json::Value&)> "
541 << ClassName(interface, ClassNames::CLIENT) << "::logFunc;\n";
542 writer->Close();
543 file_decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
544 }
545
Christopher Wiley36570f42015-10-08 17:20:11 -0700546 // Clients define a method per transaction.
547 for (const auto& method : interface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900548 unique_ptr<Declaration> m;
549 if (method->IsUserDefined()) {
550 m = DefineClientTransaction(types, interface, *method, options);
551 } else {
552 m = DefineClientMetaTransaction(types, interface, *method, options);
553 }
Christopher Wiley36570f42015-10-08 17:20:11 -0700554 if (!m) { return nullptr; }
555 file_decls.push_back(std::move(m));
556 }
557 return unique_ptr<Document>{new CppSource{
558 include_list,
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700559 NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700560}
561
Christopher Wileyad339272015-10-05 19:11:58 -0700562namespace {
563
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900564bool HandleServerTransaction(const TypeNamespace& types, const AidlInterface& interface,
565 const AidlMethod& method, const Options& options, StatementBlock* b) {
Christopher Wileyad339272015-10-05 19:11:58 -0700566 // Declare all the parameters now. In the common case, we expect no errors
567 // in serialization.
568 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
Steven Moreland1c41e972018-07-09 16:07:00 -0700569 if (!DeclareLocalVariable(*a, b)) {
570 return false;
571 }
Christopher Wileyad339272015-10-05 19:11:58 -0700572 }
573
574 // Declare a variable to hold the return value.
Casey Dahlina2f77c42015-12-01 18:26:02 -0800575 const Type* return_type = method.GetType().GetLanguageType<Type>();
Christopher Wileyad339272015-10-05 19:11:58 -0700576 if (return_type != types.VoidType()) {
577 b->AddLiteral(StringPrintf(
Casey Dahlina2f77c42015-12-01 18:26:02 -0800578 "%s %s", return_type->CppType().c_str(),
Casey Dahlinb0966612015-10-19 16:35:26 -0700579 kReturnVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700580 }
581
Christopher Wiley8993cb52015-10-21 09:53:24 -0700582 // Check that the client is calling the correct interface.
583 IfStatement* interface_check = new IfStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800584 new MethodCall(StringPrintf("%s.checkInterface",
585 kDataVarName), "this"),
Christopher Wiley8993cb52015-10-21 09:53:24 -0700586 true /* invert the check */);
587 b->AddStatement(interface_check);
588 interface_check->OnTrue()->AddStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800589 new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
Christopher Wiley8993cb52015-10-21 09:53:24 -0700590 interface_check->OnTrue()->AddLiteral("break");
591
Christopher Wileyad339272015-10-05 19:11:58 -0700592 // Deserialize each "in" parameter to the transaction.
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700593 for (const auto& a: method.GetArguments()) {
Christopher Wileyad339272015-10-05 19:11:58 -0700594 // Deserialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800595 // _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
596 // if (_aidl_ret_status != ::android::OK) { break; }
Casey Dahlina2f77c42015-12-01 18:26:02 -0800597 const Type* type = a->GetType().GetLanguageType<Type>();
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700598 const string& readMethod = type->ReadFromParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700599
Christopher Wiley74b7bf12016-08-19 11:06:32 -0700600 if (a->IsIn()) {
601 b->AddStatement(new Assignment{
602 kAndroidStatusVarName,
603 new MethodCall{string(kDataVarName) + "." + readMethod,
604 "&" + BuildVarName(*a)}});
605 b->AddStatement(BreakOnStatusNotOk());
606 } else if (a->IsOut() && a->GetType().IsArray()) {
607 // Special case, the length of the out array is written into the parcel.
608 // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
609 // if (_aidl_ret_status != ::android::OK) { break; }
610 b->AddStatement(new Assignment{
611 kAndroidStatusVarName,
612 new MethodCall{string(kDataVarName) + ".resizeOutVector",
613 "&" + BuildVarName(*a)}});
614 b->AddStatement(BreakOnStatusNotOk());
615 }
Christopher Wileyad339272015-10-05 19:11:58 -0700616 }
617
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900618 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100619 b->AddStatement(new Statement(new MethodCall("atrace_begin",
620 ArgList{{"ATRACE_TAG_AIDL",
621 StringPrintf("\"%s::%s::cppServer\"",
622 interface.GetName().c_str(),
623 method.GetName().c_str())}})));
624 }
625
Christopher Wileyad339272015-10-05 19:11:58 -0700626 // Call the actual method. This is implemented by the subclass.
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800627 vector<unique_ptr<AstNode>> status_args;
628 status_args.emplace_back(new MethodCall(
Christopher Wileyad339272015-10-05 19:11:58 -0700629 method.GetName(),
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800630 BuildArgList(types, method, false /* not for method decl */)));
631 b->AddStatement(new Statement(new MethodCall(
632 StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
633 ArgList(std::move(status_args)))));
Christopher Wileyad339272015-10-05 19:11:58 -0700634
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900635 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100636 b->AddStatement(new Statement(new MethodCall("atrace_end",
637 "ATRACE_TAG_AIDL")));
638 }
639
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800640 // Write exceptions during transaction handling to parcel.
641 if (!method.IsOneway()) {
642 b->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800643 kAndroidStatusVarName,
644 StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800645 b->AddStatement(BreakOnStatusNotOk());
646 IfStatement* exception_check = new IfStatement(
647 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
648 b->AddStatement(exception_check);
649 exception_check->OnTrue()->AddLiteral("break");
650 }
Casey Dahlinb0966612015-10-19 16:35:26 -0700651
Christopher Wiley36570f42015-10-08 17:20:11 -0700652 // If we have a return value, write it first.
653 if (return_type != types.VoidType()) {
Christopher Wiley2aaeda82015-10-19 15:16:49 -0700654 string writeMethod =
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800655 string(kReplyVarName) + "->" +
Casey Dahlina2f77c42015-12-01 18:26:02 -0800656 return_type->WriteToParcelMethod();
Christopher Wiley36570f42015-10-08 17:20:11 -0700657 b->AddStatement(new Assignment{
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800658 kAndroidStatusVarName, new MethodCall{writeMethod,
Casey Dahlin389781f2015-10-22 13:13:21 -0700659 ArgList{return_type->WriteCast(kReturnVarName)}}});
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700660 b->AddStatement(BreakOnStatusNotOk());
Christopher Wiley36570f42015-10-08 17:20:11 -0700661 }
662
Christopher Wileyad339272015-10-05 19:11:58 -0700663 // Write each out parameter to the reply parcel.
664 for (const AidlArgument* a : method.GetOutArguments()) {
665 // Serialization looks roughly like:
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800666 // _aidl_ret_status = data.WriteInt32(out_param_name);
667 // if (_aidl_ret_status != ::android::OK) { break; }
Casey Dahlina2f77c42015-12-01 18:26:02 -0800668 const Type* type = a->GetType().GetLanguageType<Type>();
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700669 const string& writeMethod = type->WriteToParcelMethod();
Casey Dahlinb0966612015-10-19 16:35:26 -0700670
Christopher Wileyad339272015-10-05 19:11:58 -0700671 b->AddStatement(new Assignment{
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800672 kAndroidStatusVarName,
673 new MethodCall{string(kReplyVarName) + "->" + writeMethod,
Casey Dahlin389781f2015-10-22 13:13:21 -0700674 type->WriteCast(BuildVarName(*a))}});
Christopher Wiley0eb903e2015-10-20 17:07:08 -0700675 b->AddStatement(BreakOnStatusNotOk());
Christopher Wileyad339272015-10-05 19:11:58 -0700676 }
677
678 return true;
679}
680
Jiyong Park309668e2018-07-28 16:55:44 +0900681bool HandleServerMetaTransaction(const TypeNamespace&, const AidlInterface& interface,
682 const AidlMethod& method, const Options& options,
683 StatementBlock* b) {
684 CHECK(!method.IsUserDefined());
685
686 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
687 std::ostringstream code;
Jiyong Park965c5b92018-11-21 13:37:15 +0900688 code << "_aidl_data.checkInterface(this);\n"
689 << "_aidl_reply->writeInt32(" << ClassName(interface, ClassNames::INTERFACE)
Jiyong Park309668e2018-07-28 16:55:44 +0900690 << "::VERSION)";
691 b->AddLiteral(code.str());
692 return true;
693 }
694 return false;
695}
696
Christopher Wileyad339272015-10-05 19:11:58 -0700697} // namespace
698
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900699unique_ptr<Document> BuildServerSource(const TypeNamespace& types, const AidlInterface& interface,
700 const Options& options) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700701 const string bn_name = ClassName(interface, ClassNames::SERVER);
702 vector<string> include_list{
703 HeaderFile(interface, ClassNames::SERVER, false),
704 kParcelHeader
705 };
Christopher Wileyad339272015-10-05 19:11:58 -0700706 unique_ptr<MethodImpl> on_transact{new MethodImpl{
707 kAndroidStatusLiteral, bn_name, "onTransact",
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800708 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
709 StringPrintf("const %s& %s", kAndroidParcelLiteral,
710 kDataVarName),
711 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
712 StringPrintf("uint32_t %s", kFlagsVarName)}}
Christopher Wiley36570f42015-10-08 17:20:11 -0700713 }};
Christopher Wileyad339272015-10-05 19:11:58 -0700714
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800715 // Declare the status_t variable
Christopher Wiley05f4f892015-10-14 13:30:43 -0700716 on_transact->GetStatementBlock()->AddLiteral(
Christopher Wiley10957122015-12-04 14:35:38 -0800717 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
718 kAndroidStatusOk));
Christopher Wiley05f4f892015-10-14 13:30:43 -0700719
Christopher Wileyad339272015-10-05 19:11:58 -0700720 // Add the all important switch statement, but retain a pointer to it.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800721 SwitchStatement* s = new SwitchStatement{kCodeVarName};
Christopher Wileyf9688b02015-10-08 17:17:50 -0700722 on_transact->GetStatementBlock()->AddStatement(s);
Christopher Wileyad339272015-10-05 19:11:58 -0700723
724 // The switch statement has a case statement for each transaction code.
Christopher Wiley054afbd2015-10-16 17:08:43 -0700725 for (const auto& method : interface.GetMethods()) {
Jeongik Chab5d962f2018-11-17 09:12:28 +0900726 StatementBlock* b = s->AddCase(GetTransactionIdFor(*method));
Christopher Wileyad339272015-10-05 19:11:58 -0700727 if (!b) { return nullptr; }
728
Jiyong Park309668e2018-07-28 16:55:44 +0900729 bool success = false;
730 if (method->IsUserDefined()) {
731 success = HandleServerTransaction(types, interface, *method, options, b);
732 } else {
733 success = HandleServerMetaTransaction(types, interface, *method, options, b);
734 }
735 if (!success) {
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900736 return nullptr;
737 }
Christopher Wileyad339272015-10-05 19:11:58 -0700738 }
739
740 // The switch statement has a default case which defers to the super class.
741 // The superclass handles a few pre-defined transactions.
742 StatementBlock* b = s->AddCase("");
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800743 b->AddLiteral(StringPrintf(
744 "%s = ::android::BBinder::onTransact(%s, %s, "
745 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
746 kDataVarName, kReplyVarName, kFlagsVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700747
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800748 // If we saw a null reference, we can map that to an appropriate exception.
749 IfStatement* null_check = new IfStatement(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800750 new LiteralExpression(string(kAndroidStatusVarName) +
751 " == ::android::UNEXPECTED_NULL"));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800752 on_transact->GetStatementBlock()->AddStatement(null_check);
753 null_check->OnTrue()->AddStatement(new Assignment(
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800754 kAndroidStatusVarName,
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800755 StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800756 ".writeToParcel(%s)",
757 kBinderStatusLiteral, kBinderStatusLiteral,
758 kReplyVarName)));
Christopher Wiley433c8bb2015-11-12 14:20:46 -0800759
Christopher Wileyad339272015-10-05 19:11:58 -0700760 // Finally, the server's onTransact method just returns a status code.
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800761 on_transact->GetStatementBlock()->AddLiteral(
762 StringPrintf("return %s", kAndroidStatusVarName));
Christopher Wileyad339272015-10-05 19:11:58 -0700763
764 return unique_ptr<Document>{new CppSource{
765 include_list,
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700766 NestInNamespaces(std::move(on_transact), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700767}
768
Jiyong Park75e1a742018-07-04 12:31:23 +0900769unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& types,
Jiyong Park309668e2018-07-28 16:55:44 +0900770 const AidlInterface& interface, const Options& options) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700771 vector<string> include_list{
772 HeaderFile(interface, ClassNames::INTERFACE, false),
773 HeaderFile(interface, ClassNames::CLIENT, false),
774 };
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700775
Christopher Wiley054afbd2015-10-16 17:08:43 -0700776 string fq_name = ClassName(interface, ClassNames::INTERFACE);
777 if (!interface.GetPackage().empty()) {
778 fq_name = interface.GetPackage() + "." + fq_name;
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700779 }
780
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700781 vector<unique_ptr<Declaration>> decls;
782
Christopher Wiley11a9d792016-02-24 17:20:33 -0800783 unique_ptr<MacroDecl> meta_if{new MacroDecl{
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700784 "IMPLEMENT_META_INTERFACE",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700785 ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
Christopher Wileyade4b452015-10-10 11:06:03 -0700786 '"' + fq_name + '"'}}}};
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700787 decls.push_back(std::move(meta_if));
788
Steven Moreland693640b2018-07-19 13:46:27 -0700789 for (const auto& constant : interface.GetConstantDeclarations()) {
790 const AidlConstantValue& value = constant->GetValue();
791 if (value.GetType() != AidlConstantValue::Type::STRING) continue;
792
Steven Moreland4d12f9a2018-10-31 14:30:55 -0700793 std::string cppType = constant->GetType().GetLanguageType<Type>()->CppType();
794
795 unique_ptr<MethodImpl> getter(new MethodImpl("const " + cppType + "&",
796 ClassName(interface, ClassNames::INTERFACE),
797 constant->GetName(), {}));
Steven Moreland860b1942018-08-16 14:59:28 -0700798 getter->GetStatementBlock()->AddLiteral(
Steven Moreland4d12f9a2018-10-31 14:30:55 -0700799 StringPrintf("static const %s value(%s)", cppType.c_str(),
Steven Moreland860b1942018-08-16 14:59:28 -0700800 constant->ValueString(ConstantValueDecorator).c_str()));
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700801 getter->GetStatementBlock()->AddLiteral("return value");
802 decls.push_back(std::move(getter));
803 }
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700804
Jiyong Park75e1a742018-07-04 12:31:23 +0900805 // Implement the default impl class.
806 // onAsBinder returns nullptr as this interface is not associated with a
807 // real binder.
808 const string default_impl(ClassName(interface, ClassNames::DEFAULT_IMPL));
809 decls.emplace_back(
810 new LiteralDecl(StringPrintf("::android::IBinder* %s::onAsBinder() {\n"
811 " return nullptr;\n"
812 "}\n",
813 default_impl.c_str())));
814 // Each interface method by default returns UNKNOWN_TRANSACTION with is
815 // the same status that is returned by transact() when the method is
816 // not implemented in the server side. In other words, these default
817 // methods do nothing; they only exist to aid making a real default
818 // impl class without having to override all methods in an interface.
819 for (const auto& method : interface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900820 if (method->IsUserDefined()) {
821 std::ostringstream code;
822 code << "::android::binder::Status " << default_impl << "::" << method->GetName()
823 << BuildArgList(types, *method, true, true).ToString() << " {\n"
824 << " return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
825 << "}\n";
826 decls.emplace_back(new LiteralDecl(code.str()));
827 } else {
828 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
829 std::ostringstream code;
830 code << "int32_t " << default_impl << "::" << kGetInterfaceVersion << "() {\n"
831 << " return 0;\n"
832 << "}\n";
833 decls.emplace_back(new LiteralDecl(code.str()));
834 }
835 }
Jiyong Park75e1a742018-07-04 12:31:23 +0900836 }
837
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700838 return unique_ptr<Document>{new CppSource{
839 include_list,
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700840 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700841}
842
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900843unique_ptr<Document> BuildClientHeader(const TypeNamespace& types, const AidlInterface& interface,
Jiyong Park309668e2018-07-28 16:55:44 +0900844 const Options& options) {
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700845 const string i_name = ClassName(interface, ClassNames::INTERFACE);
846 const string bp_name = ClassName(interface, ClassNames::CLIENT);
Casey Dahlina834dd42015-09-23 11:52:15 -0700847
Jiyong Parkb064cbb2018-11-06 02:47:18 +0900848 vector<string> includes = {kIBinderHeader, kIInterfaceHeader, "utils/Errors.h",
Jiyong Parkce50e262018-10-29 09:54:20 +0900849 HeaderFile(interface, ClassNames::INTERFACE, false)};
850
Christopher Wileyb23149d2015-10-14 13:52:21 -0700851 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
852 bp_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800853 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
854 kImplVarName)},
Christopher Wileyb23149d2015-10-14 13:52:21 -0700855 ConstructorDecl::IS_EXPLICIT
856 }};
857 unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
858 "~" + bp_name,
859 ArgList{},
860 ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
Casey Dahlina834dd42015-09-23 11:52:15 -0700861
Christopher Wileyf944e792015-09-29 10:00:46 -0700862 vector<unique_ptr<Declaration>> publics;
Casey Dahlina834dd42015-09-23 11:52:15 -0700863 publics.push_back(std::move(constructor));
864 publics.push_back(std::move(destructor));
865
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700866 for (const auto& method: interface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +0900867 if (method->IsUserDefined()) {
868 publics.push_back(BuildMethodDecl(*method, types, false));
869 } else {
870 publics.push_back(BuildMetaMethodDecl(*method, types, options, false));
871 }
Casey Dahlina834dd42015-09-23 11:52:15 -0700872 }
873
Jiyong Parkce50e262018-10-29 09:54:20 +0900874 if (options.GenLog()) {
Jiyong Parkb064cbb2018-11-06 02:47:18 +0900875 includes.emplace_back("chrono"); // for std::chrono::steady_clock
876 includes.emplace_back("functional"); // for std::function
877 includes.emplace_back("json/value.h");
Jiyong Parkce50e262018-10-29 09:54:20 +0900878 publics.emplace_back(
879 new LiteralDecl{"static std::function<void(const Json::Value&)> logFunc;\n"});
880 }
881
Jiyong Park309668e2018-07-28 16:55:44 +0900882 vector<unique_ptr<Declaration>> privates;
883
884 if (options.Version() > 0) {
885 privates.emplace_back(new LiteralDecl("int32_t cached_version_ = -1;\n"));
886 }
887
888 unique_ptr<ClassDecl> bp_class{new ClassDecl{
889 bp_name,
890 "::android::BpInterface<" + i_name + ">",
891 std::move(publics),
892 std::move(privates),
893 }};
Casey Dahlina834dd42015-09-23 11:52:15 -0700894
Jiyong Parkce50e262018-10-29 09:54:20 +0900895 return unique_ptr<Document>{
Jiyong Parkb064cbb2018-11-06 02:47:18 +0900896 new CppHeader{BuildHeaderGuard(interface, ClassNames::CLIENT), includes,
Jiyong Parkce50e262018-10-29 09:54:20 +0900897 NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700898}
899
Christopher Wileyf59c4992015-10-08 13:12:44 -0700900unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900901 const AidlInterface& interface, const Options&) {
Christopher Wileyfd51d602015-10-14 13:04:48 -0700902 const string i_name = ClassName(interface, ClassNames::INTERFACE);
903 const string bn_name = ClassName(interface, ClassNames::SERVER);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700904
Christopher Wileyfd51d602015-10-14 13:04:48 -0700905 unique_ptr<Declaration> on_transact{new MethodDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700906 kAndroidStatusLiteral, "onTransact",
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800907 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
908 StringPrintf("const %s& %s", kAndroidParcelLiteral,
909 kDataVarName),
910 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
Jiyong Park8533bd02018-10-29 21:31:18 +0900911 StringPrintf("uint32_t %s", kFlagsVarName)}},
Christopher Wileyfd51d602015-10-14 13:04:48 -0700912 MethodDecl::IS_OVERRIDE
913 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700914
Christopher Wileyf944e792015-09-29 10:00:46 -0700915 std::vector<unique_ptr<Declaration>> publics;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700916 publics.push_back(std::move(on_transact));
917
Christopher Wileyf944e792015-09-29 10:00:46 -0700918 unique_ptr<ClassDecl> bn_class{
919 new ClassDecl{bn_name,
Casey Dahlinb8d9e882015-11-24 10:57:23 -0800920 "::android::BnInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700921 std::move(publics),
922 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700923 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700924
Christopher Wiley0c732db2015-09-29 14:36:44 -0700925 return unique_ptr<Document>{new CppHeader{
Christopher Wileyfd51d602015-10-14 13:04:48 -0700926 BuildHeaderGuard(interface, ClassNames::SERVER),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700927 {"binder/IInterface.h",
Christopher Wiley054afbd2015-10-16 17:08:43 -0700928 HeaderFile(interface, ClassNames::INTERFACE, false)},
Christopher Wileyb656a3b2015-10-16 11:11:09 -0700929 NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700930}
931
Christopher Wileye3550c62015-09-29 13:26:10 -0700932unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900933 const AidlInterface& interface, const Options& options) {
Jiyong Park75e1a742018-07-04 12:31:23 +0900934 set<string> includes = {kIBinderHeader, kIInterfaceHeader, kStatusHeader, kStrongPointerHeader};
Casey Dahlince776cf2015-10-15 18:45:54 -0700935
936 for (const auto& method : interface.GetMethods()) {
937 for (const auto& argument : method->GetArguments()) {
Casey Dahlina2f77c42015-12-01 18:26:02 -0800938 const Type* type = argument->GetType().GetLanguageType<Type>();
939 type->GetHeaders(&includes);
Casey Dahlince776cf2015-10-15 18:45:54 -0700940 }
941
Casey Dahlina2f77c42015-12-01 18:26:02 -0800942 const Type* return_type = method->GetType().GetLanguageType<Type>();
Jiyong Parkb034bf02018-07-30 17:44:33 +0900943 if (return_type != nullptr) {
944 return_type->GetHeaders(&includes);
945 }
Casey Dahlince776cf2015-10-15 18:45:54 -0700946 }
947
Jiyong Park75e1a742018-07-04 12:31:23 +0900948 const string i_name = ClassName(interface, ClassNames::INTERFACE);
949 unique_ptr<ClassDecl> if_class{new ClassDecl{i_name, "::android::IInterface"}};
Christopher Wiley11a9d792016-02-24 17:20:33 -0800950 if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700951 "DECLARE_META_INTERFACE",
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700952 ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
Christopher Wiley0c732db2015-09-29 14:36:44 -0700953
Jiyong Park309668e2018-07-28 16:55:44 +0900954 if (options.Version() > 0) {
955 std::ostringstream code;
956 code << "const int32_t VERSION = " << options.Version() << ";\n";
957
958 if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
959 }
960
Steven Moreland693640b2018-07-19 13:46:27 -0700961 std::vector<std::unique_ptr<Declaration>> string_constants;
962 unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t"}};
963 for (const auto& constant : interface.GetConstantDeclarations()) {
964 const AidlConstantValue& value = constant->GetValue();
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800965
Steven Moreland693640b2018-07-19 13:46:27 -0700966 switch (value.GetType()) {
967 case AidlConstantValue::Type::STRING: {
Steven Moreland4d12f9a2018-10-31 14:30:55 -0700968 std::string cppType = constant->GetType().GetLanguageType<Type>()->CppType();
969 unique_ptr<Declaration> getter(new MethodDecl("const " + cppType + "&", constant->GetName(),
970 {}, MethodDecl::IS_STATIC));
Steven Moreland693640b2018-07-19 13:46:27 -0700971 string_constants.push_back(std::move(getter));
972 break;
973 }
Steven Moreland25294322018-08-07 18:13:55 -0700974 case AidlConstantValue::Type::INTEGRAL:
975 case AidlConstantValue::Type::HEXIDECIMAL: {
Steven Moreland860b1942018-08-16 14:59:28 -0700976 int_constant_enum->AddValue(constant->GetName(),
977 constant->ValueString(ConstantValueDecorator));
Steven Moreland693640b2018-07-19 13:46:27 -0700978 break;
979 }
980 default: {
981 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
982 }
983 }
984 }
985 if (int_constant_enum->HasValues()) {
986 if_class->AddPublic(std::move(int_constant_enum));
987 }
988 if (!string_constants.empty()) {
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700989 includes.insert(kString16Header);
Steven Moreland693640b2018-07-19 13:46:27 -0700990
991 for (auto& string_constant : string_constants) {
992 if_class->AddPublic(std::move(string_constant));
993 }
Christopher Wiley69b44cf2016-05-03 13:43:33 -0700994 }
Martijn Coenenf1b50782018-02-21 21:06:23 +0100995
Jiyong Parkfbbfa932018-07-30 21:44:10 +0900996 if (options.GenTraces()) {
Martijn Coenenf1b50782018-02-21 21:06:23 +0100997 includes.insert(kTraceHeader);
998 }
999
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -07001000 if (!interface.GetMethods().empty()) {
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -07001001 for (const auto& method : interface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001002 if (method->IsUserDefined()) {
1003 // Each method gets an enum entry and pure virtual declaration.
1004 if_class->AddPublic(BuildMethodDecl(*method, types, true));
Jiyong Park309668e2018-07-28 16:55:44 +09001005 } else {
1006 if_class->AddPublic(BuildMetaMethodDecl(*method, types, options, true));
Jiyong Park309668e2018-07-28 16:55:44 +09001007 }
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -07001008 }
Christopher Wiley0c732db2015-09-29 14:36:44 -07001009 }
Christopher Wiley0c732db2015-09-29 14:36:44 -07001010
Jiyong Park75e1a742018-07-04 12:31:23 +09001011 vector<unique_ptr<Declaration>> decls;
1012 decls.emplace_back(std::move(if_class));
1013
1014 // Base class for the default implementation.
1015 vector<string> method_decls;
1016 for (const auto& method : interface.GetMethods()) {
Jiyong Park309668e2018-07-28 16:55:44 +09001017 if (method->IsUserDefined()) {
1018 method_decls.emplace_back(BuildMethodDecl(*method, types, false)->ToString());
1019 } else {
1020 method_decls.emplace_back(BuildMetaMethodDecl(*method, types, options, false)->ToString());
1021 }
Jiyong Park75e1a742018-07-04 12:31:23 +09001022 }
Jiyong Park309668e2018-07-28 16:55:44 +09001023
Jiyong Park75e1a742018-07-04 12:31:23 +09001024 decls.emplace_back(new LiteralDecl(
1025 android::base::StringPrintf("class %s : public %s {\n"
1026 "public:\n"
1027 " ::android::IBinder* onAsBinder() override;\n"
1028 " %s\n"
1029 "};\n",
1030 ClassName(interface, ClassNames::DEFAULT_IMPL).c_str(),
1031 i_name.c_str(), Join(method_decls, " ").c_str())));
1032
1033 return unique_ptr<Document>{
1034 new CppHeader{BuildHeaderGuard(interface, ClassNames::INTERFACE),
1035 vector<string>(includes.begin(), includes.end()),
1036 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001037}
1038
Steven Moreland5557f1c2018-07-02 13:50:23 -07001039std::unique_ptr<Document> BuildParcelHeader(const TypeNamespace& /*types*/,
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001040 const AidlStructuredParcelable& parcel,
1041 const Options&) {
Steven Moreland5557f1c2018-07-02 13:50:23 -07001042 unique_ptr<ClassDecl> parcel_class{new ClassDecl{parcel.GetName(), "::android::Parcelable"}};
1043
1044 set<string> includes = {kStatusHeader, kParcelHeader};
1045 for (const auto& variable : parcel.GetFields()) {
1046 const Type* type = variable->GetType().GetLanguageType<Type>();
1047 type->GetHeaders(&includes);
1048 }
1049
1050 for (const auto& variable : parcel.GetFields()) {
1051 const Type* type = variable->GetType().GetLanguageType<Type>();
1052
Steven Moreland9ea10e32018-07-19 15:26:09 -07001053 std::ostringstream out;
1054 out << type->CppType().c_str() << " " << variable->GetName().c_str();
Steven Moreland25294322018-08-07 18:13:55 -07001055 if (variable->GetDefaultValue()) {
Steven Moreland860b1942018-08-16 14:59:28 -07001056 out << " = " << type->CppType().c_str() << "("
1057 << variable->ValueString(ConstantValueDecorator) << ")";
Steven Moreland9ea10e32018-07-19 15:26:09 -07001058 }
1059 out << ";\n";
1060
1061 parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
Steven Moreland5557f1c2018-07-02 13:50:23 -07001062 }
1063
1064 unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
Steven Morelandce39c532018-07-11 16:59:50 -07001065 ArgList("const ::android::Parcel* _aidl_parcel"),
Jeongik Chaa2ada0c2018-11-17 15:11:45 +09001066 MethodDecl::IS_OVERRIDE | MethodDecl::IS_FINAL));
Steven Moreland5557f1c2018-07-02 13:50:23 -07001067 parcel_class->AddPublic(std::move(read));
Jeongik Chaa2ada0c2018-11-17 15:11:45 +09001068 unique_ptr<MethodDecl> write(new MethodDecl(
1069 kAndroidStatusLiteral, "writeToParcel", ArgList("::android::Parcel* _aidl_parcel"),
1070 MethodDecl::IS_OVERRIDE | MethodDecl::IS_CONST | MethodDecl::IS_FINAL));
Steven Moreland5557f1c2018-07-02 13:50:23 -07001071 parcel_class->AddPublic(std::move(write));
1072
1073 return unique_ptr<Document>{new CppHeader{
1074 BuildHeaderGuard(parcel, ClassNames::BASE), vector<string>(includes.begin(), includes.end()),
1075 NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage())}};
1076}
Steven Moreland1c41e972018-07-09 16:07:00 -07001077std::unique_ptr<Document> BuildParcelSource(const TypeNamespace& /*types*/,
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001078 const AidlStructuredParcelable& parcel,
1079 const Options&) {
Steven Moreland5557f1c2018-07-02 13:50:23 -07001080 unique_ptr<MethodImpl> read{new MethodImpl{kAndroidStatusLiteral, parcel.GetName(),
1081 "readFromParcel",
Steven Morelandce39c532018-07-11 16:59:50 -07001082 ArgList("const ::android::Parcel* _aidl_parcel")}};
Steven Moreland5557f1c2018-07-02 13:50:23 -07001083 StatementBlock* read_block = read->GetStatementBlock();
1084 read_block->AddLiteral(
1085 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
Jeongik Cha95eba572018-11-22 09:14:52 +09001086
1087 read_block->AddLiteral(
1088 "size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1089 "int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();\n"
1090 "if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;\n"
1091 "size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);\n");
1092
Steven Moreland5557f1c2018-07-02 13:50:23 -07001093 for (const auto& variable : parcel.GetFields()) {
1094 string method = variable->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
1095
1096 read_block->AddStatement(new Assignment(
1097 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1098 ArgList("&" + variable->GetName()))));
1099 read_block->AddStatement(ReturnOnStatusNotOk());
Jeongik Cha95eba572018-11-22 09:14:52 +09001100 read_block->AddLiteral(StringPrintf(
1101 "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1102 " _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
1103 " return %s;\n"
1104 "}",
1105 kAndroidStatusVarName));
Steven Moreland5557f1c2018-07-02 13:50:23 -07001106 }
1107 read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1108
Steven Morelandce39c532018-07-11 16:59:50 -07001109 unique_ptr<MethodImpl> write{
1110 new MethodImpl{kAndroidStatusLiteral, parcel.GetName(), "writeToParcel",
1111 ArgList("::android::Parcel* _aidl_parcel"), true /*const*/}};
Steven Moreland5557f1c2018-07-02 13:50:23 -07001112 StatementBlock* write_block = write->GetStatementBlock();
1113 write_block->AddLiteral(
1114 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
Jeongik Cha95eba572018-11-22 09:14:52 +09001115
1116 write_block->AddLiteral(
1117 "auto _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1118 "_aidl_parcel->writeInt32(0);");
1119
Steven Moreland5557f1c2018-07-02 13:50:23 -07001120 for (const auto& variable : parcel.GetFields()) {
1121 string method = variable->GetType().GetLanguageType<Type>()->WriteToParcelMethod();
1122
1123 write_block->AddStatement(new Assignment(
1124 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1125 ArgList(variable->GetName()))));
1126 write_block->AddStatement(ReturnOnStatusNotOk());
1127 }
Jeongik Cha95eba572018-11-22 09:14:52 +09001128
1129 write_block->AddLiteral(
1130 "auto _aidl_end_pos = _aidl_parcel->dataPosition();\n"
1131 "_aidl_parcel->setDataPosition(_aidl_start_pos);\n"
1132 "_aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);\n"
1133 "_aidl_parcel->setDataPosition(_aidl_end_pos);");
Steven Moreland5557f1c2018-07-02 13:50:23 -07001134 write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1135
1136 vector<unique_ptr<Declaration>> file_decls;
1137 file_decls.push_back(std::move(read));
1138 file_decls.push_back(std::move(write));
1139
1140 set<string> includes = {};
1141 parcel.GetLanguageType<Type>()->GetHeaders(&includes);
1142
1143 return unique_ptr<Document>{
1144 new CppSource{vector<string>(includes.begin(), includes.end()),
1145 NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
1146}
1147
Jiyong Park74595c12018-07-23 15:22:50 +09001148bool WriteHeader(const Options& options, const TypeNamespace& types, const AidlInterface& interface,
1149 const IoDelegate& io_delegate, ClassNames header_type) {
Christopher Wiley054afbd2015-10-16 17:08:43 -07001150 unique_ptr<Document> header;
1151 switch (header_type) {
1152 case ClassNames::INTERFACE:
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001153 header = BuildInterfaceHeader(types, interface, options);
Christopher Wiley054afbd2015-10-16 17:08:43 -07001154 break;
1155 case ClassNames::CLIENT:
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001156 header = BuildClientHeader(types, interface, options);
Christopher Wiley054afbd2015-10-16 17:08:43 -07001157 break;
1158 case ClassNames::SERVER:
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001159 header = BuildServerHeader(types, interface, options);
Christopher Wiley054afbd2015-10-16 17:08:43 -07001160 break;
1161 default:
1162 LOG(FATAL) << "aidl internal error";
1163 }
1164 if (!header) {
1165 LOG(ERROR) << "aidl internal error: Failed to generate header.";
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001166 return false;
1167 }
Christopher Wiley054afbd2015-10-16 17:08:43 -07001168
Jiyong Park05463732018-08-09 16:03:02 +09001169 const string header_path = options.OutputHeaderDir() + HeaderFile(interface, header_type);
Christopher Wiley9d6e0b22015-11-13 12:18:16 -08001170 unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
1171 header->Write(code_writer.get());
Christopher Wiley054afbd2015-10-16 17:08:43 -07001172
Christopher Wiley9d6e0b22015-11-13 12:18:16 -08001173 const bool success = code_writer->Close();
1174 if (!success) {
1175 io_delegate.RemovePath(header_path);
1176 }
1177
1178 return success;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001179}
1180
Casey Dahlina834dd42015-09-23 11:52:15 -07001181} // namespace internals
1182
1183using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001184
Jiyong Park74595c12018-07-23 15:22:50 +09001185bool GenerateCppInterface(const string& output_file, const Options& options,
1186 const TypeNamespace& types, const AidlInterface& interface,
1187 const IoDelegate& io_delegate) {
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001188 auto interface_src = BuildInterfaceSource(types, interface, options);
1189 auto client_src = BuildClientSource(types, interface, options);
1190 auto server_src = BuildServerSource(types, interface, options);
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001191
Christopher Wiley054afbd2015-10-16 17:08:43 -07001192 if (!interface_src || !client_src || !server_src) {
1193 return false;
1194 }
Christopher Wiley9a8e1d92015-09-19 10:34:33 -07001195
Christopher Wiley054afbd2015-10-16 17:08:43 -07001196 if (!WriteHeader(options, types, interface, io_delegate,
1197 ClassNames::INTERFACE) ||
1198 !WriteHeader(options, types, interface, io_delegate,
1199 ClassNames::CLIENT) ||
1200 !WriteHeader(options, types, interface, io_delegate,
1201 ClassNames::SERVER)) {
1202 return false;
1203 }
1204
Jiyong Park74595c12018-07-23 15:22:50 +09001205 unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(output_file);
Christopher Wiley054afbd2015-10-16 17:08:43 -07001206 interface_src->Write(writer.get());
1207 client_src->Write(writer.get());
1208 server_src->Write(writer.get());
1209
Christopher Wiley9d6e0b22015-11-13 12:18:16 -08001210 const bool success = writer->Close();
1211 if (!success) {
Steven Morelandc209cab2018-08-27 01:25:21 -07001212 io_delegate.RemovePath(output_file);
Christopher Wiley9d6e0b22015-11-13 12:18:16 -08001213 }
1214
1215 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -07001216}
1217
Jiyong Park74595c12018-07-23 15:22:50 +09001218bool GenerateCppParcel(const string& output_file, const Options& options,
1219 const cpp::TypeNamespace& types, const AidlStructuredParcelable& parcelable,
1220 const IoDelegate& io_delegate) {
Jiyong Parkfbbfa932018-07-30 21:44:10 +09001221 auto header = BuildParcelHeader(types, parcelable, options);
1222 auto source = BuildParcelSource(types, parcelable, options);
Steven Moreland5557f1c2018-07-02 13:50:23 -07001223
1224 if (!header || !source) {
1225 return false;
1226 }
1227
Jiyong Park05463732018-08-09 16:03:02 +09001228 const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::BASE);
Steven Moreland5557f1c2018-07-02 13:50:23 -07001229 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1230 header->Write(header_writer.get());
1231 CHECK(header_writer->Close());
1232
Steven Moreland81079f92018-07-06 16:15:53 -07001233 // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
Jiyong Park05463732018-08-09 16:03:02 +09001234 const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
Steven Moreland81079f92018-07-06 16:15:53 -07001235 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1236 bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
1237 CHECK(bp_writer->Close());
Jiyong Park05463732018-08-09 16:03:02 +09001238 const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
Steven Moreland81079f92018-07-06 16:15:53 -07001239 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1240 bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
1241 CHECK(bn_writer->Close());
1242
Jiyong Park74595c12018-07-23 15:22:50 +09001243 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
Steven Moreland5557f1c2018-07-02 13:50:23 -07001244 source->Write(source_writer.get());
1245 CHECK(source_writer->Close());
1246
1247 return true;
1248}
1249
Jiyong Park74595c12018-07-23 15:22:50 +09001250bool GenerateCpp(const string& output_file, const Options& options, const TypeNamespace& types,
Steven Moreland5557f1c2018-07-02 13:50:23 -07001251 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
1252 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
1253 if (parcelable != nullptr) {
Jiyong Park74595c12018-07-23 15:22:50 +09001254 return GenerateCppParcel(output_file, options, types, *parcelable, io_delegate);
Steven Moreland5557f1c2018-07-02 13:50:23 -07001255 }
1256
1257 const AidlInterface* interface = defined_type.AsInterface();
1258 if (interface != nullptr) {
Jiyong Park74595c12018-07-23 15:22:50 +09001259 return GenerateCppInterface(output_file, options, types, *interface, io_delegate);
Steven Moreland5557f1c2018-07-02 13:50:23 -07001260 }
1261
1262 CHECK(false) << "Unrecognized type sent for cpp generation.";
1263 return false;
1264}
1265
Christopher Wileyf944e792015-09-29 10:00:46 -07001266} // namespace cpp
Christopher Wileyeb1acc12015-09-16 11:25:13 -07001267} // namespace aidl
Christopher Wileyf944e792015-09-29 10:00:46 -07001268} // namespace android