blob: 1fc98bf6dbff733d72c2f4362a6adb49824bc5c0 [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
534void AST::emitCppReaderWriter(
535 Formatter &out,
536 const std::string &parcelObj,
537 bool parcelObjIsPointer,
538 const TypedVar *arg,
539 bool isReader,
540 Type::ErrorMode mode) const {
541 const Type &type = arg->type();
542
543 if (isReader) {
544 std::string extra;
545 out << type.getCppResultType(&extra)
546 << " "
547 << arg->name()
548 << extra
549 << ";\n";
550 }
551
552 type.emitReaderWriter(
553 out,
554 arg->name(),
555 parcelObj,
556 parcelObjIsPointer,
557 isReader,
558 mode);
559}
560
561status_t AST::generateProxySource(
562 Formatter &out, const std::string &baseName) const {
563 const std::string klassName = "Bp" + baseName;
564
565 out << klassName
566 << "::"
567 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700568 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700569
570 out.indent();
571 out.indent();
572
573 out << ": BpInterface"
574 << "<I"
575 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700576 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700577
578 out.unindent();
579 out.unindent();
580 out << "}\n\n";
581
582 const Interface *iface = mRootScope->getInterface();
583
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700584 std::vector<const Interface *> chain;
585 while (iface != NULL) {
586 chain.push_back(iface);
587 iface = iface->superType();
588 }
Andreas Huber881227d2016-08-02 14:20:21 -0700589
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700590 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
591 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700592
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700593 for (const auto &method : superInterface->methods()) {
594 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700595
Andreas Huber8a82ff72016-08-04 10:29:39 -0700596 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700597 << klassName
598 << "::"
599 << method->name()
600 << "("
601 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700602
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700603 if (returnsValue) {
604 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700605 out << ", ";
606 }
607
Iliyan Malchev549e2592016-08-10 08:59:12 -0700608 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700609 }
610
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700611 out << ") {\n";
612
613 out.indent();
614
Iliyan Malchev549e2592016-08-10 08:59:12 -0700615 out << "::android::hardware::Parcel _hidl_data;\n";
616 out << "::android::hardware::Parcel _hidl_reply;\n";
617 out << "::android::status_t _hidl_err;\n\n";
618 out << "::android::hardware::Status _hidl_status;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700619
Iliyan Malchev549e2592016-08-10 08:59:12 -0700620 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700621 << superInterface->fullName()
622 << "::getInterfaceDescriptor());\n";
623
Iliyan Malchev549e2592016-08-10 08:59:12 -0700624 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700625
626 for (const auto &arg : method->args()) {
627 emitCppReaderWriter(
628 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700629 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700630 false /* parcelObjIsPointer */,
631 arg,
632 false /* reader */,
633 Type::ErrorMode_Goto);
634 }
635
Iliyan Malchev549e2592016-08-10 08:59:12 -0700636 out << "_hidl_err = remote()->transact(I"
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700637 << baseName
638 << "::"
639 << upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700640 << ", _hidl_data, &_hidl_reply";
641 if (method->isOneway()) {
642 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700643 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700644 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700645
Iliyan Malchev639bff82016-08-13 14:24:11 -0700646 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700647
Iliyan Malchev639bff82016-08-13 14:24:11 -0700648 if (!method->isOneway()) {
649 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
650 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
651
652 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
653
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700654 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700655 emitCppReaderWriter(
656 out,
657 "_hidl_reply",
658 false /* parcelObjIsPointer */,
659 arg,
660 true /* reader */,
661 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700662 }
663
Iliyan Malchev639bff82016-08-13 14:24:11 -0700664 if (returnsValue) {
665 out << "if (_hidl_cb != nullptr) {\n";
666 out.indent();
667 out << "_hidl_cb(";
668
669 bool first = true;
670 for (const auto &arg : method->results()) {
671 if (!first) {
672 out << ", ";
673 }
674
675 if (arg->type().resultNeedsDeref()) {
676 out << "*";
677 }
678 out << arg->name();
679
680 first = false;
681 }
682
683 out << ");\n";
684 out.unindent();
685 out << "}\n\n";
686 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700687 }
688
689 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700690 out << "_hidl_error:\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700691 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700692 out << "_hidl_status.setFromStatusT(_hidl_err);\n"
693 << "return _hidl_status;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700694
Andreas Huber881227d2016-08-02 14:20:21 -0700695 out.unindent();
696 out << "}\n\n";
697 }
Andreas Huber881227d2016-08-02 14:20:21 -0700698 }
699
700 return OK;
701}
702
703status_t AST::generateStubSource(
704 Formatter &out, const std::string &baseName) const {
705 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
706 << baseName
707 << ", \""
708 << mPackage.string()
709 << "::I"
710 << baseName
711 << "\");\n\n";
712
713 const std::string klassName = "Bn" + baseName;
714
715 out << "::android::status_t " << klassName << "::onTransact(\n";
716
717 out.indent();
718 out.indent();
719
Iliyan Malchev549e2592016-08-10 08:59:12 -0700720 out << "uint32_t _hidl_code,\n"
721 << "const ::android::hardware::Parcel &_hidl_data,\n"
722 << "::android::hardware::Parcel *_hidl_reply,\n"
723 << "uint32_t _hidl_flags,\n"
724 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700725
726 out.unindent();
727
Iliyan Malchev549e2592016-08-10 08:59:12 -0700728 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700729
Iliyan Malchev549e2592016-08-10 08:59:12 -0700730 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700731 out.indent();
732
733 const Interface *iface = mRootScope->getInterface();
734
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700735 std::vector<const Interface *> chain;
736 while (iface != NULL) {
737 chain.push_back(iface);
738 iface = iface->superType();
739 }
Andreas Huber881227d2016-08-02 14:20:21 -0700740
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700741 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
742 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700743
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700744 for (const auto &method : superInterface->methods()) {
745 out << "case "
746 << superInterface->fullName()
747 << "::Call::"
748 << upcase(method->name())
749 << ":\n{\n";
750
751 out.indent();
752
753 status_t err =
754 generateStubSourceForMethod(out, superInterface, method);
755
756 if (err != OK) {
757 return err;
758 }
759
760 out.unindent();
761 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700762 }
Andreas Huber881227d2016-08-02 14:20:21 -0700763 }
764
765 out << "default:\n{\n";
766 out.indent();
767
Andreas Huber8a82ff72016-08-04 10:29:39 -0700768 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700769 << baseName
770 << ">::onTransact(\n";
771
772 out.indent();
773 out.indent();
774
Iliyan Malchev549e2592016-08-10 08:59:12 -0700775 out << "_hidl_code, _hidl_data, _hidl_reply, "
776 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700777
778 out.unindent();
779 out.unindent();
780
781 out.unindent();
782 out << "}\n";
783
784 out.unindent();
785 out << "}\n\n";
786
Iliyan Malchev549e2592016-08-10 08:59:12 -0700787 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700788 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700789 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700790 out.indent();
791 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700792 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700793 out.indent();
794 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700795 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700796 out.unindent();
797 out.unindent();
798 out.unindent();
799 out.unindent();
800
801 out.unindent();
802 out << "}\n\n";
803
Iliyan Malchev549e2592016-08-10 08:59:12 -0700804 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700805
806 out.unindent();
807 out << "}\n\n";
808
809 return OK;
810}
811
812status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700813 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700814 out << "if (!_hidl_data.enforceInterface("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700815 << iface->fullName()
816 << "::getInterfaceDescriptor())) {\n";
817
Andreas Huber881227d2016-08-02 14:20:21 -0700818 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700819 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700820 out << "break;\n";
821 out.unindent();
822 out << "}\n\n";
823
824 for (const auto &arg : method->args()) {
825 emitCppReaderWriter(
826 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700827 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -0700828 false /* parcelObjIsPointer */,
829 arg,
830 true /* reader */,
831 Type::ErrorMode_Break);
832 }
833
834 const bool returnsValue = !method->results().empty();
835
836 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700837 out << "bool _hidl_callbackCalled = false;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700838 }
839
Iliyan Malchev549e2592016-08-10 08:59:12 -0700840 out << "::android::hardware::Status _hidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700841 out.indent();
842 out.indent();
843 out << method->name() << "(";
844
845 bool first = true;
846 for (const auto &arg : method->args()) {
847 if (!first) {
848 out << ", ";
849 }
850
851 if (arg->type().resultNeedsDeref()) {
852 out << "*";
853 }
854
855 out << arg->name();
856
857 first = false;
858 }
859
860 if (returnsValue) {
861 if (!first) {
862 out << ", ";
863 }
864
865 out << "[&](";
866
867 first = true;
868 for (const auto &arg : method->results()) {
869 if (!first) {
870 out << ", ";
871 }
872
873 out << "const auto &" << arg->name();
874
875 first = false;
876 }
877
878 out << ") {\n";
879 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700880 out << "_hidl_callbackCalled = true;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700881
Andreas Huber8a82ff72016-08-04 10:29:39 -0700882 out << "::android::hardware::Status::ok()"
Iliyan Malchev549e2592016-08-10 08:59:12 -0700883 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700884
885 for (const auto &arg : method->results()) {
886 emitCppReaderWriter(
887 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700888 "_hidl_reply",
Andreas Huber881227d2016-08-02 14:20:21 -0700889 true /* parcelObjIsPointer */,
890 arg,
891 false /* reader */,
892 Type::ErrorMode_Ignore);
893 }
894
Iliyan Malchev549e2592016-08-10 08:59:12 -0700895 out << "_hidl_cb(*_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700896
897 out.unindent();
898 out << "}\n";
899 }
900
901 out.unindent();
902 out.unindent();
903 out << "));\n\n";
904
905 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700906 out << "if (!_hidl_callbackCalled) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700907 out.indent();
908 }
909
Iliyan Malchev549e2592016-08-10 08:59:12 -0700910 out << "_hidl_err = _hidl_status.writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700911
912 if (returnsValue) {
913 out.unindent();
914 out << "}\n\n";
915 }
916
917 out << "break;\n";
918
919 return OK;
920}
921
922} // namespace android
923