blob: e4722456d6c941007f77fe41e9bdb83700c82274 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huber881227d2016-08-02 14:20:21 -070017#include "AST.h"
18
19#include "Coordinator.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070020#include "EnumType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070021#include "Formatter.h"
22#include "Interface.h"
23#include "Method.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070024#include "ScalarType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070025#include "Scope.h"
26
Andreas Huberdca261f2016-08-04 13:47:51 -070027#include <algorithm>
Andreas Huber881227d2016-08-02 14:20:21 -070028#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070029#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070030#include <vector>
31
32namespace android {
33
Andreas Huber881227d2016-08-02 14:20:21 -070034static std::string upcase(const std::string in) {
35 std::string out{in};
36
37 for (auto &ch : out) {
38 ch = toupper(ch);
39 }
40
41 return out;
42}
43
Andreas Huberb82318c2016-08-02 14:45:54 -070044status_t AST::generateCpp(const std::string &outputPath) const {
45 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070046
47 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070048 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070049 }
50
51 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070052 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070053 }
54
55 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070056 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070057 }
58
59 return err;
60}
61
Andreas Huber737080b2016-08-02 15:38:04 -070062void AST::getPackageComponents(
63 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070064 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070065}
66
67void AST::getPackageAndVersionComponents(
68 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070069 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070070}
71
Andreas Huber881227d2016-08-02 14:20:21 -070072std::string AST::makeHeaderGuard(const std::string &baseName) const {
73 std::vector<std::string> packageComponents;
74 getPackageAndVersionComponents(
75 &packageComponents, true /* cpp_compatible */);
76
77 std::string guard = "HIDL_GENERATED";
78 for (const auto &component : packageComponents) {
79 guard += "_";
80 guard += component;
81 }
82
83 guard += "_";
84 guard += baseName;
85 guard += "_H_";
86
87 return guard;
88}
89
90void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
91 std::vector<std::string> packageComponents;
92 getPackageAndVersionComponents(
93 &packageComponents, true /* cpp_compatible */);
94
95 if (enter) {
96 for (const auto &component : packageComponents) {
97 out << "namespace " << component << " {\n";
98 }
Andreas Huber0e00de42016-08-03 09:56:02 -070099
Andreas Huber2831d512016-08-15 09:33:47 -0700100 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -0700101 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700102 out.setNamespace(std::string());
103
Andreas Huber881227d2016-08-02 14:20:21 -0700104 for (auto it = packageComponents.rbegin();
105 it != packageComponents.rend();
106 ++it) {
107 out << "} // namespace " << *it << "\n";
108 }
109 }
110}
111
Andreas Huberb82318c2016-08-02 14:45:54 -0700112status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700113
Andreas Huberb82318c2016-08-02 14:45:54 -0700114 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700115 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700116 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700117
118 std::string ifaceName;
119 bool isInterface = true;
120 if (!AST::isInterface(&ifaceName)) {
121 ifaceName = "types";
122 isInterface = false;
123 }
124 path.append(ifaceName);
125 path.append(".h");
126
Andreas Huberd2943e12016-08-05 11:59:31 -0700127 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700128 FILE *file = fopen(path.c_str(), "w");
129
130 if (file == NULL) {
131 return -errno;
132 }
133
134 Formatter out(file);
135
136 const std::string guard = makeHeaderGuard(ifaceName);
137
138 out << "#ifndef " << guard << "\n";
139 out << "#define " << guard << "\n\n";
140
Andreas Huber737080b2016-08-02 15:38:04 -0700141 for (const auto &item : mImportedNames) {
142 out << "#include <";
143
144 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700145 item.getPackageAndVersionComponents(
146 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700147
148 for (const auto &component : components) {
149 out << component << "/";
150 }
151
152 out << item.name()
153 << ".h>\n";
154 }
155
156 if (!mImportedNames.empty()) {
157 out << "\n";
158 }
159
Martijn Coenen7473fab2016-08-19 14:05:40 +0200160 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700161
162 if (isInterface) {
163 out << "#include <hwbinder/IBinder.h>\n";
164 out << "#include <hwbinder/IInterface.h>\n";
165 out << "#include <hwbinder/Status.h>\n";
166 }
167
168 out << "#include <utils/NativeHandle.h>\n\n";
169
170 enterLeaveNamespace(out, true /* enter */);
171 out << "\n";
172
173 if (isInterface) {
174 out << "struct "
175 << ifaceName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700176 << " : public ";
177
178 const Interface *iface = mRootScope->getInterface();
179 const Interface *superType = iface->superType();
180
181 if (superType != NULL) {
182 out << superType->fullName();
183 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700184 out << "::android::hardware::IInterface";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700185 }
186
187 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700188
189 out.indent();
190
Andreas Huber737080b2016-08-02 15:38:04 -0700191 // cut off the leading 'I'.
192 const std::string baseName = ifaceName.substr(1);
193
194 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700195 }
196
197 status_t err = emitTypeDeclarations(out);
198
199 if (err != OK) {
200 return err;
201 }
202
203 if (isInterface) {
204 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700205 const Interface *superType = iface->superType();
Andreas Huber881227d2016-08-02 14:20:21 -0700206
207 out << "enum Call {\n";
208 out.indent();
209
210 bool first = true;
211 for (const auto &method : iface->methods()) {
212 out << upcase(method->name());
213
214 if (first) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700215 out << " = ";
216 if (superType != NULL) {
217 out << superType->fullName()
218 << "::Call::CallCount";
219 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700220 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700221 }
222
Andreas Huber881227d2016-08-02 14:20:21 -0700223 first = false;
224 }
225
226 out << ",\n";
227 }
228
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700229 out << "CallCount\n";
230
Andreas Huber881227d2016-08-02 14:20:21 -0700231 out.unindent();
232 out << "};\n\n";
233
234 bool haveCallbacks = false;
235 for (const auto &method : iface->methods()) {
236 const bool returnsValue = !method->results().empty();
237
238 if (!returnsValue) {
239 continue;
240 }
241
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700242 if (method->canElideCallback() != nullptr) {
243 continue;
244 }
245
Andreas Huber881227d2016-08-02 14:20:21 -0700246 haveCallbacks = true;
247
248 out << "using "
249 << method->name()
250 << "_cb = std::function<void("
251 << Method::GetSignature(method->results())
252 << ")>;\n";
253 }
254
255 if (haveCallbacks) {
256 out << "\n";
257 }
258
259 for (const auto &method : iface->methods()) {
260 const bool returnsValue = !method->results().empty();
261
Andreas Huber3599d922016-08-09 10:42:57 -0700262 method->dumpAnnotations(out);
263
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700264 const TypedVar *elidedReturn = method->canElideCallback();
265 if (elidedReturn) {
266 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700267 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700268 out << elidedReturn->type().getCppResultType(&extra) << "> ";
269 } else {
270 out << "virtual ::android::hardware::Status ";
271 }
272
273 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700274 << "("
275 << Method::GetSignature(method->args());
276
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700277 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700278 if (!method->args().empty()) {
279 out << ", ";
280 }
281
Iliyan Malchev549e2592016-08-10 08:59:12 -0700282 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700283 }
284
285 out << ") = 0;\n";
286 }
287 }
288
289 if (isInterface) {
290 out.unindent();
291
292 out << "};\n";
293 }
294
295 out << "\n";
296 enterLeaveNamespace(out, false /* enter */);
297
298 out << "\n#endif // " << guard << "\n";
299
300 return OK;
301}
302
303status_t AST::emitTypeDeclarations(Formatter &out) const {
304 return mRootScope->emitTypeDeclarations(out);
305}
306
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700307status_t AST::generateHeaderMethodSignatures(
308 Formatter &out, bool abstract) const {
309 const Interface *iface = mRootScope->getInterface();
310
311 std::vector<const Interface *> chain;
312 while (iface != NULL) {
313 chain.push_back(iface);
314 iface = iface->superType();
315 }
316
317 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
318 const Interface *superInterface = *it;
319
320 out << "// Methods from "
321 << superInterface->fullName()
322 << " follow.\n";
323
324 for (const auto &method : superInterface->methods()) {
325 const bool returnsValue = !method->results().empty();
326
327 const TypedVar *elidedReturn = method->canElideCallback();
328
329 if (elidedReturn == nullptr) {
330 out << "::android::hardware::Status ";
331 } else {
332 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700333 out << "::android::hardware::Return<";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700334 out << elidedReturn->type().getCppResultType(&extra) << "> ";
335 }
336 out << method->name()
337 << "("
338 << Method::GetSignature(method->args());
339
340 if (returnsValue && elidedReturn == nullptr) {
341 if (!method->args().empty()) {
342 out << ", ";
343 }
344
345 out << method->name() << "_cb _hidl_cb";
346 }
347
348 out << ") ";
349 out << (abstract ? "= 0" : "override");
350 out << ";\n";
351 }
352
353 out << "\n";
354 }
355
356 return OK;
357}
358
Andreas Huberb82318c2016-08-02 14:45:54 -0700359status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700360 std::string ifaceName;
361 if (!AST::isInterface(&ifaceName)) {
362 // types.hal does not get a stub header.
363 return OK;
364 }
365
Andreas Huber881227d2016-08-02 14:20:21 -0700366 // cut off the leading 'I'.
367 const std::string baseName = ifaceName.substr(1);
368
Andreas Huberb82318c2016-08-02 14:45:54 -0700369 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700370 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700371 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700372 path.append("Bn");
373 path.append(baseName);
374 path.append(".h");
375
Andreas Huberd2943e12016-08-05 11:59:31 -0700376 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700377 FILE *file = fopen(path.c_str(), "w");
378
379 if (file == NULL) {
380 return -errno;
381 }
382
383 Formatter out(file);
384
385 const std::string guard = makeHeaderGuard("Bn" + baseName);
386
387 out << "#ifndef " << guard << "\n";
388 out << "#define " << guard << "\n\n";
389
390 std::vector<std::string> packageComponents;
391 getPackageAndVersionComponents(
392 &packageComponents, false /* cpp_compatible */);
393
394 out << "#include <";
395 for (const auto &component : packageComponents) {
396 out << component << "/";
397 }
398 out << ifaceName << ".h>\n\n";
399
400 enterLeaveNamespace(out, true /* enter */);
401 out << "\n";
402
403 out << "struct "
404 << "Bn"
405 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700406 << " : public ::android::hardware::BnInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700407 << ifaceName
408 << "> {\n";
409
410 out.indent();
411
412 out << "::android::status_t onTransact(\n";
413 out.indent();
414 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700415 out << "uint32_t _hidl_code,\n";
416 out << "const ::android::hardware::Parcel &_hidl_data,\n";
417 out << "::android::hardware::Parcel *_hidl_reply,\n";
418 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700419 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700420 out.unindent();
421 out.unindent();
422
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700423 generateHeaderMethodSignatures(out, true); // = 0
424
Andreas Huber881227d2016-08-02 14:20:21 -0700425 out.unindent();
426
427 out << "};\n\n";
428
429 enterLeaveNamespace(out, false /* enter */);
430
431 out << "\n#endif // " << guard << "\n";
432
433 return OK;
434}
435
Andreas Huberb82318c2016-08-02 14:45:54 -0700436status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700437 std::string ifaceName;
438 if (!AST::isInterface(&ifaceName)) {
439 // types.hal does not get a proxy header.
440 return OK;
441 }
442
Andreas Huber881227d2016-08-02 14:20:21 -0700443 // cut off the leading 'I'.
444 const std::string baseName = ifaceName.substr(1);
445
Andreas Huberb82318c2016-08-02 14:45:54 -0700446 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700447 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700448 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700449 path.append("Bp");
450 path.append(baseName);
451 path.append(".h");
452
Andreas Huberd2943e12016-08-05 11:59:31 -0700453 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700454 FILE *file = fopen(path.c_str(), "w");
455
456 if (file == NULL) {
457 return -errno;
458 }
459
460 Formatter out(file);
461
462 const std::string guard = makeHeaderGuard("Bp" + baseName);
463
464 out << "#ifndef " << guard << "\n";
465 out << "#define " << guard << "\n\n";
466
467 std::vector<std::string> packageComponents;
468 getPackageAndVersionComponents(
469 &packageComponents, false /* cpp_compatible */);
470
471 out << "#include <";
472 for (const auto &component : packageComponents) {
473 out << component << "/";
474 }
475 out << ifaceName << ".h>\n\n";
476
477 enterLeaveNamespace(out, true /* enter */);
478 out << "\n";
479
480 out << "struct "
481 << "Bp"
482 << baseName
Andreas Huber8a82ff72016-08-04 10:29:39 -0700483 << " : public ::android::hardware::BpInterface<"
Andreas Huber881227d2016-08-02 14:20:21 -0700484 << ifaceName
485 << "> {\n";
486
487 out.indent();
488
489 out << "explicit Bp"
490 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700491 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700492 << "\n\n";
493
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700494 generateHeaderMethodSignatures(out, false); // override
Andreas Huber881227d2016-08-02 14:20:21 -0700495
496 out.unindent();
497
498 out << "};\n\n";
499
500 enterLeaveNamespace(out, false /* enter */);
501
502 out << "\n#endif // " << guard << "\n";
503
504 return OK;
505}
506
Andreas Huberb82318c2016-08-02 14:45:54 -0700507status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700508
Andreas Huberb82318c2016-08-02 14:45:54 -0700509 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700510 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700511 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700512
513 std::string ifaceName;
514 std::string baseName;
515
516 bool isInterface = true;
517 if (!AST::isInterface(&ifaceName)) {
518 baseName = "types";
519 isInterface = false;
520 } else {
521 baseName = ifaceName.substr(1); // cut off the leading 'I'.
522 }
523
524 path.append(baseName);
525
526 if (baseName != "types") {
527 path.append("All");
528 }
529
530 path.append(".cpp");
531
Andreas Huberd2943e12016-08-05 11:59:31 -0700532 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700533 FILE *file = fopen(path.c_str(), "w");
534
535 if (file == NULL) {
536 return -errno;
537 }
538
539 Formatter out(file);
540
541 std::vector<std::string> packageComponents;
542 getPackageAndVersionComponents(
543 &packageComponents, false /* cpp_compatible */);
544
545 std::string prefix;
546 for (const auto &component : packageComponents) {
547 prefix += component;
548 prefix += "/";
549 }
550
551 if (isInterface) {
552 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
553 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
554 } else {
555 out << "#include <" << prefix << "types.h>\n";
556 }
557
558 out << "\n";
559
560 enterLeaveNamespace(out, true /* enter */);
561 out << "\n";
562
563 status_t err = generateTypeSource(out, ifaceName);
564
565 if (err == OK && isInterface) {
566 err = generateProxySource(out, baseName);
567 }
568
569 if (err == OK && isInterface) {
570 err = generateStubSource(out, baseName);
571 }
572
573 enterLeaveNamespace(out, false /* enter */);
574
575 return err;
576}
577
578status_t AST::generateTypeSource(
579 Formatter &out, const std::string &ifaceName) const {
580 return mRootScope->emitTypeDefinitions(out, ifaceName);
581}
582
Andreas Hubere7ff2282016-08-16 13:50:03 -0700583void AST::declareCppReaderLocals(
584 Formatter &out, const std::vector<TypedVar *> &args) const {
585 if (args.empty()) {
586 return;
587 }
588
589 for (const auto &arg : args) {
590 const Type &type = arg->type();
591
592 std::string extra;
593 out << type.getCppResultType(&extra)
594 << " "
595 << arg->name()
596 << extra
597 << ";\n";
598 }
599
600 out << "\n";
601}
602
Andreas Huber881227d2016-08-02 14:20:21 -0700603void AST::emitCppReaderWriter(
604 Formatter &out,
605 const std::string &parcelObj,
606 bool parcelObjIsPointer,
607 const TypedVar *arg,
608 bool isReader,
609 Type::ErrorMode mode) const {
610 const Type &type = arg->type();
611
Andreas Huber881227d2016-08-02 14:20:21 -0700612 type.emitReaderWriter(
613 out,
614 arg->name(),
615 parcelObj,
616 parcelObjIsPointer,
617 isReader,
618 mode);
619}
620
621status_t AST::generateProxySource(
622 Formatter &out, const std::string &baseName) const {
623 const std::string klassName = "Bp" + baseName;
624
625 out << klassName
626 << "::"
627 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700628 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700629
630 out.indent();
631 out.indent();
632
633 out << ": BpInterface"
634 << "<I"
635 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700636 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700637
638 out.unindent();
639 out.unindent();
640 out << "}\n\n";
641
642 const Interface *iface = mRootScope->getInterface();
643
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700644 std::vector<const Interface *> chain;
645 while (iface != NULL) {
646 chain.push_back(iface);
647 iface = iface->superType();
648 }
Andreas Huber881227d2016-08-02 14:20:21 -0700649
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700650 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
651 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700652
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700653 for (const auto &method : superInterface->methods()) {
654 const bool returnsValue = !method->results().empty();
Andreas Huber881227d2016-08-02 14:20:21 -0700655
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700656 const TypedVar *elidedReturn = method->canElideCallback();
657 if (elidedReturn) {
658 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700659 out << "::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700660 out << elidedReturn->type().getCppResultType(&extra) << "> ";
661 } else {
662 out << "::android::hardware::Status ";
663 }
664
665 out << klassName
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700666 << "::"
667 << method->name()
668 << "("
669 << Method::GetSignature(method->args());
Andreas Huber881227d2016-08-02 14:20:21 -0700670
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700671 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700672 if (!method->args().empty()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700673 out << ", ";
674 }
675
Iliyan Malchev549e2592016-08-10 08:59:12 -0700676 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700677 }
678
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700679 out << ") {\n";
680
681 out.indent();
682
Iliyan Malchev549e2592016-08-10 08:59:12 -0700683 out << "::android::hardware::Parcel _hidl_data;\n";
684 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700685 out << "::android::status_t _hidl_err;\n";
686 out << "::android::hardware::Status _hidl_status;\n\n";
687
688 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700689
Iliyan Malchev549e2592016-08-10 08:59:12 -0700690 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700691 << superInterface->fullName()
692 << "::getInterfaceDescriptor());\n";
693
Iliyan Malchev549e2592016-08-10 08:59:12 -0700694 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700695
696 for (const auto &arg : method->args()) {
697 emitCppReaderWriter(
698 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700699 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700700 false /* parcelObjIsPointer */,
701 arg,
702 false /* reader */,
703 Type::ErrorMode_Goto);
704 }
705
Iliyan Malchev549e2592016-08-10 08:59:12 -0700706 out << "_hidl_err = remote()->transact(I"
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700707 << baseName
708 << "::"
709 << upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700710 << ", _hidl_data, &_hidl_reply";
711 if (method->isOneway()) {
712 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700713 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700714 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700715
Iliyan Malchev639bff82016-08-13 14:24:11 -0700716 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700717
Iliyan Malchev639bff82016-08-13 14:24:11 -0700718 if (!method->isOneway()) {
719 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
720 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700721 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
722
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700723 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700724 emitCppReaderWriter(
725 out,
726 "_hidl_reply",
727 false /* parcelObjIsPointer */,
728 arg,
729 true /* reader */,
730 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700731 }
732
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700733 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700734 out << "if (_hidl_cb != nullptr) {\n";
735 out.indent();
736 out << "_hidl_cb(";
737
738 bool first = true;
739 for (const auto &arg : method->results()) {
740 if (!first) {
741 out << ", ";
742 }
743
744 if (arg->type().resultNeedsDeref()) {
745 out << "*";
746 }
747 out << arg->name();
748
749 first = false;
750 }
751
752 out << ");\n";
753 out.unindent();
754 out << "}\n\n";
755 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700756 }
757
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700758 if (elidedReturn != nullptr) {
759 std::string extra;
760
761 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700762 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700763 out << elidedReturn->type().getCppResultType(&extra)
764 << ">(" << elidedReturn->name() << ");\n\n";
765
766 out.unindent();
767 out << "_hidl_error:\n";
768 out.indent();
769 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700770 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700771 out << method->results().at(0)->type().getCppResultType(&extra)
772 << ">(_hidl_status);\n";
773 } else {
774 out.unindent();
775 out << "_hidl_error:\n";
776 out.indent();
777 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
778 out << "return _hidl_status;\n";
779 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700780
Andreas Huber881227d2016-08-02 14:20:21 -0700781 out.unindent();
782 out << "}\n\n";
783 }
Andreas Huber881227d2016-08-02 14:20:21 -0700784 }
785
786 return OK;
787}
788
789status_t AST::generateStubSource(
790 Formatter &out, const std::string &baseName) const {
791 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
792 << baseName
793 << ", \""
794 << mPackage.string()
795 << "::I"
796 << baseName
797 << "\");\n\n";
798
799 const std::string klassName = "Bn" + baseName;
800
801 out << "::android::status_t " << klassName << "::onTransact(\n";
802
803 out.indent();
804 out.indent();
805
Iliyan Malchev549e2592016-08-10 08:59:12 -0700806 out << "uint32_t _hidl_code,\n"
807 << "const ::android::hardware::Parcel &_hidl_data,\n"
808 << "::android::hardware::Parcel *_hidl_reply,\n"
809 << "uint32_t _hidl_flags,\n"
810 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700811
812 out.unindent();
813
Iliyan Malchev549e2592016-08-10 08:59:12 -0700814 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700815
Iliyan Malchev549e2592016-08-10 08:59:12 -0700816 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700817 out.indent();
818
819 const Interface *iface = mRootScope->getInterface();
820
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700821 std::vector<const Interface *> chain;
822 while (iface != NULL) {
823 chain.push_back(iface);
824 iface = iface->superType();
825 }
Andreas Huber881227d2016-08-02 14:20:21 -0700826
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700827 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
828 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700829
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700830 for (const auto &method : superInterface->methods()) {
831 out << "case "
832 << superInterface->fullName()
833 << "::Call::"
834 << upcase(method->name())
835 << ":\n{\n";
836
837 out.indent();
838
839 status_t err =
840 generateStubSourceForMethod(out, superInterface, method);
841
842 if (err != OK) {
843 return err;
844 }
845
846 out.unindent();
847 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700848 }
Andreas Huber881227d2016-08-02 14:20:21 -0700849 }
850
851 out << "default:\n{\n";
852 out.indent();
853
Andreas Huber8a82ff72016-08-04 10:29:39 -0700854 out << "return ::android::hardware::BnInterface<I"
Andreas Huber881227d2016-08-02 14:20:21 -0700855 << baseName
856 << ">::onTransact(\n";
857
858 out.indent();
859 out.indent();
860
Iliyan Malchev549e2592016-08-10 08:59:12 -0700861 out << "_hidl_code, _hidl_data, _hidl_reply, "
862 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700863
864 out.unindent();
865 out.unindent();
866
867 out.unindent();
868 out << "}\n";
869
870 out.unindent();
871 out << "}\n\n";
872
Iliyan Malchev549e2592016-08-10 08:59:12 -0700873 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700874 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700875 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700876 out.indent();
877 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -0700878 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700879 out.indent();
880 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700881 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700882 out.unindent();
883 out.unindent();
884 out.unindent();
885 out.unindent();
886
887 out.unindent();
888 out << "}\n\n";
889
Iliyan Malchev549e2592016-08-10 08:59:12 -0700890 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700891
892 out.unindent();
893 out << "}\n\n";
894
895 return OK;
896}
897
898status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700899 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700900 out << "if (!_hidl_data.enforceInterface("
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700901 << iface->fullName()
902 << "::getInterfaceDescriptor())) {\n";
903
Andreas Huber881227d2016-08-02 14:20:21 -0700904 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700905 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700906 out << "break;\n";
907 out.unindent();
908 out << "}\n\n";
909
Andreas Hubere7ff2282016-08-16 13:50:03 -0700910 declareCppReaderLocals(out, method->args());
911
Andreas Huber881227d2016-08-02 14:20:21 -0700912 for (const auto &arg : method->args()) {
913 emitCppReaderWriter(
914 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700915 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -0700916 false /* parcelObjIsPointer */,
917 arg,
918 true /* reader */,
919 Type::ErrorMode_Break);
920 }
921
922 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700923 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -0700924
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700925 if (elidedReturn != nullptr) {
926 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -0700927
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700928 out << elidedReturn->type().getCppResultType(&extra) << " ";
929 out << elidedReturn->name() << " = ";
930 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -0700931
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700932 bool first = true;
933 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700934 if (!first) {
935 out << ", ";
936 }
937
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700938 if (arg->type().resultNeedsDeref()) {
939 out << "*";
940 }
941
942 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -0700943
944 first = false;
945 }
946
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700947 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700948 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700949 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700950
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700951 elidedReturn->type().emitReaderWriter(
952 out,
953 elidedReturn->name(),
954 "_hidl_reply",
955 true, /* parcelObjIsPointer */
956 false, /* isReader */
957 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -0700958
Iliyan Malchev549e2592016-08-10 08:59:12 -0700959 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700960 } else {
961 if (returnsValue) {
962 out << "bool _hidl_callbackCalled = false;\n\n";
963 }
Andreas Huber881227d2016-08-02 14:20:21 -0700964
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700965 out << "::android::hardware::Status _hidl_status(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700966 out.indent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700967 out.indent();
968 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -0700969
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700970 bool first = true;
971 for (const auto &arg : method->args()) {
972 if (!first) {
973 out << ", ";
974 }
Andreas Huber881227d2016-08-02 14:20:21 -0700975
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700976 if (arg->type().resultNeedsDeref()) {
977 out << "*";
978 }
979
980 out << arg->name();
981
982 first = false;
983 }
984
985 if (returnsValue) {
986 if (!first) {
987 out << ", ";
988 }
989
990 out << "[&](";
991
992 first = true;
993 for (const auto &arg : method->results()) {
994 if (!first) {
995 out << ", ";
996 }
997
998 out << "const auto &" << arg->name();
999
1000 first = false;
1001 }
1002
1003 out << ") {\n";
1004 out.indent();
1005 out << "_hidl_callbackCalled = true;\n\n";
1006
1007 out << "::android::hardware::Status::ok()"
1008 << ".writeToParcel(_hidl_reply);\n\n";
1009
1010 for (const auto &arg : method->results()) {
1011 emitCppReaderWriter(
1012 out,
1013 "_hidl_reply",
1014 true /* parcelObjIsPointer */,
1015 arg,
1016 false /* reader */,
1017 Type::ErrorMode_Ignore);
1018 }
1019
1020 out << "_hidl_cb(*_hidl_reply);\n";
1021
1022 out.unindent();
1023 out << "}\n";
1024 }
1025
Andreas Huber881227d2016-08-02 14:20:21 -07001026 out.unindent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001027 out.unindent();
1028 out << "));\n\n";
1029
1030 if (returnsValue) {
1031 out << "if (!_hidl_callbackCalled) {\n";
1032 out.indent();
1033 }
1034
1035 out << "_hidl_err = _hidl_status.writeToParcel(_hidl_reply);\n";
1036
1037 if (returnsValue) {
1038 out.unindent();
1039 out << "}\n\n";
1040 }
Andreas Huber881227d2016-08-02 14:20:21 -07001041 }
1042
1043 out << "break;\n";
1044
1045 return OK;
1046}
1047
1048} // namespace android
1049