blob: a8f95a610892958ff01d912aa332a0e9ab9d7891 [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
82 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 Malchev549e2592016-08-10 08:59:12 -0700640 << ", _hidl_data, &_hidl_reply);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700641
Iliyan Malchev549e2592016-08-10 08:59:12 -0700642 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700643
Iliyan Malchev549e2592016-08-10 08:59:12 -0700644 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
645 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700646
Iliyan Malchev549e2592016-08-10 08:59:12 -0700647 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700648
649 for (const auto &arg : method->results()) {
650 emitCppReaderWriter(
651 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700652 "_hidl_reply",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700653 false /* parcelObjIsPointer */,
654 arg,
655 true /* reader */,
656 Type::ErrorMode_Goto);
657 }
658
659 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700660 out << "if (_hidl_cb != nullptr) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700661 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700662 out << "_hidl_cb(";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700663
664 bool first = true;
665 for (const auto &arg : method->results()) {
666 if (!first) {
667 out << ", ";
668 }
669
670 if (arg->type().resultNeedsDeref()) {
671 out << "*";
672 }
673 out << arg->name();
674
675 first = false;
676 }
677
678 out << ");\n";
679 out.unindent();
680 out << "}\n\n";
681 }
682
683 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700684 out << "_hidl_error:\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700685 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700686 out << "_hidl_status.setFromStatusT(_hidl_err);\n"
687 << "return _hidl_status;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700688
Andreas Huber881227d2016-08-02 14:20:21 -0700689 out.unindent();
690 out << "}\n\n";
691 }
Andreas Huber881227d2016-08-02 14:20:21 -0700692 }
693
694 return OK;
695}
696
697status_t AST::generateStubSource(
698 Formatter &out, const std::string &baseName) const {
699 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
700 << baseName
701 << ", \""
702 << mPackage.string()
703 << "::I"
704 << baseName
705 << "\");\n\n";
706
707 const std::string klassName = "Bn" + baseName;
708
709 out << "::android::status_t " << klassName << "::onTransact(\n";
710
711 out.indent();
712 out.indent();
713
Iliyan Malchev549e2592016-08-10 08:59:12 -0700714 out << "uint32_t _hidl_code,\n"
715 << "const ::android::hardware::Parcel &_hidl_data,\n"
716 << "::android::hardware::Parcel *_hidl_reply,\n"
717 << "uint32_t _hidl_flags,\n"
718 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700719
720 out.unindent();
721
Iliyan Malchev549e2592016-08-10 08:59:12 -0700722 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700723
Iliyan Malchev549e2592016-08-10 08:59:12 -0700724 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700725 out.indent();
726
727 const Interface *iface = mRootScope->getInterface();
728
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700729 std::vector<const Interface *> chain;
730 while (iface != NULL) {
731 chain.push_back(iface);
732 iface = iface->superType();
733 }
Andreas Huber881227d2016-08-02 14:20:21 -0700734
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700735 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
736 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700737
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700738 for (const auto &method : superInterface->methods()) {
739 out << "case "
740 << superInterface->fullName()
741 << "::Call::"
742 << upcase(method->name())
743 << ":\n{\n";
744
745 out.indent();
746
747 status_t err =
748 generateStubSourceForMethod(out, superInterface, method);
749
750 if (err != OK) {
751 return err;
752 }
753
754 out.unindent();
755 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700756 }
Andreas Huber881227d2016-08-02 14:20:21 -0700757 }
758
759 out << "default:\n{\n";
760 out.indent();
761
Andreas Huber8a82ff72016-08-04 10:29:39 -0700762 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700763 << baseName
764 << ">::onTransact(\n";
765
766 out.indent();
767 out.indent();
768
Iliyan Malchev549e2592016-08-10 08:59:12 -0700769 out << "_hidl_code, _hidl_data, _hidl_reply, "
770 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700771
772 out.unindent();
773 out.unindent();
774
775 out.unindent();
776 out << "}\n";
777
778 out.unindent();
779 out << "}\n\n";
780
Iliyan Malchev549e2592016-08-10 08:59:12 -0700781 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700782 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700783 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700784 out.indent();
785 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700786 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700787 out.indent();
788 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700789 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700790 out.unindent();
791 out.unindent();
792 out.unindent();
793 out.unindent();
794
795 out.unindent();
796 out << "}\n\n";
797
Iliyan Malchev549e2592016-08-10 08:59:12 -0700798 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700799
800 out.unindent();
801 out << "}\n\n";
802
803 return OK;
804}
805
806status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700807 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700808 out << "if (!_hidl_data.enforceInterface("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700809 << iface->fullName()
810 << "::getInterfaceDescriptor())) {\n";
811
Andreas Huber881227d2016-08-02 14:20:21 -0700812 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700813 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700814 out << "break;\n";
815 out.unindent();
816 out << "}\n\n";
817
818 for (const auto &arg : method->args()) {
819 emitCppReaderWriter(
820 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700821 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -0700822 false /* parcelObjIsPointer */,
823 arg,
824 true /* reader */,
825 Type::ErrorMode_Break);
826 }
827
828 const bool returnsValue = !method->results().empty();
829
830 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700831 out << "bool _hidl_callbackCalled = false;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700832 }
833
Iliyan Malchev549e2592016-08-10 08:59:12 -0700834 out << "::android::hardware::Status _hidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700835 out.indent();
836 out.indent();
837 out << method->name() << "(";
838
839 bool first = true;
840 for (const auto &arg : method->args()) {
841 if (!first) {
842 out << ", ";
843 }
844
845 if (arg->type().resultNeedsDeref()) {
846 out << "*";
847 }
848
849 out << arg->name();
850
851 first = false;
852 }
853
854 if (returnsValue) {
855 if (!first) {
856 out << ", ";
857 }
858
859 out << "[&](";
860
861 first = true;
862 for (const auto &arg : method->results()) {
863 if (!first) {
864 out << ", ";
865 }
866
867 out << "const auto &" << arg->name();
868
869 first = false;
870 }
871
872 out << ") {\n";
873 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700874 out << "_hidl_callbackCalled = true;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700875
Andreas Huber8a82ff72016-08-04 10:29:39 -0700876 out << "::android::hardware::Status::ok()"
Iliyan Malchev549e2592016-08-10 08:59:12 -0700877 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700878
879 for (const auto &arg : method->results()) {
880 emitCppReaderWriter(
881 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700882 "_hidl_reply",
Andreas Huber881227d2016-08-02 14:20:21 -0700883 true /* parcelObjIsPointer */,
884 arg,
885 false /* reader */,
886 Type::ErrorMode_Ignore);
887 }
888
Iliyan Malchev549e2592016-08-10 08:59:12 -0700889 out << "_hidl_cb(*_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700890
891 out.unindent();
892 out << "}\n";
893 }
894
895 out.unindent();
896 out.unindent();
897 out << "));\n\n";
898
899 if (returnsValue) {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700900 out << "if (!_hidl_callbackCalled) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700901 out.indent();
902 }
903
Iliyan Malchev549e2592016-08-10 08:59:12 -0700904 out << "_hidl_err = _hidl_status.writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700905
906 if (returnsValue) {
907 out.unindent();
908 out << "}\n\n";
909 }
910
911 out << "break;\n";
912
913 return OK;
914}
915
916} // namespace android
917