blob: 8e6da68476febdebe479f4ab2bebabf92b98ea39 [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 Huber8a82ff72016-08-04 10:29:39 -0700240 out << "virtual ::android::hardware::Status "
Andreas Huber881227d2016-08-02 14:20:21 -0700241 << method->name()
242 << "("
243 << Method::GetSignature(method->args());
244
245 if (returnsValue) {
246 if (!method->args().empty()) {
247 out << ", ";
248 }
249
250 out << method->name() << "_cb _aidl_cb = nullptr";
251 }
252
253 out << ") = 0;\n";
254 }
255 }
256
257 if (isInterface) {
258 out.unindent();
259
260 out << "};\n";
261 }
262
263 out << "\n";
264 enterLeaveNamespace(out, false /* enter */);
265
266 out << "\n#endif // " << guard << "\n";
267
268 return OK;
269}
270
271status_t AST::emitTypeDeclarations(Formatter &out) const {
272 return mRootScope->emitTypeDeclarations(out);
273}
274
Andreas Huberb82318c2016-08-02 14:45:54 -0700275status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700276 std::string ifaceName;
277 if (!AST::isInterface(&ifaceName)) {
278 // types.hal does not get a stub header.
279 return OK;
280 }
281
Andreas Huber881227d2016-08-02 14:20:21 -0700282 // cut off the leading 'I'.
283 const std::string baseName = ifaceName.substr(1);
284
Andreas Huberb82318c2016-08-02 14:45:54 -0700285 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700286 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700287 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700288 path.append("Bn");
289 path.append(baseName);
290 path.append(".h");
291
Andreas Huberd2943e12016-08-05 11:59:31 -0700292 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700293 FILE *file = fopen(path.c_str(), "w");
294
295 if (file == NULL) {
296 return -errno;
297 }
298
299 Formatter out(file);
300
301 const std::string guard = makeHeaderGuard("Bn" + baseName);
302
303 out << "#ifndef " << guard << "\n";
304 out << "#define " << guard << "\n\n";
305
306 std::vector<std::string> packageComponents;
307 getPackageAndVersionComponents(
308 &packageComponents, false /* cpp_compatible */);
309
310 out << "#include <";
311 for (const auto &component : packageComponents) {
312 out << component << "/";
313 }
314 out << ifaceName << ".h>\n\n";
315
316 enterLeaveNamespace(out, true /* enter */);
317 out << "\n";
318
319 out << "struct "
320 << "Bn"
321 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700322 << " : public ::android::hardware::BnInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700323 << ifaceName
324 << "> {\n";
325
326 out.indent();
327
328 out << "::android::status_t onTransact(\n";
329 out.indent();
330 out.indent();
331 out << "uint32_t _aidl_code,\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700332 out << "const ::android::hardware::Parcel &_aidl_data,\n";
333 out << "::android::hardware::Parcel *_aidl_reply,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700334 out << "uint32_t _aidl_flags = 0,\n";
335 out << "TransactCallback _aidl_cb = nullptr) override;\n";
336 out.unindent();
337 out.unindent();
338
339 out.unindent();
340
341 out << "};\n\n";
342
343 enterLeaveNamespace(out, false /* enter */);
344
345 out << "\n#endif // " << guard << "\n";
346
347 return OK;
348}
349
Andreas Huberb82318c2016-08-02 14:45:54 -0700350status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700351 std::string ifaceName;
352 if (!AST::isInterface(&ifaceName)) {
353 // types.hal does not get a proxy header.
354 return OK;
355 }
356
Andreas Huber881227d2016-08-02 14:20:21 -0700357 // cut off the leading 'I'.
358 const std::string baseName = ifaceName.substr(1);
359
Andreas Huberb82318c2016-08-02 14:45:54 -0700360 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700361 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700362 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700363 path.append("Bp");
364 path.append(baseName);
365 path.append(".h");
366
Andreas Huberd2943e12016-08-05 11:59:31 -0700367 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700368 FILE *file = fopen(path.c_str(), "w");
369
370 if (file == NULL) {
371 return -errno;
372 }
373
374 Formatter out(file);
375
376 const std::string guard = makeHeaderGuard("Bp" + baseName);
377
378 out << "#ifndef " << guard << "\n";
379 out << "#define " << guard << "\n\n";
380
381 std::vector<std::string> packageComponents;
382 getPackageAndVersionComponents(
383 &packageComponents, false /* cpp_compatible */);
384
385 out << "#include <";
386 for (const auto &component : packageComponents) {
387 out << component << "/";
388 }
389 out << ifaceName << ".h>\n\n";
390
391 enterLeaveNamespace(out, true /* enter */);
392 out << "\n";
393
394 out << "struct "
395 << "Bp"
396 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700397 << " : public ::android::hardware::BpInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700398 << ifaceName
399 << "> {\n";
400
401 out.indent();
402
403 out << "explicit Bp"
404 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700405 << "(const ::android::sp<::android::hardware::IBinder> &_aidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700406 << "\n\n";
407
408 const Interface *iface = mRootScope->getInterface();
409
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700410 std::vector<const Interface *> chain;
411 while (iface != NULL) {
412 chain.push_back(iface);
413 iface = iface->superType();
414 }
Andreas Huber881227d2016-08-02 14:20:21 -0700415
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700416 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
417 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700418
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700419 out << "// Methods from "
420 << superInterface->fullName()
421 << " follow.\n";
422
423 for (const auto &method : superInterface->methods()) {
424 const bool returnsValue = !method->results().empty();
425
Andreas Huber8a82ff72016-08-04 10:29:39 -0700426 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700427 << method->name()
428 << "("
429 << Method::GetSignature(method->args());
430
431 if (returnsValue) {
432 if (!method->args().empty()) {
433 out << ", ";
434 }
435
436 out << method->name() << "_cb _aidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700437 }
438
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700439 out << ") override;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700440 }
441
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700442 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700443 }
444
445 out.unindent();
446
447 out << "};\n\n";
448
449 enterLeaveNamespace(out, false /* enter */);
450
451 out << "\n#endif // " << guard << "\n";
452
453 return OK;
454}
455
Andreas Huberb82318c2016-08-02 14:45:54 -0700456status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700457
Andreas Huberb82318c2016-08-02 14:45:54 -0700458 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700459 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700460 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700461
462 std::string ifaceName;
463 std::string baseName;
464
465 bool isInterface = true;
466 if (!AST::isInterface(&ifaceName)) {
467 baseName = "types";
468 isInterface = false;
469 } else {
470 baseName = ifaceName.substr(1); // cut off the leading 'I'.
471 }
472
473 path.append(baseName);
474
475 if (baseName != "types") {
476 path.append("All");
477 }
478
479 path.append(".cpp");
480
Andreas Huberd2943e12016-08-05 11:59:31 -0700481 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700482 FILE *file = fopen(path.c_str(), "w");
483
484 if (file == NULL) {
485 return -errno;
486 }
487
488 Formatter out(file);
489
490 std::vector<std::string> packageComponents;
491 getPackageAndVersionComponents(
492 &packageComponents, false /* cpp_compatible */);
493
494 std::string prefix;
495 for (const auto &component : packageComponents) {
496 prefix += component;
497 prefix += "/";
498 }
499
500 if (isInterface) {
501 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
502 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
503 } else {
504 out << "#include <" << prefix << "types.h>\n";
505 }
506
507 out << "\n";
508
509 enterLeaveNamespace(out, true /* enter */);
510 out << "\n";
511
512 status_t err = generateTypeSource(out, ifaceName);
513
514 if (err == OK && isInterface) {
515 err = generateProxySource(out, baseName);
516 }
517
518 if (err == OK && isInterface) {
519 err = generateStubSource(out, baseName);
520 }
521
522 enterLeaveNamespace(out, false /* enter */);
523
524 return err;
525}
526
527status_t AST::generateTypeSource(
528 Formatter &out, const std::string &ifaceName) const {
529 return mRootScope->emitTypeDefinitions(out, ifaceName);
530}
531
532void AST::emitCppReaderWriter(
533 Formatter &out,
534 const std::string &parcelObj,
535 bool parcelObjIsPointer,
536 const TypedVar *arg,
537 bool isReader,
538 Type::ErrorMode mode) const {
539 const Type &type = arg->type();
540
541 if (isReader) {
542 std::string extra;
543 out << type.getCppResultType(&extra)
544 << " "
545 << arg->name()
546 << extra
547 << ";\n";
548 }
549
550 type.emitReaderWriter(
551 out,
552 arg->name(),
553 parcelObj,
554 parcelObjIsPointer,
555 isReader,
556 mode);
557}
558
559status_t AST::generateProxySource(
560 Formatter &out, const std::string &baseName) const {
561 const std::string klassName = "Bp" + baseName;
562
563 out << klassName
564 << "::"
565 << klassName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700566 << "(const ::android::sp<::android::hardware::IBinder> &_aidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700567
568 out.indent();
569 out.indent();
570
571 out << ": BpInterface"
572 << "<I"
573 << baseName
574 << ">(_aidl_impl) {\n";
575
576 out.unindent();
577 out.unindent();
578 out << "}\n\n";
579
580 const Interface *iface = mRootScope->getInterface();
581
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700582 std::vector<const Interface *> chain;
583 while (iface != NULL) {
584 chain.push_back(iface);
585 iface = iface->superType();
586 }
Andreas Huber881227d2016-08-02 14:20:21 -0700587
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700588 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
589 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700590
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700591 for (const auto &method : superInterface->methods()) {
592 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700593
Andreas Huber8a82ff72016-08-04 10:29:39 -0700594 out << "::android::hardware::Status "
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700595 << klassName
596 << "::"
597 << method->name()
598 << "("
599 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700600
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700601 if (returnsValue) {
602 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700603 out << ", ";
604 }
605
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700606 out << method->name() << "_cb _aidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700607 }
608
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700609 out << ") {\n";
610
611 out.indent();
612
Andreas Huber8a82ff72016-08-04 10:29:39 -0700613 out << "::android::hardware::Parcel _aidl_data;\n";
614 out << "::android::hardware::Parcel _aidl_reply;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700615 out << "::android::status_t _aidl_err;\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700616 out << "::android::hardware::Status _aidl_status;\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700617
618 out << "_aidl_err = _aidl_data.writeInterfaceToken("
619 << superInterface->fullName()
620 << "::getInterfaceDescriptor());\n";
621
622 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
623
624 for (const auto &arg : method->args()) {
625 emitCppReaderWriter(
626 out,
627 "_aidl_data",
628 false /* parcelObjIsPointer */,
629 arg,
630 false /* reader */,
631 Type::ErrorMode_Goto);
632 }
633
634 out << "_aidl_err = remote()->transact(I"
635 << baseName
636 << "::"
637 << upcase(method->name())
638 << ", _aidl_data, &_aidl_reply);\n";
639
640 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
641
642 out << "_aidl_err = _aidl_status.readFromParcel(_aidl_reply);\n";
643 out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
644
645 out << "if (!_aidl_status.isOk()) { return _aidl_status; }\n\n";
646
647 for (const auto &arg : method->results()) {
648 emitCppReaderWriter(
649 out,
650 "_aidl_reply",
651 false /* parcelObjIsPointer */,
652 arg,
653 true /* reader */,
654 Type::ErrorMode_Goto);
655 }
656
657 if (returnsValue) {
658 out << "if (_aidl_cb != nullptr) {\n";
659 out.indent();
660 out << "_aidl_cb(";
661
662 bool first = true;
663 for (const auto &arg : method->results()) {
664 if (!first) {
665 out << ", ";
666 }
667
668 if (arg->type().resultNeedsDeref()) {
669 out << "*";
670 }
671 out << arg->name();
672
673 first = false;
674 }
675
676 out << ");\n";
677 out.unindent();
678 out << "}\n\n";
679 }
680
681 out.unindent();
682 out << "_aidl_error:\n";
683 out.indent();
684 out << "_aidl_status.setFromStatusT(_aidl_err);\n"
685 << "return _aidl_status;\n";
686
Andreas Huber881227d2016-08-02 14:20:21 -0700687 out.unindent();
688 out << "}\n\n";
689 }
Andreas Huber881227d2016-08-02 14:20:21 -0700690 }
691
692 return OK;
693}
694
695status_t AST::generateStubSource(
696 Formatter &out, const std::string &baseName) const {
697 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
698 << baseName
699 << ", \""
700 << mPackage.string()
701 << "::I"
702 << baseName
703 << "\");\n\n";
704
705 const std::string klassName = "Bn" + baseName;
706
707 out << "::android::status_t " << klassName << "::onTransact(\n";
708
709 out.indent();
710 out.indent();
711
712 out << "uint32_t _aidl_code,\n"
Andreas Huber8a82ff72016-08-04 10:29:39 -0700713 << "const ::android::hardware::Parcel &_aidl_data,\n"
714 << "::android::hardware::Parcel *_aidl_reply,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700715 << "uint32_t _aidl_flags,\n"
716 << "TransactCallback _aidl_cb) {\n";
717
718 out.unindent();
719
720 out << "::android::status_t _aidl_err = ::android::OK;\n\n";
721
722 out << "switch (_aidl_code) {\n";
723 out.indent();
724
725 const Interface *iface = mRootScope->getInterface();
726
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700727 std::vector<const Interface *> chain;
728 while (iface != NULL) {
729 chain.push_back(iface);
730 iface = iface->superType();
731 }
Andreas Huber881227d2016-08-02 14:20:21 -0700732
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700733 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
734 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700735
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700736 for (const auto &method : superInterface->methods()) {
737 out << "case "
738 << superInterface->fullName()
739 << "::Call::"
740 << upcase(method->name())
741 << ":\n{\n";
742
743 out.indent();
744
745 status_t err =
746 generateStubSourceForMethod(out, superInterface, method);
747
748 if (err != OK) {
749 return err;
750 }
751
752 out.unindent();
753 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700754 }
Andreas Huber881227d2016-08-02 14:20:21 -0700755 }
756
757 out << "default:\n{\n";
758 out.indent();
759
Andreas Huber8a82ff72016-08-04 10:29:39 -0700760 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700761 << baseName
762 << ">::onTransact(\n";
763
764 out.indent();
765 out.indent();
766
767 out << "_aidl_code, _aidl_data, _aidl_reply, "
768 << "_aidl_flags, _aidl_cb);\n";
769
770 out.unindent();
771 out.unindent();
772
773 out.unindent();
774 out << "}\n";
775
776 out.unindent();
777 out << "}\n\n";
778
779 out << "if (_aidl_err == ::android::UNEXPECTED_NULL) {\n";
780 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700781 out << "_aidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700782 out.indent();
783 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700784 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700785 out.indent();
786 out.indent();
787 out << ".writeToParcel(_aidl_reply);\n";
788 out.unindent();
789 out.unindent();
790 out.unindent();
791 out.unindent();
792
793 out.unindent();
794 out << "}\n\n";
795
796 out << "return _aidl_err;\n";
797
798 out.unindent();
799 out << "}\n\n";
800
801 return OK;
802}
803
804status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700805 Formatter &out, const Interface *iface, const Method *method) const {
806 out << "if (!_aidl_data.enforceInterface("
807 << iface->fullName()
808 << "::getInterfaceDescriptor())) {\n";
809
Andreas Huber881227d2016-08-02 14:20:21 -0700810 out.indent();
811 out << "_aidl_err = ::android::BAD_TYPE;\n";
812 out << "break;\n";
813 out.unindent();
814 out << "}\n\n";
815
816 for (const auto &arg : method->args()) {
817 emitCppReaderWriter(
818 out,
819 "_aidl_data",
820 false /* parcelObjIsPointer */,
821 arg,
822 true /* reader */,
823 Type::ErrorMode_Break);
824 }
825
826 const bool returnsValue = !method->results().empty();
827
828 if (returnsValue) {
829 out << "bool _aidl_callbackCalled = false;\n\n";
830 }
831
Andreas Huber8a82ff72016-08-04 10:29:39 -0700832 out << "::android::hardware::Status _aidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700833 out.indent();
834 out.indent();
835 out << method->name() << "(";
836
837 bool first = true;
838 for (const auto &arg : method->args()) {
839 if (!first) {
840 out << ", ";
841 }
842
843 if (arg->type().resultNeedsDeref()) {
844 out << "*";
845 }
846
847 out << arg->name();
848
849 first = false;
850 }
851
852 if (returnsValue) {
853 if (!first) {
854 out << ", ";
855 }
856
857 out << "[&](";
858
859 first = true;
860 for (const auto &arg : method->results()) {
861 if (!first) {
862 out << ", ";
863 }
864
865 out << "const auto &" << arg->name();
866
867 first = false;
868 }
869
870 out << ") {\n";
871 out.indent();
872 out << "_aidl_callbackCalled = true;\n\n";
873
Andreas Huber8a82ff72016-08-04 10:29:39 -0700874 out << "::android::hardware::Status::ok()"
Andreas Huber881227d2016-08-02 14:20:21 -0700875 << ".writeToParcel(_aidl_reply);\n\n";
876
877 for (const auto &arg : method->results()) {
878 emitCppReaderWriter(
879 out,
880 "_aidl_reply",
881 true /* parcelObjIsPointer */,
882 arg,
883 false /* reader */,
884 Type::ErrorMode_Ignore);
885 }
886
887 out << "_aidl_cb(*_aidl_reply);\n";
888
889 out.unindent();
890 out << "}\n";
891 }
892
893 out.unindent();
894 out.unindent();
895 out << "));\n\n";
896
897 if (returnsValue) {
898 out << "if (!_aidl_callbackCalled) {\n";
899 out.indent();
900 }
901
902 out << "_aidl_err = _aidl_status.writeToParcel(_aidl_reply);\n";
903
904 if (returnsValue) {
905 out.unindent();
906 out << "}\n\n";
907 }
908
909 out << "break;\n";
910
911 return OK;
912}
913
914} // namespace android
915