blob: 3f35c38a0fd28cf94aa288b9c200246d37b7d104 [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
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700187 << " : public ";
188
189 const Interface *iface = mRootScope->getInterface();
190 const Interface *superType = iface->superType();
191
192 if (superType != NULL) {
193 out << superType->fullName();
194 } else {
195 out << "::android::hidl::IInterface";
196 }
197
198 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700199
200 out.indent();
201
Andreas Huber737080b2016-08-02 15:38:04 -0700202 // cut off the leading 'I'.
203 const std::string baseName = ifaceName.substr(1);
204
205 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700206 }
207
208 status_t err = emitTypeDeclarations(out);
209
210 if (err != OK) {
211 return err;
212 }
213
214 if (isInterface) {
215 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700216 const Interface *superType = iface->superType();
Andreas Huber881227d2016-08-02 14:20:21 -0700217
218 out << "enum Call {\n";
219 out.indent();
220
221 bool first = true;
222 for (const auto &method : iface->methods()) {
223 out << upcase(method->name());
224
225 if (first) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700226 out << " = ";
227 if (superType != NULL) {
228 out << superType->fullName()
229 << "::Call::CallCount";
230 } else {
231 out << "::android::hidl::IBinder::FIRST_CALL_TRANSACTION";
232 }
233
Andreas Huber881227d2016-08-02 14:20:21 -0700234 first = false;
235 }
236
237 out << ",\n";
238 }
239
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700240 out << "CallCount\n";
241
Andreas Huber881227d2016-08-02 14:20:21 -0700242 out.unindent();
243 out << "};\n\n";
244
245 bool haveCallbacks = false;
246 for (const auto &method : iface->methods()) {
247 const bool returnsValue = !method->results().empty();
248
249 if (!returnsValue) {
250 continue;
251 }
252
253 haveCallbacks = true;
254
255 out << "using "
256 << method->name()
257 << "_cb = std::function<void("
258 << Method::GetSignature(method->results())
259 << ")>;\n";
260 }
261
262 if (haveCallbacks) {
263 out << "\n";
264 }
265
266 for (const auto &method : iface->methods()) {
267 const bool returnsValue = !method->results().empty();
268
269 out << "virtual ::android::hidl::binder::Status "
270 << method->name()
271 << "("
272 << Method::GetSignature(method->args());
273
274 if (returnsValue) {
275 if (!method->args().empty()) {
276 out << ", ";
277 }
278
279 out << method->name() << "_cb _aidl_cb = nullptr";
280 }
281
282 out << ") = 0;\n";
283 }
284 }
285
286 if (isInterface) {
287 out.unindent();
288
289 out << "};\n";
290 }
291
292 out << "\n";
293 enterLeaveNamespace(out, false /* enter */);
294
295 out << "\n#endif // " << guard << "\n";
296
297 return OK;
298}
299
300status_t AST::emitTypeDeclarations(Formatter &out) const {
301 return mRootScope->emitTypeDeclarations(out);
302}
303
Andreas Huberb82318c2016-08-02 14:45:54 -0700304status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700305 std::string ifaceName;
306 if (!AST::isInterface(&ifaceName)) {
307 // types.hal does not get a stub header.
308 return OK;
309 }
310
311 const std::string packagePath =
312 mCoordinator->getPackagePath(mPackage, true /* relative */);
313
314 // cut off the leading 'I'.
315 const std::string baseName = ifaceName.substr(1);
316
Andreas Huberb82318c2016-08-02 14:45:54 -0700317 std::string path = outputPath;
318 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700319 path.append(packagePath);
320 path.append("Bn");
321 path.append(baseName);
322 path.append(".h");
323
324 CHECK(MakeParentHierarchy(path));
325 FILE *file = fopen(path.c_str(), "w");
326
327 if (file == NULL) {
328 return -errno;
329 }
330
331 Formatter out(file);
332
333 const std::string guard = makeHeaderGuard("Bn" + baseName);
334
335 out << "#ifndef " << guard << "\n";
336 out << "#define " << guard << "\n\n";
337
338 std::vector<std::string> packageComponents;
339 getPackageAndVersionComponents(
340 &packageComponents, false /* cpp_compatible */);
341
342 out << "#include <";
343 for (const auto &component : packageComponents) {
344 out << component << "/";
345 }
346 out << ifaceName << ".h>\n\n";
347
348 enterLeaveNamespace(out, true /* enter */);
349 out << "\n";
350
351 out << "struct "
352 << "Bn"
353 << baseName
354 << " : public ::android::hidl::BnInterface<"
355 << ifaceName
356 << "> {\n";
357
358 out.indent();
359
360 out << "::android::status_t onTransact(\n";
361 out.indent();
362 out.indent();
363 out << "uint32_t _aidl_code,\n";
364 out << "const ::android::hidl::Parcel &_aidl_data,\n";
365 out << "::android::hidl::Parcel *_aidl_reply,\n";
366 out << "uint32_t _aidl_flags = 0,\n";
367 out << "TransactCallback _aidl_cb = nullptr) override;\n";
368 out.unindent();
369 out.unindent();
370
371 out.unindent();
372
373 out << "};\n\n";
374
375 enterLeaveNamespace(out, false /* enter */);
376
377 out << "\n#endif // " << guard << "\n";
378
379 return OK;
380}
381
Andreas Huberb82318c2016-08-02 14:45:54 -0700382status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700383 std::string ifaceName;
384 if (!AST::isInterface(&ifaceName)) {
385 // types.hal does not get a proxy header.
386 return OK;
387 }
388
389 const std::string packagePath =
390 mCoordinator->getPackagePath(mPackage, true /* relative */);
391
392 // cut off the leading 'I'.
393 const std::string baseName = ifaceName.substr(1);
394
Andreas Huberb82318c2016-08-02 14:45:54 -0700395 std::string path = outputPath;
396 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700397 path.append(packagePath);
398 path.append("Bp");
399 path.append(baseName);
400 path.append(".h");
401
402 CHECK(MakeParentHierarchy(path));
403 FILE *file = fopen(path.c_str(), "w");
404
405 if (file == NULL) {
406 return -errno;
407 }
408
409 Formatter out(file);
410
411 const std::string guard = makeHeaderGuard("Bp" + baseName);
412
413 out << "#ifndef " << guard << "\n";
414 out << "#define " << guard << "\n\n";
415
416 std::vector<std::string> packageComponents;
417 getPackageAndVersionComponents(
418 &packageComponents, false /* cpp_compatible */);
419
420 out << "#include <";
421 for (const auto &component : packageComponents) {
422 out << component << "/";
423 }
424 out << ifaceName << ".h>\n\n";
425
426 enterLeaveNamespace(out, true /* enter */);
427 out << "\n";
428
429 out << "struct "
430 << "Bp"
431 << baseName
432 << " : public ::android::hidl::BpInterface<"
433 << ifaceName
434 << "> {\n";
435
436 out.indent();
437
438 out << "explicit Bp"
439 << baseName
440 << "(const ::android::sp<::android::hidl::IBinder> &_aidl_impl);"
441 << "\n\n";
442
443 const Interface *iface = mRootScope->getInterface();
444
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700445 std::vector<const Interface *> chain;
446 while (iface != NULL) {
447 chain.push_back(iface);
448 iface = iface->superType();
449 }
Andreas Huber881227d2016-08-02 14:20:21 -0700450
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700451 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
452 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700453
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700454 out << "// Methods from "
455 << superInterface->fullName()
456 << " follow.\n";
457
458 for (const auto &method : superInterface->methods()) {
459 const bool returnsValue = !method->results().empty();
460
461 out << "::android::hidl::binder::Status "
462 << method->name()
463 << "("
464 << Method::GetSignature(method->args());
465
466 if (returnsValue) {
467 if (!method->args().empty()) {
468 out << ", ";
469 }
470
471 out << method->name() << "_cb _aidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700472 }
473
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700474 out << ") override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700475 }
476
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700477 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700478 }
479
480 out.unindent();
481
482 out << "};\n\n";
483
484 enterLeaveNamespace(out, false /* enter */);
485
486 out << "\n#endif // " << guard << "\n";
487
488 return OK;
489}
490
Andreas Huberb82318c2016-08-02 14:45:54 -0700491status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700492 const std::string packagePath =
493 mCoordinator->getPackagePath(mPackage, true /* relative */);
494
Andreas Huberb82318c2016-08-02 14:45:54 -0700495 std::string path = outputPath;
496 path.append("android/hardware/");
Andreas Huber881227d2016-08-02 14:20:21 -0700497 path.append(packagePath);
498
499 std::string ifaceName;
500 std::string baseName;
501
502 bool isInterface = true;
503 if (!AST::isInterface(&ifaceName)) {
504 baseName = "types";
505 isInterface = false;
506 } else {
507 baseName = ifaceName.substr(1); // cut off the leading 'I'.
508 }
509
510 path.append(baseName);
511
512 if (baseName != "types") {
513 path.append("All");
514 }
515
516 path.append(".cpp");
517
518 CHECK(MakeParentHierarchy(path));
519 FILE *file = fopen(path.c_str(), "w");
520
521 if (file == NULL) {
522 return -errno;
523 }
524
525 Formatter out(file);
526
527 std::vector<std::string> packageComponents;
528 getPackageAndVersionComponents(
529 &packageComponents, false /* cpp_compatible */);
530
531 std::string prefix;
532 for (const auto &component : packageComponents) {
533 prefix += component;
534 prefix += "/";
535 }
536
537 if (isInterface) {
538 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
539 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
540 } else {
541 out << "#include <" << prefix << "types.h>\n";
542 }
543
544 out << "\n";
545
546 enterLeaveNamespace(out, true /* enter */);
547 out << "\n";
548
549 status_t err = generateTypeSource(out, ifaceName);
550
551 if (err == OK && isInterface) {
552 err = generateProxySource(out, baseName);
553 }
554
555 if (err == OK && isInterface) {
556 err = generateStubSource(out, baseName);
557 }
558
559 enterLeaveNamespace(out, false /* enter */);
560
561 return err;
562}
563
564status_t AST::generateTypeSource(
565 Formatter &out, const std::string &ifaceName) const {
566 return mRootScope->emitTypeDefinitions(out, ifaceName);
567}
568
569void AST::emitCppReaderWriter(
570 Formatter &out,
571 const std::string &parcelObj,
572 bool parcelObjIsPointer,
573 const TypedVar *arg,
574 bool isReader,
575 Type::ErrorMode mode) const {
576 const Type &type = arg->type();
577
578 if (isReader) {
579 std::string extra;
580 out << type.getCppResultType(&extra)
581 << " "
582 << arg->name()
583 << extra
584 << ";\n";
585 }
586
587 type.emitReaderWriter(
588 out,
589 arg->name(),
590 parcelObj,
591 parcelObjIsPointer,
592 isReader,
593 mode);
594}
595
596status_t AST::generateProxySource(
597 Formatter &out, const std::string &baseName) const {
598 const std::string klassName = "Bp" + baseName;
599
600 out << klassName
601 << "::"
602 << klassName
603 << "(const ::android::sp<::android::hidl::IBinder> &_aidl_impl)\n";
604
605 out.indent();
606 out.indent();
607
608 out << ": BpInterface"
609 << "<I"
610 << baseName
611 << ">(_aidl_impl) {\n";
612
613 out.unindent();
614 out.unindent();
615 out << "}\n\n";
616
617 const Interface *iface = mRootScope->getInterface();
618
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700619 std::vector<const Interface *> chain;
620 while (iface != NULL) {
621 chain.push_back(iface);
622 iface = iface->superType();
623 }
Andreas Huber881227d2016-08-02 14:20:21 -0700624
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700625 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
626 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700627
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700628 for (const auto &method : superInterface->methods()) {
629 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700630
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700631 out << "::android::hidl::binder::Status "
632 << klassName
633 << "::"
634 << method->name()
635 << "("
636 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700637
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700638 if (returnsValue) {
639 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700640 out << ", ";
641 }
642
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700643 out << method->name() << "_cb _aidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700644 }
645
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700646 out << ") {\n";
647
648 out.indent();
649
650 out << "::android::hidl::Parcel _aidl_data;\n";
651 out << "::android::hidl::Parcel _aidl_reply;\n";
652 out << "::android::status_t _aidl_err;\n\n";
653 out << "::android::hidl::binder::Status _aidl_status;\n";
654
655 out << "_aidl_err = _aidl_data.writeInterfaceToken("
656 << superInterface->fullName()
657 << "::getInterfaceDescriptor());\n";
658
659 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
660
661 for (const auto &arg : method->args()) {
662 emitCppReaderWriter(
663 out,
664 "_aidl_data",
665 false /* parcelObjIsPointer */,
666 arg,
667 false /* reader */,
668 Type::ErrorMode_Goto);
669 }
670
671 out << "_aidl_err = remote()->transact(I"
672 << baseName
673 << "::"
674 << upcase(method->name())
675 << ", _aidl_data, &_aidl_reply);\n";
676
677 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
678
679 out << "_aidl_err = _aidl_status.readFromParcel(_aidl_reply);\n";
680 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
681
682 out << "if (!_aidl_status.isOk()) { return _aidl_status; }\n\n";
683
684 for (const auto &arg : method->results()) {
685 emitCppReaderWriter(
686 out,
687 "_aidl_reply",
688 false /* parcelObjIsPointer */,
689 arg,
690 true /* reader */,
691 Type::ErrorMode_Goto);
692 }
693
694 if (returnsValue) {
695 out << "if (_aidl_cb != nullptr) {\n";
696 out.indent();
697 out << "_aidl_cb(";
698
699 bool first = true;
700 for (const auto &arg : method->results()) {
701 if (!first) {
702 out << ", ";
703 }
704
705 if (arg->type().resultNeedsDeref()) {
706 out << "*";
707 }
708 out << arg->name();
709
710 first = false;
711 }
712
713 out << ");\n";
714 out.unindent();
715 out << "}\n\n";
716 }
717
718 out.unindent();
719 out << "_aidl_error:\n";
720 out.indent();
721 out << "_aidl_status.setFromStatusT(_aidl_err);\n"
722 << "return _aidl_status;\n";
723
Andreas Huber881227d2016-08-02 14:20:21 -0700724 out.unindent();
725 out << "}\n\n";
726 }
Andreas Huber881227d2016-08-02 14:20:21 -0700727 }
728
729 return OK;
730}
731
732status_t AST::generateStubSource(
733 Formatter &out, const std::string &baseName) const {
734 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
735 << baseName
736 << ", \""
737 << mPackage.string()
738 << "::I"
739 << baseName
740 << "\");\n\n";
741
742 const std::string klassName = "Bn" + baseName;
743
744 out << "::android::status_t " << klassName << "::onTransact(\n";
745
746 out.indent();
747 out.indent();
748
749 out << "uint32_t _aidl_code,\n"
750 << "const ::android::hidl::Parcel &_aidl_data,\n"
751 << "::android::hidl::Parcel *_aidl_reply,\n"
752 << "uint32_t _aidl_flags,\n"
753 << "TransactCallback _aidl_cb) {\n";
754
755 out.unindent();
756
757 out << "::android::status_t _aidl_err = ::android::OK;\n\n";
758
759 out << "switch (_aidl_code) {\n";
760 out.indent();
761
762 const Interface *iface = mRootScope->getInterface();
763
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700764 std::vector<const Interface *> chain;
765 while (iface != NULL) {
766 chain.push_back(iface);
767 iface = iface->superType();
768 }
Andreas Huber881227d2016-08-02 14:20:21 -0700769
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700770 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
771 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700772
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700773 for (const auto &method : superInterface->methods()) {
774 out << "case "
775 << superInterface->fullName()
776 << "::Call::"
777 << upcase(method->name())
778 << ":\n{\n";
779
780 out.indent();
781
782 status_t err =
783 generateStubSourceForMethod(out, superInterface, method);
784
785 if (err != OK) {
786 return err;
787 }
788
789 out.unindent();
790 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700791 }
Andreas Huber881227d2016-08-02 14:20:21 -0700792 }
793
794 out << "default:\n{\n";
795 out.indent();
796
797 out << "return ::android::hidl::BnInterface<I"
798 << baseName
799 << ">::onTransact(\n";
800
801 out.indent();
802 out.indent();
803
804 out << "_aidl_code, _aidl_data, _aidl_reply, "
805 << "_aidl_flags, _aidl_cb);\n";
806
807 out.unindent();
808 out.unindent();
809
810 out.unindent();
811 out << "}\n";
812
813 out.unindent();
814 out << "}\n\n";
815
816 out << "if (_aidl_err == ::android::UNEXPECTED_NULL) {\n";
817 out.indent();
818 out << "_aidl_err = ::android::hidl::binder::Status::fromExceptionCode(\n";
819 out.indent();
820 out.indent();
821 out << "::android::hidl::binder::Status::EX_NULL_POINTER)\n";
822 out.indent();
823 out.indent();
824 out << ".writeToParcel(_aidl_reply);\n";
825 out.unindent();
826 out.unindent();
827 out.unindent();
828 out.unindent();
829
830 out.unindent();
831 out << "}\n\n";
832
833 out << "return _aidl_err;\n";
834
835 out.unindent();
836 out << "}\n\n";
837
838 return OK;
839}
840
841status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700842 Formatter &out, const Interface *iface, const Method *method) const {
843 out << "if (!_aidl_data.enforceInterface("
844 << iface->fullName()
845 << "::getInterfaceDescriptor())) {\n";
846
Andreas Huber881227d2016-08-02 14:20:21 -0700847 out.indent();
848 out << "_aidl_err = ::android::BAD_TYPE;\n";
849 out << "break;\n";
850 out.unindent();
851 out << "}\n\n";
852
853 for (const auto &arg : method->args()) {
854 emitCppReaderWriter(
855 out,
856 "_aidl_data",
857 false /* parcelObjIsPointer */,
858 arg,
859 true /* reader */,
860 Type::ErrorMode_Break);
861 }
862
863 const bool returnsValue = !method->results().empty();
864
865 if (returnsValue) {
866 out << "bool _aidl_callbackCalled = false;\n\n";
867 }
868
869 out << "::android::hidl::binder::Status _aidl_status(\n";
870 out.indent();
871 out.indent();
872 out << method->name() << "(";
873
874 bool first = true;
875 for (const auto &arg : method->args()) {
876 if (!first) {
877 out << ", ";
878 }
879
880 if (arg->type().resultNeedsDeref()) {
881 out << "*";
882 }
883
884 out << arg->name();
885
886 first = false;
887 }
888
889 if (returnsValue) {
890 if (!first) {
891 out << ", ";
892 }
893
894 out << "[&](";
895
896 first = true;
897 for (const auto &arg : method->results()) {
898 if (!first) {
899 out << ", ";
900 }
901
902 out << "const auto &" << arg->name();
903
904 first = false;
905 }
906
907 out << ") {\n";
908 out.indent();
909 out << "_aidl_callbackCalled = true;\n\n";
910
911 out << "::android::hidl::binder::Status::ok()"
912 << ".writeToParcel(_aidl_reply);\n\n";
913
914 for (const auto &arg : method->results()) {
915 emitCppReaderWriter(
916 out,
917 "_aidl_reply",
918 true /* parcelObjIsPointer */,
919 arg,
920 false /* reader */,
921 Type::ErrorMode_Ignore);
922 }
923
924 out << "_aidl_cb(*_aidl_reply);\n";
925
926 out.unindent();
927 out << "}\n";
928 }
929
930 out.unindent();
931 out.unindent();
932 out << "));\n\n";
933
934 if (returnsValue) {
935 out << "if (!_aidl_callbackCalled) {\n";
936 out.indent();
937 }
938
939 out << "_aidl_err = _aidl_status.writeToParcel(_aidl_reply);\n";
940
941 if (returnsValue) {
942 out.unindent();
943 out << "}\n\n";
944 }
945
946 out << "break;\n";
947
948 return OK;
949}
950
951} // namespace android
952