blob: f259258733366deb7ba0d7f43b2d3d808e98e767 [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
Andreas Huberdca261f2016-08-04 13:47:51 -07009#include <algorithm>
Andreas Huber881227d2016-08-02 14:20:21 -070010#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070011#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070012#include <sys/stat.h>
13#include <vector>
14
15namespace android {
16
17static bool MakeParentHierarchy(const std::string &path) {
18 static const mode_t kMode = 0755;
19
20 size_t start = 1; // Ignore leading '/'
21 size_t slashPos;
22 while ((slashPos = path.find("/", start)) != std::string::npos) {
23 std::string partial = path.substr(0, slashPos);
24
25 struct stat st;
26 if (stat(partial.c_str(), &st) < 0) {
27 if (errno != ENOENT) {
28 return false;
29 }
30
31 int res = mkdir(partial.c_str(), kMode);
32 if (res < 0) {
33 return false;
34 }
35 } else if (!S_ISDIR(st.st_mode)) {
36 return false;
37 }
38
39 start = slashPos + 1;
40 }
41
42 return true;
43}
44
Andreas Huber881227d2016-08-02 14:20:21 -070045static std::string upcase(const std::string in) {
46 std::string out{in};
47
48 for (auto &ch : out) {
49 ch = toupper(ch);
50 }
51
52 return out;
53}
54
Andreas Huberb82318c2016-08-02 14:45:54 -070055status_t AST::generateCpp(const std::string &outputPath) const {
56 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070057
58 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070059 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070060 }
61
62 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070063 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070064 }
65
66 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070067 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070068 }
69
70 return err;
71}
72
Andreas Huber737080b2016-08-02 15:38:04 -070073void AST::getPackageComponents(
74 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070075 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070076}
77
78void AST::getPackageAndVersionComponents(
79 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070080 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070081}
82
Andreas Huber881227d2016-08-02 14:20:21 -070083std::string AST::makeHeaderGuard(const std::string &baseName) const {
84 std::vector<std::string> packageComponents;
85 getPackageAndVersionComponents(
86 &packageComponents, true /* cpp_compatible */);
87
88 std::string guard = "HIDL_GENERATED";
89 for (const auto &component : packageComponents) {
90 guard += "_";
91 guard += component;
92 }
93
94 guard += "_";
95 guard += baseName;
96 guard += "_H_";
97
98 return guard;
99}
100
101void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
102 std::vector<std::string> packageComponents;
103 getPackageAndVersionComponents(
104 &packageComponents, true /* cpp_compatible */);
105
106 if (enter) {
107 for (const auto &component : packageComponents) {
108 out << "namespace " << component << " {\n";
109 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700110
111 out.setNamespace(mPackage.cppNamespace());
Andreas Huber881227d2016-08-02 14:20:21 -0700112 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700113 out.setNamespace(std::string());
114
Andreas Huber881227d2016-08-02 14:20:21 -0700115 for (auto it = packageComponents.rbegin();
116 it != packageComponents.rend();
117 ++it) {
118 out << "} // namespace " << *it << "\n";
119 }
120 }
121}
122
Andreas Huberdca261f2016-08-04 13:47:51 -0700123// Given an FQName of "android.hardware.nfc@1.0::INfc", return
124// "android/hardware/".
125static std::string ConvertPackageRootToPath(
126 const Coordinator *coordinator, const FQName &fqName) {
127 std::string packageRoot = coordinator->getPackageRoot(fqName);
128
129 if (*(packageRoot.end()--) != '.') {
130 packageRoot += '.';
131 }
132
133 std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
134
135 return packageRoot; // now converted to a path
136}
137
Andreas Huberb82318c2016-08-02 14:45:54 -0700138status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700139
Andreas Huberb82318c2016-08-02 14:45:54 -0700140 std::string path = outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -0700141 path.append(ConvertPackageRootToPath(mCoordinator, mPackage));
142 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700143
144 std::string ifaceName;
145 bool isInterface = true;
146 if (!AST::isInterface(&ifaceName)) {
147 ifaceName = "types";
148 isInterface = false;
149 }
150 path.append(ifaceName);
151 path.append(".h");
152
153 CHECK(MakeParentHierarchy(path));
154 FILE *file = fopen(path.c_str(), "w");
155
156 if (file == NULL) {
157 return -errno;
158 }
159
160 Formatter out(file);
161
162 const std::string guard = makeHeaderGuard(ifaceName);
163
164 out << "#ifndef " << guard << "\n";
165 out << "#define " << guard << "\n\n";
166
Andreas Huber737080b2016-08-02 15:38:04 -0700167 for (const auto &item : mImportedNames) {
168 out << "#include <";
169
170 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700171 item.getPackageAndVersionComponents(
172 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700173
174 for (const auto &component : components) {
175 out << component << "/";
176 }
177
178 out << item.name()
179 << ".h>\n";
180 }
181
182 if (!mImportedNames.empty()) {
183 out << "\n";
184 }
185
Andreas Huber881227d2016-08-02 14:20:21 -0700186 out << "#include <hwbinder/HidlSupport.h>\n";
187
188 if (isInterface) {
189 out << "#include <hwbinder/IBinder.h>\n";
190 out << "#include <hwbinder/IInterface.h>\n";
191 out << "#include <hwbinder/Status.h>\n";
192 }
193
194 out << "#include <utils/NativeHandle.h>\n\n";
195
196 enterLeaveNamespace(out, true /* enter */);
197 out << "\n";
198
199 if (isInterface) {
200 out << "struct "
201 << ifaceName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700202 << " : public ";
203
204 const Interface *iface = mRootScope->getInterface();
205 const Interface *superType = iface->superType();
206
207 if (superType != NULL) {
208 out << superType->fullName();
209 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700210 out << "::android::hardware::IInterface";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700211 }
212
213 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700214
215 out.indent();
216
Andreas Huber737080b2016-08-02 15:38:04 -0700217 // cut off the leading 'I'.
218 const std::string baseName = ifaceName.substr(1);
219
220 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700221 }
222
223 status_t err = emitTypeDeclarations(out);
224
225 if (err != OK) {
226 return err;
227 }
228
229 if (isInterface) {
230 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700231 const Interface *superType = iface->superType();
Andreas Huber881227d2016-08-02 14:20:21 -0700232
233 out << "enum Call {\n";
234 out.indent();
235
236 bool first = true;
237 for (const auto &method : iface->methods()) {
238 out << upcase(method->name());
239
240 if (first) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700241 out << " = ";
242 if (superType != NULL) {
243 out << superType->fullName()
244 << "::Call::CallCount";
245 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700246 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700247 }
248
Andreas Huber881227d2016-08-02 14:20:21 -0700249 first = false;
250 }
251
252 out << ",\n";
253 }
254
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700255 out << "CallCount\n";
256
Andreas Huber881227d2016-08-02 14:20:21 -0700257 out.unindent();
258 out << "};\n\n";
259
260 bool haveCallbacks = false;
261 for (const auto &method : iface->methods()) {
262 const bool returnsValue = !method->results().empty();
263
264 if (!returnsValue) {
265 continue;
266 }
267
268 haveCallbacks = true;
269
270 out << "using "
271 << method->name()
272 << "_cb = std::function<void("
273 << Method::GetSignature(method->results())
274 << ")>;\n";
275 }
276
277 if (haveCallbacks) {
278 out << "\n";
279 }
280
281 for (const auto &method : iface->methods()) {
282 const bool returnsValue = !method->results().empty();
283
Andreas Huber8a82ff72016-08-04 10:29:39 -0700284 out << "virtual ::android::hardware::Status "
Andreas Huber881227d2016-08-02 14:20:21 -0700285 << method->name()
286 << "("
287 << Method::GetSignature(method->args());
288
289 if (returnsValue) {
290 if (!method->args().empty()) {
291 out << ", ";
292 }
293
294 out << method->name() << "_cb _aidl_cb = nullptr";
295 }
296
297 out << ") = 0;\n";
298 }
299 }
300
301 if (isInterface) {
302 out.unindent();
303
304 out << "};\n";
305 }
306
307 out << "\n";
308 enterLeaveNamespace(out, false /* enter */);
309
310 out << "\n#endif // " << guard << "\n";
311
312 return OK;
313}
314
315status_t AST::emitTypeDeclarations(Formatter &out) const {
316 return mRootScope->emitTypeDeclarations(out);
317}
318
Andreas Huberb82318c2016-08-02 14:45:54 -0700319status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700320 std::string ifaceName;
321 if (!AST::isInterface(&ifaceName)) {
322 // types.hal does not get a stub header.
323 return OK;
324 }
325
Andreas Huber881227d2016-08-02 14:20:21 -0700326 // cut off the leading 'I'.
327 const std::string baseName = ifaceName.substr(1);
328
Andreas Huberb82318c2016-08-02 14:45:54 -0700329 std::string path = outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -0700330 path.append(ConvertPackageRootToPath(mCoordinator, mPackage));
331 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700332 path.append("Bn");
333 path.append(baseName);
334 path.append(".h");
335
336 CHECK(MakeParentHierarchy(path));
337 FILE *file = fopen(path.c_str(), "w");
338
339 if (file == NULL) {
340 return -errno;
341 }
342
343 Formatter out(file);
344
345 const std::string guard = makeHeaderGuard("Bn" + baseName);
346
347 out << "#ifndef " << guard << "\n";
348 out << "#define " << guard << "\n\n";
349
350 std::vector<std::string> packageComponents;
351 getPackageAndVersionComponents(
352 &packageComponents, false /* cpp_compatible */);
353
354 out << "#include <";
355 for (const auto &component : packageComponents) {
356 out << component << "/";
357 }
358 out << ifaceName << ".h>\n\n";
359
360 enterLeaveNamespace(out, true /* enter */);
361 out << "\n";
362
363 out << "struct "
364 << "Bn"
365 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700366 << " : public ::android::hardware::BnInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700367 << ifaceName
368 << "> {\n";
369
370 out.indent();
371
372 out << "::android::status_t onTransact(\n";
373 out.indent();
374 out.indent();
375 out << "uint32_t _aidl_code,\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700376 out << "const ::android::hardware::Parcel &_aidl_data,\n";
377 out << "::android::hardware::Parcel *_aidl_reply,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700378 out << "uint32_t _aidl_flags = 0,\n";
379 out << "TransactCallback _aidl_cb = nullptr) override;\n";
380 out.unindent();
381 out.unindent();
382
383 out.unindent();
384
385 out << "};\n\n";
386
387 enterLeaveNamespace(out, false /* enter */);
388
389 out << "\n#endif // " << guard << "\n";
390
391 return OK;
392}
393
Andreas Huberb82318c2016-08-02 14:45:54 -0700394status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700395 std::string ifaceName;
396 if (!AST::isInterface(&ifaceName)) {
397 // types.hal does not get a proxy header.
398 return OK;
399 }
400
Andreas Huber881227d2016-08-02 14:20:21 -0700401 // cut off the leading 'I'.
402 const std::string baseName = ifaceName.substr(1);
403
Andreas Huberb82318c2016-08-02 14:45:54 -0700404 std::string path = outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -0700405 path.append(ConvertPackageRootToPath(mCoordinator, mPackage));
406 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700407 path.append("Bp");
408 path.append(baseName);
409 path.append(".h");
410
411 CHECK(MakeParentHierarchy(path));
412 FILE *file = fopen(path.c_str(), "w");
413
414 if (file == NULL) {
415 return -errno;
416 }
417
418 Formatter out(file);
419
420 const std::string guard = makeHeaderGuard("Bp" + baseName);
421
422 out << "#ifndef " << guard << "\n";
423 out << "#define " << guard << "\n\n";
424
425 std::vector<std::string> packageComponents;
426 getPackageAndVersionComponents(
427 &packageComponents, false /* cpp_compatible */);
428
429 out << "#include <";
430 for (const auto &component : packageComponents) {
431 out << component << "/";
432 }
433 out << ifaceName << ".h>\n\n";
434
435 enterLeaveNamespace(out, true /* enter */);
436 out << "\n";
437
438 out << "struct "
439 << "Bp"
440 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700441 << " : public ::android::hardware::BpInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700442 << ifaceName
443 << "> {\n";
444
445 out.indent();
446
447 out << "explicit Bp"
448 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700449 << "(const ::android::sp<::android::hardware::IBinder> &_aidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700450 << "\n\n";
451
452 const Interface *iface = mRootScope->getInterface();
453
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700454 std::vector<const Interface *> chain;
455 while (iface != NULL) {
456 chain.push_back(iface);
457 iface = iface->superType();
458 }
Andreas Huber881227d2016-08-02 14:20:21 -0700459
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700460 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
461 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700462
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700463 out << "// Methods from "
464 << superInterface->fullName()
465 << " follow.\n";
466
467 for (const auto &method : superInterface->methods()) {
468 const bool returnsValue = !method->results().empty();
469
Andreas Huber8a82ff72016-08-04 10:29:39 -0700470 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700471 << method->name()
472 << "("
473 << Method::GetSignature(method->args());
474
475 if (returnsValue) {
476 if (!method->args().empty()) {
477 out << ", ";
478 }
479
480 out << method->name() << "_cb _aidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700481 }
482
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700483 out << ") override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700484 }
485
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700486 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700487 }
488
489 out.unindent();
490
491 out << "};\n\n";
492
493 enterLeaveNamespace(out, false /* enter */);
494
495 out << "\n#endif // " << guard << "\n";
496
497 return OK;
498}
499
Andreas Huberb82318c2016-08-02 14:45:54 -0700500status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700501
Andreas Huberb82318c2016-08-02 14:45:54 -0700502 std::string path = outputPath;
Andreas Huberdca261f2016-08-04 13:47:51 -0700503 path.append(ConvertPackageRootToPath(mCoordinator, mPackage));
504 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700505
506 std::string ifaceName;
507 std::string baseName;
508
509 bool isInterface = true;
510 if (!AST::isInterface(&ifaceName)) {
511 baseName = "types";
512 isInterface = false;
513 } else {
514 baseName = ifaceName.substr(1); // cut off the leading 'I'.
515 }
516
517 path.append(baseName);
518
519 if (baseName != "types") {
520 path.append("All");
521 }
522
523 path.append(".cpp");
524
525 CHECK(MakeParentHierarchy(path));
526 FILE *file = fopen(path.c_str(), "w");
527
528 if (file == NULL) {
529 return -errno;
530 }
531
532 Formatter out(file);
533
534 std::vector<std::string> packageComponents;
535 getPackageAndVersionComponents(
536 &packageComponents, false /* cpp_compatible */);
537
538 std::string prefix;
539 for (const auto &component : packageComponents) {
540 prefix += component;
541 prefix += "/";
542 }
543
544 if (isInterface) {
545 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
546 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
547 } else {
548 out << "#include <" << prefix << "types.h>\n";
549 }
550
551 out << "\n";
552
553 enterLeaveNamespace(out, true /* enter */);
554 out << "\n";
555
556 status_t err = generateTypeSource(out, ifaceName);
557
558 if (err == OK && isInterface) {
559 err = generateProxySource(out, baseName);
560 }
561
562 if (err == OK && isInterface) {
563 err = generateStubSource(out, baseName);
564 }
565
566 enterLeaveNamespace(out, false /* enter */);
567
568 return err;
569}
570
571status_t AST::generateTypeSource(
572 Formatter &out, const std::string &ifaceName) const {
573 return mRootScope->emitTypeDefinitions(out, ifaceName);
574}
575
576void AST::emitCppReaderWriter(
577 Formatter &out,
578 const std::string &parcelObj,
579 bool parcelObjIsPointer,
580 const TypedVar *arg,
581 bool isReader,
582 Type::ErrorMode mode) const {
583 const Type &type = arg->type();
584
585 if (isReader) {
586 std::string extra;
587 out << type.getCppResultType(&extra)
588 << " "
589 << arg->name()
590 << extra
591 << ";\n";
592 }
593
594 type.emitReaderWriter(
595 out,
596 arg->name(),
597 parcelObj,
598 parcelObjIsPointer,
599 isReader,
600 mode);
601}
602
603status_t AST::generateProxySource(
604 Formatter &out, const std::string &baseName) const {
605 const std::string klassName = "Bp" + baseName;
606
607 out << klassName
608 << "::"
609 << klassName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700610 << "(const ::android::sp<::android::hardware::IBinder> &_aidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700611
612 out.indent();
613 out.indent();
614
615 out << ": BpInterface"
616 << "<I"
617 << baseName
618 << ">(_aidl_impl) {\n";
619
620 out.unindent();
621 out.unindent();
622 out << "}\n\n";
623
624 const Interface *iface = mRootScope->getInterface();
625
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700626 std::vector<const Interface *> chain;
627 while (iface != NULL) {
628 chain.push_back(iface);
629 iface = iface->superType();
630 }
Andreas Huber881227d2016-08-02 14:20:21 -0700631
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700632 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
633 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700634
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700635 for (const auto &method : superInterface->methods()) {
636 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700637
Andreas Huber8a82ff72016-08-04 10:29:39 -0700638 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700639 << klassName
640 << "::"
641 << method->name()
642 << "("
643 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700644
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700645 if (returnsValue) {
646 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700647 out << ", ";
648 }
649
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700650 out << method->name() << "_cb _aidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700651 }
652
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700653 out << ") {\n";
654
655 out.indent();
656
Andreas Huber8a82ff72016-08-04 10:29:39 -0700657 out << "::android::hardware::Parcel _aidl_data;\n";
658 out << "::android::hardware::Parcel _aidl_reply;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700659 out << "::android::status_t _aidl_err;\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700660 out << "::android::hardware::Status _aidl_status;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700661
662 out << "_aidl_err = _aidl_data.writeInterfaceToken("
663 << superInterface->fullName()
664 << "::getInterfaceDescriptor());\n";
665
666 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
667
668 for (const auto &arg : method->args()) {
669 emitCppReaderWriter(
670 out,
671 "_aidl_data",
672 false /* parcelObjIsPointer */,
673 arg,
674 false /* reader */,
675 Type::ErrorMode_Goto);
676 }
677
678 out << "_aidl_err = remote()->transact(I"
679 << baseName
680 << "::"
681 << upcase(method->name())
682 << ", _aidl_data, &_aidl_reply);\n";
683
684 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
685
686 out << "_aidl_err = _aidl_status.readFromParcel(_aidl_reply);\n";
687 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
688
689 out << "if (!_aidl_status.isOk()) { return _aidl_status; }\n\n";
690
691 for (const auto &arg : method->results()) {
692 emitCppReaderWriter(
693 out,
694 "_aidl_reply",
695 false /* parcelObjIsPointer */,
696 arg,
697 true /* reader */,
698 Type::ErrorMode_Goto);
699 }
700
701 if (returnsValue) {
702 out << "if (_aidl_cb != nullptr) {\n";
703 out.indent();
704 out << "_aidl_cb(";
705
706 bool first = true;
707 for (const auto &arg : method->results()) {
708 if (!first) {
709 out << ", ";
710 }
711
712 if (arg->type().resultNeedsDeref()) {
713 out << "*";
714 }
715 out << arg->name();
716
717 first = false;
718 }
719
720 out << ");\n";
721 out.unindent();
722 out << "}\n\n";
723 }
724
725 out.unindent();
726 out << "_aidl_error:\n";
727 out.indent();
728 out << "_aidl_status.setFromStatusT(_aidl_err);\n"
729 << "return _aidl_status;\n";
730
Andreas Huber881227d2016-08-02 14:20:21 -0700731 out.unindent();
732 out << "}\n\n";
733 }
Andreas Huber881227d2016-08-02 14:20:21 -0700734 }
735
736 return OK;
737}
738
739status_t AST::generateStubSource(
740 Formatter &out, const std::string &baseName) const {
741 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
742 << baseName
743 << ", \""
744 << mPackage.string()
745 << "::I"
746 << baseName
747 << "\");\n\n";
748
749 const std::string klassName = "Bn" + baseName;
750
751 out << "::android::status_t " << klassName << "::onTransact(\n";
752
753 out.indent();
754 out.indent();
755
756 out << "uint32_t _aidl_code,\n"
Andreas Huber8a82ff72016-08-04 10:29:39 -0700757 << "const ::android::hardware::Parcel &_aidl_data,\n"
758 << "::android::hardware::Parcel *_aidl_reply,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700759 << "uint32_t _aidl_flags,\n"
760 << "TransactCallback _aidl_cb) {\n";
761
762 out.unindent();
763
764 out << "::android::status_t _aidl_err = ::android::OK;\n\n";
765
766 out << "switch (_aidl_code) {\n";
767 out.indent();
768
769 const Interface *iface = mRootScope->getInterface();
770
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700771 std::vector<const Interface *> chain;
772 while (iface != NULL) {
773 chain.push_back(iface);
774 iface = iface->superType();
775 }
Andreas Huber881227d2016-08-02 14:20:21 -0700776
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700777 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
778 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700779
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700780 for (const auto &method : superInterface->methods()) {
781 out << "case "
782 << superInterface->fullName()
783 << "::Call::"
784 << upcase(method->name())
785 << ":\n{\n";
786
787 out.indent();
788
789 status_t err =
790 generateStubSourceForMethod(out, superInterface, method);
791
792 if (err != OK) {
793 return err;
794 }
795
796 out.unindent();
797 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700798 }
Andreas Huber881227d2016-08-02 14:20:21 -0700799 }
800
801 out << "default:\n{\n";
802 out.indent();
803
Andreas Huber8a82ff72016-08-04 10:29:39 -0700804 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700805 << baseName
806 << ">::onTransact(\n";
807
808 out.indent();
809 out.indent();
810
811 out << "_aidl_code, _aidl_data, _aidl_reply, "
812 << "_aidl_flags, _aidl_cb);\n";
813
814 out.unindent();
815 out.unindent();
816
817 out.unindent();
818 out << "}\n";
819
820 out.unindent();
821 out << "}\n\n";
822
823 out << "if (_aidl_err == ::android::UNEXPECTED_NULL) {\n";
824 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700825 out << "_aidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700826 out.indent();
827 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700828 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700829 out.indent();
830 out.indent();
831 out << ".writeToParcel(_aidl_reply);\n";
832 out.unindent();
833 out.unindent();
834 out.unindent();
835 out.unindent();
836
837 out.unindent();
838 out << "}\n\n";
839
840 out << "return _aidl_err;\n";
841
842 out.unindent();
843 out << "}\n\n";
844
845 return OK;
846}
847
848status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700849 Formatter &out, const Interface *iface, const Method *method) const {
850 out << "if (!_aidl_data.enforceInterface("
851 << iface->fullName()
852 << "::getInterfaceDescriptor())) {\n";
853
Andreas Huber881227d2016-08-02 14:20:21 -0700854 out.indent();
855 out << "_aidl_err = ::android::BAD_TYPE;\n";
856 out << "break;\n";
857 out.unindent();
858 out << "}\n\n";
859
860 for (const auto &arg : method->args()) {
861 emitCppReaderWriter(
862 out,
863 "_aidl_data",
864 false /* parcelObjIsPointer */,
865 arg,
866 true /* reader */,
867 Type::ErrorMode_Break);
868 }
869
870 const bool returnsValue = !method->results().empty();
871
872 if (returnsValue) {
873 out << "bool _aidl_callbackCalled = false;\n\n";
874 }
875
Andreas Huber8a82ff72016-08-04 10:29:39 -0700876 out << "::android::hardware::Status _aidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700877 out.indent();
878 out.indent();
879 out << method->name() << "(";
880
881 bool first = true;
882 for (const auto &arg : method->args()) {
883 if (!first) {
884 out << ", ";
885 }
886
887 if (arg->type().resultNeedsDeref()) {
888 out << "*";
889 }
890
891 out << arg->name();
892
893 first = false;
894 }
895
896 if (returnsValue) {
897 if (!first) {
898 out << ", ";
899 }
900
901 out << "[&](";
902
903 first = true;
904 for (const auto &arg : method->results()) {
905 if (!first) {
906 out << ", ";
907 }
908
909 out << "const auto &" << arg->name();
910
911 first = false;
912 }
913
914 out << ") {\n";
915 out.indent();
916 out << "_aidl_callbackCalled = true;\n\n";
917
Andreas Huber8a82ff72016-08-04 10:29:39 -0700918 out << "::android::hardware::Status::ok()"
Andreas Huber881227d2016-08-02 14:20:21 -0700919 << ".writeToParcel(_aidl_reply);\n\n";
920
921 for (const auto &arg : method->results()) {
922 emitCppReaderWriter(
923 out,
924 "_aidl_reply",
925 true /* parcelObjIsPointer */,
926 arg,
927 false /* reader */,
928 Type::ErrorMode_Ignore);
929 }
930
931 out << "_aidl_cb(*_aidl_reply);\n";
932
933 out.unindent();
934 out << "}\n";
935 }
936
937 out.unindent();
938 out.unindent();
939 out << "));\n\n";
940
941 if (returnsValue) {
942 out << "if (!_aidl_callbackCalled) {\n";
943 out.indent();
944 }
945
946 out << "_aidl_err = _aidl_status.writeToParcel(_aidl_reply);\n";
947
948 if (returnsValue) {
949 out.unindent();
950 out << "}\n\n";
951 }
952
953 out << "break;\n";
954
955 return OK;
956}
957
958} // namespace android
959