blob: f61659a8c1bd3699c2bd425f8ff7e6e638097d30 [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
Andreas Huber881227d2016-08-02 14:20:21 -0700144 out << "#include <hwbinder/HidlSupport.h>\n";
145
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;
251 out << "virtual ::android::hardware::SimpleReturn<";
252 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
Andreas Huberb82318c2016-08-02 14:45:54 -0700291status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700292 std::string ifaceName;
293 if (!AST::isInterface(&ifaceName)) {
294 // types.hal does not get a stub header.
295 return OK;
296 }
297
Andreas Huber881227d2016-08-02 14:20:21 -0700298 // cut off the leading 'I'.
299 const std::string baseName = ifaceName.substr(1);
300
Andreas Huberb82318c2016-08-02 14:45:54 -0700301 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700302 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700303 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700304 path.append("Bn");
305 path.append(baseName);
306 path.append(".h");
307
Andreas Huberd2943e12016-08-05 11:59:31 -0700308 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700309 FILE *file = fopen(path.c_str(), "w");
310
311 if (file == NULL) {
312 return -errno;
313 }
314
315 Formatter out(file);
316
317 const std::string guard = makeHeaderGuard("Bn" + baseName);
318
319 out << "#ifndef " << guard << "\n";
320 out << "#define " << guard << "\n\n";
321
322 std::vector<std::string> packageComponents;
323 getPackageAndVersionComponents(
324 &packageComponents, false /* cpp_compatible */);
325
326 out << "#include <";
327 for (const auto &component : packageComponents) {
328 out << component << "/";
329 }
330 out << ifaceName << ".h>\n\n";
331
332 enterLeaveNamespace(out, true /* enter */);
333 out << "\n";
334
335 out << "struct "
336 << "Bn"
337 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700338 << " : public ::android::hardware::BnInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700339 << ifaceName
340 << "> {\n";
341
342 out.indent();
343
344 out << "::android::status_t onTransact(\n";
345 out.indent();
346 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700347 out << "uint32_t _hidl_code,\n";
348 out << "const ::android::hardware::Parcel &_hidl_data,\n";
349 out << "::android::hardware::Parcel *_hidl_reply,\n";
350 out << "uint32_t _hidl_flags = 0,\n";
351 out << "TransactCallback _hidl_cb = nullptr) override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700352 out.unindent();
353 out.unindent();
354
355 out.unindent();
356
357 out << "};\n\n";
358
359 enterLeaveNamespace(out, false /* enter */);
360
361 out << "\n#endif // " << guard << "\n";
362
363 return OK;
364}
365
Andreas Huberb82318c2016-08-02 14:45:54 -0700366status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700367 std::string ifaceName;
368 if (!AST::isInterface(&ifaceName)) {
369 // types.hal does not get a proxy header.
370 return OK;
371 }
372
Andreas Huber881227d2016-08-02 14:20:21 -0700373 // cut off the leading 'I'.
374 const std::string baseName = ifaceName.substr(1);
375
Andreas Huberb82318c2016-08-02 14:45:54 -0700376 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700377 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700378 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700379 path.append("Bp");
380 path.append(baseName);
381 path.append(".h");
382
Andreas Huberd2943e12016-08-05 11:59:31 -0700383 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700384 FILE *file = fopen(path.c_str(), "w");
385
386 if (file == NULL) {
387 return -errno;
388 }
389
390 Formatter out(file);
391
392 const std::string guard = makeHeaderGuard("Bp" + baseName);
393
394 out << "#ifndef " << guard << "\n";
395 out << "#define " << guard << "\n\n";
396
397 std::vector<std::string> packageComponents;
398 getPackageAndVersionComponents(
399 &packageComponents, false /* cpp_compatible */);
400
401 out << "#include <";
402 for (const auto &component : packageComponents) {
403 out << component << "/";
404 }
405 out << ifaceName << ".h>\n\n";
406
407 enterLeaveNamespace(out, true /* enter */);
408 out << "\n";
409
410 out << "struct "
411 << "Bp"
412 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700413 << " : public ::android::hardware::BpInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700414 << ifaceName
415 << "> {\n";
416
417 out.indent();
418
419 out << "explicit Bp"
420 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700421 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700422 << "\n\n";
423
424 const Interface *iface = mRootScope->getInterface();
425
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700426 std::vector<const Interface *> chain;
427 while (iface != NULL) {
428 chain.push_back(iface);
429 iface = iface->superType();
430 }
Andreas Huber881227d2016-08-02 14:20:21 -0700431
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700432 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
433 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700434
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700435 out << "// Methods from "
436 << superInterface->fullName()
437 << " follow.\n";
438
439 for (const auto &method : superInterface->methods()) {
440 const bool returnsValue = !method->results().empty();
441
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700442 const TypedVar *elidedReturn = method->canElideCallback();
443
444 if (elidedReturn == nullptr) {
445 out << "::android::hardware::Status ";
446 } else {
447 std::string extra;
448 out << "::android::hardware::SimpleReturn<";
449 out << elidedReturn->type().getCppResultType(&extra) << "> ";
450 }
451 out << method->name()
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700452 << "("
453 << Method::GetSignature(method->args());
454
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700455 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700456 if (!method->args().empty()) {
457 out << ", ";
458 }
459
Iliyan Malchev549e2592016-08-10 08:59:12 -0700460 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700461 }
462
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700463 out << ") override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700464 }
465
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700466 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700467 }
468
469 out.unindent();
470
471 out << "};\n\n";
472
473 enterLeaveNamespace(out, false /* enter */);
474
475 out << "\n#endif // " << guard << "\n";
476
477 return OK;
478}
479
Andreas Huberb82318c2016-08-02 14:45:54 -0700480status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700481
Andreas Huberb82318c2016-08-02 14:45:54 -0700482 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700483 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700484 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700485
486 std::string ifaceName;
487 std::string baseName;
488
489 bool isInterface = true;
490 if (!AST::isInterface(&ifaceName)) {
491 baseName = "types";
492 isInterface = false;
493 } else {
494 baseName = ifaceName.substr(1); // cut off the leading 'I'.
495 }
496
497 path.append(baseName);
498
499 if (baseName != "types") {
500 path.append("All");
501 }
502
503 path.append(".cpp");
504
Andreas Huberd2943e12016-08-05 11:59:31 -0700505 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700506 FILE *file = fopen(path.c_str(), "w");
507
508 if (file == NULL) {
509 return -errno;
510 }
511
512 Formatter out(file);
513
514 std::vector<std::string> packageComponents;
515 getPackageAndVersionComponents(
516 &packageComponents, false /* cpp_compatible */);
517
518 std::string prefix;
519 for (const auto &component : packageComponents) {
520 prefix += component;
521 prefix += "/";
522 }
523
524 if (isInterface) {
525 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
526 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
527 } else {
528 out << "#include <" << prefix << "types.h>\n";
529 }
530
531 out << "\n";
532
533 enterLeaveNamespace(out, true /* enter */);
534 out << "\n";
535
536 status_t err = generateTypeSource(out, ifaceName);
537
538 if (err == OK && isInterface) {
539 err = generateProxySource(out, baseName);
540 }
541
542 if (err == OK && isInterface) {
543 err = generateStubSource(out, baseName);
544 }
545
546 enterLeaveNamespace(out, false /* enter */);
547
548 return err;
549}
550
551status_t AST::generateTypeSource(
552 Formatter &out, const std::string &ifaceName) const {
553 return mRootScope->emitTypeDefinitions(out, ifaceName);
554}
555
Andreas Hubere7ff2282016-08-16 13:50:03 -0700556void AST::declareCppReaderLocals(
557 Formatter &out, const std::vector<TypedVar *> &args) const {
558 if (args.empty()) {
559 return;
560 }
561
562 for (const auto &arg : args) {
563 const Type &type = arg->type();
564
565 std::string extra;
566 out << type.getCppResultType(&extra)
567 << " "
568 << arg->name()
569 << extra
570 << ";\n";
571 }
572
573 out << "\n";
574}
575
Andreas Huber881227d2016-08-02 14:20:21 -0700576void 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
Andreas Huber881227d2016-08-02 14:20:21 -0700585 type.emitReaderWriter(
586 out,
587 arg->name(),
588 parcelObj,
589 parcelObjIsPointer,
590 isReader,
591 mode);
592}
593
594status_t AST::generateProxySource(
595 Formatter &out, const std::string &baseName) const {
596 const std::string klassName = "Bp" + baseName;
597
598 out << klassName
599 << "::"
600 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700601 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700602
603 out.indent();
604 out.indent();
605
606 out << ": BpInterface"
607 << "<I"
608 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700609 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700610
611 out.unindent();
612 out.unindent();
613 out << "}\n\n";
614
615 const Interface *iface = mRootScope->getInterface();
616
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700617 std::vector<const Interface *> chain;
618 while (iface != NULL) {
619 chain.push_back(iface);
620 iface = iface->superType();
621 }
Andreas Huber881227d2016-08-02 14:20:21 -0700622
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700623 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
624 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700625
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700626 for (const auto &method : superInterface->methods()) {
627 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700628
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700629 const TypedVar *elidedReturn = method->canElideCallback();
630 if (elidedReturn) {
631 std::string extra;
632 out << "::android::hardware::SimpleReturn<";
633 out << elidedReturn->type().getCppResultType(&extra) << "> ";
634 } else {
635 out << "::android::hardware::Status ";
636 }
637
638 out << klassName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700639 << "::"
640 << method->name()
641 << "("
642 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700643
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700644 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700645 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700646 out << ", ";
647 }
648
Iliyan Malchev549e2592016-08-10 08:59:12 -0700649 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700650 }
651
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700652 out << ") {\n";
653
654 out.indent();
655
Iliyan Malchev549e2592016-08-10 08:59:12 -0700656 out << "::android::hardware::Parcel _hidl_data;\n";
657 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700658 out << "::android::status_t _hidl_err;\n";
659 out << "::android::hardware::Status _hidl_status;\n\n";
660
661 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700662
Iliyan Malchev549e2592016-08-10 08:59:12 -0700663 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700664 << superInterface->fullName()
665 << "::getInterfaceDescriptor());\n";
666
Iliyan Malchev549e2592016-08-10 08:59:12 -0700667 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700668
669 for (const auto &arg : method->args()) {
670 emitCppReaderWriter(
671 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700672 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700673 false /* parcelObjIsPointer */,
674 arg,
675 false /* reader */,
676 Type::ErrorMode_Goto);
677 }
678
Iliyan Malchev549e2592016-08-10 08:59:12 -0700679 out << "_hidl_err = remote()->transact(I"
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700680 << baseName
681 << "::"
682 << upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700683 << ", _hidl_data, &_hidl_reply";
684 if (method->isOneway()) {
685 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700686 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700687 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700688
Iliyan Malchev639bff82016-08-13 14:24:11 -0700689 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700690
Iliyan Malchev639bff82016-08-13 14:24:11 -0700691 if (!method->isOneway()) {
692 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
693 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700694 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
695
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700696 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700697 emitCppReaderWriter(
698 out,
699 "_hidl_reply",
700 false /* parcelObjIsPointer */,
701 arg,
702 true /* reader */,
703 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700704 }
705
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700706 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700707 out << "if (_hidl_cb != nullptr) {\n";
708 out.indent();
709 out << "_hidl_cb(";
710
711 bool first = true;
712 for (const auto &arg : method->results()) {
713 if (!first) {
714 out << ", ";
715 }
716
717 if (arg->type().resultNeedsDeref()) {
718 out << "*";
719 }
720 out << arg->name();
721
722 first = false;
723 }
724
725 out << ");\n";
726 out.unindent();
727 out << "}\n\n";
728 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700729 }
730
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700731 if (elidedReturn != nullptr) {
732 std::string extra;
733
734 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
735 out << "return ::android::hardware::SimpleReturn<";
736 out << elidedReturn->type().getCppResultType(&extra)
737 << ">(" << elidedReturn->name() << ");\n\n";
738
739 out.unindent();
740 out << "_hidl_error:\n";
741 out.indent();
742 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
743 out << "return ::android::hardware::SimpleReturn<";
744 out << method->results().at(0)->type().getCppResultType(&extra)
745 << ">(_hidl_status);\n";
746 } else {
747 out.unindent();
748 out << "_hidl_error:\n";
749 out.indent();
750 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
751 out << "return _hidl_status;\n";
752 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700753
Andreas Huber881227d2016-08-02 14:20:21 -0700754 out.unindent();
755 out << "}\n\n";
756 }
Andreas Huber881227d2016-08-02 14:20:21 -0700757 }
758
759 return OK;
760}
761
762status_t AST::generateStubSource(
763 Formatter &out, const std::string &baseName) const {
764 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
765 << baseName
766 << ", \""
767 << mPackage.string()
768 << "::I"
769 << baseName
770 << "\");\n\n";
771
772 const std::string klassName = "Bn" + baseName;
773
774 out << "::android::status_t " << klassName << "::onTransact(\n";
775
776 out.indent();
777 out.indent();
778
Iliyan Malchev549e2592016-08-10 08:59:12 -0700779 out << "uint32_t _hidl_code,\n"
780 << "const ::android::hardware::Parcel &_hidl_data,\n"
781 << "::android::hardware::Parcel *_hidl_reply,\n"
782 << "uint32_t _hidl_flags,\n"
783 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700784
785 out.unindent();
786
Iliyan Malchev549e2592016-08-10 08:59:12 -0700787 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700788
Iliyan Malchev549e2592016-08-10 08:59:12 -0700789 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700790 out.indent();
791
792 const Interface *iface = mRootScope->getInterface();
793
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700794 std::vector<const Interface *> chain;
795 while (iface != NULL) {
796 chain.push_back(iface);
797 iface = iface->superType();
798 }
Andreas Huber881227d2016-08-02 14:20:21 -0700799
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700800 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
801 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700802
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700803 for (const auto &method : superInterface->methods()) {
804 out << "case "
805 << superInterface->fullName()
806 << "::Call::"
807 << upcase(method->name())
808 << ":\n{\n";
809
810 out.indent();
811
812 status_t err =
813 generateStubSourceForMethod(out, superInterface, method);
814
815 if (err != OK) {
816 return err;
817 }
818
819 out.unindent();
820 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700821 }
Andreas Huber881227d2016-08-02 14:20:21 -0700822 }
823
824 out << "default:\n{\n";
825 out.indent();
826
Andreas Huber8a82ff72016-08-04 10:29:39 -0700827 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700828 << baseName
829 << ">::onTransact(\n";
830
831 out.indent();
832 out.indent();
833
Iliyan Malchev549e2592016-08-10 08:59:12 -0700834 out << "_hidl_code, _hidl_data, _hidl_reply, "
835 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700836
837 out.unindent();
838 out.unindent();
839
840 out.unindent();
841 out << "}\n";
842
843 out.unindent();
844 out << "}\n\n";
845
Iliyan Malchev549e2592016-08-10 08:59:12 -0700846 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700847 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700848 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700849 out.indent();
850 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700851 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700852 out.indent();
853 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700854 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700855 out.unindent();
856 out.unindent();
857 out.unindent();
858 out.unindent();
859
860 out.unindent();
861 out << "}\n\n";
862
Iliyan Malchev549e2592016-08-10 08:59:12 -0700863 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700864
865 out.unindent();
866 out << "}\n\n";
867
868 return OK;
869}
870
871status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700872 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700873 out << "if (!_hidl_data.enforceInterface("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700874 << iface->fullName()
875 << "::getInterfaceDescriptor())) {\n";
876
Andreas Huber881227d2016-08-02 14:20:21 -0700877 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700878 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700879 out << "break;\n";
880 out.unindent();
881 out << "}\n\n";
882
Andreas Hubere7ff2282016-08-16 13:50:03 -0700883 declareCppReaderLocals(out, method->args());
884
Andreas Huber881227d2016-08-02 14:20:21 -0700885 for (const auto &arg : method->args()) {
886 emitCppReaderWriter(
887 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700888 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -0700889 false /* parcelObjIsPointer */,
890 arg,
891 true /* reader */,
892 Type::ErrorMode_Break);
893 }
894
895 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700896 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -0700897
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700898 if (elidedReturn != nullptr) {
899 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -0700900
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700901 out << elidedReturn->type().getCppResultType(&extra) << " ";
902 out << elidedReturn->name() << " = ";
903 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -0700904
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700905 bool first = true;
906 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700907 if (!first) {
908 out << ", ";
909 }
910
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700911 if (arg->type().resultNeedsDeref()) {
912 out << "*";
913 }
914
915 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -0700916
917 first = false;
918 }
919
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700920 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700921 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700922 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700923
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700924 elidedReturn->type().emitReaderWriter(
925 out,
926 elidedReturn->name(),
927 "_hidl_reply",
928 true, /* parcelObjIsPointer */
929 false, /* isReader */
930 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -0700931
Iliyan Malchev549e2592016-08-10 08:59:12 -0700932 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700933 } else {
934 if (returnsValue) {
935 out << "bool _hidl_callbackCalled = false;\n\n";
936 }
Andreas Huber881227d2016-08-02 14:20:21 -0700937
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700938 out << "::android::hardware::Status _hidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700939 out.indent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700940 out.indent();
941 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -0700942
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700943 bool first = true;
944 for (const auto &arg : method->args()) {
945 if (!first) {
946 out << ", ";
947 }
Andreas Huber881227d2016-08-02 14:20:21 -0700948
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700949 if (arg->type().resultNeedsDeref()) {
950 out << "*";
951 }
952
953 out << arg->name();
954
955 first = false;
956 }
957
958 if (returnsValue) {
959 if (!first) {
960 out << ", ";
961 }
962
963 out << "[&](";
964
965 first = true;
966 for (const auto &arg : method->results()) {
967 if (!first) {
968 out << ", ";
969 }
970
971 out << "const auto &" << arg->name();
972
973 first = false;
974 }
975
976 out << ") {\n";
977 out.indent();
978 out << "_hidl_callbackCalled = true;\n\n";
979
980 out << "::android::hardware::Status::ok()"
981 << ".writeToParcel(_hidl_reply);\n\n";
982
983 for (const auto &arg : method->results()) {
984 emitCppReaderWriter(
985 out,
986 "_hidl_reply",
987 true /* parcelObjIsPointer */,
988 arg,
989 false /* reader */,
990 Type::ErrorMode_Ignore);
991 }
992
993 out << "_hidl_cb(*_hidl_reply);\n";
994
995 out.unindent();
996 out << "}\n";
997 }
998
Andreas Huber881227d2016-08-02 14:20:21 -0700999 out.unindent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001000 out.unindent();
1001 out << "));\n\n";
1002
1003 if (returnsValue) {
1004 out << "if (!_hidl_callbackCalled) {\n";
1005 out.indent();
1006 }
1007
1008 out << "_hidl_err = _hidl_status.writeToParcel(_hidl_reply);\n";
1009
1010 if (returnsValue) {
1011 out.unindent();
1012 out << "}\n\n";
1013 }
Andreas Huber881227d2016-08-02 14:20:21 -07001014 }
1015
1016 out << "break;\n";
1017
1018 return OK;
1019}
1020
1021} // namespace android
1022