blob: 0985fb2f76ddaa44b34551d55fa85bf7c60c8095 [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 <vector>
13
14namespace android {
15
Andreas Huber881227d2016-08-02 14:20:21 -070016static std::string upcase(const std::string in) {
17 std::string out{in};
18
19 for (auto &ch : out) {
20 ch = toupper(ch);
21 }
22
23 return out;
24}
25
Andreas Huberb82318c2016-08-02 14:45:54 -070026status_t AST::generateCpp(const std::string &outputPath) const {
27 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070028
29 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070030 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070031 }
32
33 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070034 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070035 }
36
37 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070038 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070039 }
40
41 return err;
42}
43
Andreas Huber737080b2016-08-02 15:38:04 -070044void AST::getPackageComponents(
45 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070046 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070047}
48
49void AST::getPackageAndVersionComponents(
50 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070051 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070052}
53
Andreas Huber881227d2016-08-02 14:20:21 -070054std::string AST::makeHeaderGuard(const std::string &baseName) const {
55 std::vector<std::string> packageComponents;
56 getPackageAndVersionComponents(
57 &packageComponents, true /* cpp_compatible */);
58
59 std::string guard = "HIDL_GENERATED";
60 for (const auto &component : packageComponents) {
61 guard += "_";
62 guard += component;
63 }
64
65 guard += "_";
66 guard += baseName;
67 guard += "_H_";
68
69 return guard;
70}
71
72void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
73 std::vector<std::string> packageComponents;
74 getPackageAndVersionComponents(
75 &packageComponents, true /* cpp_compatible */);
76
77 if (enter) {
78 for (const auto &component : packageComponents) {
79 out << "namespace " << component << " {\n";
80 }
Andreas Huber0e00de42016-08-03 09:56:02 -070081
Andreas Huber2831d512016-08-15 09:33:47 -070082 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -070083 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -070084 out.setNamespace(std::string());
85
Andreas Huber881227d2016-08-02 14:20:21 -070086 for (auto it = packageComponents.rbegin();
87 it != packageComponents.rend();
88 ++it) {
89 out << "} // namespace " << *it << "\n";
90 }
91 }
92}
93
Andreas Huberb82318c2016-08-02 14:45:54 -070094status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -070095
Andreas Huberb82318c2016-08-02 14:45:54 -070096 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -070097 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -070098 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -070099
100 std::string ifaceName;
101 bool isInterface = true;
102 if (!AST::isInterface(&ifaceName)) {
103 ifaceName = "types";
104 isInterface = false;
105 }
106 path.append(ifaceName);
107 path.append(".h");
108
Andreas Huberd2943e12016-08-05 11:59:31 -0700109 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700110 FILE *file = fopen(path.c_str(), "w");
111
112 if (file == NULL) {
113 return -errno;
114 }
115
116 Formatter out(file);
117
118 const std::string guard = makeHeaderGuard(ifaceName);
119
120 out << "#ifndef " << guard << "\n";
121 out << "#define " << guard << "\n\n";
122
Andreas Huber737080b2016-08-02 15:38:04 -0700123 for (const auto &item : mImportedNames) {
124 out << "#include <";
125
126 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700127 item.getPackageAndVersionComponents(
128 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700129
130 for (const auto &component : components) {
131 out << component << "/";
132 }
133
134 out << item.name()
135 << ".h>\n";
136 }
137
138 if (!mImportedNames.empty()) {
139 out << "\n";
140 }
141
Andreas Huber881227d2016-08-02 14:20:21 -0700142 out << "#include <hwbinder/HidlSupport.h>\n";
143
144 if (isInterface) {
145 out << "#include <hwbinder/IBinder.h>\n";
146 out << "#include <hwbinder/IInterface.h>\n";
147 out << "#include <hwbinder/Status.h>\n";
148 }
149
150 out << "#include <utils/NativeHandle.h>\n\n";
151
152 enterLeaveNamespace(out, true /* enter */);
153 out << "\n";
154
155 if (isInterface) {
156 out << "struct "
157 << ifaceName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700158 << " : public ";
159
160 const Interface *iface = mRootScope->getInterface();
161 const Interface *superType = iface->superType();
162
163 if (superType != NULL) {
164 out << superType->fullName();
165 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700166 out << "::android::hardware::IInterface";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700167 }
168
169 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700170
171 out.indent();
172
Andreas Huber737080b2016-08-02 15:38:04 -0700173 // cut off the leading 'I'.
174 const std::string baseName = ifaceName.substr(1);
175
176 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700177 }
178
179 status_t err = emitTypeDeclarations(out);
180
181 if (err != OK) {
182 return err;
183 }
184
185 if (isInterface) {
186 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700187 const Interface *superType = iface->superType();
Andreas Huber881227d2016-08-02 14:20:21 -0700188
189 out << "enum Call {\n";
190 out.indent();
191
192 bool first = true;
193 for (const auto &method : iface->methods()) {
194 out << upcase(method->name());
195
196 if (first) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700197 out << " = ";
198 if (superType != NULL) {
199 out << superType->fullName()
200 << "::Call::CallCount";
201 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700202 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700203 }
204
Andreas Huber881227d2016-08-02 14:20:21 -0700205 first = false;
206 }
207
208 out << ",\n";
209 }
210
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700211 out << "CallCount\n";
212
Andreas Huber881227d2016-08-02 14:20:21 -0700213 out.unindent();
214 out << "};\n\n";
215
216 bool haveCallbacks = false;
217 for (const auto &method : iface->methods()) {
218 const bool returnsValue = !method->results().empty();
219
220 if (!returnsValue) {
221 continue;
222 }
223
224 haveCallbacks = true;
225
226 out << "using "
227 << method->name()
228 << "_cb = std::function<void("
229 << Method::GetSignature(method->results())
230 << ")>;\n";
231 }
232
233 if (haveCallbacks) {
234 out << "\n";
235 }
236
237 for (const auto &method : iface->methods()) {
238 const bool returnsValue = !method->results().empty();
239
Andreas Huber3599d922016-08-09 10:42:57 -0700240 method->dumpAnnotations(out);
241
Andreas Huber8a82ff72016-08-04 10:29:39 -0700242 out << "virtual ::android::hardware::Status "
Andreas Huber881227d2016-08-02 14:20:21 -0700243 << method->name()
244 << "("
245 << Method::GetSignature(method->args());
246
247 if (returnsValue) {
248 if (!method->args().empty()) {
249 out << ", ";
250 }
251
Iliyan Malchev549e2592016-08-10 08:59:12 -0700252 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700253 }
254
255 out << ") = 0;\n";
256 }
257 }
258
259 if (isInterface) {
260 out.unindent();
261
262 out << "};\n";
263 }
264
265 out << "\n";
266 enterLeaveNamespace(out, false /* enter */);
267
268 out << "\n#endif // " << guard << "\n";
269
270 return OK;
271}
272
273status_t AST::emitTypeDeclarations(Formatter &out) const {
274 return mRootScope->emitTypeDeclarations(out);
275}
276
Andreas Huberb82318c2016-08-02 14:45:54 -0700277status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700278 std::string ifaceName;
279 if (!AST::isInterface(&ifaceName)) {
280 // types.hal does not get a stub header.
281 return OK;
282 }
283
Andreas Huber881227d2016-08-02 14:20:21 -0700284 // cut off the leading 'I'.
285 const std::string baseName = ifaceName.substr(1);
286
Andreas Huberb82318c2016-08-02 14:45:54 -0700287 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700288 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700289 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700290 path.append("Bn");
291 path.append(baseName);
292 path.append(".h");
293
Andreas Huberd2943e12016-08-05 11:59:31 -0700294 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700295 FILE *file = fopen(path.c_str(), "w");
296
297 if (file == NULL) {
298 return -errno;
299 }
300
301 Formatter out(file);
302
303 const std::string guard = makeHeaderGuard("Bn" + baseName);
304
305 out << "#ifndef " << guard << "\n";
306 out << "#define " << guard << "\n\n";
307
308 std::vector<std::string> packageComponents;
309 getPackageAndVersionComponents(
310 &packageComponents, false /* cpp_compatible */);
311
312 out << "#include <";
313 for (const auto &component : packageComponents) {
314 out << component << "/";
315 }
316 out << ifaceName << ".h>\n\n";
317
318 enterLeaveNamespace(out, true /* enter */);
319 out << "\n";
320
321 out << "struct "
322 << "Bn"
323 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700324 << " : public ::android::hardware::BnInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700325 << ifaceName
326 << "> {\n";
327
328 out.indent();
329
330 out << "::android::status_t onTransact(\n";
331 out.indent();
332 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700333 out << "uint32_t _hidl_code,\n";
334 out << "const ::android::hardware::Parcel &_hidl_data,\n";
335 out << "::android::hardware::Parcel *_hidl_reply,\n";
336 out << "uint32_t _hidl_flags = 0,\n";
337 out << "TransactCallback _hidl_cb = nullptr) override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700338 out.unindent();
339 out.unindent();
340
341 out.unindent();
342
343 out << "};\n\n";
344
345 enterLeaveNamespace(out, false /* enter */);
346
347 out << "\n#endif // " << guard << "\n";
348
349 return OK;
350}
351
Andreas Huberb82318c2016-08-02 14:45:54 -0700352status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700353 std::string ifaceName;
354 if (!AST::isInterface(&ifaceName)) {
355 // types.hal does not get a proxy header.
356 return OK;
357 }
358
Andreas Huber881227d2016-08-02 14:20:21 -0700359 // cut off the leading 'I'.
360 const std::string baseName = ifaceName.substr(1);
361
Andreas Huberb82318c2016-08-02 14:45:54 -0700362 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700363 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700364 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700365 path.append("Bp");
366 path.append(baseName);
367 path.append(".h");
368
Andreas Huberd2943e12016-08-05 11:59:31 -0700369 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700370 FILE *file = fopen(path.c_str(), "w");
371
372 if (file == NULL) {
373 return -errno;
374 }
375
376 Formatter out(file);
377
378 const std::string guard = makeHeaderGuard("Bp" + baseName);
379
380 out << "#ifndef " << guard << "\n";
381 out << "#define " << guard << "\n\n";
382
383 std::vector<std::string> packageComponents;
384 getPackageAndVersionComponents(
385 &packageComponents, false /* cpp_compatible */);
386
387 out << "#include <";
388 for (const auto &component : packageComponents) {
389 out << component << "/";
390 }
391 out << ifaceName << ".h>\n\n";
392
393 enterLeaveNamespace(out, true /* enter */);
394 out << "\n";
395
396 out << "struct "
397 << "Bp"
398 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700399 << " : public ::android::hardware::BpInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700400 << ifaceName
401 << "> {\n";
402
403 out.indent();
404
405 out << "explicit Bp"
406 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700407 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700408 << "\n\n";
409
410 const Interface *iface = mRootScope->getInterface();
411
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700412 std::vector<const Interface *> chain;
413 while (iface != NULL) {
414 chain.push_back(iface);
415 iface = iface->superType();
416 }
Andreas Huber881227d2016-08-02 14:20:21 -0700417
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700418 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
419 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700420
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700421 out << "// Methods from "
422 << superInterface->fullName()
423 << " follow.\n";
424
425 for (const auto &method : superInterface->methods()) {
426 const bool returnsValue = !method->results().empty();
427
Andreas Huber8a82ff72016-08-04 10:29:39 -0700428 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700429 << method->name()
430 << "("
431 << Method::GetSignature(method->args());
432
433 if (returnsValue) {
434 if (!method->args().empty()) {
435 out << ", ";
436 }
437
Iliyan Malchev549e2592016-08-10 08:59:12 -0700438 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700439 }
440
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700441 out << ") override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700442 }
443
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700444 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700445 }
446
447 out.unindent();
448
449 out << "};\n\n";
450
451 enterLeaveNamespace(out, false /* enter */);
452
453 out << "\n#endif // " << guard << "\n";
454
455 return OK;
456}
457
Andreas Huberb82318c2016-08-02 14:45:54 -0700458status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700459
Andreas Huberb82318c2016-08-02 14:45:54 -0700460 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700461 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700462 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700463
464 std::string ifaceName;
465 std::string baseName;
466
467 bool isInterface = true;
468 if (!AST::isInterface(&ifaceName)) {
469 baseName = "types";
470 isInterface = false;
471 } else {
472 baseName = ifaceName.substr(1); // cut off the leading 'I'.
473 }
474
475 path.append(baseName);
476
477 if (baseName != "types") {
478 path.append("All");
479 }
480
481 path.append(".cpp");
482
Andreas Huberd2943e12016-08-05 11:59:31 -0700483 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700484 FILE *file = fopen(path.c_str(), "w");
485
486 if (file == NULL) {
487 return -errno;
488 }
489
490 Formatter out(file);
491
492 std::vector<std::string> packageComponents;
493 getPackageAndVersionComponents(
494 &packageComponents, false /* cpp_compatible */);
495
496 std::string prefix;
497 for (const auto &component : packageComponents) {
498 prefix += component;
499 prefix += "/";
500 }
501
502 if (isInterface) {
503 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
504 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
505 } else {
506 out << "#include <" << prefix << "types.h>\n";
507 }
508
509 out << "\n";
510
511 enterLeaveNamespace(out, true /* enter */);
512 out << "\n";
513
514 status_t err = generateTypeSource(out, ifaceName);
515
516 if (err == OK && isInterface) {
517 err = generateProxySource(out, baseName);
518 }
519
520 if (err == OK && isInterface) {
521 err = generateStubSource(out, baseName);
522 }
523
524 enterLeaveNamespace(out, false /* enter */);
525
526 return err;
527}
528
529status_t AST::generateTypeSource(
530 Formatter &out, const std::string &ifaceName) const {
531 return mRootScope->emitTypeDefinitions(out, ifaceName);
532}
533
Andreas Hubere7ff2282016-08-16 13:50:03 -0700534void AST::declareCppReaderLocals(
535 Formatter &out, const std::vector<TypedVar *> &args) const {
536 if (args.empty()) {
537 return;
538 }
539
540 for (const auto &arg : args) {
541 const Type &type = arg->type();
542
543 std::string extra;
544 out << type.getCppResultType(&extra)
545 << " "
546 << arg->name()
547 << extra
548 << ";\n";
549 }
550
551 out << "\n";
552}
553
Andreas Huber881227d2016-08-02 14:20:21 -0700554void AST::emitCppReaderWriter(
555 Formatter &out,
556 const std::string &parcelObj,
557 bool parcelObjIsPointer,
558 const TypedVar *arg,
559 bool isReader,
560 Type::ErrorMode mode) const {
561 const Type &type = arg->type();
562
Andreas Huber881227d2016-08-02 14:20:21 -0700563 type.emitReaderWriter(
564 out,
565 arg->name(),
566 parcelObj,
567 parcelObjIsPointer,
568 isReader,
569 mode);
570}
571
572status_t AST::generateProxySource(
573 Formatter &out, const std::string &baseName) const {
574 const std::string klassName = "Bp" + baseName;
575
576 out << klassName
577 << "::"
578 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700579 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700580
581 out.indent();
582 out.indent();
583
584 out << ": BpInterface"
585 << "<I"
586 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700587 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700588
589 out.unindent();
590 out.unindent();
591 out << "}\n\n";
592
593 const Interface *iface = mRootScope->getInterface();
594
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700595 std::vector<const Interface *> chain;
596 while (iface != NULL) {
597 chain.push_back(iface);
598 iface = iface->superType();
599 }
Andreas Huber881227d2016-08-02 14:20:21 -0700600
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700601 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
602 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700603
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700604 for (const auto &method : superInterface->methods()) {
605 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700606
Andreas Huber8a82ff72016-08-04 10:29:39 -0700607 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700608 << klassName
609 << "::"
610 << method->name()
611 << "("
612 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700613
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700614 if (returnsValue) {
615 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700616 out << ", ";
617 }
618
Iliyan Malchev549e2592016-08-10 08:59:12 -0700619 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700620 }
621
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700622 out << ") {\n";
623
624 out.indent();
625
Iliyan Malchev549e2592016-08-10 08:59:12 -0700626 out << "::android::hardware::Parcel _hidl_data;\n";
627 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700628 out << "::android::status_t _hidl_err;\n";
629 out << "::android::hardware::Status _hidl_status;\n\n";
630
631 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700632
Iliyan Malchev549e2592016-08-10 08:59:12 -0700633 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700634 << superInterface->fullName()
635 << "::getInterfaceDescriptor());\n";
636
Iliyan Malchev549e2592016-08-10 08:59:12 -0700637 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700638
639 for (const auto &arg : method->args()) {
640 emitCppReaderWriter(
641 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700642 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700643 false /* parcelObjIsPointer */,
644 arg,
645 false /* reader */,
646 Type::ErrorMode_Goto);
647 }
648
Iliyan Malchev549e2592016-08-10 08:59:12 -0700649 out << "_hidl_err = remote()->transact(I"
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700650 << baseName
651 << "::"
652 << upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700653 << ", _hidl_data, &_hidl_reply";
654 if (method->isOneway()) {
655 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700656 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700657 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700658
Iliyan Malchev639bff82016-08-13 14:24:11 -0700659 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700660
Iliyan Malchev639bff82016-08-13 14:24:11 -0700661 if (!method->isOneway()) {
662 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
663 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
664
665 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
666
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700667 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700668 emitCppReaderWriter(
669 out,
670 "_hidl_reply",
671 false /* parcelObjIsPointer */,
672 arg,
673 true /* reader */,
674 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700675 }
676
Iliyan Malchev639bff82016-08-13 14:24:11 -0700677 if (returnsValue) {
678 out << "if (_hidl_cb != nullptr) {\n";
679 out.indent();
680 out << "_hidl_cb(";
681
682 bool first = true;
683 for (const auto &arg : method->results()) {
684 if (!first) {
685 out << ", ";
686 }
687
688 if (arg->type().resultNeedsDeref()) {
689 out << "*";
690 }
691 out << arg->name();
692
693 first = false;
694 }
695
696 out << ");\n";
697 out.unindent();
698 out << "}\n\n";
699 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700700 }
701
702 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700703 out << "_hidl_error:\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700704 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700705 out << "_hidl_status.setFromStatusT(_hidl_err);\n"
706 << "return _hidl_status;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700707
Andreas Huber881227d2016-08-02 14:20:21 -0700708 out.unindent();
709 out << "}\n\n";
710 }
Andreas Huber881227d2016-08-02 14:20:21 -0700711 }
712
713 return OK;
714}
715
716status_t AST::generateStubSource(
717 Formatter &out, const std::string &baseName) const {
718 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
719 << baseName
720 << ", \""
721 << mPackage.string()
722 << "::I"
723 << baseName
724 << "\");\n\n";
725
726 const std::string klassName = "Bn" + baseName;
727
728 out << "::android::status_t " << klassName << "::onTransact(\n";
729
730 out.indent();
731 out.indent();
732
Iliyan Malchev549e2592016-08-10 08:59:12 -0700733 out << "uint32_t _hidl_code,\n"
734 << "const ::android::hardware::Parcel &_hidl_data,\n"
735 << "::android::hardware::Parcel *_hidl_reply,\n"
736 << "uint32_t _hidl_flags,\n"
737 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700738
739 out.unindent();
740
Iliyan Malchev549e2592016-08-10 08:59:12 -0700741 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700742
Iliyan Malchev549e2592016-08-10 08:59:12 -0700743 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700744 out.indent();
745
746 const Interface *iface = mRootScope->getInterface();
747
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700748 std::vector<const Interface *> chain;
749 while (iface != NULL) {
750 chain.push_back(iface);
751 iface = iface->superType();
752 }
Andreas Huber881227d2016-08-02 14:20:21 -0700753
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700754 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
755 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700756
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700757 for (const auto &method : superInterface->methods()) {
758 out << "case "
759 << superInterface->fullName()
760 << "::Call::"
761 << upcase(method->name())
762 << ":\n{\n";
763
764 out.indent();
765
766 status_t err =
767 generateStubSourceForMethod(out, superInterface, method);
768
769 if (err != OK) {
770 return err;
771 }
772
773 out.unindent();
774 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700775 }
Andreas Huber881227d2016-08-02 14:20:21 -0700776 }
777
778 out << "default:\n{\n";
779 out.indent();
780
Andreas Huber8a82ff72016-08-04 10:29:39 -0700781 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700782 << baseName
783 << ">::onTransact(\n";
784
785 out.indent();
786 out.indent();
787
Iliyan Malchev549e2592016-08-10 08:59:12 -0700788 out << "_hidl_code, _hidl_data, _hidl_reply, "
789 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700790
791 out.unindent();
792 out.unindent();
793
794 out.unindent();
795 out << "}\n";
796
797 out.unindent();
798 out << "}\n\n";
799
Iliyan Malchev549e2592016-08-10 08:59:12 -0700800 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700801 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700802 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700803 out.indent();
804 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700805 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700806 out.indent();
807 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700808 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700809 out.unindent();
810 out.unindent();
811 out.unindent();
812 out.unindent();
813
814 out.unindent();
815 out << "}\n\n";
816
Iliyan Malchev549e2592016-08-10 08:59:12 -0700817 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700818
819 out.unindent();
820 out << "}\n\n";
821
822 return OK;
823}
824
825status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700826 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700827 out << "if (!_hidl_data.enforceInterface("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700828 << iface->fullName()
829 << "::getInterfaceDescriptor())) {\n";
830
Andreas Huber881227d2016-08-02 14:20:21 -0700831 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700832 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700833 out << "break;\n";
834 out.unindent();
835 out << "}\n\n";
836
Andreas Hubere7ff2282016-08-16 13:50:03 -0700837 declareCppReaderLocals(out, method->args());
838
Andreas Huber881227d2016-08-02 14:20:21 -0700839 for (const auto &arg : method->args()) {
840 emitCppReaderWriter(
841 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700842 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -0700843 false /* parcelObjIsPointer */,
844 arg,
845 true /* reader */,
846 Type::ErrorMode_Break);
847 }
848
849 const bool returnsValue = !method->results().empty();
850
851 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700852 out << "bool _hidl_callbackCalled = false;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700853 }
854
Iliyan Malchev549e2592016-08-10 08:59:12 -0700855 out << "::android::hardware::Status _hidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700856 out.indent();
857 out.indent();
858 out << method->name() << "(";
859
860 bool first = true;
861 for (const auto &arg : method->args()) {
862 if (!first) {
863 out << ", ";
864 }
865
866 if (arg->type().resultNeedsDeref()) {
867 out << "*";
868 }
869
870 out << arg->name();
871
872 first = false;
873 }
874
875 if (returnsValue) {
876 if (!first) {
877 out << ", ";
878 }
879
880 out << "[&](";
881
882 first = true;
883 for (const auto &arg : method->results()) {
884 if (!first) {
885 out << ", ";
886 }
887
888 out << "const auto &" << arg->name();
889
890 first = false;
891 }
892
893 out << ") {\n";
894 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700895 out << "_hidl_callbackCalled = true;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700896
Andreas Huber8a82ff72016-08-04 10:29:39 -0700897 out << "::android::hardware::Status::ok()"
Iliyan Malchev549e2592016-08-10 08:59:12 -0700898 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700899
900 for (const auto &arg : method->results()) {
901 emitCppReaderWriter(
902 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700903 "_hidl_reply",
Andreas Huber881227d2016-08-02 14:20:21 -0700904 true /* parcelObjIsPointer */,
905 arg,
906 false /* reader */,
907 Type::ErrorMode_Ignore);
908 }
909
Iliyan Malchev549e2592016-08-10 08:59:12 -0700910 out << "_hidl_cb(*_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700911
912 out.unindent();
913 out << "}\n";
914 }
915
916 out.unindent();
917 out.unindent();
918 out << "));\n\n";
919
920 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700921 out << "if (!_hidl_callbackCalled) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700922 out.indent();
923 }
924
Iliyan Malchev549e2592016-08-10 08:59:12 -0700925 out << "_hidl_err = _hidl_status.writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700926
927 if (returnsValue) {
928 out.unindent();
929 out << "}\n\n";
930 }
931
932 out << "break;\n";
933
934 return OK;
935}
936
937} // namespace android
938