blob: 889ac86e558be699165a865b6bf0860d39234f54 [file] [log] [blame]
Andreas Huber881227d2016-08-02 14:20:21 -07001#include "AST.h"
2
3#include "Coordinator.h"
4#include "Formatter.h"
5#include "Interface.h"
6#include "Method.h"
7#include "Scope.h"
8
9#include <android-base/logging.h>
10#include <sys/stat.h>
11#include <vector>
12
13namespace android {
14
15static bool MakeParentHierarchy(const std::string &path) {
16 static const mode_t kMode = 0755;
17
18 size_t start = 1; // Ignore leading '/'
19 size_t slashPos;
20 while ((slashPos = path.find("/", start)) != std::string::npos) {
21 std::string partial = path.substr(0, slashPos);
22
23 struct stat st;
24 if (stat(partial.c_str(), &st) < 0) {
25 if (errno != ENOENT) {
26 return false;
27 }
28
29 int res = mkdir(partial.c_str(), kMode);
30 if (res < 0) {
31 return false;
32 }
33 } else if (!S_ISDIR(st.st_mode)) {
34 return false;
35 }
36
37 start = slashPos + 1;
38 }
39
40 return true;
41}
42
Andreas Huber881227d2016-08-02 14:20:21 -070043static std::string upcase(const std::string in) {
44 std::string out{in};
45
46 for (auto &ch : out) {
47 ch = toupper(ch);
48 }
49
50 return out;
51}
52
Andreas Huberb82318c2016-08-02 14:45:54 -070053status_t AST::generateCpp(const std::string &outputPath) const {
54 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070055
56 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070057 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070058 }
59
60 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070061 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070062 }
63
64 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070065 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070066 }
67
68 return err;
69}
70
Andreas Huber737080b2016-08-02 15:38:04 -070071void AST::getPackageComponents(
72 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070073 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070074}
75
76void AST::getPackageAndVersionComponents(
77 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070078 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070079}
80
Andreas Huber881227d2016-08-02 14:20:21 -070081std::string AST::makeHeaderGuard(const std::string &baseName) const {
82 std::vector<std::string> packageComponents;
83 getPackageAndVersionComponents(
84 &packageComponents, true /* cpp_compatible */);
85
86 std::string guard = "HIDL_GENERATED";
87 for (const auto &component : packageComponents) {
88 guard += "_";
89 guard += component;
90 }
91
92 guard += "_";
93 guard += baseName;
94 guard += "_H_";
95
96 return guard;
97}
98
99void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
100 std::vector<std::string> packageComponents;
101 getPackageAndVersionComponents(
102 &packageComponents, true /* cpp_compatible */);
103
104 if (enter) {
105 for (const auto &component : packageComponents) {
106 out << "namespace " << component << " {\n";
107 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700108
109 out.setNamespace(mPackage.cppNamespace());
Andreas Huber881227d2016-08-02 14:20:21 -0700110 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700111 out.setNamespace(std::string());
112
Andreas Huber881227d2016-08-02 14:20:21 -0700113 for (auto it = packageComponents.rbegin();
114 it != packageComponents.rend();
115 ++it) {
116 out << "} // namespace " << *it << "\n";
117 }
118 }
119}
120
Andreas Huberb82318c2016-08-02 14:45:54 -0700121status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700122 const std::string packagePath =
123 mCoordinator->getPackagePath(mPackage, true /* relative */);
124
Andreas Huberb82318c2016-08-02 14:45:54 -0700125 std::string path = outputPath;
126 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700127 path.append(packagePath);
128
129 std::string ifaceName;
130 bool isInterface = true;
131 if (!AST::isInterface(&ifaceName)) {
132 ifaceName = "types";
133 isInterface = false;
134 }
135 path.append(ifaceName);
136 path.append(".h");
137
138 CHECK(MakeParentHierarchy(path));
139 FILE *file = fopen(path.c_str(), "w");
140
141 if (file == NULL) {
142 return -errno;
143 }
144
145 Formatter out(file);
146
147 const std::string guard = makeHeaderGuard(ifaceName);
148
149 out << "#ifndef " << guard << "\n";
150 out << "#define " << guard << "\n\n";
151
Andreas Huber737080b2016-08-02 15:38:04 -0700152 for (const auto &item : mImportedNames) {
153 out << "#include <";
154
155 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700156 item.getPackageAndVersionComponents(
157 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700158
159 for (const auto &component : components) {
160 out << component << "/";
161 }
162
163 out << item.name()
164 << ".h>\n";
165 }
166
167 if (!mImportedNames.empty()) {
168 out << "\n";
169 }
170
Andreas Huber881227d2016-08-02 14:20:21 -0700171 out << "#include <hwbinder/HidlSupport.h>\n";
172
173 if (isInterface) {
174 out << "#include <hwbinder/IBinder.h>\n";
175 out << "#include <hwbinder/IInterface.h>\n";
176 out << "#include <hwbinder/Status.h>\n";
177 }
178
179 out << "#include <utils/NativeHandle.h>\n\n";
180
181 enterLeaveNamespace(out, true /* enter */);
182 out << "\n";
183
184 if (isInterface) {
185 out << "struct "
186 << ifaceName
187 << " : public ::android::hidl::IInterface {\n";
188
189 out.indent();
190
Andreas Huber737080b2016-08-02 15:38:04 -0700191 // cut off the leading 'I'.
192 const std::string baseName = ifaceName.substr(1);
193
194 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700195 }
196
197 status_t err = emitTypeDeclarations(out);
198
199 if (err != OK) {
200 return err;
201 }
202
203 if (isInterface) {
204 const Interface *iface = mRootScope->getInterface();
205
206 out << "enum Call {\n";
207 out.indent();
208
209 bool first = true;
210 for (const auto &method : iface->methods()) {
211 out << upcase(method->name());
212
213 if (first) {
214 out << " = ::android::hidl::IBinder::FIRST_CALL_TRANSACTION";
215 first = false;
216 }
217
218 out << ",\n";
219 }
220
221 out.unindent();
222 out << "};\n\n";
223
224 bool haveCallbacks = false;
225 for (const auto &method : iface->methods()) {
226 const bool returnsValue = !method->results().empty();
227
228 if (!returnsValue) {
229 continue;
230 }
231
232 haveCallbacks = true;
233
234 out << "using "
235 << method->name()
236 << "_cb = std::function<void("
237 << Method::GetSignature(method->results())
238 << ")>;\n";
239 }
240
241 if (haveCallbacks) {
242 out << "\n";
243 }
244
245 for (const auto &method : iface->methods()) {
246 const bool returnsValue = !method->results().empty();
247
248 out << "virtual ::android::hidl::binder::Status "
249 << method->name()
250 << "("
251 << Method::GetSignature(method->args());
252
253 if (returnsValue) {
254 if (!method->args().empty()) {
255 out << ", ";
256 }
257
258 out << method->name() << "_cb _aidl_cb = nullptr";
259 }
260
261 out << ") = 0;\n";
262 }
263 }
264
265 if (isInterface) {
266 out.unindent();
267
268 out << "};\n";
269 }
270
271 out << "\n";
272 enterLeaveNamespace(out, false /* enter */);
273
274 out << "\n#endif // " << guard << "\n";
275
276 return OK;
277}
278
279status_t AST::emitTypeDeclarations(Formatter &out) const {
280 return mRootScope->emitTypeDeclarations(out);
281}
282
Andreas Huberb82318c2016-08-02 14:45:54 -0700283status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700284 std::string ifaceName;
285 if (!AST::isInterface(&ifaceName)) {
286 // types.hal does not get a stub header.
287 return OK;
288 }
289
290 const std::string packagePath =
291 mCoordinator->getPackagePath(mPackage, true /* relative */);
292
293 // cut off the leading 'I'.
294 const std::string baseName = ifaceName.substr(1);
295
Andreas Huberb82318c2016-08-02 14:45:54 -0700296 std::string path = outputPath;
297 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700298 path.append(packagePath);
299 path.append("Bn");
300 path.append(baseName);
301 path.append(".h");
302
303 CHECK(MakeParentHierarchy(path));
304 FILE *file = fopen(path.c_str(), "w");
305
306 if (file == NULL) {
307 return -errno;
308 }
309
310 Formatter out(file);
311
312 const std::string guard = makeHeaderGuard("Bn" + baseName);
313
314 out << "#ifndef " << guard << "\n";
315 out << "#define " << guard << "\n\n";
316
317 std::vector<std::string> packageComponents;
318 getPackageAndVersionComponents(
319 &packageComponents, false /* cpp_compatible */);
320
321 out << "#include <";
322 for (const auto &component : packageComponents) {
323 out << component << "/";
324 }
325 out << ifaceName << ".h>\n\n";
326
327 enterLeaveNamespace(out, true /* enter */);
328 out << "\n";
329
330 out << "struct "
331 << "Bn"
332 << baseName
333 << " : public ::android::hidl::BnInterface<"
334 << ifaceName
335 << "> {\n";
336
337 out.indent();
338
339 out << "::android::status_t onTransact(\n";
340 out.indent();
341 out.indent();
342 out << "uint32_t _aidl_code,\n";
343 out << "const ::android::hidl::Parcel &_aidl_data,\n";
344 out << "::android::hidl::Parcel *_aidl_reply,\n";
345 out << "uint32_t _aidl_flags = 0,\n";
346 out << "TransactCallback _aidl_cb = nullptr) override;\n";
347 out.unindent();
348 out.unindent();
349
350 out.unindent();
351
352 out << "};\n\n";
353
354 enterLeaveNamespace(out, false /* enter */);
355
356 out << "\n#endif // " << guard << "\n";
357
358 return OK;
359}
360
Andreas Huberb82318c2016-08-02 14:45:54 -0700361status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700362 std::string ifaceName;
363 if (!AST::isInterface(&ifaceName)) {
364 // types.hal does not get a proxy header.
365 return OK;
366 }
367
368 const std::string packagePath =
369 mCoordinator->getPackagePath(mPackage, true /* relative */);
370
371 // cut off the leading 'I'.
372 const std::string baseName = ifaceName.substr(1);
373
Andreas Huberb82318c2016-08-02 14:45:54 -0700374 std::string path = outputPath;
375 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700376 path.append(packagePath);
377 path.append("Bp");
378 path.append(baseName);
379 path.append(".h");
380
381 CHECK(MakeParentHierarchy(path));
382 FILE *file = fopen(path.c_str(), "w");
383
384 if (file == NULL) {
385 return -errno;
386 }
387
388 Formatter out(file);
389
390 const std::string guard = makeHeaderGuard("Bp" + baseName);
391
392 out << "#ifndef " << guard << "\n";
393 out << "#define " << guard << "\n\n";
394
395 std::vector<std::string> packageComponents;
396 getPackageAndVersionComponents(
397 &packageComponents, false /* cpp_compatible */);
398
399 out << "#include <";
400 for (const auto &component : packageComponents) {
401 out << component << "/";
402 }
403 out << ifaceName << ".h>\n\n";
404
405 enterLeaveNamespace(out, true /* enter */);
406 out << "\n";
407
408 out << "struct "
409 << "Bp"
410 << baseName
411 << " : public ::android::hidl::BpInterface<"
412 << ifaceName
413 << "> {\n";
414
415 out.indent();
416
417 out << "explicit Bp"
418 << baseName
419 << "(const ::android::sp<::android::hidl::IBinder> &_aidl_impl);"
420 << "\n\n";
421
422 const Interface *iface = mRootScope->getInterface();
423
424 for (const auto &method : iface->methods()) {
425 const bool returnsValue = !method->results().empty();
426
427 out << "::android::hidl::binder::Status "
428 << method->name()
429 << "("
430 << Method::GetSignature(method->args());
431
432 if (returnsValue) {
433 if (!method->args().empty()) {
434 out << ", ";
435 }
436
437 out << method->name() << "_cb _aidl_cb";
438 }
439
440 out << ") override;\n";
441 }
442
443 out.unindent();
444
445 out << "};\n\n";
446
447 enterLeaveNamespace(out, false /* enter */);
448
449 out << "\n#endif // " << guard << "\n";
450
451 return OK;
452}
453
Andreas Huberb82318c2016-08-02 14:45:54 -0700454status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700455 const std::string packagePath =
456 mCoordinator->getPackagePath(mPackage, true /* relative */);
457
Andreas Huberb82318c2016-08-02 14:45:54 -0700458 std::string path = outputPath;
459 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700460 path.append(packagePath);
461
462 std::string ifaceName;
463 std::string baseName;
464
465 bool isInterface = true;
466 if (!AST::isInterface(&ifaceName)) {
467 baseName = "types";
468 isInterface = false;
469 } else {
470 baseName = ifaceName.substr(1); // cut off the leading 'I'.
471 }
472
473 path.append(baseName);
474
475 if (baseName != "types") {
476 path.append("All");
477 }
478
479 path.append(".cpp");
480
481 CHECK(MakeParentHierarchy(path));
482 FILE *file = fopen(path.c_str(), "w");
483
484 if (file == NULL) {
485 return -errno;
486 }
487
488 Formatter out(file);
489
490 std::vector<std::string> packageComponents;
491 getPackageAndVersionComponents(
492 &packageComponents, false /* cpp_compatible */);
493
494 std::string prefix;
495 for (const auto &component : packageComponents) {
496 prefix += component;
497 prefix += "/";
498 }
499
500 if (isInterface) {
501 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
502 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
503 } else {
504 out << "#include <" << prefix << "types.h>\n";
505 }
506
507 out << "\n";
508
509 enterLeaveNamespace(out, true /* enter */);
510 out << "\n";
511
512 status_t err = generateTypeSource(out, ifaceName);
513
514 if (err == OK && isInterface) {
515 err = generateProxySource(out, baseName);
516 }
517
518 if (err == OK && isInterface) {
519 err = generateStubSource(out, baseName);
520 }
521
522 enterLeaveNamespace(out, false /* enter */);
523
524 return err;
525}
526
527status_t AST::generateTypeSource(
528 Formatter &out, const std::string &ifaceName) const {
529 return mRootScope->emitTypeDefinitions(out, ifaceName);
530}
531
532void AST::emitCppReaderWriter(
533 Formatter &out,
534 const std::string &parcelObj,
535 bool parcelObjIsPointer,
536 const TypedVar *arg,
537 bool isReader,
538 Type::ErrorMode mode) const {
539 const Type &type = arg->type();
540
541 if (isReader) {
542 std::string extra;
543 out << type.getCppResultType(&extra)
544 << " "
545 << arg->name()
546 << extra
547 << ";\n";
548 }
549
550 type.emitReaderWriter(
551 out,
552 arg->name(),
553 parcelObj,
554 parcelObjIsPointer,
555 isReader,
556 mode);
557}
558
559status_t AST::generateProxySource(
560 Formatter &out, const std::string &baseName) const {
561 const std::string klassName = "Bp" + baseName;
562
563 out << klassName
564 << "::"
565 << klassName
566 << "(const ::android::sp<::android::hidl::IBinder> &_aidl_impl)\n";
567
568 out.indent();
569 out.indent();
570
571 out << ": BpInterface"
572 << "<I"
573 << baseName
574 << ">(_aidl_impl) {\n";
575
576 out.unindent();
577 out.unindent();
578 out << "}\n\n";
579
580 const Interface *iface = mRootScope->getInterface();
581
582 for (const auto &method : iface->methods()) {
583 const bool returnsValue = !method->results().empty();
584
585 out << "::android::hidl::binder::Status "
586 << klassName
587 << "::"
588 << method->name()
589 << "("
590 << Method::GetSignature(method->args());
591
592 if (returnsValue) {
593 if (!method->args().empty()) {
594 out << ", ";
595 }
596
597 out << method->name() << "_cb _aidl_cb";
598 }
599
600 out << ") {\n";
601
602 out.indent();
603
604 out << "::android::hidl::Parcel _aidl_data;\n";
605 out << "::android::hidl::Parcel _aidl_reply;\n";
606 out << "::android::status_t _aidl_err;\n\n";
607 out << "::android::hidl::binder::Status _aidl_status;\n";
608
609 out << "_aidl_err = _aidl_data.writeInterfaceToken("
610 "getInterfaceDescriptor());\n";
611
612 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
613
614 for (const auto &arg : method->args()) {
615 emitCppReaderWriter(
616 out,
617 "_aidl_data",
618 false /* parcelObjIsPointer */,
619 arg,
620 false /* reader */,
621 Type::ErrorMode_Goto);
622 }
623
624 out << "_aidl_err = remote()->transact(I"
625 << baseName
626 << "::"
627 << upcase(method->name())
628 << ", _aidl_data, &_aidl_reply);\n";
629
630 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
631
632 out << "_aidl_err = _aidl_status.readFromParcel(_aidl_reply);\n";
633 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
634
635 out << "if (!_aidl_status.isOk()) { return _aidl_status; }\n\n";
636
637 for (const auto &arg : method->results()) {
638 emitCppReaderWriter(
639 out,
640 "_aidl_reply",
641 false /* parcelObjIsPointer */,
642 arg,
643 true /* reader */,
644 Type::ErrorMode_Goto);
645 }
646
647 if (returnsValue) {
648 out << "if (_aidl_cb != nullptr) {\n";
649 out.indent();
650 out << "_aidl_cb(";
651
652 bool first = true;
653 for (const auto &arg : method->results()) {
654 if (!first) {
655 out << ", ";
656 }
657
658 if (arg->type().resultNeedsDeref()) {
659 out << "*";
660 }
661 out << arg->name();
662
663 first = false;
664 }
665
666 out << ");\n";
667 out.unindent();
668 out << "}\n\n";
669 }
670
671 out.unindent();
672 out << "_aidl_error:\n";
673 out.indent();
674 out << "_aidl_status.setFromStatusT(_aidl_err);\n"
675 << "return _aidl_status;\n";
676
677 out.unindent();
678 out << "}\n\n";
679 }
680
681 return OK;
682}
683
684status_t AST::generateStubSource(
685 Formatter &out, const std::string &baseName) const {
686 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
687 << baseName
688 << ", \""
689 << mPackage.string()
690 << "::I"
691 << baseName
692 << "\");\n\n";
693
694 const std::string klassName = "Bn" + baseName;
695
696 out << "::android::status_t " << klassName << "::onTransact(\n";
697
698 out.indent();
699 out.indent();
700
701 out << "uint32_t _aidl_code,\n"
702 << "const ::android::hidl::Parcel &_aidl_data,\n"
703 << "::android::hidl::Parcel *_aidl_reply,\n"
704 << "uint32_t _aidl_flags,\n"
705 << "TransactCallback _aidl_cb) {\n";
706
707 out.unindent();
708
709 out << "::android::status_t _aidl_err = ::android::OK;\n\n";
710
711 out << "switch (_aidl_code) {\n";
712 out.indent();
713
714 const Interface *iface = mRootScope->getInterface();
715
716 for (const auto &method : iface->methods()) {
717 out << "case Call::" << upcase(method->name()) << ":\n{\n";
718 out.indent();
719
720 status_t err = generateStubSourceForMethod(out, method);
721
722 if (err != OK) {
723 return err;
724 }
725
726 out.unindent();
727 out << "}\n\n";
728 }
729
730 out << "default:\n{\n";
731 out.indent();
732
733 out << "return ::android::hidl::BnInterface<I"
734 << baseName
735 << ">::onTransact(\n";
736
737 out.indent();
738 out.indent();
739
740 out << "_aidl_code, _aidl_data, _aidl_reply, "
741 << "_aidl_flags, _aidl_cb);\n";
742
743 out.unindent();
744 out.unindent();
745
746 out.unindent();
747 out << "}\n";
748
749 out.unindent();
750 out << "}\n\n";
751
752 out << "if (_aidl_err == ::android::UNEXPECTED_NULL) {\n";
753 out.indent();
754 out << "_aidl_err = ::android::hidl::binder::Status::fromExceptionCode(\n";
755 out.indent();
756 out.indent();
757 out << "::android::hidl::binder::Status::EX_NULL_POINTER)\n";
758 out.indent();
759 out.indent();
760 out << ".writeToParcel(_aidl_reply);\n";
761 out.unindent();
762 out.unindent();
763 out.unindent();
764 out.unindent();
765
766 out.unindent();
767 out << "}\n\n";
768
769 out << "return _aidl_err;\n";
770
771 out.unindent();
772 out << "}\n\n";
773
774 return OK;
775}
776
777status_t AST::generateStubSourceForMethod(
778 Formatter &out, const Method *method) const {
779 out << "if (!_aidl_data.checkInterface(this)) {\n";
780 out.indent();
781 out << "_aidl_err = ::android::BAD_TYPE;\n";
782 out << "break;\n";
783 out.unindent();
784 out << "}\n\n";
785
786 for (const auto &arg : method->args()) {
787 emitCppReaderWriter(
788 out,
789 "_aidl_data",
790 false /* parcelObjIsPointer */,
791 arg,
792 true /* reader */,
793 Type::ErrorMode_Break);
794 }
795
796 const bool returnsValue = !method->results().empty();
797
798 if (returnsValue) {
799 out << "bool _aidl_callbackCalled = false;\n\n";
800 }
801
802 out << "::android::hidl::binder::Status _aidl_status(\n";
803 out.indent();
804 out.indent();
805 out << method->name() << "(";
806
807 bool first = true;
808 for (const auto &arg : method->args()) {
809 if (!first) {
810 out << ", ";
811 }
812
813 if (arg->type().resultNeedsDeref()) {
814 out << "*";
815 }
816
817 out << arg->name();
818
819 first = false;
820 }
821
822 if (returnsValue) {
823 if (!first) {
824 out << ", ";
825 }
826
827 out << "[&](";
828
829 first = true;
830 for (const auto &arg : method->results()) {
831 if (!first) {
832 out << ", ";
833 }
834
835 out << "const auto &" << arg->name();
836
837 first = false;
838 }
839
840 out << ") {\n";
841 out.indent();
842 out << "_aidl_callbackCalled = true;\n\n";
843
844 out << "::android::hidl::binder::Status::ok()"
845 << ".writeToParcel(_aidl_reply);\n\n";
846
847 for (const auto &arg : method->results()) {
848 emitCppReaderWriter(
849 out,
850 "_aidl_reply",
851 true /* parcelObjIsPointer */,
852 arg,
853 false /* reader */,
854 Type::ErrorMode_Ignore);
855 }
856
857 out << "_aidl_cb(*_aidl_reply);\n";
858
859 out.unindent();
860 out << "}\n";
861 }
862
863 out.unindent();
864 out.unindent();
865 out << "));\n\n";
866
867 if (returnsValue) {
868 out << "if (!_aidl_callbackCalled) {\n";
869 out.indent();
870 }
871
872 out << "_aidl_err = _aidl_status.writeToParcel(_aidl_reply);\n";
873
874 if (returnsValue) {
875 out.unindent();
876 out << "}\n\n";
877 }
878
879 out << "break;\n";
880
881 return OK;
882}
883
884} // namespace android
885