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 <algorithm>
21 #include <cctype>
22 #include <cstring>
23 #include <memory>
24 #include <random>
25 #include <set>
26 #include <string>
27
28 #include <android-base/format.h>
29 #include <android-base/stringprintf.h>
30 #include <android-base/strings.h>
31
32 #include "aidl_language.h"
33 #include "aidl_to_cpp.h"
34 #include "ast_cpp.h"
35 #include "code_writer.h"
36 #include "logging.h"
37 #include "os.h"
38
39 using android::base::Join;
40 using android::base::StringPrintf;
41 using std::set;
42 using std::string;
43 using std::unique_ptr;
44 using std::vector;
45
46 namespace android {
47 namespace aidl {
48 namespace cpp {
49 namespace internals {
50 namespace {
51
52 const char kAndroidStatusVarName[] = "_aidl_ret_status";
53 const char kCodeVarName[] = "_aidl_code";
54 const char kFlagsVarName[] = "_aidl_flags";
55 const char kDataVarName[] = "_aidl_data";
56 const char kErrorLabel[] = "_aidl_error";
57 const char kImplVarName[] = "_aidl_impl";
58 const char kParcelVarName[] = "_aidl_parcel";
59 const char kReplyVarName[] = "_aidl_reply";
60 const char kReturnVarName[] = "_aidl_return";
61 const char kStatusVarName[] = "_aidl_status";
62 const char kTraceVarName[] = "_aidl_trace";
63 const char kAndroidParcelLiteral[] = "::android::Parcel";
64 const char kAndroidStatusLiteral[] = "::android::status_t";
65 const char kAndroidStatusOk[] = "::android::OK";
66 const char kAndroidStatusBadValue[] = "::android::BAD_VALUE";
67 const char kBinderStatusLiteral[] = "::android::binder::Status";
68 const char kIBinderHeader[] = "binder/IBinder.h";
69 const char kIInterfaceHeader[] = "binder/IInterface.h";
70 const char kParcelHeader[] = "binder/Parcel.h";
71 const char kStabilityHeader[] = "binder/Stability.h";
72 const char kStatusHeader[] = "binder/Status.h";
73 const char kString16Header[] = "utils/String16.h";
74 const char kTraceHeader[] = "utils/Trace.h";
75 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
76 const char kAndroidBaseMacrosHeader[] = "android-base/macros.h";
77
BreakOnStatusNotOk()78 unique_ptr<AstNode> BreakOnStatusNotOk() {
79 IfStatement* ret = new IfStatement(new Comparison(
80 new LiteralExpression(kAndroidStatusVarName), "!=",
81 new LiteralExpression(kAndroidStatusOk)));
82 ret->OnTrue()->AddLiteral("break");
83 return unique_ptr<AstNode>(ret);
84 }
85
GotoErrorOnBadStatus()86 unique_ptr<AstNode> GotoErrorOnBadStatus() {
87 IfStatement* ret = new IfStatement(new Comparison(
88 new LiteralExpression(kAndroidStatusVarName), "!=",
89 new LiteralExpression(kAndroidStatusOk)));
90 ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
91 return unique_ptr<AstNode>(ret);
92 }
93
ReturnOnStatusNotOk()94 unique_ptr<AstNode> ReturnOnStatusNotOk() {
95 IfStatement* ret = new IfStatement(new Comparison(new LiteralExpression(kAndroidStatusVarName),
96 "!=", new LiteralExpression(kAndroidStatusOk)));
97 ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
98 return unique_ptr<AstNode>(ret);
99 }
100
BuildArgList(const AidlTypenames & typenames,const AidlMethod & method,bool for_declaration,bool type_name_only=false)101 ArgList BuildArgList(const AidlTypenames& typenames, const AidlMethod& method, bool for_declaration,
102 bool type_name_only = false) {
103 // Build up the argument list for the server method call.
104 vector<string> method_arguments;
105 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
106 string literal;
107 // b/144943748: CppNameOf FileDescriptor is unique_fd. Don't pass it by
108 // const reference but by value to make it easier for the user to keep
109 // it beyond the scope of the call. unique_fd is a thin wrapper for an
110 // int (fd) so passing by value is not expensive.
111 const bool nonCopyable = IsNonCopyableType(a->GetType(), typenames);
112 if (for_declaration) {
113 // Method declarations need typenames, pointers to out params, and variable
114 // names that match the .aidl specification.
115 literal = CppNameOf(a->GetType(), typenames);
116
117 if (a->IsOut()) {
118 literal = literal + "*";
119 } else {
120 const auto definedType = typenames.TryGetDefinedType(a->GetType().GetName());
121
122 const bool isEnum = definedType && definedType->AsEnumDeclaration() != nullptr;
123 const bool isPrimitive = AidlTypenames::IsPrimitiveTypename(a->GetType().GetName());
124
125 // We pass in parameters that are not primitives by const reference.
126 // Arrays of primitives are not primitives.
127 if (!(isPrimitive || isEnum || nonCopyable) || a->GetType().IsArray()) {
128 literal = "const " + literal + "&";
129 }
130 }
131 if (!type_name_only) {
132 literal += " " + a->GetName();
133 }
134 } else {
135 std::string varName = BuildVarName(*a);
136 if (a->IsOut()) {
137 literal = "&" + varName;
138 } else if (nonCopyable) {
139 literal = "std::move(" + varName + ")";
140 } else {
141 literal = varName;
142 }
143 }
144 method_arguments.push_back(literal);
145 }
146
147 if (method.GetType().GetName() != "void") {
148 string literal;
149 if (for_declaration) {
150 literal = CppNameOf(method.GetType(), typenames) + "*";
151 if (!type_name_only) {
152 literal += " " + string(kReturnVarName);
153 }
154 } else {
155 literal = string{"&"} + kReturnVarName;
156 }
157 method_arguments.push_back(literal);
158 }
159
160 return ArgList(method_arguments);
161 }
162
BuildMethodDecl(const AidlMethod & method,const AidlTypenames & typenames,bool for_interface)163 unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method, const AidlTypenames& typenames,
164 bool for_interface) {
165 uint32_t modifiers = 0;
166 if (for_interface) {
167 modifiers |= MethodDecl::IS_VIRTUAL;
168 modifiers |= MethodDecl::IS_PURE_VIRTUAL;
169 } else {
170 modifiers |= MethodDecl::IS_OVERRIDE;
171 }
172
173 const string attribute = GetDeprecatedAttribute(method);
174 return unique_ptr<Declaration>{new MethodDecl{
175 kBinderStatusLiteral, method.GetName(),
176 BuildArgList(typenames, method, true /* for method decl */), modifiers, attribute}};
177 }
178
BuildMetaMethodDecl(const AidlMethod & method,const AidlTypenames &,const Options & options,bool for_interface)179 unique_ptr<Declaration> BuildMetaMethodDecl(const AidlMethod& method, const AidlTypenames&,
180 const Options& options, bool for_interface) {
181 AIDL_FATAL_IF(method.IsUserDefined(), method);
182 if (method.GetName() == kGetInterfaceVersion && options.Version()) {
183 std::ostringstream code;
184 if (for_interface) {
185 code << "virtual ";
186 }
187 code << "int32_t " << kGetInterfaceVersion << "()";
188 if (for_interface) {
189 code << " = 0;\n";
190 } else {
191 code << " override;\n";
192 }
193 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
194 }
195 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
196 std::ostringstream code;
197 if (for_interface) {
198 code << "virtual ";
199 }
200 code << "std::string " << kGetInterfaceHash << "()";
201 if (for_interface) {
202 code << " = 0;\n";
203 } else {
204 code << " override;\n";
205 }
206 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
207 }
208 return nullptr;
209 }
210
NestInNamespaces(vector<unique_ptr<Declaration>> decls,const vector<string> & package)211 std::vector<unique_ptr<Declaration>> NestInNamespaces(vector<unique_ptr<Declaration>> decls,
212 const vector<string>& package) {
213 auto it = package.crbegin(); // Iterate over the namespaces inner to outer
214 for (; it != package.crend(); ++it) {
215 vector<unique_ptr<Declaration>> inner;
216 inner.emplace_back(unique_ptr<Declaration>{new CppNamespace{*it, std::move(decls)}});
217
218 decls = std::move(inner);
219 }
220 return decls;
221 }
222
NestInNamespaces(unique_ptr<Declaration> decl,const vector<string> & package)223 std::vector<unique_ptr<Declaration>> NestInNamespaces(unique_ptr<Declaration> decl,
224 const vector<string>& package) {
225 vector<unique_ptr<Declaration>> decls;
226 decls.push_back(std::move(decl));
227 return NestInNamespaces(std::move(decls), package);
228 }
229
DefineClientTransaction(const AidlTypenames & typenames,const AidlInterface & interface,const AidlMethod & method,const Options & options)230 unique_ptr<Declaration> DefineClientTransaction(const AidlTypenames& typenames,
231 const AidlInterface& interface,
232 const AidlMethod& method, const Options& options) {
233 const string i_name = ClassName(interface, ClassNames::INTERFACE);
234 const string bp_name = ClassName(interface, ClassNames::CLIENT);
235 unique_ptr<MethodImpl> ret{
236 new MethodImpl{kBinderStatusLiteral,
237 bp_name,
238 method.GetName(),
239 {},
240 ArgList{BuildArgList(typenames, method, true /* for method decl */)}}};
241 StatementBlock* b = ret->GetStatementBlock();
242
243 // Declare parcels to hold our query and the response.
244 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
245 if (interface.IsSensitiveData()) {
246 b->AddLiteral(StringPrintf("%s.markSensitive()", kDataVarName));
247 }
248 b->AddLiteral(StringPrintf("%s.markForBinder(remoteStrong())", kDataVarName));
249
250 // Even if we're oneway, the transact method still takes a parcel.
251 b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
252
253 // Declare the status_t variable we need for error handling.
254 b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
255 kAndroidStatusVarName,
256 kAndroidStatusOk));
257 // We unconditionally return a Status object.
258 b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
259
260 if (options.GenTraces()) {
261 b->AddLiteral(
262 StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppClient\")",
263 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
264 }
265
266 if (options.GenLog()) {
267 b->AddLiteral(GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */),
268 false /* no semicolon */);
269 }
270
271 // Add the name of the interface we're hoping to call.
272 b->AddStatement(new Assignment(
273 kAndroidStatusVarName,
274 new MethodCall(StringPrintf("%s.writeInterfaceToken",
275 kDataVarName),
276 "getInterfaceDescriptor()")));
277 b->AddStatement(GotoErrorOnBadStatus());
278
279 for (const auto& a: method.GetArguments()) {
280 const string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
281
282 if (a->IsIn()) {
283 // Serialization looks roughly like:
284 // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
285 // if (_aidl_ret_status != ::android::OK) { goto error; }
286 const string& method = ParcelWriteMethodOf(a->GetType(), typenames);
287 b->AddStatement(
288 new Assignment(kAndroidStatusVarName,
289 new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
290 ParcelWriteCastOf(a->GetType(), typenames, var_name))));
291 b->AddStatement(GotoErrorOnBadStatus());
292 } else if (a->IsOut() && a->GetType().IsArray()) {
293 // Special case, the length of the out array is written into the parcel.
294 // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
295 // if (_aidl_ret_status != ::android::OK) { goto error; }
296 b->AddStatement(new Assignment(
297 kAndroidStatusVarName,
298 new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName), var_name)));
299 b->AddStatement(GotoErrorOnBadStatus());
300 }
301 }
302
303 // Invoke the transaction on the remote binder and confirm status.
304 string transaction_code = GetTransactionIdFor(interface, method);
305
306 vector<string> args = {transaction_code, kDataVarName,
307 StringPrintf("&%s", kReplyVarName)};
308
309 std::vector<std::string> flags;
310 if (method.IsOneway()) flags.push_back("::android::IBinder::FLAG_ONEWAY");
311 if (interface.IsSensitiveData()) flags.push_back("::android::IBinder::FLAG_CLEAR_BUF");
312
313 args.push_back(flags.empty() ? "0" : Join(flags, " | "));
314
315 b->AddStatement(new Assignment(
316 kAndroidStatusVarName,
317 new MethodCall("remote()->transact",
318 ArgList(args))));
319
320 // If the method is not implemented in the remote side, try to call the
321 // default implementation, if provided.
322 vector<string> arg_names;
323 for (const auto& a : method.GetArguments()) {
324 if (IsNonCopyableType(a->GetType(), typenames)) {
325 arg_names.emplace_back(StringPrintf("std::move(%s)", a->GetName().c_str()));
326 } else {
327 arg_names.emplace_back(a->GetName());
328 }
329 }
330 if (method.GetType().GetName() != "void") {
331 arg_names.emplace_back(kReturnVarName);
332 }
333 b->AddLiteral(StringPrintf("if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && "
334 "%s::getDefaultImpl())) {\n"
335 " return %s::getDefaultImpl()->%s(%s);\n"
336 "}\n",
337 i_name.c_str(), i_name.c_str(), method.GetName().c_str(),
338 Join(arg_names, ", ").c_str()),
339 false /* no semicolon */);
340
341 b->AddStatement(GotoErrorOnBadStatus());
342
343 if (!method.IsOneway()) {
344 // Strip off the exception header and fail if we see a remote exception.
345 // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
346 // if (_aidl_ret_status != ::android::OK) { goto error; }
347 // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
348 b->AddStatement(new Assignment(
349 kAndroidStatusVarName,
350 StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
351 b->AddStatement(GotoErrorOnBadStatus());
352 IfStatement* exception_check = new IfStatement(
353 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
354 b->AddStatement(exception_check);
355 exception_check->OnTrue()->AddLiteral(
356 StringPrintf("return %s", kStatusVarName));
357 }
358
359 // Type checking should guarantee that nothing below emits code until "return
360 // status" if we are a oneway method, so no more fear of accessing reply.
361
362 // If the method is expected to return something, read it first by convention.
363 if (method.GetType().GetName() != "void") {
364 const string& method_call = ParcelReadMethodOf(method.GetType(), typenames);
365 b->AddStatement(new Assignment(
366 kAndroidStatusVarName,
367 new MethodCall(StringPrintf("%s.%s", kReplyVarName, method_call.c_str()),
368 ParcelReadCastOf(method.GetType(), typenames, kReturnVarName))));
369 b->AddStatement(GotoErrorOnBadStatus());
370 }
371
372 for (const AidlArgument* a : method.GetOutArguments()) {
373 // Deserialization looks roughly like:
374 // _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
375 // if (_aidl_status != ::android::OK) { goto _aidl_error; }
376 string method = ParcelReadMethodOf(a->GetType(), typenames);
377
378 b->AddStatement(
379 new Assignment(kAndroidStatusVarName,
380 new MethodCall(StringPrintf("%s.%s", kReplyVarName, method.c_str()),
381 ParcelReadCastOf(a->GetType(), typenames, a->GetName()))));
382 b->AddStatement(GotoErrorOnBadStatus());
383 }
384
385 // If we've gotten to here, one of two things is true:
386 // 1) We've read some bad status_t
387 // 2) We've only read status_t == OK and there was no exception in the
388 // response.
389 // In both cases, we're free to set Status from the status_t and return.
390 b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
391 b->AddLiteral(
392 StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
393 kAndroidStatusVarName));
394
395 if (options.GenLog()) {
396 b->AddLiteral(GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
397 false /* isServer */, false /* isNdk */),
398 false /* no semicolon */);
399 }
400
401 b->AddLiteral(StringPrintf("return %s", kStatusVarName));
402
403 return unique_ptr<Declaration>(ret.release());
404 }
405
DefineClientMetaTransaction(const AidlTypenames &,const AidlInterface & interface,const AidlMethod & method,const Options & options)406 unique_ptr<Declaration> DefineClientMetaTransaction(const AidlTypenames& /* typenames */,
407 const AidlInterface& interface,
408 const AidlMethod& method,
409 const Options& options) {
410 AIDL_FATAL_IF(method.IsUserDefined(), method);
411 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
412 const string iface = ClassName(interface, ClassNames::INTERFACE);
413 const string proxy = ClassName(interface, ClassNames::CLIENT);
414 // Note: race condition can happen here, but no locking is required
415 // because 1) writing an interger is atomic and 2) this transaction
416 // will always return the same value, i.e., competing threads will
417 // give write the same value to cached_version_.
418 std::ostringstream code;
419 code << "int32_t " << proxy << "::" << kGetInterfaceVersion << "() {\n"
420 << " if (cached_version_ == -1) {\n"
421 << " ::android::Parcel data;\n"
422 << " ::android::Parcel reply;\n"
423 << " data.writeInterfaceToken(getInterfaceDescriptor());\n"
424 << " ::android::status_t err = remote()->transact(" << GetTransactionIdFor(interface, method)
425 << ", data, &reply);\n"
426 << " if (err == ::android::OK) {\n"
427 << " ::android::binder::Status _aidl_status;\n"
428 << " err = _aidl_status.readFromParcel(reply);\n"
429 << " if (err == ::android::OK && _aidl_status.isOk()) {\n"
430 << " cached_version_ = reply.readInt32();\n"
431 << " }\n"
432 << " }\n"
433 << " }\n"
434 << " return cached_version_;\n"
435 << "}\n";
436 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
437 }
438 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
439 const string iface = ClassName(interface, ClassNames::INTERFACE);
440 const string proxy = ClassName(interface, ClassNames::CLIENT);
441 std::ostringstream code;
442 code << "std::string " << proxy << "::" << kGetInterfaceHash << "() {\n"
443 << " std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);\n"
444 << " if (cached_hash_ == \"-1\") {\n"
445 << " ::android::Parcel data;\n"
446 << " ::android::Parcel reply;\n"
447 << " data.writeInterfaceToken(getInterfaceDescriptor());\n"
448 << " ::android::status_t err = remote()->transact(" << GetTransactionIdFor(interface, method)
449 << ", data, &reply);\n"
450 << " if (err == ::android::OK) {\n"
451 << " ::android::binder::Status _aidl_status;\n"
452 << " err = _aidl_status.readFromParcel(reply);\n"
453 << " if (err == ::android::OK && _aidl_status.isOk()) {\n"
454 << " reply.readUtf8FromUtf16(&cached_hash_);\n"
455 << " }\n"
456 << " }\n"
457 << " }\n"
458 << " return cached_hash_;\n"
459 << "}\n";
460 return unique_ptr<Declaration>(new LiteralDecl(code.str()));
461 }
462 return nullptr;
463 }
464
465 } // namespace
466
BuildClientSource(const AidlTypenames & typenames,const AidlInterface & interface,const Options & options)467 unique_ptr<Document> BuildClientSource(const AidlTypenames& typenames,
468 const AidlInterface& interface, const Options& options) {
469 vector<string> include_list = {
470 HeaderFile(interface, ClassNames::CLIENT, false),
471 HeaderFile(interface, ClassNames::SERVER, false), // for TRANSACTION_* consts
472 kParcelHeader,
473 kAndroidBaseMacrosHeader
474 };
475 if (options.GenLog()) {
476 include_list.emplace_back("chrono");
477 include_list.emplace_back("functional");
478 }
479 vector<unique_ptr<Declaration>> file_decls;
480
481 // The constructor just passes the IBinder instance up to the super
482 // class.
483 const string i_name = ClassName(interface, ClassNames::INTERFACE);
484 const string bp_name = ClassName(interface, ClassNames::CLIENT);
485 file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
486 bp_name,
487 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s", kImplVarName)},
488 {"BpInterface<" + i_name + ">(" + kImplVarName + ")"}}});
489
490 if (options.GenLog()) {
491 string code;
492 CodeWriterPtr writer = CodeWriter::ForString(&code);
493 (*writer) << "std::function<void(const " + bp_name + "::TransactionLog&)> " << bp_name
494 << "::logFunc;\n";
495 writer->Close();
496 file_decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
497 }
498
499 // Clients define a method per transaction.
500 for (const auto& method : interface.GetMethods()) {
501 unique_ptr<Declaration> m;
502 if (method->IsUserDefined()) {
503 m = DefineClientTransaction(typenames, interface, *method, options);
504 } else {
505 m = DefineClientMetaTransaction(typenames, interface, *method, options);
506 }
507 if (!m) { return nullptr; }
508 file_decls.push_back(std::move(m));
509 }
510 return unique_ptr<Document>{new CppSource{
511 include_list,
512 NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
513 }
514
515 namespace {
516
BuildConstantDefinitions(const AidlDefinedType & type,const AidlTypenames & typenames,const std::vector<std::string> & type_params,const std::string & class_name,vector<unique_ptr<Declaration>> & decls)517 void BuildConstantDefinitions(const AidlDefinedType& type, const AidlTypenames& typenames,
518 const std::vector<std::string>& type_params,
519 const std::string& class_name,
520 vector<unique_ptr<Declaration>>& decls) {
521 for (const auto& constant : type.GetConstantDeclarations()) {
522 const AidlConstantValue& value = constant->GetValue();
523 if (value.GetType() != AidlConstantValue::Type::STRING) continue;
524
525 std::string cppType = CppNameOf(constant->GetType(), typenames);
526 unique_ptr<MethodImpl> getter(
527 new MethodImpl("const " + cppType + "&", class_name, constant->GetName(), type_params, {}));
528 getter->GetStatementBlock()->AddLiteral(
529 StringPrintf("static const %s value(%s)", cppType.c_str(),
530 constant->ValueString(ConstantValueDecorator).c_str()));
531 getter->GetStatementBlock()->AddLiteral("return value");
532 decls.push_back(std::move(getter));
533 }
534 }
535
BuildConstantDeclarations(const AidlDefinedType & type,const AidlTypenames & typenames,unique_ptr<ClassDecl> & cls,set<string> & includes)536 void BuildConstantDeclarations(const AidlDefinedType& type, const AidlTypenames& typenames,
537 unique_ptr<ClassDecl>& cls, set<string>& includes) {
538 std::vector<std::unique_ptr<Declaration>> string_constants;
539 unique_ptr<Enum> byte_constant_enum{new Enum{"", "int8_t", false}};
540 unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t", false}};
541 unique_ptr<Enum> long_constant_enum{new Enum{"", "int64_t", false}};
542 for (const auto& constant : type.GetConstantDeclarations()) {
543 const AidlTypeSpecifier& type = constant->GetType();
544 const AidlConstantValue& value = constant->GetValue();
545
546 const string attribute = GetDeprecatedAttribute(*constant);
547 if (type.Signature() == "String") {
548 std::string cppType = CppNameOf(constant->GetType(), typenames);
549 unique_ptr<Declaration> getter(new MethodDecl("const " + cppType + "&", constant->GetName(),
550 {}, MethodDecl::IS_STATIC, attribute));
551 string_constants.push_back(std::move(getter));
552 } else if (type.Signature() == "byte") {
553 byte_constant_enum->AddValue(constant->GetName(),
554 constant->ValueString(ConstantValueDecorator), attribute);
555 } else if (type.Signature() == "int") {
556 int_constant_enum->AddValue(constant->GetName(),
557 constant->ValueString(ConstantValueDecorator), attribute);
558 } else if (type.Signature() == "long") {
559 long_constant_enum->AddValue(constant->GetName(),
560 constant->ValueString(ConstantValueDecorator), attribute);
561 } else {
562 AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature();
563 }
564 }
565 if (byte_constant_enum->HasValues()) {
566 cls->AddPublic(std::move(byte_constant_enum));
567 }
568 if (int_constant_enum->HasValues()) {
569 cls->AddPublic(std::move(int_constant_enum));
570 }
571 if (long_constant_enum->HasValues()) {
572 cls->AddPublic(std::move(long_constant_enum));
573 }
574 if (!string_constants.empty()) {
575 includes.insert(kString16Header);
576
577 for (auto& string_constant : string_constants) {
578 cls->AddPublic(std::move(string_constant));
579 }
580 }
581 }
582
HandleServerTransaction(const AidlTypenames & typenames,const AidlInterface & interface,const AidlMethod & method,const Options & options,StatementBlock * b)583 bool HandleServerTransaction(const AidlTypenames& typenames, const AidlInterface& interface,
584 const AidlMethod& method, const Options& options, StatementBlock* b) {
585 // Declare all the parameters now. In the common case, we expect no errors
586 // in serialization.
587 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
588 b->AddLiteral(StringPrintf("%s %s", CppNameOf(a->GetType(), typenames).c_str(),
589 BuildVarName(*a).c_str()));
590 }
591
592 // Declare a variable to hold the return value.
593 if (method.GetType().GetName() != "void") {
594 string type = CppNameOf(method.GetType(), typenames);
595 b->AddLiteral(StringPrintf("%s %s", type.c_str(), kReturnVarName));
596 }
597
598 // Check that the client is calling the correct interface.
599 IfStatement* interface_check = new IfStatement(
600 new MethodCall(StringPrintf("%s.checkInterface",
601 kDataVarName), "this"),
602 true /* invert the check */);
603 b->AddStatement(interface_check);
604 interface_check->OnTrue()->AddStatement(
605 new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
606 interface_check->OnTrue()->AddLiteral("break");
607
608 if (options.GenTraces()) {
609 b->AddLiteral(
610 StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppServer\")",
611 kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
612 }
613
614 // Deserialize each "in" parameter to the transaction.
615 for (const auto& a: method.GetArguments()) {
616 // Deserialization looks roughly like:
617 // _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
618 // if (_aidl_ret_status != ::android::OK) { break; }
619 const string& var_name = "&" + BuildVarName(*a);
620 if (a->IsIn()) {
621 const string& readMethod = ParcelReadMethodOf(a->GetType(), typenames);
622 b->AddStatement(
623 new Assignment{kAndroidStatusVarName,
624 new MethodCall{string(kDataVarName) + "." + readMethod,
625 ParcelReadCastOf(a->GetType(), typenames, var_name)}});
626 b->AddStatement(BreakOnStatusNotOk());
627 } else if (a->IsOut() && a->GetType().IsArray()) {
628 // Special case, the length of the out array is written into the parcel.
629 // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
630 // if (_aidl_ret_status != ::android::OK) { break; }
631 b->AddStatement(
632 new Assignment{kAndroidStatusVarName,
633 new MethodCall{string(kDataVarName) + ".resizeOutVector", var_name}});
634 b->AddStatement(BreakOnStatusNotOk());
635 }
636 }
637
638 const string bn_name = ClassName(interface, ClassNames::SERVER);
639 if (options.GenLog()) {
640 b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
641 false);
642 }
643 // Call the actual method. This is implemented by the subclass.
644 vector<unique_ptr<AstNode>> status_args;
645 status_args.emplace_back(new MethodCall(
646 method.GetName(), BuildArgList(typenames, method, false /* not for method decl */)));
647 b->AddStatement(new Statement(new MethodCall(
648 StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
649 ArgList(std::move(status_args)))));
650
651 if (options.GenLog()) {
652 b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
653 true /* isServer */, false /* isNdk */),
654 false);
655 }
656
657 // Write exceptions during transaction handling to parcel.
658 if (!method.IsOneway()) {
659 b->AddStatement(new Assignment(
660 kAndroidStatusVarName,
661 StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
662 b->AddStatement(BreakOnStatusNotOk());
663 IfStatement* exception_check = new IfStatement(
664 new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
665 b->AddStatement(exception_check);
666 exception_check->OnTrue()->AddLiteral("break");
667 }
668
669 // If we have a return value, write it first.
670 if (method.GetType().GetName() != "void") {
671 string writeMethod =
672 string(kReplyVarName) + "->" + ParcelWriteMethodOf(method.GetType(), typenames);
673 b->AddStatement(new Assignment(
674 kAndroidStatusVarName,
675 new MethodCall(writeMethod,
676 ParcelWriteCastOf(method.GetType(), typenames, kReturnVarName))));
677 b->AddStatement(BreakOnStatusNotOk());
678 }
679 // Write each out parameter to the reply parcel.
680 for (const AidlArgument* a : method.GetOutArguments()) {
681 // Serialization looks roughly like:
682 // _aidl_ret_status = data.WriteInt32(out_param_name);
683 // if (_aidl_ret_status != ::android::OK) { break; }
684 const string& writeMethod = ParcelWriteMethodOf(a->GetType(), typenames);
685 b->AddStatement(new Assignment(
686 kAndroidStatusVarName,
687 new MethodCall(string(kReplyVarName) + "->" + writeMethod,
688 ParcelWriteCastOf(a->GetType(), typenames, BuildVarName(*a)))));
689 b->AddStatement(BreakOnStatusNotOk());
690 }
691
692 return true;
693 }
694
HandleServerMetaTransaction(const AidlTypenames &,const AidlInterface & interface,const AidlMethod & method,const Options & options,StatementBlock * b)695 bool HandleServerMetaTransaction(const AidlTypenames&, const AidlInterface& interface,
696 const AidlMethod& method, const Options& options,
697 StatementBlock* b) {
698 AIDL_FATAL_IF(method.IsUserDefined(), method);
699
700 if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
701 std::ostringstream code;
702 code << "_aidl_data.checkInterface(this);\n"
703 << "_aidl_reply->writeNoException();\n"
704 << "_aidl_reply->writeInt32(" << ClassName(interface, ClassNames::INTERFACE)
705 << "::VERSION)";
706 b->AddLiteral(code.str());
707 return true;
708 }
709 if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
710 std::ostringstream code;
711 code << "_aidl_data.checkInterface(this);\n"
712 << "_aidl_reply->writeNoException();\n"
713 << "_aidl_reply->writeUtf8AsUtf16(" << ClassName(interface, ClassNames::INTERFACE)
714 << "::HASH)";
715 b->AddLiteral(code.str());
716 return true;
717 }
718 return false;
719 }
720
721 } // namespace
722
BuildServerSource(const AidlTypenames & typenames,const AidlInterface & interface,const Options & options)723 unique_ptr<Document> BuildServerSource(const AidlTypenames& typenames,
724 const AidlInterface& interface, const Options& options) {
725 const string bn_name = ClassName(interface, ClassNames::SERVER);
726 vector<string> include_list{
727 HeaderFile(interface, ClassNames::SERVER, false),
728 kParcelHeader,
729 kStabilityHeader,
730 };
731 if (options.GenLog()) {
732 include_list.emplace_back("chrono");
733 include_list.emplace_back("functional");
734 }
735
736 unique_ptr<ConstructorImpl> constructor{new ConstructorImpl{bn_name, ArgList{}, {}}};
737
738 if (interface.IsVintfStability()) {
739 constructor->GetStatementBlock()->AddLiteral("::android::internal::Stability::markVintf(this)");
740 } else {
741 constructor->GetStatementBlock()->AddLiteral(
742 "::android::internal::Stability::markCompilationUnit(this)");
743 }
744
745 unique_ptr<MethodImpl> on_transact{
746 new MethodImpl{kAndroidStatusLiteral,
747 bn_name,
748 "onTransact",
749 {},
750 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
751 StringPrintf("const %s& %s", kAndroidParcelLiteral, kDataVarName),
752 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
753 StringPrintf("uint32_t %s", kFlagsVarName)}}}};
754
755 // Declare the status_t variable
756 on_transact->GetStatementBlock()->AddLiteral(
757 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
758 kAndroidStatusOk));
759
760 // Add the all important switch statement, but retain a pointer to it.
761 SwitchStatement* s = new SwitchStatement{kCodeVarName};
762 on_transact->GetStatementBlock()->AddStatement(s);
763
764 // The switch statement has a case statement for each transaction code.
765 for (const auto& method : interface.GetMethods()) {
766 StatementBlock* b = s->AddCase(GetTransactionIdFor(interface, *method));
767 if (!b) { return nullptr; }
768
769 bool success = false;
770 if (method->IsUserDefined()) {
771 success = HandleServerTransaction(typenames, interface, *method, options, b);
772 } else {
773 success = HandleServerMetaTransaction(typenames, interface, *method, options, b);
774 }
775 if (!success) {
776 return nullptr;
777 }
778 }
779
780 // The switch statement has a default case which defers to the super class.
781 // The superclass handles a few pre-defined transactions.
782 StatementBlock* b = s->AddCase("");
783 b->AddLiteral(StringPrintf(
784 "%s = ::android::BBinder::onTransact(%s, %s, "
785 "%s, %s)", kAndroidStatusVarName, kCodeVarName,
786 kDataVarName, kReplyVarName, kFlagsVarName));
787
788 // If we saw a null reference, we can map that to an appropriate exception.
789 IfStatement* null_check = new IfStatement(
790 new LiteralExpression(string(kAndroidStatusVarName) +
791 " == ::android::UNEXPECTED_NULL"));
792 on_transact->GetStatementBlock()->AddStatement(null_check);
793 null_check->OnTrue()->AddStatement(new Assignment(
794 kAndroidStatusVarName,
795 StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
796 ".writeToParcel(%s)",
797 kBinderStatusLiteral, kBinderStatusLiteral,
798 kReplyVarName)));
799
800 // Finally, the server's onTransact method just returns a status code.
801 on_transact->GetStatementBlock()->AddLiteral(
802 StringPrintf("return %s", kAndroidStatusVarName));
803 vector<unique_ptr<Declaration>> decls;
804 decls.push_back(std::move(constructor));
805
806 bool deprecated = interface.IsDeprecated() ||
807 std::any_of(interface.GetMethods().begin(), interface.GetMethods().end(),
808 [](const auto& m) { return m->IsDeprecated(); });
809 if (deprecated) {
810 decls.emplace_back(
811 new LiteralDecl("#pragma clang diagnostic push\n"
812 "#pragma clang diagnostic ignored \"-Wdeprecated\"\n"));
813 }
814 decls.push_back(std::move(on_transact));
815 if (deprecated) {
816 decls.emplace_back(new LiteralDecl("#pragma clang diagnostic pop\n"));
817 }
818
819 if (options.Version() > 0) {
820 std::ostringstream code;
821 code << "int32_t " << bn_name << "::" << kGetInterfaceVersion << "() {\n"
822 << " return " << ClassName(interface, ClassNames::INTERFACE) << "::VERSION;\n"
823 << "}\n";
824 decls.emplace_back(new LiteralDecl(code.str()));
825 }
826 if (!options.Hash().empty()) {
827 std::ostringstream code;
828 code << "std::string " << bn_name << "::" << kGetInterfaceHash << "() {\n"
829 << " return " << ClassName(interface, ClassNames::INTERFACE) << "::HASH;\n"
830 << "}\n";
831 decls.emplace_back(new LiteralDecl(code.str()));
832 }
833
834 if (options.GenLog()) {
835 string code;
836 CodeWriterPtr writer = CodeWriter::ForString(&code);
837 (*writer) << "std::function<void(const " + bn_name + "::TransactionLog&)> " << bn_name
838 << "::logFunc;\n";
839 writer->Close();
840 decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
841 }
842 return unique_ptr<Document>{
843 new CppSource{include_list, NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
844 }
845
BuildInterfaceSource(const AidlTypenames & typenames,const AidlInterface & interface,const Options & options)846 unique_ptr<Document> BuildInterfaceSource(const AidlTypenames& typenames,
847 const AidlInterface& interface,
848 [[maybe_unused]] const Options& options) {
849 vector<string> include_list{
850 HeaderFile(interface, ClassNames::RAW, false),
851 HeaderFile(interface, ClassNames::CLIENT, false),
852 };
853
854 vector<unique_ptr<Declaration>> decls;
855
856 unique_ptr<MacroDecl> meta_if{
857 new MacroDecl{"DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE",
858 ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
859 '"' + interface.GetDescriptor() + '"'}}}};
860 decls.push_back(std::move(meta_if));
861
862 BuildConstantDefinitions(interface, typenames, {}, ClassName(interface, ClassNames::INTERFACE),
863 decls);
864
865 return unique_ptr<Document>{new CppSource{
866 include_list,
867 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
868 }
869
BuildClientHeader(const AidlTypenames & typenames,const AidlInterface & interface,const Options & options)870 unique_ptr<Document> BuildClientHeader(const AidlTypenames& typenames,
871 const AidlInterface& interface, const Options& options) {
872 const string i_name = ClassName(interface, ClassNames::INTERFACE);
873 const string bp_name = ClassName(interface, ClassNames::CLIENT);
874
875 vector<string> includes = {kIBinderHeader, kIInterfaceHeader, "utils/Errors.h",
876 HeaderFile(interface, ClassNames::RAW, false)};
877
878 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
879 bp_name,
880 ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
881 kImplVarName)},
882 ConstructorDecl::IS_EXPLICIT
883 }};
884 unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
885 "~" + bp_name,
886 ArgList{},
887 ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
888
889 vector<unique_ptr<Declaration>> publics;
890 vector<unique_ptr<Declaration>> privates;
891
892 publics.push_back(std::move(constructor));
893 publics.push_back(std::move(destructor));
894
895 for (const auto& method: interface.GetMethods()) {
896 if (method->IsUserDefined()) {
897 publics.push_back(BuildMethodDecl(*method, typenames, false));
898 } else {
899 publics.push_back(BuildMetaMethodDecl(*method, typenames, options, false));
900 }
901 }
902
903 if (options.GenLog()) {
904 includes.emplace_back("functional"); // for std::function
905 includes.emplace_back("android/binder_to_string.h");
906
907 publics.emplace_back(new LiteralDecl{kTransactionLogStruct});
908 publics.emplace_back(
909 new LiteralDecl{"static std::function<void(const TransactionLog&)> logFunc;\n"});
910 }
911
912 if (options.Version() > 0) {
913 privates.emplace_back(new LiteralDecl("int32_t cached_version_ = -1;\n"));
914 }
915 if (!options.Hash().empty()) {
916 privates.emplace_back(new LiteralDecl("std::string cached_hash_ = \"-1\";\n"));
917 privates.emplace_back(new LiteralDecl("std::mutex cached_hash_mutex_;\n"));
918 }
919
920 const string attribute = GetDeprecatedAttribute(interface);
921 unique_ptr<ClassDecl> bp_class{new ClassDecl{
922 bp_name,
923 "::android::BpInterface<" + i_name + ">",
924 {},
925 std::move(publics),
926 std::move(privates),
927 attribute,
928 }};
929
930 return unique_ptr<Document>{
931 new CppHeader{includes, NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
932 }
933
BuildServerHeader(const AidlTypenames &,const AidlInterface & interface,const Options & options)934 unique_ptr<Document> BuildServerHeader(const AidlTypenames& /* typenames */,
935 const AidlInterface& interface, const Options& options) {
936 const string i_name = ClassName(interface, ClassNames::INTERFACE);
937 const string bn_name = ClassName(interface, ClassNames::SERVER);
938
939 unique_ptr<ConstructorDecl> constructor{
940 new ConstructorDecl{bn_name, ArgList{}, ConstructorDecl::IS_EXPLICIT}};
941
942 unique_ptr<Declaration> on_transact{new MethodDecl{
943 kAndroidStatusLiteral, "onTransact",
944 ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
945 StringPrintf("const %s& %s", kAndroidParcelLiteral,
946 kDataVarName),
947 StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
948 StringPrintf("uint32_t %s", kFlagsVarName)}},
949 MethodDecl::IS_OVERRIDE
950 }};
951 vector<string> includes = {"binder/IInterface.h", HeaderFile(interface, ClassNames::RAW, false)};
952
953 vector<unique_ptr<Declaration>> publics;
954 vector<unique_ptr<Declaration>> privates;
955
956 for (const auto& method : interface.GetMethods()) {
957 std::ostringstream code;
958 code << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
959 << "::android::IBinder::FIRST_CALL_TRANSACTION + " << method->GetId() << ";\n";
960 publics.push_back(std::make_unique<LiteralDecl>(code.str()));
961 }
962
963 publics.push_back(std::move(constructor));
964 publics.push_back(std::move(on_transact));
965
966 if (options.Version() > 0) {
967 std::ostringstream code;
968 code << "int32_t " << kGetInterfaceVersion << "() final;\n";
969 publics.emplace_back(new LiteralDecl(code.str()));
970 }
971 if (!options.Hash().empty()) {
972 std::ostringstream code;
973 code << "std::string " << kGetInterfaceHash << "();\n";
974 publics.emplace_back(new LiteralDecl(code.str()));
975 }
976
977 if (options.GenLog()) {
978 includes.emplace_back("functional"); // for std::function
979 includes.emplace_back("android/binder_to_string.h");
980
981 publics.emplace_back(new LiteralDecl{kTransactionLogStruct});
982 publics.emplace_back(
983 new LiteralDecl{"static std::function<void(const TransactionLog&)> logFunc;\n"});
984 }
985 const string attribute = GetDeprecatedAttribute(interface);
986 unique_ptr<ClassDecl> bn_class{new ClassDecl{
987 bn_name,
988 "::android::BnInterface<" + i_name + ">",
989 {},
990 std::move(publics),
991 std::move(privates),
992 attribute,
993 }};
994
995 return unique_ptr<Document>{
996 new CppHeader{includes, NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
997 }
998
BuildInterfaceHeader(const AidlTypenames & typenames,const AidlInterface & interface,const Options & options)999 unique_ptr<Document> BuildInterfaceHeader(const AidlTypenames& typenames,
1000 const AidlInterface& interface, const Options& options) {
1001 set<string> includes = {kIBinderHeader, kIInterfaceHeader, kStatusHeader, kStrongPointerHeader};
1002
1003 for (const auto& method : interface.GetMethods()) {
1004 for (const auto& argument : method->GetArguments()) {
1005 AddHeaders(argument->GetType(), typenames, &includes);
1006 }
1007
1008 AddHeaders(method->GetType(), typenames, &includes);
1009 }
1010
1011 const string i_name = ClassName(interface, ClassNames::INTERFACE);
1012 const string attribute = GetDeprecatedAttribute(interface);
1013 unique_ptr<ClassDecl> if_class{new ClassDecl{i_name, "::android::IInterface", {}, attribute}};
1014 if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
1015 "DECLARE_META_INTERFACE",
1016 ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
1017
1018 if (options.Version() > 0) {
1019 std::ostringstream code;
1020 code << "const int32_t VERSION = " << options.Version() << ";\n";
1021
1022 if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
1023 }
1024 if (!options.Hash().empty()) {
1025 std::ostringstream code;
1026 code << "const std::string HASH = \"" << options.Hash() << "\";\n";
1027
1028 if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
1029 }
1030
1031 BuildConstantDeclarations(interface, typenames, if_class, includes);
1032
1033 if (options.GenTraces()) {
1034 includes.insert(kTraceHeader);
1035 }
1036
1037 if (!interface.GetMethods().empty()) {
1038 for (const auto& method : interface.GetMethods()) {
1039 if (method->IsUserDefined()) {
1040 // Each method gets an enum entry and pure virtual declaration.
1041 if_class->AddPublic(BuildMethodDecl(*method, typenames, true));
1042 } else {
1043 if_class->AddPublic(BuildMetaMethodDecl(*method, typenames, options, true));
1044 }
1045 }
1046 }
1047
1048 // Implement the default impl class.
1049 vector<unique_ptr<Declaration>> method_decls;
1050 // onAsBinder returns nullptr as this interface is not associated with a
1051 // real binder.
1052 method_decls.emplace_back(
1053 new LiteralDecl("::android::IBinder* onAsBinder() override {\n"
1054 " return nullptr;\n"
1055 "}\n"));
1056 // Each interface method by default returns UNKNOWN_TRANSACTION with is
1057 // the same status that is returned by transact() when the method is
1058 // not implemented in the server side. In other words, these default
1059 // methods do nothing; they only exist to aid making a real default
1060 // impl class without having to override all methods in an interface.
1061 for (const auto& method : interface.GetMethods()) {
1062 if (method->IsUserDefined()) {
1063 std::ostringstream code;
1064 code << "::android::binder::Status " << method->GetName()
1065 << BuildArgList(typenames, *method, true, true).ToString() << " override";
1066 GenerateDeprecated(code, *method);
1067 code << " {\n"
1068 << " return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
1069 << "}\n";
1070 method_decls.emplace_back(new LiteralDecl(code.str()));
1071 } else {
1072 if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1073 std::ostringstream code;
1074 code << "int32_t " << kGetInterfaceVersion << "() override {\n"
1075 << " return 0;\n"
1076 << "}\n";
1077 method_decls.emplace_back(new LiteralDecl(code.str()));
1078 }
1079 if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1080 std::ostringstream code;
1081 code << "std::string " << kGetInterfaceHash << "() override {\n"
1082 << " return \"\";\n"
1083 << "}\n";
1084 method_decls.emplace_back(new LiteralDecl(code.str()));
1085 }
1086 }
1087 }
1088
1089 vector<unique_ptr<Declaration>> decls;
1090 decls.emplace_back(std::move(if_class));
1091 decls.emplace_back(new ClassDecl{
1092 ClassName(interface, ClassNames::DEFAULT_IMPL),
1093 i_name,
1094 {},
1095 std::move(method_decls),
1096 {},
1097 attribute, // inherits the same attributes
1098 });
1099
1100 return unique_ptr<Document>{
1101 new CppHeader{vector<string>(includes.begin(), includes.end()),
1102 NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
1103 }
1104
GetInitializer(const AidlTypenames & typenames,const AidlVariableDeclaration & variable)1105 string GetInitializer(const AidlTypenames& typenames, const AidlVariableDeclaration& variable) {
1106 string cppType = CppNameOf(variable.GetType(), typenames);
1107 return cppType + "(" + variable.ValueString(ConstantValueDecorator) + ")";
1108 }
1109
AddTypeSpecificHeaders(const AidlStructuredParcelable &,std::set<std::string> & includes)1110 void AddTypeSpecificHeaders(const AidlStructuredParcelable&, std::set<std::string>& includes) {
1111 includes.insert("tuple"); // std::tie in comparison operators
1112 }
1113
BuildReadFromParcel(const AidlStructuredParcelable & parcel,const AidlTypenames & typenames,StatementBlock * read_block)1114 void BuildReadFromParcel(const AidlStructuredParcelable& parcel, const AidlTypenames& typenames,
1115 StatementBlock* read_block) {
1116 read_block->AddLiteral(
1117 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
1118
1119 read_block->AddLiteral(
1120 "[[maybe_unused]] size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1121 "int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();\n"
1122 "if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;\n"
1123 "[[maybe_unused]] size_t _aidl_parcelable_size = "
1124 "static_cast<size_t>(_aidl_parcelable_raw_size);\n"
1125 "if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;\n",
1126 /*add_semicolon=*/false);
1127
1128 auto checkAvailableData = StringPrintf(
1129 "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n"
1130 " _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
1131 " return %s;\n"
1132 "}\n",
1133 kAndroidStatusVarName);
1134
1135 for (const auto& variable : parcel.GetFields()) {
1136 read_block->AddLiteral(checkAvailableData, /*add_semicolon=*/false);
1137 string method = ParcelReadMethodOf(variable->GetType(), typenames);
1138 read_block->AddStatement(new Assignment(
1139 kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1140 ParcelReadCastOf(variable->GetType(), typenames,
1141 "&" + variable->GetName()))));
1142 read_block->AddStatement(ReturnOnStatusNotOk());
1143 }
1144 read_block->AddLiteral("_aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size)");
1145 read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1146 }
1147
BuildWriteToParcel(const AidlStructuredParcelable & parcel,const AidlTypenames & typenames,StatementBlock * write_block)1148 void BuildWriteToParcel(const AidlStructuredParcelable& parcel, const AidlTypenames& typenames,
1149 StatementBlock* write_block) {
1150 write_block->AddLiteral(
1151 StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
1152
1153 write_block->AddLiteral(
1154 "auto _aidl_start_pos = _aidl_parcel->dataPosition();\n"
1155 "_aidl_parcel->writeInt32(0);\n",
1156 /*add_semicolon=*/false);
1157
1158 for (const auto& variable : parcel.GetFields()) {
1159 string method = ParcelWriteMethodOf(variable->GetType(), typenames);
1160 write_block->AddStatement(new Assignment(
1161 kAndroidStatusVarName,
1162 new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
1163 ParcelWriteCastOf(variable->GetType(), typenames, variable->GetName()))));
1164 write_block->AddStatement(ReturnOnStatusNotOk());
1165 }
1166
1167 write_block->AddLiteral(
1168 "auto _aidl_end_pos = _aidl_parcel->dataPosition();\n"
1169 "_aidl_parcel->setDataPosition(_aidl_start_pos);\n"
1170 "_aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);\n"
1171 "_aidl_parcel->setDataPosition(_aidl_end_pos);\n",
1172 /*add_semicolon=*/false);
1173 write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
1174 }
1175
GetParcelWriterContext(const AidlTypenames & typenames)1176 ParcelWriterContext GetParcelWriterContext(const AidlTypenames& typenames) {
1177 return ParcelWriterContext{
1178 .status_type = kAndroidStatusLiteral,
1179 .status_ok = kAndroidStatusOk,
1180 .status_bad = kAndroidStatusBadValue,
1181 .read_func =
1182 [&](CodeWriter& out, const string& var, const AidlTypeSpecifier& type) {
1183 out << fmt::format("{}->{}({})", kParcelVarName, ParcelReadMethodOf(type, typenames),
1184 ParcelReadCastOf(type, typenames, "&" + var));
1185 },
1186 .write_func =
1187 [&](CodeWriter& out, const string& value, const AidlTypeSpecifier& type) {
1188 out << fmt::format("{}->{}({})", kParcelVarName, ParcelWriteMethodOf(type, typenames),
1189 ParcelWriteCastOf(type, typenames, value));
1190 },
1191 };
1192 }
1193
AddTypeSpecificHeaders(const AidlUnionDecl &,std::set<std::string> & includes)1194 void AddTypeSpecificHeaders(const AidlUnionDecl&, std::set<std::string>& includes) {
1195 includes.insert(std::begin(UnionWriter::headers), std::end(UnionWriter::headers));
1196 }
1197
BuildReadFromParcel(const AidlUnionDecl & decl,const AidlTypenames & typenames,StatementBlock * read_block)1198 void BuildReadFromParcel(const AidlUnionDecl& decl, const AidlTypenames& typenames,
1199 StatementBlock* read_block) {
1200 string body;
1201 UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
1202 uw.ReadFromParcel(*CodeWriter::ForString(&body), GetParcelWriterContext(typenames));
1203 read_block->AddLiteral(body, /*add_semicolon=*/false);
1204 }
1205
BuildWriteToParcel(const AidlUnionDecl & decl,const AidlTypenames & typenames,StatementBlock * write_block)1206 void BuildWriteToParcel(const AidlUnionDecl& decl, const AidlTypenames& typenames,
1207 StatementBlock* write_block) {
1208 string body;
1209 UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
1210 uw.WriteToParcel(*CodeWriter::ForString(&body), GetParcelWriterContext(typenames));
1211 write_block->AddLiteral(body, /*add_semicolon=*/false);
1212 }
1213
BuildParcelFields(ClassDecl & clazz,const AidlStructuredParcelable & decl,const AidlTypenames & typenames)1214 void BuildParcelFields(ClassDecl& clazz, const AidlStructuredParcelable& decl,
1215 const AidlTypenames& typenames) {
1216 for (const auto& variable : decl.GetFields()) {
1217 std::ostringstream out;
1218 std::string cppType = CppNameOf(variable->GetType(), typenames);
1219 out << cppType;
1220 GenerateDeprecated(out, *variable);
1221 out << " " << variable->GetName().c_str();
1222 if (variable->GetDefaultValue()) {
1223 out << " = " << GetInitializer(typenames, *variable);
1224 } else if (variable->GetType().GetName() == "ParcelableHolder") {
1225 if (decl.IsVintfStability()) {
1226 out << " { ::android::Parcelable::Stability::STABILITY_VINTF }";
1227 } else {
1228 out << " { ::android::Parcelable::Stability::STABILITY_LOCAL }";
1229 }
1230 }
1231 out << ";\n";
1232
1233 clazz.AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
1234 }
1235 }
1236
BuildParcelFields(ClassDecl & clazz,const AidlUnionDecl & decl,const AidlTypenames & typenames)1237 void BuildParcelFields(ClassDecl& clazz, const AidlUnionDecl& decl,
1238 const AidlTypenames& typenames) {
1239 UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
1240 string public_fields;
1241 string private_fields;
1242 uw.PublicFields(*CodeWriter::ForString(&public_fields));
1243 uw.PrivateFields(*CodeWriter::ForString(&private_fields));
1244 clazz.AddPublic(std::make_unique<LiteralDecl>(public_fields));
1245 clazz.AddPrivate(std::make_unique<LiteralDecl>(private_fields));
1246 }
1247
1248 template <typename ParcelableType>
BuildParcelHeader(const AidlTypenames & typenames,const ParcelableType & parcel,const Options &)1249 std::unique_ptr<Document> BuildParcelHeader(const AidlTypenames& typenames,
1250 const ParcelableType& parcel, const Options&) {
1251 const std::vector<std::string>& type_params =
1252 parcel.IsGeneric() ? parcel.GetTypeParameters() : std::vector<std::string>();
1253 const std::string attribute = GetDeprecatedAttribute(parcel);
1254 unique_ptr<ClassDecl> parcel_class{
1255 new ClassDecl{parcel.GetName(), "::android::Parcelable", type_params, attribute}};
1256
1257 set<string> includes = {kStatusHeader, kParcelHeader, kString16Header};
1258 AddTypeSpecificHeaders(parcel, includes);
1259
1260 for (const auto& variable : parcel.GetFields()) {
1261 AddHeaders(variable->GetType(), typenames, &includes);
1262 }
1263
1264 string operator_code;
1265 GenerateParcelableComparisonOperators(*CodeWriter::ForString(&operator_code), parcel);
1266 parcel_class->AddPublic(std::make_unique<LiteralDecl>(operator_code));
1267
1268 BuildParcelFields(*parcel_class, parcel, typenames);
1269 BuildConstantDeclarations(parcel, typenames, parcel_class, includes);
1270
1271 if (parcel.IsVintfStability()) {
1272 parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(
1273 new LiteralDecl("::android::Parcelable::Stability getStability() const override { return "
1274 "::android::Parcelable::Stability::STABILITY_VINTF; }\n")));
1275 }
1276
1277 unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
1278 ArgList("const ::android::Parcel* _aidl_parcel"),
1279 MethodDecl::IS_FINAL));
1280 parcel_class->AddPublic(std::move(read));
1281 unique_ptr<MethodDecl> write(new MethodDecl(kAndroidStatusLiteral, "writeToParcel",
1282 ArgList("::android::Parcel* _aidl_parcel"),
1283 MethodDecl::IS_CONST | MethodDecl::IS_FINAL));
1284 parcel_class->AddPublic(std::move(write));
1285
1286 parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(
1287 new LiteralDecl(StringPrintf("static const ::android::String16& getParcelableDescriptor() {\n"
1288 " static const ::android::StaticString16 DESCIPTOR (u\"%s\");\n"
1289 " return DESCIPTOR;\n"
1290 "}\n",
1291 parcel.GetCanonicalName().c_str()))));
1292
1293 // toString() method
1294 includes.insert("android/binder_to_string.h");
1295 string to_string;
1296 GenerateToString(*CodeWriter::ForString(&to_string), parcel);
1297 parcel_class->AddPublic(std::make_unique<LiteralDecl>(to_string));
1298
1299 auto decls = NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage());
1300 // TODO(b/31559095) bionic on host should define this
1301 if (parcel.AsUnionDeclaration()) {
1302 decls.insert(decls.begin(),
1303 std::make_unique<LiteralDecl>(
1304 "#ifndef __BIONIC__\n#define __assert2(a,b,c,d) ((void)0)\n#endif\n\n"));
1305 }
1306 return unique_ptr<Document>{
1307 new CppHeader{vector<string>(includes.begin(), includes.end()), std::move(decls)}};
1308 }
1309
1310 template <typename T>
BuildParcelSource(const AidlTypenames & typenames,const T & parcel,const Options &)1311 std::unique_ptr<Document> BuildParcelSource(const AidlTypenames& typenames, const T& parcel,
1312 const Options&) {
1313 const std::vector<std::string>& type_params =
1314 parcel.IsGeneric() ? parcel.GetTypeParameters() : std::vector<std::string>();
1315 auto read =
1316 std::make_unique<MethodImpl>(kAndroidStatusLiteral, parcel.GetName(), "readFromParcel",
1317 type_params, ArgList("const ::android::Parcel* _aidl_parcel"));
1318 BuildReadFromParcel(parcel, typenames, read->GetStatementBlock());
1319
1320 auto write = std::make_unique<MethodImpl>(
1321 kAndroidStatusLiteral, parcel.GetName(), "writeToParcel", type_params,
1322 ArgList("::android::Parcel* _aidl_parcel"), true /*const*/);
1323 BuildWriteToParcel(parcel, typenames, write->GetStatementBlock());
1324
1325 vector<unique_ptr<Declaration>> file_decls;
1326 BuildConstantDefinitions(parcel, typenames, type_params, parcel.GetName(), file_decls);
1327 file_decls.push_back(std::move(read));
1328 file_decls.push_back(std::move(write));
1329
1330 set<string> includes = {};
1331 AddHeaders(parcel, &includes);
1332
1333 return unique_ptr<Document>{
1334 new CppSource{vector<string>(includes.begin(), includes.end()),
1335 NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
1336 }
1337
GenerateEnumToString(const AidlTypenames & typenames,const AidlEnumDeclaration & enum_decl)1338 std::string GenerateEnumToString(const AidlTypenames& typenames,
1339 const AidlEnumDeclaration& enum_decl) {
1340 std::ostringstream code;
1341 code << "[[nodiscard]]";
1342 GenerateDeprecated(code, enum_decl);
1343 code << " static inline std::string toString(" << enum_decl.GetName() << " val)";
1344 code << " {\n";
1345 code << " switch(val) {\n";
1346 std::set<std::string> unique_cases;
1347 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1348 std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
1349 // Only add a case if its value has not yet been used in the switch
1350 // statement. C++ does not allow multiple cases with the same value, but
1351 // enums does allow this. In this scenario, the first declared
1352 // enumerator with the given value is printed.
1353 if (unique_cases.count(c) == 0) {
1354 unique_cases.insert(c);
1355 code << " case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
1356 code << " return \"" << enumerator->GetName() << "\";\n";
1357 }
1358 }
1359 code << " default:\n";
1360 code << " return std::to_string(static_cast<"
1361 << CppNameOf(enum_decl.GetBackingType(), typenames) << ">(val));\n";
1362 code << " }\n";
1363 code << "}\n";
1364 return code.str();
1365 }
1366
BuildEnumHeader(const AidlTypenames & typenames,const AidlEnumDeclaration & enum_decl)1367 std::unique_ptr<Document> BuildEnumHeader(const AidlTypenames& typenames,
1368 const AidlEnumDeclaration& enum_decl) {
1369 const std::string attribute = GetDeprecatedAttribute(enum_decl);
1370 std::unique_ptr<Enum> generated_enum{new Enum{
1371 enum_decl.GetName(), CppNameOf(enum_decl.GetBackingType(), typenames), true, attribute}};
1372 for (const auto& enumerator : enum_decl.GetEnumerators()) {
1373 generated_enum->AddValue(
1374 enumerator->GetName(),
1375 enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator));
1376 }
1377
1378 std::set<std::string> includes = {
1379 "array",
1380 "binder/Enums.h",
1381 "string",
1382 };
1383 AddHeaders(enum_decl.GetBackingType(), typenames, &includes);
1384
1385 std::vector<std::unique_ptr<Declaration>> decls1;
1386 decls1.push_back(std::move(generated_enum));
1387 decls1.push_back(std::make_unique<LiteralDecl>(GenerateEnumToString(typenames, enum_decl)));
1388
1389 std::vector<std::unique_ptr<Declaration>> decls2;
1390 decls2.push_back(std::make_unique<LiteralDecl>(GenerateEnumValues(enum_decl, {""})));
1391
1392 return unique_ptr<Document>{
1393 new CppHeader{vector<string>(includes.begin(), includes.end()),
1394 Append(NestInNamespaces(std::move(decls1), enum_decl.GetSplitPackage()),
1395 NestInNamespaces(std::move(decls2), {"android", "internal"}))}};
1396 }
1397
WriteHeader(const Options & options,const AidlTypenames & typenames,const AidlInterface & interface,const IoDelegate & io_delegate,ClassNames header_type)1398 bool WriteHeader(const Options& options, const AidlTypenames& typenames,
1399 const AidlInterface& interface, const IoDelegate& io_delegate,
1400 ClassNames header_type) {
1401 unique_ptr<Document> header;
1402 switch (header_type) {
1403 case ClassNames::INTERFACE:
1404 header = BuildInterfaceHeader(typenames, interface, options);
1405 header_type = ClassNames::RAW;
1406 break;
1407 case ClassNames::CLIENT:
1408 header = BuildClientHeader(typenames, interface, options);
1409 break;
1410 case ClassNames::SERVER:
1411 header = BuildServerHeader(typenames, interface, options);
1412 break;
1413 default:
1414 AIDL_FATAL(interface) << "aidl internal error";
1415 }
1416 if (!header) {
1417 AIDL_ERROR(interface) << "aidl internal error: Failed to generate header.";
1418 return false;
1419 }
1420
1421 const string header_path = options.OutputHeaderDir() + HeaderFile(interface, header_type);
1422 unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
1423 header->Write(code_writer.get());
1424
1425 const bool success = code_writer->Close();
1426 if (!success) {
1427 io_delegate.RemovePath(header_path);
1428 }
1429
1430 return success;
1431 }
1432
1433 } // namespace internals
1434
1435 using namespace internals;
1436
GenerateCppInterface(const string & output_file,const Options & options,const AidlTypenames & typenames,const AidlInterface & interface,const IoDelegate & io_delegate)1437 bool GenerateCppInterface(const string& output_file, const Options& options,
1438 const AidlTypenames& typenames, const AidlInterface& interface,
1439 const IoDelegate& io_delegate) {
1440 auto interface_src = BuildInterfaceSource(typenames, interface, options);
1441 auto client_src = BuildClientSource(typenames, interface, options);
1442 auto server_src = BuildServerSource(typenames, interface, options);
1443
1444 if (!interface_src || !client_src || !server_src) {
1445 return false;
1446 }
1447
1448 if (!WriteHeader(options, typenames, interface, io_delegate, ClassNames::INTERFACE) ||
1449 !WriteHeader(options, typenames, interface, io_delegate, ClassNames::CLIENT) ||
1450 !WriteHeader(options, typenames, interface, io_delegate, ClassNames::SERVER)) {
1451 return false;
1452 }
1453
1454 unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(output_file);
1455 interface_src->Write(writer.get());
1456 client_src->Write(writer.get());
1457 server_src->Write(writer.get());
1458
1459 const bool success = writer->Close();
1460 if (!success) {
1461 io_delegate.RemovePath(output_file);
1462 }
1463
1464 return success;
1465 }
1466
1467 template <typename ParcelableType>
GenerateCppParcelable(const std::string & output_file,const Options & options,const AidlTypenames & typenames,const ParcelableType & parcelable,const IoDelegate & io_delegate)1468 bool GenerateCppParcelable(const std::string& output_file, const Options& options,
1469 const AidlTypenames& typenames, const ParcelableType& parcelable,
1470 const IoDelegate& io_delegate) {
1471 auto header = BuildParcelHeader(typenames, parcelable, options);
1472 auto source = BuildParcelSource(typenames, parcelable, options);
1473
1474 if (!header || !source) {
1475 return false;
1476 }
1477
1478 const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
1479 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1480 header->Write(header_writer.get());
1481 if (parcelable.IsGeneric()) {
1482 // Need to write all of the source in the header file, not cpp file.
1483 source->Write(header_writer.get());
1484 }
1485 AIDL_FATAL_IF(!header_writer->Close(), header_path);
1486
1487 // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
1488 const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
1489 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1490 bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
1491 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
1492 const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
1493 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1494 bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
1495 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
1496
1497 unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
1498 if (parcelable.IsGeneric()) {
1499 // Since the type is generic, the source is written in the header file
1500 auto empty_source = unique_ptr<Document>{new CppSource{{}, {}}};
1501 empty_source->Write(source_writer.get());
1502 } else {
1503 source->Write(source_writer.get());
1504 }
1505 AIDL_FATAL_IF(!source_writer->Close(), output_file);
1506
1507 return true;
1508 }
1509
GenerateCppParcelDeclaration(const std::string & filename,const Options & options,const AidlParcelable & parcelable,const IoDelegate & io_delegate)1510 bool GenerateCppParcelDeclaration(const std::string& filename, const Options& options,
1511 const AidlParcelable& parcelable, const IoDelegate& io_delegate) {
1512 CodeWriterPtr source_writer = io_delegate.GetCodeWriter(filename);
1513 *source_writer
1514 << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
1515 AIDL_FATAL_IF(!source_writer->Close(), filename);
1516
1517 // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
1518 const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
1519 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1520 header_writer->Write("#error TODO(b/111362593) parcelables do not have headers");
1521 AIDL_FATAL_IF(!header_writer->Close(), header_path);
1522 const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
1523 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1524 bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
1525 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
1526 const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
1527 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1528 bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
1529 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
1530
1531 return true;
1532 }
1533
GenerateCppEnumDeclaration(const std::string & filename,const Options & options,const AidlTypenames & typenames,const AidlEnumDeclaration & enum_decl,const IoDelegate & io_delegate)1534 bool GenerateCppEnumDeclaration(const std::string& filename, const Options& options,
1535 const AidlTypenames& typenames,
1536 const AidlEnumDeclaration& enum_decl,
1537 const IoDelegate& io_delegate) {
1538 auto header = BuildEnumHeader(typenames, enum_decl);
1539 if (!header) return false;
1540
1541 const string header_path = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::RAW);
1542 unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
1543 header->Write(header_writer.get());
1544 AIDL_FATAL_IF(!header_writer->Close(), header_path);
1545
1546 // TODO(b/111362593): no unnecessary files just to have consistent output with interfaces
1547 CodeWriterPtr source_writer = io_delegate.GetCodeWriter(filename);
1548 *source_writer
1549 << "// This file is intentionally left blank as placeholder for enum declaration.\n";
1550 AIDL_FATAL_IF(!source_writer->Close(), filename);
1551 const string bp_header = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::CLIENT);
1552 unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
1553 bp_writer->Write("#error TODO(b/111362593) enums do not have bp classes");
1554 AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
1555 const string bn_header = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::SERVER);
1556 unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
1557 bn_writer->Write("#error TODO(b/111362593) enums do not have bn classes");
1558 AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
1559
1560 return true;
1561 }
1562
1563 // Ensures that output_file is <out_dir>/<packagename>/<typename>.cpp
ValidateOutputFilePath(const string & output_file,const Options & options,const AidlDefinedType & defined_type)1564 bool ValidateOutputFilePath(const string& output_file, const Options& options,
1565 const AidlDefinedType& defined_type) {
1566 const auto& out_dir =
1567 !options.OutputDir().empty() ? options.OutputDir() : options.OutputHeaderDir();
1568 if (output_file.empty() || !android::base::StartsWith(output_file, out_dir)) {
1569 // If output_file is not set (which happens in the unit tests) or is outside of out_dir, we can
1570 // help but accepting it, because the path is what the user has requested.
1571 return true;
1572 }
1573
1574 string canonical_name = defined_type.GetCanonicalName();
1575 std::replace(canonical_name.begin(), canonical_name.end(), '.', OS_PATH_SEPARATOR);
1576 const string expected = out_dir + canonical_name + ".cpp";
1577 if (expected != output_file) {
1578 AIDL_ERROR(defined_type) << "Output file is expected to be at " << expected << ", but is "
1579 << output_file << ".\n If this is an Android platform "
1580 << "build, consider providing the input AIDL files using a filegroup "
1581 << "with `path:\"<base>\"` so that the AIDL files are located at "
1582 << "<base>/<packagename>/<typename>.aidl.";
1583 return false;
1584 }
1585 return true;
1586 }
1587
GenerateCpp(const string & output_file,const Options & options,const AidlTypenames & typenames,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)1588 bool GenerateCpp(const string& output_file, const Options& options, const AidlTypenames& typenames,
1589 const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
1590 if (!ValidateOutputFilePath(output_file, options, defined_type)) {
1591 return false;
1592 }
1593
1594 const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
1595 if (parcelable != nullptr) {
1596 return GenerateCppParcelable(output_file, options, typenames, *parcelable, io_delegate);
1597 }
1598
1599 // should come before AsParcelable() because union is a parcelable
1600 const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
1601 if (union_decl != nullptr) {
1602 return GenerateCppParcelable(output_file, options, typenames, *union_decl, io_delegate);
1603 }
1604
1605 // unstructured parcelable
1606 const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
1607 if (parcelable_decl != nullptr) {
1608 return GenerateCppParcelDeclaration(output_file, options, *parcelable_decl, io_delegate);
1609 }
1610
1611 const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
1612 if (enum_decl != nullptr) {
1613 return GenerateCppEnumDeclaration(output_file, options, typenames, *enum_decl, io_delegate);
1614 }
1615
1616 const AidlInterface* interface = defined_type.AsInterface();
1617 if (interface != nullptr) {
1618 return GenerateCppInterface(output_file, options, typenames, *interface, io_delegate);
1619 }
1620
1621 AIDL_FATAL(defined_type) << "Unrecognized type sent for cpp generation.";
1622 return false;
1623 }
1624
1625 } // namespace cpp
1626 } // namespace aidl
1627 } // namespace android
1628