blob: d2180dc59625c54a3b442e69bbc21beab9d22b4a [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
Christopher Wileye3550c62015-09-29 13:26:10 -070026#include <base/stringprintf.h>
Christopher Wileyad339272015-10-05 19:11:58 -070027#include <base/strings.h>
Christopher Wileye3550c62015-09-29 13:26:10 -070028
Casey Dahlina834dd42015-09-23 11:52:15 -070029#include "aidl_language.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070030#include "ast_cpp.h"
31#include "code_writer.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070032#include "logging.h"
33
Christopher Wileye3550c62015-09-29 13:26:10 -070034using android::base::StringPrintf;
Christopher Wileyad339272015-10-05 19:11:58 -070035using android::base::Join;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070036using std::string;
Casey Dahlin082f1d12015-09-21 14:06:25 -070037using std::unique_ptr;
Casey Dahlina834dd42015-09-23 11:52:15 -070038using std::vector;
Casey Dahlince776cf2015-10-15 18:45:54 -070039using std::set;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070040
Christopher Wileyeb1acc12015-09-16 11:25:13 -070041namespace android {
42namespace aidl {
Christopher Wileyf944e792015-09-29 10:00:46 -070043namespace cpp {
Casey Dahlina834dd42015-09-23 11:52:15 -070044namespace internals {
Christopher Wiley0c732db2015-09-29 14:36:44 -070045namespace {
Christopher Wiley36570f42015-10-08 17:20:11 -070046
Christopher Wileyad339272015-10-05 19:11:58 -070047const char kStatusOkOrBreakCheck[] = "if (status != android::OK) { break; }";
Christopher Wiley36570f42015-10-08 17:20:11 -070048const char kStatusOkOrReturnLiteral[] =
49 "if (status != android::OK) { return status; }";
Christopher Wileyad339272015-10-05 19:11:58 -070050const char kReturnVarName[] = "_aidl_return";
Christopher Wiley0c732db2015-09-29 14:36:44 -070051const char kAndroidStatusLiteral[] = "android::status_t";
Christopher Wiley36570f42015-10-08 17:20:11 -070052const char kAndroidParcelLiteral[] = "android::Parcel";
Christopher Wiley0c732db2015-09-29 14:36:44 -070053const char kIBinderHeader[] = "binder/IBinder.h";
54const char kIInterfaceHeader[] = "binder/IInterface.h";
Christopher Wileyad339272015-10-05 19:11:58 -070055const char kParcelHeader[] = "binder/Parcel.h";
Casey Dahlin082f1d12015-09-21 14:06:25 -070056
Christopher Wiley0c732db2015-09-29 14:36:44 -070057string UpperCase(const std::string& s) {
58 string result = s;
59 for (char& c : result)
60 c = toupper(c);
61 return result;
Casey Dahlina834dd42015-09-23 11:52:15 -070062}
Casey Dahlin082f1d12015-09-21 14:06:25 -070063
Christopher Wileyad339272015-10-05 19:11:58 -070064string BuildVarName(const AidlArgument& a) {
65 string prefix = "out_";
66 if (a.GetDirection() & AidlArgument::IN_DIR) {
67 prefix = "in_";
Christopher Wileye3550c62015-09-29 13:26:10 -070068 }
Christopher Wileyad339272015-10-05 19:11:58 -070069 return prefix + a.GetName();
70}
71
Christopher Wileyade4b452015-10-10 11:06:03 -070072ArgList BuildArgList(const TypeNamespace& types,
73 const AidlMethod& method,
74 bool for_declaration) {
Christopher Wileyad339272015-10-05 19:11:58 -070075 // Build up the argument list for the server method call.
76 vector<string> method_arguments;
77 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
78 string literal;
79 if (for_declaration) {
80 // Method declarations need types, pointers to out params, and variable
81 // names that match the .aidl specification.
82 const Type* type = types.Find(a->GetType().GetName());
Casey Dahlince776cf2015-10-15 18:45:54 -070083
Christopher Wileyad339272015-10-05 19:11:58 -070084 literal = StringPrintf(
85 "%s%s %s", type->CppType().c_str(),
86 (a->IsOut()) ? "*" : "",
87 a->GetName().c_str());
88 } else {
89 if (a->IsOut()) { literal = "&"; }
90 literal += BuildVarName(*a);
91 }
92 method_arguments.push_back(literal);
93 }
94
95 const Type* return_type = types.Find(method.GetType().GetName());
Casey Dahlince776cf2015-10-15 18:45:54 -070096
Christopher Wileyad339272015-10-05 19:11:58 -070097 if (return_type != types.VoidType()) {
Christopher Wileyade4b452015-10-10 11:06:03 -070098 string literal;
Christopher Wileyad339272015-10-05 19:11:58 -070099 if (for_declaration) {
Christopher Wileyade4b452015-10-10 11:06:03 -0700100 literal = StringPrintf(
101 "%s* %s", return_type->CppType().c_str(), kReturnVarName);
Christopher Wileyad339272015-10-05 19:11:58 -0700102 } else {
Christopher Wileyade4b452015-10-10 11:06:03 -0700103 literal = string{"&"} + kReturnVarName;
Christopher Wileyad339272015-10-05 19:11:58 -0700104 }
Christopher Wileyade4b452015-10-10 11:06:03 -0700105 method_arguments.push_back(literal);
Christopher Wileyad339272015-10-05 19:11:58 -0700106 }
107
Christopher Wileyade4b452015-10-10 11:06:03 -0700108 return ArgList(method_arguments);
Casey Dahlina834dd42015-09-23 11:52:15 -0700109}
110
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700111unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
Christopher Wiley0c732db2015-09-29 14:36:44 -0700112 const TypeNamespace& types,
113 bool for_interface) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700114 uint32_t modifiers = 0;
115 if (for_interface) {
116 modifiers |= MethodDecl::IS_VIRTUAL;
117 modifiers |= MethodDecl::IS_PURE_VIRTUAL;
118 } else {
119 modifiers |= MethodDecl::IS_OVERRIDE;
120 }
121
122 return unique_ptr<Declaration>{
123 new MethodDecl{kAndroidStatusLiteral,
Casey Dahlinf4a93112015-10-05 16:58:09 -0700124 method.GetName(),
Christopher Wileyad339272015-10-05 19:11:58 -0700125 BuildArgList(types, method, true /* for method decl */),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700126 modifiers}};
127}
128
129unique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl) {
130 using N = CppNamespace;
131 using NPtr = unique_ptr<N>;
132 return NPtr{new N{"android", NPtr{new N{"generated", std::move(decl)}}}};
133}
134
Christopher Wiley36570f42015-10-08 17:20:11 -0700135unique_ptr<CppNamespace> NestInNamespaces(
136 vector<unique_ptr<Declaration>> decls) {
137 using N = CppNamespace;
138 using NPtr = unique_ptr<N>;
139 return NPtr{new N{"android", NPtr{new N{"generated", std::move(decls)}}}};
140}
141
Christopher Wileyad339272015-10-05 19:11:58 -0700142bool DeclareLocalVariable(const TypeNamespace& types, const AidlArgument& a,
143 StatementBlock* b) {
144 const Type* cpp_type = types.Find(a.GetType().GetName());
145 if (!cpp_type) { return false; }
146
147 b->AddLiteral(cpp_type->CppType() + " " + BuildVarName(a));
148 return true;
149}
150
Christopher Wiley0c732db2015-09-29 14:36:44 -0700151enum class ClassNames { BASE, CLIENT, SERVER, INTERFACE };
152
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700153string ClassName(const AidlInterface& interface, ClassNames type) {
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700154 string c_name = interface.GetName();
Christopher Wiley0c732db2015-09-29 14:36:44 -0700155
156 if (c_name.length() >= 2 && c_name[0] == 'I' && isupper(c_name[1]))
157 c_name = c_name.substr(1);
158
159 switch (type) {
160 case ClassNames::CLIENT:
161 c_name = "Bp" + c_name;
162 break;
163 case ClassNames::SERVER:
164 c_name = "Bn" + c_name;
165 break;
166 case ClassNames::INTERFACE:
167 c_name = "I" + c_name;
168 break;
169 case ClassNames::BASE:
170 break;
171 }
172 return c_name;
173}
174
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700175string BuildHeaderGuard(const AidlInterface& interface,
176 ClassNames header_type) {
177 string class_name = ClassName(interface, header_type);
178 for (size_t i = 1; i < class_name.size(); ++i) {
179 if (isupper(class_name[i])) {
180 class_name.insert(i, "_");
181 ++i;
182 }
183 }
184 string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_",
185 interface.GetPackage().c_str(),
186 class_name.c_str());
187 for (char& c : ret) {
188 if (c == '.') {
189 c = '_';
190 }
191 c = toupper(c);
192 }
193 return ret;
194}
Christopher Wiley36570f42015-10-08 17:20:11 -0700195
196unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
197 const AidlInterface& interface,
198 const AidlMethod& method) {
199 const string i_name = ClassName(interface, ClassNames::INTERFACE);
200 const string bp_name = ClassName(interface, ClassNames::CLIENT);
201 unique_ptr<MethodImpl> ret{new MethodImpl{
202 kAndroidStatusLiteral, bp_name, method.GetName(),
203 ArgList{BuildArgList(types, method, true /* for method decl */)}}};
204 StatementBlock* b = ret->GetStatementBlock();
205
206 // Declare parcels to hold our query and the response.
207 b->AddLiteral(StringPrintf("%s data", kAndroidParcelLiteral));
208 b->AddLiteral(StringPrintf("%s reply", kAndroidParcelLiteral));
209 // And declare the status variable we need for error handling.
210 b->AddLiteral(StringPrintf("%s status", kAndroidStatusLiteral));
211
212 // Serialization looks roughly like:
213 // status = data.WriteInt32(in_param_name);
214 // if (status != android::OK) { return status; }
215 for (const AidlArgument* a : method.GetInArguments()) {
216 string method = types.Find(a->GetType().GetName())->WriteToParcelMethod();
217 string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
218 b->AddStatement(new Assignment(
219 "status",
220 new MethodCall("data." + method, ArgList(var_name))));
221 b->AddLiteral(kStatusOkOrReturnLiteral, false /* no semicolon */);
222 }
223
224 // Invoke the transaction on the remote binder and confirm status.
225 string transaction_code = StringPrintf(
226 "%s::%s", i_name.c_str(), UpperCase(method.GetName()).c_str());
227 b->AddStatement(new Assignment(
228 "status",
229 new MethodCall("remote()->transact",
230 ArgList({transaction_code, "data", "&reply"}))));
231 b->AddLiteral(kStatusOkOrReturnLiteral, false /* no semicolon */);
232
233 // If the method is expected to return something, read it first by convention.
234 const Type* return_type = types.Find(method.GetType().GetName());
235 if (return_type != types.VoidType()) {
236 string method = return_type->ReadFromParcelMethod();
237 b->AddStatement(new Assignment(
238 "status",
239 new MethodCall("reply." + method, ArgList(kReturnVarName))));
240 b->AddLiteral(kStatusOkOrReturnLiteral, false /* no semicolon */);
241 }
242
243 for (const AidlArgument* a : method.GetOutArguments()) {
244 // Deserialization looks roughly like:
245 // status = reply.ReadInt32(out_param_name);
246 // if (status != android::OK) { return status; }
247 string method = types.Find(a->GetType().GetName())->ReadFromParcelMethod();
248 b->AddStatement(new Assignment(
249 "status",
250 new MethodCall("reply." + method, ArgList(a->GetName()))));
251 b->AddLiteral(kStatusOkOrReturnLiteral, false /* no semicolon */);
252 }
253
254 b->AddLiteral("return status");
255
256 return unique_ptr<Declaration>(ret.release());
257}
258
259} // namespace
260
Christopher Wileye3550c62015-09-29 13:26:10 -0700261unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
Christopher Wiley36570f42015-10-08 17:20:11 -0700262 const AidlInterface& interface) {
263 const string bp_name = ClassName(interface, ClassNames::CLIENT);
264 vector<string> include_list = { bp_name + ".h", kParcelHeader };
265 vector<unique_ptr<Declaration>> file_decls;
266
267 // The constructor just passes the IBinder instance up to the super
268 // class.
269 file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
270 bp_name,
271 ArgList{"const android::sp<android::IBinder>& impl"},
272 { "BpInterface<IPingResponder>(impl)" }}});
273
274 // Clients define a method per transaction.
275 for (const auto& method : interface.GetMethods()) {
276 unique_ptr<Declaration> m = DefineClientTransaction(
277 types, interface, *method);
278 if (!m) { return nullptr; }
279 file_decls.push_back(std::move(m));
280 }
281 return unique_ptr<Document>{new CppSource{
282 include_list,
283 NestInNamespaces(std::move(file_decls))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700284}
285
Christopher Wileyad339272015-10-05 19:11:58 -0700286namespace {
287
288bool HandleServerTransaction(const TypeNamespace& types,
289 const AidlMethod& method,
290 StatementBlock* b) {
291 // Declare all the parameters now. In the common case, we expect no errors
292 // in serialization.
293 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
294 if (!DeclareLocalVariable(types, *a, b)) { return false; }
295 }
296
297 // Declare a variable to hold the return value.
298 const Type* return_type = types.Find(method.GetType().GetName());
299 if (return_type != types.VoidType()) {
300 b->AddLiteral(StringPrintf(
301 "%s %s", return_type->CppType().c_str(), kReturnVarName));
302 }
303
Christopher Wileyad339272015-10-05 19:11:58 -0700304 // Deserialize each "in" parameter to the transaction.
305 for (const AidlArgument* a : method.GetInArguments()) {
306 // Deserialization looks roughly like:
307 // status = data.ReadInt32(&in_param_name);
308 // if (status != android::OK) { break; }
309 const Type* type = types.Find(a->GetType().GetName());
310 b->AddStatement(new Assignment{
311 "status",
312 new MethodCall{"data." + type->ReadFromParcelMethod(),
313 "&" + BuildVarName(*a)}});
314 b->AddLiteral(kStatusOkOrBreakCheck, false /* no semicolon */);
315 }
316
317 // Call the actual method. This is implemented by the subclass.
318 b->AddStatement(new Assignment{
319 "status", new MethodCall{
320 method.GetName(),
Christopher Wileyade4b452015-10-10 11:06:03 -0700321 BuildArgList(types, method, false /* not for method decl */)}});
Christopher Wileyad339272015-10-05 19:11:58 -0700322 b->AddLiteral(kStatusOkOrBreakCheck, false /* no semicolon */);
323
Christopher Wiley36570f42015-10-08 17:20:11 -0700324 // If we have a return value, write it first.
325 if (return_type != types.VoidType()) {
326 string method = "reply->" + return_type->WriteToParcelMethod();
327 b->AddStatement(new Assignment{
328 "status", new MethodCall{method, ArgList{kReturnVarName}}});
329 b->AddLiteral(kStatusOkOrBreakCheck, false /* no semicolon */);
330 }
331
Christopher Wileyad339272015-10-05 19:11:58 -0700332 // Write each out parameter to the reply parcel.
333 for (const AidlArgument* a : method.GetOutArguments()) {
334 // Serialization looks roughly like:
335 // status = data.WriteInt32(out_param_name);
336 // if (status != android::OK) { break; }
337 const Type* type = types.Find(a->GetType().GetName());
338 b->AddStatement(new Assignment{
339 "status",
340 new MethodCall{"reply->" + type->WriteToParcelMethod(),
341 BuildVarName(*a)}});
342 b->AddLiteral(kStatusOkOrBreakCheck, false /* no semicolon */);
343 }
344
345 return true;
346}
347
348} // namespace
349
Christopher Wileye3550c62015-09-29 13:26:10 -0700350unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700351 const AidlInterface& parsed_doc) {
Christopher Wileyad339272015-10-05 19:11:58 -0700352 const string bn_name = ClassName(parsed_doc, ClassNames::SERVER);
353 vector<string> include_list{bn_name + ".h", kParcelHeader};
354 unique_ptr<MethodImpl> on_transact{new MethodImpl{
355 kAndroidStatusLiteral, bn_name, "onTransact",
Christopher Wileyade4b452015-10-10 11:06:03 -0700356 ArgList{{"uint32_t code",
Christopher Wiley36570f42015-10-08 17:20:11 -0700357 StringPrintf("const %s& data", kAndroidParcelLiteral),
358 StringPrintf("%s* reply", kAndroidParcelLiteral),
359 "uint32_t flags"}}
360 }};
Christopher Wileyad339272015-10-05 19:11:58 -0700361
Christopher Wiley05f4f892015-10-14 13:30:43 -0700362 // Declare the status variable
363 on_transact->GetStatementBlock()->AddLiteral(
364 StringPrintf("%s status", kAndroidStatusLiteral));
365
Christopher Wileyad339272015-10-05 19:11:58 -0700366 // Add the all important switch statement, but retain a pointer to it.
367 SwitchStatement* s = new SwitchStatement{"code"};
Christopher Wileyf9688b02015-10-08 17:17:50 -0700368 on_transact->GetStatementBlock()->AddStatement(s);
Christopher Wileyad339272015-10-05 19:11:58 -0700369
370 // The switch statement has a case statement for each transaction code.
371 for (const auto& method : parsed_doc.GetMethods()) {
372 StatementBlock* b = s->AddCase("Call::" + UpperCase(method->GetName()));
373 if (!b) { return nullptr; }
374
375 if (!HandleServerTransaction(types, *method, b)) { return nullptr; }
376 }
377
378 // The switch statement has a default case which defers to the super class.
379 // The superclass handles a few pre-defined transactions.
380 StatementBlock* b = s->AddCase("");
381 b->AddLiteral(
382 "status = android::BBinder::onTransact(code, data, reply, flags)");
383
384 // Finally, the server's onTransact method just returns a status code.
Christopher Wileyf9688b02015-10-08 17:17:50 -0700385 on_transact->GetStatementBlock()->AddLiteral("return status");
Christopher Wileyad339272015-10-05 19:11:58 -0700386
387 return unique_ptr<Document>{new CppSource{
388 include_list,
389 NestInNamespaces(std::move(on_transact))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700390}
391
Christopher Wileyf59c4992015-10-08 13:12:44 -0700392unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& /* types */,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700393 const AidlInterface& parsed_doc) {
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700394 const string i_name = ClassName(parsed_doc, ClassNames::INTERFACE);
395 const string bp_name = ClassName(parsed_doc, ClassNames::CLIENT);
396 vector<string> include_list{i_name + ".h", bp_name + ".h"};
397
398 string fq_name = i_name;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700399 if (!parsed_doc.GetPackage().empty()) {
400 fq_name = StringPrintf("%s.%s", parsed_doc.GetPackage().c_str(), i_name.c_str());
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700401 }
402
403 unique_ptr<ConstructorDecl> meta_if{new ConstructorDecl{
404 "IMPLEMENT_META_INTERFACE",
Christopher Wileyade4b452015-10-10 11:06:03 -0700405 ArgList{vector<string>{ClassName(parsed_doc, ClassNames::BASE),
406 '"' + fq_name + '"'}}}};
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700407
408 return unique_ptr<Document>{new CppSource{
409 include_list,
410 NestInNamespaces(std::move(meta_if))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700411}
412
Christopher Wileye3550c62015-09-29 13:26:10 -0700413unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700414 const AidlInterface& interface) {
415 const string i_name = ClassName(interface, ClassNames::INTERFACE);
416 const string bp_name = ClassName(interface, ClassNames::CLIENT);
Casey Dahlina834dd42015-09-23 11:52:15 -0700417
Christopher Wileyb23149d2015-10-14 13:52:21 -0700418 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
419 bp_name,
420 ArgList{"const android::sp<android::IBinder>& impl"},
421 ConstructorDecl::IS_EXPLICIT
422 }};
423 unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
424 "~" + bp_name,
425 ArgList{},
426 ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
Casey Dahlina834dd42015-09-23 11:52:15 -0700427
Christopher Wileyf944e792015-09-29 10:00:46 -0700428 vector<unique_ptr<Declaration>> publics;
Casey Dahlina834dd42015-09-23 11:52:15 -0700429 publics.push_back(std::move(constructor));
430 publics.push_back(std::move(destructor));
431
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700432 for (const auto& method: interface.GetMethods()) {
Christopher Wiley36570f42015-10-08 17:20:11 -0700433 publics.push_back(BuildMethodDecl(*method, types, false));
Casey Dahlina834dd42015-09-23 11:52:15 -0700434 }
435
Christopher Wileyf944e792015-09-29 10:00:46 -0700436 unique_ptr<ClassDecl> bp_class{
437 new ClassDecl{bp_name,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700438 "android::BpInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700439 std::move(publics),
440 {}
Casey Dahlina834dd42015-09-23 11:52:15 -0700441 }};
442
Christopher Wiley0c732db2015-09-29 14:36:44 -0700443 return unique_ptr<Document>{new CppHeader{
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700444 BuildHeaderGuard(interface, ClassNames::CLIENT),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700445 {kIBinderHeader,
446 kIInterfaceHeader,
447 "utils/Errors.h",
448 i_name + ".h"},
449 NestInNamespaces(std::move(bp_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700450}
451
Christopher Wileyf59c4992015-10-08 13:12:44 -0700452unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
Christopher Wileyfd51d602015-10-14 13:04:48 -0700453 const AidlInterface& interface) {
454 const string i_name = ClassName(interface, ClassNames::INTERFACE);
455 const string bn_name = ClassName(interface, ClassNames::SERVER);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700456
Christopher Wileyfd51d602015-10-14 13:04:48 -0700457 unique_ptr<Declaration> on_transact{new MethodDecl{
Christopher Wileyade4b452015-10-10 11:06:03 -0700458 kAndroidStatusLiteral, "onTransact",
459 ArgList{{"uint32_t code",
Christopher Wiley36570f42015-10-08 17:20:11 -0700460 StringPrintf("const %s& data", kAndroidParcelLiteral),
461 StringPrintf("%s* reply", kAndroidParcelLiteral),
Christopher Wileyfd51d602015-10-14 13:04:48 -0700462 "uint32_t flags = 0"}},
463 MethodDecl::IS_OVERRIDE
464 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700465
Christopher Wileyf944e792015-09-29 10:00:46 -0700466 std::vector<unique_ptr<Declaration>> publics;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700467 publics.push_back(std::move(on_transact));
468
Christopher Wileyf944e792015-09-29 10:00:46 -0700469 unique_ptr<ClassDecl> bn_class{
470 new ClassDecl{bn_name,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700471 "android::BnInterface<" + i_name + ">",
Christopher Wileyf944e792015-09-29 10:00:46 -0700472 std::move(publics),
473 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700474 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700475
Christopher Wiley0c732db2015-09-29 14:36:44 -0700476 return unique_ptr<Document>{new CppHeader{
Christopher Wileyfd51d602015-10-14 13:04:48 -0700477 BuildHeaderGuard(interface, ClassNames::SERVER),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700478 {"binder/IInterface.h",
479 i_name + ".h"},
480 NestInNamespaces(std::move(bn_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700481}
482
Christopher Wileye3550c62015-09-29 13:26:10 -0700483unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700484 const AidlInterface& interface) {
Casey Dahlince776cf2015-10-15 18:45:54 -0700485 set<string> includes = { kIBinderHeader, kIInterfaceHeader };
486
487 for (const auto& method : interface.GetMethods()) {
488 for (const auto& argument : method->GetArguments()) {
489 const Type* type = types.Find(argument->GetType().GetName());
490 const std::string& header = type->Header();
491 if (! header.empty())
492 includes.insert(header);
493 }
494
495 const Type* type = types.Find(method->GetType().GetName());
496 const std::string& header = type->Header();
497 if (! header.empty())
498 includes.insert(header);
499 }
500
Christopher Wiley0c732db2015-09-29 14:36:44 -0700501 unique_ptr<ClassDecl> if_class{
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700502 new ClassDecl{ClassName(interface, ClassNames::INTERFACE),
503 "android::IInterface"}};
Christopher Wileyade4b452015-10-10 11:06:03 -0700504 if_class->AddPublic(unique_ptr<Declaration>{new ConstructorDecl{
505 "DECLARE_META_INTERFACE",
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700506 ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
Christopher Wiley0c732db2015-09-29 14:36:44 -0700507
508 unique_ptr<Enum> call_enum{new Enum{"Call"}};
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700509 for (const auto& method : interface.GetMethods()) {
510 // Each method gets an enum entry and pure virtual declaration.
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700511 if_class->AddPublic(BuildMethodDecl(*method, types, true));
Christopher Wiley0c732db2015-09-29 14:36:44 -0700512 call_enum->AddValue(
Casey Dahlinf4a93112015-10-05 16:58:09 -0700513 UpperCase(method->GetName()),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700514 StringPrintf("android::IBinder::FIRST_CALL_TRANSACTION + %d",
Casey Dahlinf4a93112015-10-05 16:58:09 -0700515 method->GetId()));
Christopher Wiley0c732db2015-09-29 14:36:44 -0700516 }
517 if_class->AddPublic(std::move(call_enum));
518
Christopher Wiley3bb6bc12015-10-14 10:58:27 -0700519 return unique_ptr<Document>{new CppHeader{
520 BuildHeaderGuard(interface, ClassNames::INTERFACE),
Casey Dahlince776cf2015-10-15 18:45:54 -0700521 vector<string>(includes.begin(), includes.end()),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700522 NestInNamespaces(std::move(if_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700523}
524
Christopher Wileyf944e792015-09-29 10:00:46 -0700525bool GenerateCppForFile(const std::string& name, unique_ptr<Document> doc) {
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700526 if (!doc) {
527 return false;
528 }
529 unique_ptr<CodeWriter> writer = GetFileWriter(name);
530 doc->Write(writer.get());
531 return true;
532}
533
Casey Dahlina834dd42015-09-23 11:52:15 -0700534} // namespace internals
535
536using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700537
Christopher Wileye3550c62015-09-29 13:26:10 -0700538bool GenerateCpp(const CppOptions& options,
539 const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700540 const AidlInterface& parsed_doc) {
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700541 bool success = true;
542
543 success &= GenerateCppForFile(options.ClientCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700544 BuildClientSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700545 success &= GenerateCppForFile(options.ClientHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700546 BuildClientHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700547 success &= GenerateCppForFile(options.ServerCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700548 BuildServerSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700549 success &= GenerateCppForFile(options.ServerHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700550 BuildServerHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700551 success &= GenerateCppForFile(options.InterfaceCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700552 BuildInterfaceSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700553 success &= GenerateCppForFile(options.InterfaceHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700554 BuildInterfaceHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700555
556 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700557}
558
Christopher Wileyf944e792015-09-29 10:00:46 -0700559} // namespace cpp
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700560} // namespace aidl
Christopher Wileyf944e792015-09-29 10:00:46 -0700561} // namespace android