blob: ab524d0bbef43216d19369d24900ea9640065662 [file] [log] [blame]
Andreas Huber881227d2016-08-02 14:20:21 -07001#include "AST.h"
2
3#include "Coordinator.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07004#include "EnumType.h"
Andreas Huber881227d2016-08-02 14:20:21 -07005#include "Formatter.h"
6#include "Interface.h"
7#include "Method.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07008#include "ScalarType.h"
Andreas Huber881227d2016-08-02 14:20:21 -07009#include "Scope.h"
10
Andreas Huberdca261f2016-08-04 13:47:51 -070011#include <algorithm>
Andreas Huber881227d2016-08-02 14:20:21 -070012#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070013#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070014#include <vector>
15
16namespace android {
17
Andreas Huber881227d2016-08-02 14:20:21 -070018static std::string upcase(const std::string in) {
19 std::string out{in};
20
21 for (auto &ch : out) {
22 ch = toupper(ch);
23 }
24
25 return out;
26}
27
Andreas Huberb82318c2016-08-02 14:45:54 -070028status_t AST::generateCpp(const std::string &outputPath) const {
29 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070030
31 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070032 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070033 }
34
35 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070036 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070037 }
38
39 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070040 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070041 }
42
43 return err;
44}
45
Andreas Huber737080b2016-08-02 15:38:04 -070046void AST::getPackageComponents(
47 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070048 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070049}
50
51void AST::getPackageAndVersionComponents(
52 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070053 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070054}
55
Andreas Huber881227d2016-08-02 14:20:21 -070056std::string AST::makeHeaderGuard(const std::string &baseName) const {
57 std::vector<std::string> packageComponents;
58 getPackageAndVersionComponents(
59 &packageComponents, true /* cpp_compatible */);
60
61 std::string guard = "HIDL_GENERATED";
62 for (const auto &component : packageComponents) {
63 guard += "_";
64 guard += component;
65 }
66
67 guard += "_";
68 guard += baseName;
69 guard += "_H_";
70
71 return guard;
72}
73
74void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
75 std::vector<std::string> packageComponents;
76 getPackageAndVersionComponents(
77 &packageComponents, true /* cpp_compatible */);
78
79 if (enter) {
80 for (const auto &component : packageComponents) {
81 out << "namespace " << component << " {\n";
82 }
Andreas Huber0e00de42016-08-03 09:56:02 -070083
Andreas Huber2831d512016-08-15 09:33:47 -070084 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -070085 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -070086 out.setNamespace(std::string());
87
Andreas Huber881227d2016-08-02 14:20:21 -070088 for (auto it = packageComponents.rbegin();
89 it != packageComponents.rend();
90 ++it) {
91 out << "} // namespace " << *it << "\n";
92 }
93 }
94}
95
Andreas Huberb82318c2016-08-02 14:45:54 -070096status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -070097
Andreas Huberb82318c2016-08-02 14:45:54 -070098 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -070099 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700100 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700101
102 std::string ifaceName;
103 bool isInterface = true;
104 if (!AST::isInterface(&ifaceName)) {
105 ifaceName = "types";
106 isInterface = false;
107 }
108 path.append(ifaceName);
109 path.append(".h");
110
Andreas Huberd2943e12016-08-05 11:59:31 -0700111 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700112 FILE *file = fopen(path.c_str(), "w");
113
114 if (file == NULL) {
115 return -errno;
116 }
117
118 Formatter out(file);
119
120 const std::string guard = makeHeaderGuard(ifaceName);
121
122 out << "#ifndef " << guard << "\n";
123 out << "#define " << guard << "\n\n";
124
Andreas Huber737080b2016-08-02 15:38:04 -0700125 for (const auto &item : mImportedNames) {
126 out << "#include <";
127
128 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700129 item.getPackageAndVersionComponents(
130 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700131
132 for (const auto &component : components) {
133 out << component << "/";
134 }
135
136 out << item.name()
137 << ".h>\n";
138 }
139
140 if (!mImportedNames.empty()) {
141 out << "\n";
142 }
143
Martijn Coenen7473fab2016-08-19 14:05:40 +0200144 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700145
146 if (isInterface) {
147 out << "#include <hwbinder/IBinder.h>\n";
148 out << "#include <hwbinder/IInterface.h>\n";
149 out << "#include <hwbinder/Status.h>\n";
150 }
151
152 out << "#include <utils/NativeHandle.h>\n\n";
153
154 enterLeaveNamespace(out, true /* enter */);
155 out << "\n";
156
157 if (isInterface) {
158 out << "struct "
159 << ifaceName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700160 << " : public ";
161
162 const Interface *iface = mRootScope->getInterface();
163 const Interface *superType = iface->superType();
164
165 if (superType != NULL) {
166 out << superType->fullName();
167 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700168 out << "::android::hardware::IInterface";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700169 }
170
171 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700172
173 out.indent();
174
Andreas Huber737080b2016-08-02 15:38:04 -0700175 // cut off the leading 'I'.
176 const std::string baseName = ifaceName.substr(1);
177
178 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700179 }
180
181 status_t err = emitTypeDeclarations(out);
182
183 if (err != OK) {
184 return err;
185 }
186
187 if (isInterface) {
188 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700189 const Interface *superType = iface->superType();
Andreas Huber881227d2016-08-02 14:20:21 -0700190
191 out << "enum Call {\n";
192 out.indent();
193
194 bool first = true;
195 for (const auto &method : iface->methods()) {
196 out << upcase(method->name());
197
198 if (first) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700199 out << " = ";
200 if (superType != NULL) {
201 out << superType->fullName()
202 << "::Call::CallCount";
203 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700204 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700205 }
206
Andreas Huber881227d2016-08-02 14:20:21 -0700207 first = false;
208 }
209
210 out << ",\n";
211 }
212
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700213 out << "CallCount\n";
214
Andreas Huber881227d2016-08-02 14:20:21 -0700215 out.unindent();
216 out << "};\n\n";
217
218 bool haveCallbacks = false;
219 for (const auto &method : iface->methods()) {
220 const bool returnsValue = !method->results().empty();
221
222 if (!returnsValue) {
223 continue;
224 }
225
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700226 if (method->canElideCallback() != nullptr) {
227 continue;
228 }
229
Andreas Huber881227d2016-08-02 14:20:21 -0700230 haveCallbacks = true;
231
232 out << "using "
233 << method->name()
234 << "_cb = std::function<void("
235 << Method::GetSignature(method->results())
236 << ")>;\n";
237 }
238
239 if (haveCallbacks) {
240 out << "\n";
241 }
242
243 for (const auto &method : iface->methods()) {
244 const bool returnsValue = !method->results().empty();
245
Andreas Huber3599d922016-08-09 10:42:57 -0700246 method->dumpAnnotations(out);
247
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700248 const TypedVar *elidedReturn = method->canElideCallback();
249 if (elidedReturn) {
250 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700251 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700252 out << elidedReturn->type().getCppResultType(&extra) << "> ";
253 } else {
254 out << "virtual ::android::hardware::Status ";
255 }
256
257 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700258 << "("
259 << Method::GetSignature(method->args());
260
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700261 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700262 if (!method->args().empty()) {
263 out << ", ";
264 }
265
Iliyan Malchev549e2592016-08-10 08:59:12 -0700266 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700267 }
268
269 out << ") = 0;\n";
270 }
271 }
272
273 if (isInterface) {
274 out.unindent();
275
276 out << "};\n";
277 }
278
279 out << "\n";
280 enterLeaveNamespace(out, false /* enter */);
281
282 out << "\n#endif // " << guard << "\n";
283
284 return OK;
285}
286
287status_t AST::emitTypeDeclarations(Formatter &out) const {
288 return mRootScope->emitTypeDeclarations(out);
289}
290
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700291status_t AST::generateHeaderMethodSignatures(
292 Formatter &out, bool abstract) const {
293 const Interface *iface = mRootScope->getInterface();
294
295 std::vector<const Interface *> chain;
296 while (iface != NULL) {
297 chain.push_back(iface);
298 iface = iface->superType();
299 }
300
301 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
302 const Interface *superInterface = *it;
303
304 out << "// Methods from "
305 << superInterface->fullName()
306 << " follow.\n";
307
308 for (const auto &method : superInterface->methods()) {
309 const bool returnsValue = !method->results().empty();
310
311 const TypedVar *elidedReturn = method->canElideCallback();
312
313 if (elidedReturn == nullptr) {
314 out << "::android::hardware::Status ";
315 } else {
316 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700317 out << "::android::hardware::Return<";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700318 out << elidedReturn->type().getCppResultType(&extra) << "> ";
319 }
320 out << method->name()
321 << "("
322 << Method::GetSignature(method->args());
323
324 if (returnsValue && elidedReturn == nullptr) {
325 if (!method->args().empty()) {
326 out << ", ";
327 }
328
329 out << method->name() << "_cb _hidl_cb";
330 }
331
332 out << ") ";
333 out << (abstract ? "= 0" : "override");
334 out << ";\n";
335 }
336
337 out << "\n";
338 }
339
340 return OK;
341}
342
Andreas Huberb82318c2016-08-02 14:45:54 -0700343status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700344 std::string ifaceName;
345 if (!AST::isInterface(&ifaceName)) {
346 // types.hal does not get a stub header.
347 return OK;
348 }
349
Andreas Huber881227d2016-08-02 14:20:21 -0700350 // cut off the leading 'I'.
351 const std::string baseName = ifaceName.substr(1);
352
Andreas Huberb82318c2016-08-02 14:45:54 -0700353 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700354 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700355 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700356 path.append("Bn");
357 path.append(baseName);
358 path.append(".h");
359
Andreas Huberd2943e12016-08-05 11:59:31 -0700360 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700361 FILE *file = fopen(path.c_str(), "w");
362
363 if (file == NULL) {
364 return -errno;
365 }
366
367 Formatter out(file);
368
369 const std::string guard = makeHeaderGuard("Bn" + baseName);
370
371 out << "#ifndef " << guard << "\n";
372 out << "#define " << guard << "\n\n";
373
374 std::vector<std::string> packageComponents;
375 getPackageAndVersionComponents(
376 &packageComponents, false /* cpp_compatible */);
377
378 out << "#include <";
379 for (const auto &component : packageComponents) {
380 out << component << "/";
381 }
382 out << ifaceName << ".h>\n\n";
383
384 enterLeaveNamespace(out, true /* enter */);
385 out << "\n";
386
387 out << "struct "
388 << "Bn"
389 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700390 << " : public ::android::hardware::BnInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700391 << ifaceName
392 << "> {\n";
393
394 out.indent();
395
396 out << "::android::status_t onTransact(\n";
397 out.indent();
398 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700399 out << "uint32_t _hidl_code,\n";
400 out << "const ::android::hardware::Parcel &_hidl_data,\n";
401 out << "::android::hardware::Parcel *_hidl_reply,\n";
402 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700403 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700404 out.unindent();
405 out.unindent();
406
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700407 generateHeaderMethodSignatures(out, true); // = 0
408
Andreas Huber881227d2016-08-02 14:20:21 -0700409 out.unindent();
410
411 out << "};\n\n";
412
413 enterLeaveNamespace(out, false /* enter */);
414
415 out << "\n#endif // " << guard << "\n";
416
417 return OK;
418}
419
Andreas Huberb82318c2016-08-02 14:45:54 -0700420status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700421 std::string ifaceName;
422 if (!AST::isInterface(&ifaceName)) {
423 // types.hal does not get a proxy header.
424 return OK;
425 }
426
Andreas Huber881227d2016-08-02 14:20:21 -0700427 // cut off the leading 'I'.
428 const std::string baseName = ifaceName.substr(1);
429
Andreas Huberb82318c2016-08-02 14:45:54 -0700430 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700431 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700432 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700433 path.append("Bp");
434 path.append(baseName);
435 path.append(".h");
436
Andreas Huberd2943e12016-08-05 11:59:31 -0700437 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700438 FILE *file = fopen(path.c_str(), "w");
439
440 if (file == NULL) {
441 return -errno;
442 }
443
444 Formatter out(file);
445
446 const std::string guard = makeHeaderGuard("Bp" + baseName);
447
448 out << "#ifndef " << guard << "\n";
449 out << "#define " << guard << "\n\n";
450
451 std::vector<std::string> packageComponents;
452 getPackageAndVersionComponents(
453 &packageComponents, false /* cpp_compatible */);
454
455 out << "#include <";
456 for (const auto &component : packageComponents) {
457 out << component << "/";
458 }
459 out << ifaceName << ".h>\n\n";
460
461 enterLeaveNamespace(out, true /* enter */);
462 out << "\n";
463
464 out << "struct "
465 << "Bp"
466 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700467 << " : public ::android::hardware::BpInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700468 << ifaceName
469 << "> {\n";
470
471 out.indent();
472
473 out << "explicit Bp"
474 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700475 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700476 << "\n\n";
477
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700478 generateHeaderMethodSignatures(out, false); // override
Andreas Huber881227d2016-08-02 14:20:21 -0700479
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
Andreas Huberb82318c2016-08-02 14:45:54 -0700493 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700494 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700495 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700496
497 std::string ifaceName;
498 std::string baseName;
499
500 bool isInterface = true;
501 if (!AST::isInterface(&ifaceName)) {
502 baseName = "types";
503 isInterface = false;
504 } else {
505 baseName = ifaceName.substr(1); // cut off the leading 'I'.
506 }
507
508 path.append(baseName);
509
510 if (baseName != "types") {
511 path.append("All");
512 }
513
514 path.append(".cpp");
515
Andreas Huberd2943e12016-08-05 11:59:31 -0700516 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700517 FILE *file = fopen(path.c_str(), "w");
518
519 if (file == NULL) {
520 return -errno;
521 }
522
523 Formatter out(file);
524
525 std::vector<std::string> packageComponents;
526 getPackageAndVersionComponents(
527 &packageComponents, false /* cpp_compatible */);
528
529 std::string prefix;
530 for (const auto &component : packageComponents) {
531 prefix += component;
532 prefix += "/";
533 }
534
535 if (isInterface) {
536 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
537 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
538 } else {
539 out << "#include <" << prefix << "types.h>\n";
540 }
541
542 out << "\n";
543
544 enterLeaveNamespace(out, true /* enter */);
545 out << "\n";
546
547 status_t err = generateTypeSource(out, ifaceName);
548
549 if (err == OK && isInterface) {
550 err = generateProxySource(out, baseName);
551 }
552
553 if (err == OK && isInterface) {
554 err = generateStubSource(out, baseName);
555 }
556
557 enterLeaveNamespace(out, false /* enter */);
558
559 return err;
560}
561
562status_t AST::generateTypeSource(
563 Formatter &out, const std::string &ifaceName) const {
564 return mRootScope->emitTypeDefinitions(out, ifaceName);
565}
566
Andreas Hubere7ff2282016-08-16 13:50:03 -0700567void AST::declareCppReaderLocals(
568 Formatter &out, const std::vector<TypedVar *> &args) const {
569 if (args.empty()) {
570 return;
571 }
572
573 for (const auto &arg : args) {
574 const Type &type = arg->type();
575
576 std::string extra;
577 out << type.getCppResultType(&extra)
578 << " "
579 << arg->name()
580 << extra
581 << ";\n";
582 }
583
584 out << "\n";
585}
586
Andreas Huber881227d2016-08-02 14:20:21 -0700587void AST::emitCppReaderWriter(
588 Formatter &out,
589 const std::string &parcelObj,
590 bool parcelObjIsPointer,
591 const TypedVar *arg,
592 bool isReader,
593 Type::ErrorMode mode) const {
594 const Type &type = arg->type();
595
Andreas Huber881227d2016-08-02 14:20:21 -0700596 type.emitReaderWriter(
597 out,
598 arg->name(),
599 parcelObj,
600 parcelObjIsPointer,
601 isReader,
602 mode);
603}
604
605status_t AST::generateProxySource(
606 Formatter &out, const std::string &baseName) const {
607 const std::string klassName = "Bp" + baseName;
608
609 out << klassName
610 << "::"
611 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700612 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700613
614 out.indent();
615 out.indent();
616
617 out << ": BpInterface"
618 << "<I"
619 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700620 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700621
622 out.unindent();
623 out.unindent();
624 out << "}\n\n";
625
626 const Interface *iface = mRootScope->getInterface();
627
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700628 std::vector<const Interface *> chain;
629 while (iface != NULL) {
630 chain.push_back(iface);
631 iface = iface->superType();
632 }
Andreas Huber881227d2016-08-02 14:20:21 -0700633
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700634 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
635 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700636
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700637 for (const auto &method : superInterface->methods()) {
638 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700639
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700640 const TypedVar *elidedReturn = method->canElideCallback();
641 if (elidedReturn) {
642 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700643 out << "::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700644 out << elidedReturn->type().getCppResultType(&extra) << "> ";
645 } else {
646 out << "::android::hardware::Status ";
647 }
648
649 out << klassName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700650 << "::"
651 << method->name()
652 << "("
653 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700654
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700655 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700656 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700657 out << ", ";
658 }
659
Iliyan Malchev549e2592016-08-10 08:59:12 -0700660 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700661 }
662
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700663 out << ") {\n";
664
665 out.indent();
666
Iliyan Malchev549e2592016-08-10 08:59:12 -0700667 out << "::android::hardware::Parcel _hidl_data;\n";
668 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700669 out << "::android::status_t _hidl_err;\n";
670 out << "::android::hardware::Status _hidl_status;\n\n";
671
672 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700673
Iliyan Malchev549e2592016-08-10 08:59:12 -0700674 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700675 << superInterface->fullName()
676 << "::getInterfaceDescriptor());\n";
677
Iliyan Malchev549e2592016-08-10 08:59:12 -0700678 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700679
680 for (const auto &arg : method->args()) {
681 emitCppReaderWriter(
682 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700683 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700684 false /* parcelObjIsPointer */,
685 arg,
686 false /* reader */,
687 Type::ErrorMode_Goto);
688 }
689
Iliyan Malchev549e2592016-08-10 08:59:12 -0700690 out << "_hidl_err = remote()->transact(I"
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700691 << baseName
692 << "::"
693 << upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700694 << ", _hidl_data, &_hidl_reply";
695 if (method->isOneway()) {
696 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700697 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700698 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700699
Iliyan Malchev639bff82016-08-13 14:24:11 -0700700 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700701
Iliyan Malchev639bff82016-08-13 14:24:11 -0700702 if (!method->isOneway()) {
703 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
704 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700705 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
706
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700707 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700708 emitCppReaderWriter(
709 out,
710 "_hidl_reply",
711 false /* parcelObjIsPointer */,
712 arg,
713 true /* reader */,
714 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700715 }
716
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700717 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700718 out << "if (_hidl_cb != nullptr) {\n";
719 out.indent();
720 out << "_hidl_cb(";
721
722 bool first = true;
723 for (const auto &arg : method->results()) {
724 if (!first) {
725 out << ", ";
726 }
727
728 if (arg->type().resultNeedsDeref()) {
729 out << "*";
730 }
731 out << arg->name();
732
733 first = false;
734 }
735
736 out << ");\n";
737 out.unindent();
738 out << "}\n\n";
739 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700740 }
741
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700742 if (elidedReturn != nullptr) {
743 std::string extra;
744
745 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700746 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700747 out << elidedReturn->type().getCppResultType(&extra)
748 << ">(" << elidedReturn->name() << ");\n\n";
749
750 out.unindent();
751 out << "_hidl_error:\n";
752 out.indent();
753 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700754 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700755 out << method->results().at(0)->type().getCppResultType(&extra)
756 << ">(_hidl_status);\n";
757 } else {
758 out.unindent();
759 out << "_hidl_error:\n";
760 out.indent();
761 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
762 out << "return _hidl_status;\n";
763 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700764
Andreas Huber881227d2016-08-02 14:20:21 -0700765 out.unindent();
766 out << "}\n\n";
767 }
Andreas Huber881227d2016-08-02 14:20:21 -0700768 }
769
770 return OK;
771}
772
773status_t AST::generateStubSource(
774 Formatter &out, const std::string &baseName) const {
775 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
776 << baseName
777 << ", \""
778 << mPackage.string()
779 << "::I"
780 << baseName
781 << "\");\n\n";
782
783 const std::string klassName = "Bn" + baseName;
784
785 out << "::android::status_t " << klassName << "::onTransact(\n";
786
787 out.indent();
788 out.indent();
789
Iliyan Malchev549e2592016-08-10 08:59:12 -0700790 out << "uint32_t _hidl_code,\n"
791 << "const ::android::hardware::Parcel &_hidl_data,\n"
792 << "::android::hardware::Parcel *_hidl_reply,\n"
793 << "uint32_t _hidl_flags,\n"
794 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700795
796 out.unindent();
797
Iliyan Malchev549e2592016-08-10 08:59:12 -0700798 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700799
Iliyan Malchev549e2592016-08-10 08:59:12 -0700800 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700801 out.indent();
802
803 const Interface *iface = mRootScope->getInterface();
804
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700805 std::vector<const Interface *> chain;
806 while (iface != NULL) {
807 chain.push_back(iface);
808 iface = iface->superType();
809 }
Andreas Huber881227d2016-08-02 14:20:21 -0700810
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700811 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
812 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700813
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700814 for (const auto &method : superInterface->methods()) {
815 out << "case "
816 << superInterface->fullName()
817 << "::Call::"
818 << upcase(method->name())
819 << ":\n{\n";
820
821 out.indent();
822
823 status_t err =
824 generateStubSourceForMethod(out, superInterface, method);
825
826 if (err != OK) {
827 return err;
828 }
829
830 out.unindent();
831 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700832 }
Andreas Huber881227d2016-08-02 14:20:21 -0700833 }
834
835 out << "default:\n{\n";
836 out.indent();
837
Andreas Huber8a82ff72016-08-04 10:29:39 -0700838 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700839 << baseName
840 << ">::onTransact(\n";
841
842 out.indent();
843 out.indent();
844
Iliyan Malchev549e2592016-08-10 08:59:12 -0700845 out << "_hidl_code, _hidl_data, _hidl_reply, "
846 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700847
848 out.unindent();
849 out.unindent();
850
851 out.unindent();
852 out << "}\n";
853
854 out.unindent();
855 out << "}\n\n";
856
Iliyan Malchev549e2592016-08-10 08:59:12 -0700857 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700858 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700859 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700860 out.indent();
861 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700862 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700863 out.indent();
864 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700865 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700866 out.unindent();
867 out.unindent();
868 out.unindent();
869 out.unindent();
870
871 out.unindent();
872 out << "}\n\n";
873
Iliyan Malchev549e2592016-08-10 08:59:12 -0700874 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700875
876 out.unindent();
877 out << "}\n\n";
878
879 return OK;
880}
881
882status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700883 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700884 out << "if (!_hidl_data.enforceInterface("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700885 << iface->fullName()
886 << "::getInterfaceDescriptor())) {\n";
887
Andreas Huber881227d2016-08-02 14:20:21 -0700888 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700889 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700890 out << "break;\n";
891 out.unindent();
892 out << "}\n\n";
893
Andreas Hubere7ff2282016-08-16 13:50:03 -0700894 declareCppReaderLocals(out, method->args());
895
Andreas Huber881227d2016-08-02 14:20:21 -0700896 for (const auto &arg : method->args()) {
897 emitCppReaderWriter(
898 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700899 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -0700900 false /* parcelObjIsPointer */,
901 arg,
902 true /* reader */,
903 Type::ErrorMode_Break);
904 }
905
906 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700907 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -0700908
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700909 if (elidedReturn != nullptr) {
910 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -0700911
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700912 out << elidedReturn->type().getCppResultType(&extra) << " ";
913 out << elidedReturn->name() << " = ";
914 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -0700915
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700916 bool first = true;
917 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700918 if (!first) {
919 out << ", ";
920 }
921
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700922 if (arg->type().resultNeedsDeref()) {
923 out << "*";
924 }
925
926 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -0700927
928 first = false;
929 }
930
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700931 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700932 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700933 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700934
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700935 elidedReturn->type().emitReaderWriter(
936 out,
937 elidedReturn->name(),
938 "_hidl_reply",
939 true, /* parcelObjIsPointer */
940 false, /* isReader */
941 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -0700942
Iliyan Malchev549e2592016-08-10 08:59:12 -0700943 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700944 } else {
945 if (returnsValue) {
946 out << "bool _hidl_callbackCalled = false;\n\n";
947 }
Andreas Huber881227d2016-08-02 14:20:21 -0700948
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700949 out << "::android::hardware::Status _hidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700950 out.indent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700951 out.indent();
952 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -0700953
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700954 bool first = true;
955 for (const auto &arg : method->args()) {
956 if (!first) {
957 out << ", ";
958 }
Andreas Huber881227d2016-08-02 14:20:21 -0700959
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700960 if (arg->type().resultNeedsDeref()) {
961 out << "*";
962 }
963
964 out << arg->name();
965
966 first = false;
967 }
968
969 if (returnsValue) {
970 if (!first) {
971 out << ", ";
972 }
973
974 out << "[&](";
975
976 first = true;
977 for (const auto &arg : method->results()) {
978 if (!first) {
979 out << ", ";
980 }
981
982 out << "const auto &" << arg->name();
983
984 first = false;
985 }
986
987 out << ") {\n";
988 out.indent();
989 out << "_hidl_callbackCalled = true;\n\n";
990
991 out << "::android::hardware::Status::ok()"
992 << ".writeToParcel(_hidl_reply);\n\n";
993
994 for (const auto &arg : method->results()) {
995 emitCppReaderWriter(
996 out,
997 "_hidl_reply",
998 true /* parcelObjIsPointer */,
999 arg,
1000 false /* reader */,
1001 Type::ErrorMode_Ignore);
1002 }
1003
1004 out << "_hidl_cb(*_hidl_reply);\n";
1005
1006 out.unindent();
1007 out << "}\n";
1008 }
1009
Andreas Huber881227d2016-08-02 14:20:21 -07001010 out.unindent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001011 out.unindent();
1012 out << "));\n\n";
1013
1014 if (returnsValue) {
1015 out << "if (!_hidl_callbackCalled) {\n";
1016 out.indent();
1017 }
1018
1019 out << "_hidl_err = _hidl_status.writeToParcel(_hidl_reply);\n";
1020
1021 if (returnsValue) {
1022 out.unindent();
1023 out << "}\n\n";
1024 }
Andreas Huber881227d2016-08-02 14:20:21 -07001025 }
1026
1027 out << "break;\n";
1028
1029 return OK;
1030}
1031
1032} // namespace android
1033