1 /*
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"
18 #include "aidl.h"
19
20 #include <cctype>
21 #include <cstring>
22 #include <memory>
23 #include <random>
24 #include <set>
25 #include <string>
26
27 #include <android-base/stringprintf.h>
28
29 #include "aidl_language.h"
30 #include "aidl_to_cpp.h"
31 #include "ast_cpp.h"
32 #include "code_writer.h"
33 #include "logging.h"
34 #include "os.h"
35
36 using android::base::Join;
37 using android::base::StringPrintf;
38 using std::set;
39 using std::string;
40 using std::unique_ptr;
41 using std::vector;
42
43 namespace android {
44 namespace aidl {
45 namespace cpp {
46 namespace internals {
47 namespace {
48
49 const char kAndroidStatusVarName[] = "_aidl_ret_status";
50 const char kCodeVarName[] = "_aidl_code";
51 const char kFlagsVarName[] = "_aidl_flags";
52 const char kDataVarName[] = "_aidl_data";
53 const char kErrorLabel[] = "_aidl_error";
54 const char kImplVarName[] = "_aidl_impl";
55 const char kReplyVarName[] = "_aidl_reply";
56 const char kReturnVarName[] = "_aidl_return";
57 const char kStatusVarName[] = "_aidl_status";
58 const char kTraceVarName[] = "_aidl_trace";
59 const char kAndroidParcelLiteral[] = "::android::Parcel";
60 const char kAndroidStatusLiteral[] = "::android::status_t";
61 const char kAndroidStatusOk[] = "::android::OK";
62 const char kBinderStatusLiteral[] = "::android::binder::Status";
63 const char kIBinderHeader[] = "binder/IBinder.h";
64 const char kIInterfaceHeader[] = "binder/IInterface.h";
65 const char kParcelHeader[] = "binder/Parcel.h";
66 const char kStatusHeader[] = "binder/Status.h";
67 const char kString16Header[] = "utils/String16.h";
68 const char kTraceHeader[] = "utils/Trace.h";
69 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
70 const char kAndroidBaseMacrosHeader[] = "android-base/macros.h";
71
BreakOnStatusNotOk()72 unique_ptr<AstNode> BreakOnStatusNotOk() {
73 IfStatement* ret = new IfStatement(new Comparison(
74 new LiteralExpression(kAndroidStatusVarName), "!=",
75 new LiteralExpression(kAndroidStatusOk)));
76 ret->OnTrue()->AddLiteral("break");
77 return unique_ptr<AstNode>(ret);
78 }
79
GotoErrorOnBadStatus()80 unique_ptr<AstNode> GotoErrorOnBadStatus() {
81 IfStatement* ret = new IfStatement(new Comparison(
82 new LiteralExpression(kAndroidStatusVarName), "!=",
83 new LiteralExpression(kAndroidStatusOk)));
84 ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
85 return unique_ptr<AstNode>(ret);
86 }
87
ReturnOnStatusNotOk()88 unique_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
BuildArgList(const TypeNamespace & types,const AidlMethod & method,bool for_declaration,bool type_name_only=false)95 ArgList BuildArgList(const TypeNamespace& types, const AidlMethod& method, bool for_declaration,
96 bool type_name_only = false) {
97 // 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.
104 const Type* type = a->GetType().GetLanguageType<Type>();
105
106 literal = type->CppType();
107
108 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 }
117 if (!type_name_only) {
118 literal += " " + a->GetName();
119 }
120 } else {
121 if (a->IsOut()) { literal = "&"; }
122 literal += BuildVarName(*a);
123 }
124 method_arguments.push_back(literal);
125 }
126
127 const Type* return_type = method.GetType().GetLanguageType<Type>();
128
129 if (return_type != types.VoidType()) {
130 string literal;
131 if (for_declaration) {
132 literal = StringPrintf("%s* %s", return_type->CppType().c_str(),
133 type_name_only ? "" : kReturnVarName);
134 } else {
135 literal = string{"&"} + kReturnVarName;
136 }
137 method_arguments.push_back(literal);
138 }
139
140 return ArgList(method_arguments);
141 }
142
BuildMethodDecl(const AidlMethod & method,const TypeNamespace & types,bool for_interface)143 unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
144 const TypeNamespace& types,
145 bool for_interface) {
146 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>{
155 new MethodDecl{kBinderStatusLiteral,
156 method.GetName(),
157 BuildArgList(types, method, true /* for method decl */),
158 modifiers}};
159 }
160
BuildMetaMethodDecl(const AidlMethod & method,const TypeNamespace &,const Options & options,bool for_interface)161 unique_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
NestInNamespaces(vector<unique_ptr<Declaration>> decls,const vector<string> & package)180 std::vector<unique_ptr<Declaration>> NestInNamespaces(vector<unique_ptr<Declaration>> decls,
181 const vector<string>& package) {
182 auto it = package.crbegin(); // Iterate over the namespaces inner to outer
183 for (; it != package.crend(); ++it) {
184 vector<unique_ptr<Declaration>> inner;
185 inner.emplace_back(unique_ptr<Declaration>{new CppNamespace{*it, std::move(decls)}});
186
187 decls = std::move(inner);
188 }
189 return decls;
190 }
191
NestInNamespaces(unique_ptr<Declaration> decl,const vector<string> & package)192 std::vector<unique_ptr<Declaration>> NestInNamespaces(unique_ptr<Declaration> decl,
193 const vector<string>& package) {
194 vector<unique_ptr<Declaration>> decls;
195 decls.push_back(std::move(decl));
196 return NestInNamespaces(std::move(decls), package);
197 }
198
DeclareLocalVariable(const AidlArgument & a,StatementBlock * b)199 bool DeclareLocalVariable(const AidlArgument& a, StatementBlock* b) {
200 const Type* cpp_type = a.GetType().GetLanguageType<Type>();
201 if (!cpp_type) { return false; }
202
203 string type = cpp_type->CppType();
204
205 b->AddLiteral(type + " " + BuildVarName(a));
206 return true;
207 }
208
BuildHeaderGuard(const AidlDefinedType & defined_type,ClassNames header_type)209 string BuildHeaderGuard(const AidlDefinedType& defined_type, ClassNames header_type) {
210 string class_name = ClassName(defined_type, header_type);
211 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 }
217 string ret = StringPrintf("AIDL_GENERATED_%s_%s_H_", defined_type.GetPackage().c_str(),
218 class_name.c_str());
219 for (char& c : ret) {
220 if (c == '.') {
221 c = '_';
222 }
223 c = toupper(c);
224 }
225 return ret;
226 }
227
DefineClientTransaction(const TypeNamespace & types,const AidlInterface & interface,const AidlMethod & method,const Options & options)228 unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
229 const AidlInterface& interface,
230 const AidlMethod& method, const Options& options) {
231 const string i_name = ClassName(interface, ClassNames::INTERFACE);
232 const string bp_name = ClassName(interface, ClassNames::CLIENT);
233 unique_ptr<MethodImpl> ret{new MethodImpl{
234 kBinderStatusLiteral, bp_name, method.GetName(),
235 ArgList{BuildArgList(types, method, true /* for method decl */)}}};
236 StatementBlock* b = ret->GetStatementBlock();
237
238 // Declare parcels to hold our query and the response.
239 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
240 // Even if we're oneway, the transact method still takes a parcel.
241 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
242
243 // Declare the status_t variable we need for error handling.
244 b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
245 kAndroidStatusVarName,
246 kAndroidStatusOk));
247 // We unconditionally return a Status object.
248 b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
249
250 if (options.GenTraces()) {
251 b->AddLiteral(
252 StringPrintf("ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
253 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
254 }
255
256 if (options.GenLog()) {
257 b->AddLiteral(GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */),
258 false /* no semicolon */);
259 }
260
261 // Add the name of the interface we're hoping to call.
262 b->AddStatement(new Assignment(
263 kAndroidStatusVarName,
264 new MethodCall(StringPrintf("%s.writeInterfaceToken",
265 kDataVarName),
266 "getInterfaceDescriptor()")));
267 b->AddStatement(GotoErrorOnBadStatus());
268
269 for (const auto& a: method.GetArguments()) {
270 const Type* type = a->GetType().GetLanguageType<Type>();
271 string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
272 var_name = type->WriteCast(var_name);
273
274 if (a->IsIn()) {
275 // Serialization looks roughly like:
276 // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
277 // if (_aidl_ret_status != ::android::OK) { goto error; }
278 const string& method = type->WriteToParcelMethod();
279 b->AddStatement(new Assignment(
280 kAndroidStatusVarName,
281 new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
282 ArgList(var_name))));
283 b->AddStatement(GotoErrorOnBadStatus());
284 } else if (a->IsOut() && a->GetType().IsArray()) {
285 // Special case, the length of the out array is written into the parcel.
286 // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
287 // if (_aidl_ret_status != ::android::OK) { goto error; }
288 b->AddStatement(new Assignment(
289 kAndroidStatusVarName,
290 new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
291 ArgList(var_name))));
292 b->AddStatement(GotoErrorOnBadStatus());
293 }
294 }
295
296 // Invoke the transaction on the remote binder and confirm status.
297 string transaction_code = GetTransactionIdFor(method);
298
299 vector<string> args = {transaction_code, kDataVarName,
300 StringPrintf("&%s", kReplyVarName)};
301
302 if (method.IsOneway()) {
303 args.push_back("::android::IBinder::FLAG_ONEWAY");
304 }
305
306 b->AddStatement(new Assignment(
307 kAndroidStatusVarName,
308 new MethodCall("remote()->transact",
309 ArgList(args))));
310
311 // If the method is not implemented in the remote side, try to call the
312 // default implementation, if provided.
313 vector<string> arg_names;
314 for (const auto& a : method.GetArguments()) {
315 arg_names.emplace_back(a->GetName());
316 }
317 if (method.GetType().GetLanguageType<Type>() != types.VoidType()) {
318 arg_names.emplace_back(kReturnVarName);
319 }
320 b->AddLiteral(StringPrintf("if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && "
321 "%s::getDefaultImpl())) {\n"
322 " return %s::getDefaultImpl()->%s(%s);\n"
323 "}\n",
324 i_name.c_str(), i_name.c_str(), method.GetName().c_str(),
325 Join(arg_names, ", ").c_str()),
326 false /* no semicolon */);
327
328 b->AddStatement(GotoErrorOnBadStatus());
329
330 if (!method.IsOneway()) {
331 // Strip off the exception header and fail if we see a remote exception.
332 // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
333 // if (_aidl_ret_status != ::android::OK) { goto error; }
334 // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
335 b->AddStatement(new Assignment(
336 kAndroidStatusVarName,
337 StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
338 b->AddStatement(GotoErrorOnBadStatus());
339 IfStatement* exception_check = new IfStatement(
340 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
341 b->AddStatement(exception_check);
342 exception_check->OnTrue()->AddLiteral(
343 StringPrintf("return %s", kStatusVarName));
344 }
345
346 // Type checking should guarantee that nothing below emits code until "return
347 // status" if we are a oneway method, so no more fear of accessing reply.
348
349 // If the method is expected to return something, read it first by convention.
350 const Type* return_type = method.GetType().GetLanguageType<Type>();
351 if (return_type != types.VoidType()) {
352 const string& method_call = return_type->ReadFromParcelMethod();
353 b->AddStatement(new Assignment(
354 kAndroidStatusVarName,
355 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
356 method_call.c_str()),
357 ArgList(kReturnVarName))));
358 b->AddStatement(GotoErrorOnBadStatus());
359 }
360
361 for (const AidlArgument* a : method.GetOutArguments()) {
362 // Deserialization looks roughly like:
363 // _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
364 // if (_aidl_status != ::android::OK) { goto _aidl_error; }
365 string method =
366 a->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
367
368 b->AddStatement(new Assignment(
369 kAndroidStatusVarName,
370 new MethodCall(StringPrintf("%s.%s", kReplyVarName,
371 method.c_str()),
372 ArgList(a->GetName()))));
373 b->AddStatement(GotoErrorOnBadStatus());
374 }
375
376 // If we've gotten to here, one of two things is true:
377 // 1) We've read some bad status_t
378 // 2) We've only read status_t == OK and there was no exception in the
379 // response.
380 // In both cases, we're free to set Status from the status_t and return.
381 b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
382 b->AddLiteral(
383 StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
384 kAndroidStatusVarName));
385
386 if (options.GenLog()) {
387 b->AddLiteral(GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
388 false /* isServer */, false /* isNdk */),
389 false /* no semicolon */);
390 }
391
392 b->AddLiteral(StringPrintf("return %s", kStatusVarName));
393
394 return unique_ptr<Declaration>(ret.release());
395 }
396
DefineClientMetaTransaction(const TypeNamespace &,const AidlInterface & interface,const AidlMethod & method,const Options & options)397 unique_ptr<Declaration> DefineClientMetaTransaction(const TypeNamespace&,
398 const AidlInterface& interface,
399 const AidlMethod& method,
400 const Options& options) {
401 CHECK(!method.IsUserDefined());
402 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
403 const string iface = ClassName(interface, ClassNames::INTERFACE);
404 const string proxy = ClassName(interface, ClassNames::CLIENT);
405 // Note: race condition can happen here, but no locking is required
406 // because 1) writing an interger is atomic and 2) this transaction
407 // will always return the same value, i.e., competing threads will
408 // give write the same value to cached_version_.
409 std::ostringstream code;
410 code << "int32_t " << proxy << "::" << kGetInterfaceVersion << "() {\n"
411 << " if (cached_version_ == -1) {\n"
412 << " ::android::Parcel data;\n"
413 << " ::android::Parcel reply;\n"
414 << " data.writeInterfaceToken(getInterfaceDescriptor());\n"
415 << " ::android::status_t err = remote()->transact(" << GetTransactionIdFor(method)
416 << ", data, &reply);\n"
417 << " if (err == ::android::OK) {\n"
418 << " ::android::binder::Status _aidl_status;\n"
419 << " err = _aidl_status.readFromParcel(reply);\n"
420 << " if (err == ::android::OK && _aidl_status.isOk()) {\n"
421 << " cached_version_ = reply.readInt32();\n"
422 << " }\n"
423 << " }\n"
424 << " }\n"
425 << " return cached_version_;\n"
426 << "}\n";
427 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
428 }
429 return nullptr;
430 }
431
432 } // namespace
433
BuildClientSource(const TypeNamespace & types,const AidlInterface & interface,const Options & options)434 unique_ptr<Document> BuildClientSource(const TypeNamespace& types, const AidlInterface& interface,
435 const Options& options) {
436 vector<string> include_list = {
437 HeaderFile(interface, ClassNames::CLIENT, false),
438 kParcelHeader,
439 kAndroidBaseMacrosHeader
440 };
441 if (options.GenLog()) {
442 include_list.emplace_back("chrono");
443 include_list.emplace_back("functional");
444 include_list.emplace_back("json/value.h");
445 }
446 vector<unique_ptr<Declaration>> file_decls;
447
448 // The constructor just passes the IBinder instance up to the super
449 // class.
450 const string i_name = ClassName(interface, ClassNames::INTERFACE);
451 file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
452 ClassName(interface, ClassNames::CLIENT),
453 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
454 kImplVarName)},
455 { "BpInterface<" + i_name + ">(" + kImplVarName + ")" }}});
456
457 if (options.GenLog()) {
458 string code;
459 ClassName(interface, ClassNames::CLIENT);
460 CodeWriterPtr writer = CodeWriter::ForString(&code);
461 (*writer) << "std::function<void(const Json::Value&)> "
462 << ClassName(interface, ClassNames::CLIENT) << "::logFunc;\n";
463 writer->Close();
464 file_decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
465 }
466
467 // Clients define a method per transaction.
468 for (const auto& method : interface.GetMethods()) {
469 unique_ptr<Declaration> m;
470 if (method->IsUserDefined()) {
471 m = DefineClientTransaction(types, interface, *method, options);
472 } else {
473 m = DefineClientMetaTransaction(types, interface, *method, options);
474 }
475 if (!m) { return nullptr; }
476 file_decls.push_back(std::move(m));
477 }
478 return unique_ptr<Document>{new CppSource{
479 include_list,
480 NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
481 }
482
483 namespace {
484
HandleServerTransaction(const TypeNamespace & types,const AidlInterface & interface,const AidlMethod & method,const Options & options,StatementBlock * b)485 bool HandleServerTransaction(const TypeNamespace& types, const AidlInterface& interface,
486 const AidlMethod& method, const Options& options, StatementBlock* b) {
487 // Declare all the parameters now. In the common case, we expect no errors
488 // in serialization.
489 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
490 if (!DeclareLocalVariable(*a, b)) {
491 return false;
492 }
493 }
494
495 // Declare a variable to hold the return value.
496 const Type* return_type = method.GetType().GetLanguageType<Type>();
497 if (return_type != types.VoidType()) {
498 b->AddLiteral(StringPrintf(
499 "%s %s", return_type->CppType().c_str(),
500 kReturnVarName));
501 }
502
503 // Check that the client is calling the correct interface.
504 IfStatement* interface_check = new IfStatement(
505 new MethodCall(StringPrintf("%s.checkInterface",
506 kDataVarName), "this"),
507 true /* invert the check */);
508 b->AddStatement(interface_check);
509 interface_check->OnTrue()->AddStatement(
510 new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
511 interface_check->OnTrue()->AddLiteral("break");
512
513 // Deserialize each "in" parameter to the transaction.
514 for (const auto& a: method.GetArguments()) {
515 // Deserialization looks roughly like:
516 // _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
517 // if (_aidl_ret_status != ::android::OK) { break; }
518 const Type* type = a->GetType().GetLanguageType<Type>();
519 const string& readMethod = type->ReadFromParcelMethod();
520
521 if (a->IsIn()) {
522 b->AddStatement(new Assignment{
523 kAndroidStatusVarName,
524 new MethodCall{string(kDataVarName) + "." + readMethod,
525 "&" + BuildVarName(*a)}});
526 b->AddStatement(BreakOnStatusNotOk());
527 } else if (a->IsOut() && a->GetType().IsArray()) {
528 // Special case, the length of the out array is written into the parcel.
529 // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
530 // if (_aidl_ret_status != ::android::OK) { break; }
531 b->AddStatement(new Assignment{
532 kAndroidStatusVarName,
533 new MethodCall{string(kDataVarName) + ".resizeOutVector",
534 "&" + BuildVarName(*a)}});
535 b->AddStatement(BreakOnStatusNotOk());
536 }
537 }
538
539 if (options.GenTraces()) {
540 b->AddStatement(new Statement(new MethodCall("atrace_begin",
541 ArgList{{"ATRACE_TAG_AIDL",
542 StringPrintf("\"%s::%s::cppServer\"",
543 interface.GetName().c_str(),
544 method.GetName().c_str())}})));
545 }
546 const string bn_name = ClassName(interface, ClassNames::SERVER);
547 if (options.GenLog()) {
548 b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
549 false);
550 }
551 // Call the actual method. This is implemented by the subclass.
552 vector<unique_ptr<AstNode>> status_args;
553 status_args.emplace_back(new MethodCall(
554 method.GetName(),
555 BuildArgList(types, method, false /* not for method decl */)));
556 b->AddStatement(new Statement(new MethodCall(
557 StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
558 ArgList(std::move(status_args)))));
559
560 if (options.GenTraces()) {
561 b->AddStatement(new Statement(new MethodCall("atrace_end",
562 "ATRACE_TAG_AIDL")));
563 }
564
565 if (options.GenLog()) {
566 b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
567 true /* isServer */, false /* isNdk */),
568 false);
569 }
570
571 // Write exceptions during transaction handling to parcel.
572 if (!method.IsOneway()) {
573 b->AddStatement(new Assignment(
574 kAndroidStatusVarName,
575 StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
576 b->AddStatement(BreakOnStatusNotOk());
577 IfStatement* exception_check = new IfStatement(
578 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
579 b->AddStatement(exception_check);
580 exception_check->OnTrue()->AddLiteral("break");
581 }
582
583 // If we have a return value, write it first.
584 if (return_type != types.VoidType()) {
585 string writeMethod =
586 string(kReplyVarName) + "->" +
587 return_type->WriteToParcelMethod();
588 b->AddStatement(new Assignment{
589 kAndroidStatusVarName, new MethodCall{writeMethod,
590 ArgList{return_type->WriteCast(kReturnVarName)}}});
591 b->AddStatement(BreakOnStatusNotOk());
592 }
593 // Write each out parameter to the reply parcel.
594 for (const AidlArgument* a : method.GetOutArguments()) {
595 // Serialization looks roughly like:
596 // _aidl_ret_status = data.WriteInt32(out_param_name);
597 // if (_aidl_ret_status != ::android::OK) { break; }
598 const Type* type = a->GetType().GetLanguageType<Type>();
599 const string& writeMethod = type->WriteToParcelMethod();
600
601 b->AddStatement(new Assignment{
602 kAndroidStatusVarName,
603 new MethodCall{string(kReplyVarName) + "->" + writeMethod,
604 type->WriteCast(BuildVarName(*a))}});
605 b->AddStatement(BreakOnStatusNotOk());
606 }
607
608 return true;
609 }
610
HandleServerMetaTransaction(const TypeNamespace &,const AidlInterface & interface,const AidlMethod & method,const Options & options,StatementBlock * b)611 bool HandleServerMetaTransaction(const TypeNamespace&, const AidlInterface& interface,
612 const AidlMethod& method, const Options& options,
613 StatementBlock* b) {
614 CHECK(!method.IsUserDefined());
615
616 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
617 std::ostringstream code;
618 code << "_aidl_data.checkInterface(this);\n"
619 << "_aidl_reply->writeNoException();\n"
620 << "_aidl_reply->writeInt32(" << ClassName(interface, ClassNames::INTERFACE)
621 << "::VERSION)";
622 b->AddLiteral(code.str());
623 return true;
624 }
625 return false;
626 }
627
628 } // namespace
629
BuildServerSource(const TypeNamespace & types,const AidlInterface & interface,const Options & options)630 unique_ptr<Document> BuildServerSource(const TypeNamespace& types, const AidlInterface& interface,
631 const Options& options) {
632 const string bn_name = ClassName(interface, ClassNames::SERVER);
633 vector<string> include_list{
634 HeaderFile(interface, ClassNames::SERVER, false),
635 kParcelHeader
636 };
637 if (options.GenLog()) {
638 include_list.emplace_back("chrono");
639 include_list.emplace_back("functional");
640 include_list.emplace_back("json/value.h");
641 }
642 unique_ptr<MethodImpl> on_transact{new MethodImpl{
643 kAndroidStatusLiteral, bn_name, "onTransact",
644 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
645 StringPrintf("const %s& %s", kAndroidParcelLiteral,
646 kDataVarName),
647 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
648 StringPrintf("uint32_t %s", kFlagsVarName)}}
649 }};
650
651 // Declare the status_t variable
652 on_transact->GetStatementBlock()->AddLiteral(
653 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
654 kAndroidStatusOk));
655
656 // Add the all important switch statement, but retain a pointer to it.
657 SwitchStatement* s = new SwitchStatement{kCodeVarName};
658 on_transact->GetStatementBlock()->AddStatement(s);
659
660 // The switch statement has a case statement for each transaction code.
661 for (const auto& method : interface.GetMethods()) {
662 StatementBlock* b = s->AddCase(GetTransactionIdFor(*method));
663 if (!b) { return nullptr; }
664
665 bool success = false;
666 if (method->IsUserDefined()) {
667 success = HandleServerTransaction(types, interface, *method, options, b);
668 } else {
669 success = HandleServerMetaTransaction(types, interface, *method, options, b);
670 }
671 if (!success) {
672 return nullptr;
673 }
674 }
675
676 // The switch statement has a default case which defers to the super class.
677 // The superclass handles a few pre-defined transactions.
678 StatementBlock* b = s->AddCase("");
679 b->AddLiteral(StringPrintf(
680 "%s = ::android::BBinder::onTransact(%s, %s, "
681 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
682 kDataVarName, kReplyVarName, kFlagsVarName));
683
684 // If we saw a null reference, we can map that to an appropriate exception.
685 IfStatement* null_check = new IfStatement(
686 new LiteralExpression(string(kAndroidStatusVarName) +
687 " == ::android::UNEXPECTED_NULL"));
688 on_transact->GetStatementBlock()->AddStatement(null_check);
689 null_check->OnTrue()->AddStatement(new Assignment(
690 kAndroidStatusVarName,
691 StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
692 ".writeToParcel(%s)",
693 kBinderStatusLiteral, kBinderStatusLiteral,
694 kReplyVarName)));
695
696 // Finally, the server's onTransact method just returns a status code.
697 on_transact->GetStatementBlock()->AddLiteral(
698 StringPrintf("return %s", kAndroidStatusVarName));
699 vector<unique_ptr<Declaration>> decls;
700 decls.push_back(std::move(on_transact));
701
702 if (options.Version() > 0) {
703 std::ostringstream code;
704 code << "int32_t " << bn_name << "::" << kGetInterfaceVersion << "() {\n"
705 << " return " << ClassName(interface, ClassNames::INTERFACE) << "::VERSION;\n"
706 << "}\n";
707 decls.emplace_back(new LiteralDecl(code.str()));
708 }
709
710 if (options.GenLog()) {
711 string code;
712 ClassName(interface, ClassNames::SERVER);
713 CodeWriterPtr writer = CodeWriter::ForString(&code);
714 (*writer) << "std::function<void(const Json::Value&)> "
715 << ClassName(interface, ClassNames::SERVER) << "::logFunc;\n";
716 writer->Close();
717 decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
718 }
719 return unique_ptr<Document>{
720 new CppSource{include_list, NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
721 }
722
BuildInterfaceSource(const TypeNamespace & types,const AidlInterface & interface,const Options & options)723 unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& types,
724 const AidlInterface& interface, const Options& options) {
725 vector<string> include_list{
726 HeaderFile(interface, ClassNames::RAW, false),
727 HeaderFile(interface, ClassNames::CLIENT, false),
728 };
729
730 string fq_name = ClassName(interface, ClassNames::INTERFACE);
731 if (!interface.GetPackage().empty()) {
732 fq_name = interface.GetPackage() + "." + fq_name;
733 }
734
735 vector<unique_ptr<Declaration>> decls;
736
737 unique_ptr<MacroDecl> meta_if{new MacroDecl{
738 "IMPLEMENT_META_INTERFACE",
739 ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
740 '"' + fq_name + '"'}}}};
741 decls.push_back(std::move(meta_if));
742
743 for (const auto& constant : interface.GetConstantDeclarations()) {
744 const AidlConstantValue& value = constant->GetValue();
745 if (value.GetType() != AidlConstantValue::Type::STRING) continue;
746
747 std::string cppType = constant->GetType().GetLanguageType<Type>()->CppType();
748
749 unique_ptr<MethodImpl> getter(new MethodImpl("const " + cppType + "&",
750 ClassName(interface, ClassNames::INTERFACE),
751 constant->GetName(), {}));
752 getter->GetStatementBlock()->AddLiteral(
753 StringPrintf("static const %s value(%s)", cppType.c_str(),
754 constant->ValueString(ConstantValueDecorator).c_str()));
755 getter->GetStatementBlock()->AddLiteral("return value");
756 decls.push_back(std::move(getter));
757 }
758
759 // Implement the default impl class.
760 // onAsBinder returns nullptr as this interface is not associated with a
761 // real binder.
762 const string default_impl(ClassName(interface, ClassNames::DEFAULT_IMPL));
763 decls.emplace_back(
764 new LiteralDecl(StringPrintf("::android::IBinder* %s::onAsBinder() {\n"
765 " return nullptr;\n"
766 "}\n",
767 default_impl.c_str())));
768 // Each interface method by default returns UNKNOWN_TRANSACTION with is
769 // the same status that is returned by transact() when the method is
770 // not implemented in the server side. In other words, these default
771 // methods do nothing; they only exist to aid making a real default
772 // impl class without having to override all methods in an interface.
773 for (const auto& method : interface.GetMethods()) {
774 if (method->IsUserDefined()) {
775 std::ostringstream code;
776 code << "::android::binder::Status " << default_impl << "::" << method->GetName()
777 << BuildArgList(types, *method, true, true).ToString() << " {\n"
778 << " return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
779 << "}\n";
780 decls.emplace_back(new LiteralDecl(code.str()));
781 } else {
782 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
783 std::ostringstream code;
784 code << "int32_t " << default_impl << "::" << kGetInterfaceVersion << "() {\n"
785 << " return 0;\n"
786 << "}\n";
787 decls.emplace_back(new LiteralDecl(code.str()));
788 }
789 }
790 }
791
792 return unique_ptr<Document>{new CppSource{
793 include_list,
794 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
795 }
796
BuildClientHeader(const TypeNamespace & types,const AidlInterface & interface,const Options & options)797 unique_ptr<Document> BuildClientHeader(const TypeNamespace& types, const AidlInterface& interface,
798 const Options& options) {
799 const string i_name = ClassName(interface, ClassNames::INTERFACE);
800 const string bp_name = ClassName(interface, ClassNames::CLIENT);
801
802 vector<string> includes = {kIBinderHeader, kIInterfaceHeader, "utils/Errors.h",
803 HeaderFile(interface, ClassNames::RAW, false)};
804
805 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
806 bp_name,
807 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
808 kImplVarName)},
809 ConstructorDecl::IS_EXPLICIT
810 }};
811 unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
812 "~" + bp_name,
813 ArgList{},
814 ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
815
816 vector<unique_ptr<Declaration>> publics;
817 publics.push_back(std::move(constructor));
818 publics.push_back(std::move(destructor));
819
820 for (const auto& method: interface.GetMethods()) {
821 if (method->IsUserDefined()) {
822 publics.push_back(BuildMethodDecl(*method, types, false));
823 } else {
824 publics.push_back(BuildMetaMethodDecl(*method, types, options, false));
825 }
826 }
827
828 if (options.GenLog()) {
829 includes.emplace_back("chrono"); // for std::chrono::steady_clock
830 includes.emplace_back("functional"); // for std::function
831 includes.emplace_back("json/value.h");
832 publics.emplace_back(
833 new LiteralDecl{"static std::function<void(const Json::Value&)> logFunc;\n"});
834 }
835
836 vector<unique_ptr<Declaration>> privates;
837
838 if (options.Version() > 0) {
839 privates.emplace_back(new LiteralDecl("int32_t cached_version_ = -1;\n"));
840 }
841
842 unique_ptr<ClassDecl> bp_class{new ClassDecl{
843 bp_name,
844 "::android::BpInterface<" + i_name + ">",
845 std::move(publics),
846 std::move(privates),
847 }};
848
849 return unique_ptr<Document>{
850 new CppHeader{BuildHeaderGuard(interface, ClassNames::CLIENT), includes,
851 NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
852 }
853
BuildServerHeader(const TypeNamespace &,const AidlInterface & interface,const Options & options)854 unique_ptr<Document> BuildServerHeader(const TypeNamespace& /* types */,
855 const AidlInterface& interface, const Options& options) {
856 const string i_name = ClassName(interface, ClassNames::INTERFACE);
857 const string bn_name = ClassName(interface, ClassNames::SERVER);
858
859 unique_ptr<Declaration> on_transact{new MethodDecl{
860 kAndroidStatusLiteral, "onTransact",
861 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
862 StringPrintf("const %s& %s", kAndroidParcelLiteral,
863 kDataVarName),
864 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
865 StringPrintf("uint32_t %s", kFlagsVarName)}},
866 MethodDecl::IS_OVERRIDE
867 }};
868 vector<string> includes = {"binder/IInterface.h", HeaderFile(interface, ClassNames::RAW, false)};
869
870 vector<unique_ptr<Declaration>> publics;
871 publics.push_back(std::move(on_transact));
872
873 if (options.Version() > 0) {
874 std::ostringstream code;
875 code << "int32_t " << kGetInterfaceVersion << "() final override;\n";
876 publics.emplace_back(new LiteralDecl(code.str()));
877 }
878
879 if (options.GenLog()) {
880 includes.emplace_back("chrono"); // for std::chrono::steady_clock
881 includes.emplace_back("functional"); // for std::function
882 includes.emplace_back("json/value.h");
883 publics.emplace_back(
884 new LiteralDecl{"static std::function<void(const Json::Value&)> logFunc;\n"});
885 }
886 unique_ptr<ClassDecl> bn_class{
887 new ClassDecl{bn_name,
888 "::android::BnInterface<" + i_name + ">",
889 std::move(publics),
890 {}
891 }};
892
893 return unique_ptr<Document>{
894 new CppHeader{BuildHeaderGuard(interface, ClassNames::SERVER), includes,
895 NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
896 }
897
BuildInterfaceHeader(const TypeNamespace & types,const AidlInterface & interface,const Options & options)898 unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
899 const AidlInterface& interface, const Options& options) {
900 set<string> includes = {kIBinderHeader, kIInterfaceHeader, kStatusHeader, kStrongPointerHeader};
901
902 for (const auto& method : interface.GetMethods()) {
903 for (const auto& argument : method->GetArguments()) {
904 const Type* type = argument->GetType().GetLanguageType<Type>();
905 type->GetHeaders(&includes);
906 }
907
908 const Type* return_type = method->GetType().GetLanguageType<Type>();
909 if (return_type != nullptr) {
910 return_type->GetHeaders(&includes);
911 }
912 }
913
914 const string i_name = ClassName(interface, ClassNames::INTERFACE);
915 unique_ptr<ClassDecl> if_class{new ClassDecl{i_name, "::android::IInterface"}};
916 if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
917 "DECLARE_META_INTERFACE",
918 ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
919
920 if (options.Version() > 0) {
921 std::ostringstream code;
922 code << "const int32_t VERSION = " << options.Version() << ";\n";
923
924 if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
925 }
926
927 std::vector<std::unique_ptr<Declaration>> string_constants;
928 unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t"}};
929 for (const auto& constant : interface.GetConstantDeclarations()) {
930 const AidlConstantValue& value = constant->GetValue();
931
932 switch (value.GetType()) {
933 case AidlConstantValue::Type::STRING: {
934 std::string cppType = constant->GetType().GetLanguageType<Type>()->CppType();
935 unique_ptr<Declaration> getter(new MethodDecl("const " + cppType + "&", constant->GetName(),
936 {}, MethodDecl::IS_STATIC));
937 string_constants.push_back(std::move(getter));
938 break;
939 }
940 case AidlConstantValue::Type::INTEGRAL:
941 case AidlConstantValue::Type::HEXIDECIMAL: {
942 int_constant_enum->AddValue(constant->GetName(),
943 constant->ValueString(ConstantValueDecorator));
944 break;
945 }
946 default: {
947 LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
948 }
949 }
950 }
951 if (int_constant_enum->HasValues()) {
952 if_class->AddPublic(std::move(int_constant_enum));
953 }
954 if (!string_constants.empty()) {
955 includes.insert(kString16Header);
956
957 for (auto& string_constant : string_constants) {
958 if_class->AddPublic(std::move(string_constant));
959 }
960 }
961
962 if (options.GenTraces()) {
963 includes.insert(kTraceHeader);
964 }
965
966 if (!interface.GetMethods().empty()) {
967 for (const auto& method : interface.GetMethods()) {
968 if (method->IsUserDefined()) {
969 // Each method gets an enum entry and pure virtual declaration.
970 if_class->AddPublic(BuildMethodDecl(*method, types, true));
971 } else {
972 if_class->AddPublic(BuildMetaMethodDecl(*method, types, options, true));
973 }
974 }
975 }
976
977 vector<unique_ptr<Declaration>> decls;
978 decls.emplace_back(std::move(if_class));
979
980 // Base class for the default implementation.
981 vector<string> method_decls;
982 for (const auto& method : interface.GetMethods()) {
983 if (method->IsUserDefined()) {
984 method_decls.emplace_back(BuildMethodDecl(*method, types, false)->ToString());
985 } else {
986 method_decls.emplace_back(BuildMetaMethodDecl(*method, types, options, false)->ToString());
987 }
988 }
989
990 decls.emplace_back(new LiteralDecl(
991 android::base::StringPrintf("class %s : public %s {\n"
992 "public:\n"
993 " ::android::IBinder* onAsBinder() override;\n"
994 " %s\n"
995 "};\n",
996 ClassName(interface, ClassNames::DEFAULT_IMPL).c_str(),
997 i_name.c_str(), Join(method_decls, " ").c_str())));
998
999 return unique_ptr<Document>{
1000 new CppHeader{BuildHeaderGuard(interface, ClassNames::INTERFACE),
1001 vector<string>(includes.begin(), includes.end()),
1002 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
1003 }
1004
BuildParcelHeader(const TypeNamespace &,const AidlStructuredParcelable & parcel,const Options &)1005 std::unique_ptr<Document> BuildParcelHeader(const TypeNamespace& /*types*/,
1006 const AidlStructuredParcelable& parcel,
1007 const Options&) {
1008 unique_ptr<ClassDecl> parcel_class{new ClassDecl{parcel.GetName(), "::android::Parcelable"}};
1009
1010 set<string> includes = {kStatusHeader, kParcelHeader};
1011 for (const auto& variable : parcel.GetFields()) {
1012 const Type* type = variable->GetType().GetLanguageType<Type>();
1013 type->GetHeaders(&includes);
1014 }
1015
1016 for (const auto& variable : parcel.GetFields()) {
1017 const Type* type = variable->GetType().GetLanguageType<Type>();
1018
1019 std::ostringstream out;
1020 out << type->CppType().c_str() << " " << variable->GetName().c_str();
1021 if (variable->GetDefaultValue()) {
1022 out << " = " << type->CppType().c_str() << "("
1023 << variable->ValueString(ConstantValueDecorator) << ")";
1024 }
1025 out << ";\n";
1026
1027 parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
1028 }
1029
1030 unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
1031 ArgList("const ::android::Parcel* _aidl_parcel"),
1032 MethodDecl::IS_OVERRIDE | MethodDecl::IS_FINAL));
1033 parcel_class->AddPublic(std::move(read));
1034 unique_ptr<MethodDecl> write(new MethodDecl(
1035 kAndroidStatusLiteral, "writeToParcel", ArgList("::android::Parcel* _aidl_parcel"),
1036 MethodDecl::IS_OVERRIDE | MethodDecl::IS_CONST | MethodDecl::IS_FINAL));
1037 parcel_class->AddPublic(std::move(write));
1038
1039 return unique_ptr<Document>{new CppHeader{
1040 BuildHeaderGuard(parcel, ClassNames::BASE), vector<string>(includes.begin(), includes.end()),
1041 NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage())}};
1042 }
BuildParcelSource(const TypeNamespace &,const AidlStructuredParcelable & parcel,const Options &)1043 std::unique_ptr<Document> BuildParcelSource(const TypeNamespace& /*types*/,
1044 const AidlStructuredParcelable& parcel,
1045 const Options&) {
1046 unique_ptr<MethodImpl> read{new MethodImpl{kAndroidStatusLiteral, parcel.GetName(),
1047 "readFromParcel",
1048 ArgList("const ::android::Parcel* _aidl_parcel")}};
1049 StatementBlock* read_block = read->GetStatementBlock();
1050 read_block->AddLiteral(
1051 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
1052
1053 read_block->AddLiteral(
1054 "size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1055 "int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();\n"
1056 "if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;\n"
1057 "size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);\n");
1058
1059 for (const auto& variable : parcel.GetFields()) {
1060 string method = variable->GetType().GetLanguageType<Type>()->ReadFromParcelMethod();
1061
1062 read_block->AddStatement(new Assignment(
1063 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1064 ArgList("&" + variable->GetName()))));
1065 read_block->AddStatement(ReturnOnStatusNotOk());
1066 read_block->AddLiteral(StringPrintf(
1067 "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1068 " _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
1069 " return %s;\n"
1070 "}",
1071 kAndroidStatusVarName));
1072 }
1073 read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1074
1075 unique_ptr<MethodImpl> write{
1076 new MethodImpl{kAndroidStatusLiteral, parcel.GetName(), "writeToParcel",
1077 ArgList("::android::Parcel* _aidl_parcel"), true /*const*/}};
1078 StatementBlock* write_block = write->GetStatementBlock();
1079 write_block->AddLiteral(
1080 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
1081
1082 write_block->AddLiteral(
1083 "auto _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1084 "_aidl_parcel->writeInt32(0);");
1085
1086 for (const auto& variable : parcel.GetFields()) {
1087 string method = variable->GetType().GetLanguageType<Type>()->WriteToParcelMethod();
1088
1089 write_block->AddStatement(new Assignment(
1090 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1091 ArgList(variable->GetName()))));
1092 write_block->AddStatement(ReturnOnStatusNotOk());
1093 }
1094
1095 write_block->AddLiteral(
1096 "auto _aidl_end_pos = _aidl_parcel->dataPosition();\n"
1097 "_aidl_parcel->setDataPosition(_aidl_start_pos);\n"
1098 "_aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);\n"
1099 "_aidl_parcel->setDataPosition(_aidl_end_pos);");
1100 write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1101
1102 vector<unique_ptr<Declaration>> file_decls;
1103 file_decls.push_back(std::move(read));
1104 file_decls.push_back(std::move(write));
1105
1106 set<string> includes = {};
1107 parcel.GetLanguageType<Type>()->GetHeaders(&includes);
1108
1109 return unique_ptr<Document>{
1110 new CppSource{vector<string>(includes.begin(), includes.end()),
1111 NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
1112 }
1113
WriteHeader(const Options & options,const TypeNamespace & types,const AidlInterface & interface,const IoDelegate & io_delegate,ClassNames header_type)1114 bool WriteHeader(const Options& options, const TypeNamespace& types, const AidlInterface& interface,
1115 const IoDelegate& io_delegate, ClassNames header_type) {
1116 unique_ptr<Document> header;
1117 switch (header_type) {
1118 case ClassNames::INTERFACE:
1119 header = BuildInterfaceHeader(types, interface, options);
1120 header_type = ClassNames::RAW;
1121 break;
1122 case ClassNames::CLIENT:
1123 header = BuildClientHeader(types, interface, options);
1124 break;
1125 case ClassNames::SERVER:
1126 header = BuildServerHeader(types, interface, options);
1127 break;
1128 default:
1129 LOG(FATAL) << "aidl internal error";
1130 }
1131 if (!header) {
1132 LOG(ERROR) << "aidl internal error: Failed to generate header.";
1133 return false;
1134 }
1135
1136 const string header_path = options.OutputHeaderDir() + HeaderFile(interface, header_type);
1137 unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
1138 header->Write(code_writer.get());
1139
1140 const bool success = code_writer->Close();
1141 if (!success) {
1142 io_delegate.RemovePath(header_path);
1143 }
1144
1145 return success;
1146 }
1147
1148 } // namespace internals
1149
1150 using namespace internals;
1151
GenerateCppInterface(const string & output_file,const Options & options,const TypeNamespace & types,const AidlInterface & interface,const IoDelegate & io_delegate)1152 bool GenerateCppInterface(const string& output_file, const Options& options,
1153 const TypeNamespace& types, const AidlInterface& interface,
1154 const IoDelegate& io_delegate) {
1155 auto interface_src = BuildInterfaceSource(types, interface, options);
1156 auto client_src = BuildClientSource(types, interface, options);
1157 auto server_src = BuildServerSource(types, interface, options);
1158
1159 if (!interface_src || !client_src || !server_src) {
1160 return false;
1161 }
1162
1163 if (!WriteHeader(options, types, interface, io_delegate,
1164 ClassNames::INTERFACE) ||
1165 !WriteHeader(options, types, interface, io_delegate,
1166 ClassNames::CLIENT) ||
1167 !WriteHeader(options, types, interface, io_delegate,
1168 ClassNames::SERVER)) {
1169 return false;
1170 }
1171
1172 unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(output_file);
1173 interface_src->Write(writer.get());
1174 client_src->Write(writer.get());
1175 server_src->Write(writer.get());
1176
1177 const bool success = writer->Close();
1178 if (!success) {
1179 io_delegate.RemovePath(output_file);
1180 }
1181
1182 return success;
1183 }
1184
GenerateCppParcel(const string & output_file,const Options & options,const cpp::TypeNamespace & types,const AidlStructuredParcelable & parcelable,const IoDelegate & io_delegate)1185 bool GenerateCppParcel(const string& output_file, const Options& options,
1186 const cpp::TypeNamespace& types, const AidlStructuredParcelable& parcelable,
1187 const IoDelegate& io_delegate) {
1188 auto header = BuildParcelHeader(types, parcelable, options);
1189 auto source = BuildParcelSource(types, parcelable, options);
1190
1191 if (!header || !source) {
1192 return false;
1193 }
1194
1195 const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
1196 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1197 header->Write(header_writer.get());
1198 CHECK(header_writer->Close());
1199
1200 // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
1201 const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
1202 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1203 bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
1204 CHECK(bp_writer->Close());
1205 const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
1206 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1207 bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
1208 CHECK(bn_writer->Close());
1209
1210 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
1211 source->Write(source_writer.get());
1212 CHECK(source_writer->Close());
1213
1214 return true;
1215 }
1216
GenerateCppParcelDeclaration(const std::string & filename,const IoDelegate & io_delegate)1217 bool GenerateCppParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
1218 CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
1219 *code_writer
1220 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
1221
1222 return true;
1223 }
1224
GenerateCpp(const string & output_file,const Options & options,const TypeNamespace & types,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)1225 bool GenerateCpp(const string& output_file, const Options& options, const TypeNamespace& types,
1226 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
1227 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
1228 if (parcelable != nullptr) {
1229 return GenerateCppParcel(output_file, options, types, *parcelable, io_delegate);
1230 }
1231
1232 const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
1233 if (parcelable_decl != nullptr) {
1234 return GenerateCppParcelDeclaration(output_file, io_delegate);
1235 }
1236
1237 const AidlInterface* interface = defined_type.AsInterface();
1238 if (interface != nullptr) {
1239 return GenerateCppInterface(output_file, options, types, *interface, io_delegate);
1240 }
1241
1242 CHECK(false) << "Unrecognized type sent for cpp generation.";
1243 return false;
1244 }
1245
1246 } // namespace cpp
1247 } // namespace aidl
1248 } // namespace android
1249