blob: f11137cf06d87aa2fee28718163a5278690bdb99 [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) {
Steven Moreland40786312016-08-16 10:29:40 -070052 err = generateHwBinderHeader(outputPath);
53 }
54
55 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070056 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070057 }
58
59 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070060 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070061 }
62
63 return err;
64}
65
Andreas Huber737080b2016-08-02 15:38:04 -070066void AST::getPackageComponents(
67 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070068 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070069}
70
71void AST::getPackageAndVersionComponents(
72 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070073 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070074}
75
Andreas Huber881227d2016-08-02 14:20:21 -070076std::string AST::makeHeaderGuard(const std::string &baseName) const {
Steven Moreland9c387612016-09-07 09:54:26 -070077 std::string guard = "HIDL_GENERATED_";
78 guard += mPackage.tokenName();
Andreas Huber881227d2016-08-02 14:20:21 -070079
80 guard += "_";
81 guard += baseName;
82 guard += "_H_";
83
84 return guard;
85}
86
87void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
88 std::vector<std::string> packageComponents;
89 getPackageAndVersionComponents(
90 &packageComponents, true /* cpp_compatible */);
91
92 if (enter) {
93 for (const auto &component : packageComponents) {
94 out << "namespace " << component << " {\n";
95 }
Andreas Huber0e00de42016-08-03 09:56:02 -070096
Andreas Huber2831d512016-08-15 09:33:47 -070097 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -070098 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -070099 out.setNamespace(std::string());
100
Andreas Huber881227d2016-08-02 14:20:21 -0700101 for (auto it = packageComponents.rbegin();
102 it != packageComponents.rend();
103 ++it) {
104 out << "} // namespace " << *it << "\n";
105 }
106 }
107}
108
Andreas Huberb82318c2016-08-02 14:45:54 -0700109status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700110
Andreas Huberb82318c2016-08-02 14:45:54 -0700111 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700112 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700113 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700114
115 std::string ifaceName;
116 bool isInterface = true;
117 if (!AST::isInterface(&ifaceName)) {
118 ifaceName = "types";
119 isInterface = false;
120 }
121 path.append(ifaceName);
122 path.append(".h");
123
Andreas Huberd2943e12016-08-05 11:59:31 -0700124 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700125 FILE *file = fopen(path.c_str(), "w");
126
127 if (file == NULL) {
128 return -errno;
129 }
130
131 Formatter out(file);
132
133 const std::string guard = makeHeaderGuard(ifaceName);
134
135 out << "#ifndef " << guard << "\n";
136 out << "#define " << guard << "\n\n";
137
Andreas Huber737080b2016-08-02 15:38:04 -0700138 for (const auto &item : mImportedNames) {
139 out << "#include <";
140
141 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700142 item.getPackageAndVersionComponents(
143 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700144
145 for (const auto &component : components) {
146 out << component << "/";
147 }
148
149 out << item.name()
150 << ".h>\n";
151 }
152
153 if (!mImportedNames.empty()) {
154 out << "\n";
155 }
156
Martijn Coenen7473fab2016-08-19 14:05:40 +0200157 out << "#include <hidl/HidlSupport.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700158 out << "#include <hidl/IServiceManager.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700159
160 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200161 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700162 }
163
164 out << "#include <utils/NativeHandle.h>\n\n";
165
166 enterLeaveNamespace(out, true /* enter */);
167 out << "\n";
168
Steven Moreland40786312016-08-16 10:29:40 -0700169 // cut off the leading 'I'.
170 const std::string baseName = ifaceName.substr(1);
171
Andreas Huber881227d2016-08-02 14:20:21 -0700172 if (isInterface) {
173 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700174 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700175
176 const Interface *iface = mRootScope->getInterface();
177 const Interface *superType = iface->superType();
178
Steven Moreland40786312016-08-16 10:29:40 -0700179 if (superType == NULL) {
180 out << " : virtual public RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700181 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700182 out << " : public "
183 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700184 }
185
186 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700187
188 out.indent();
189
Andreas Huber881227d2016-08-02 14:20:21 -0700190 }
191
192 status_t err = emitTypeDeclarations(out);
193
194 if (err != OK) {
195 return err;
196 }
197
198 if (isInterface) {
199 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700200 const Interface *superType = iface->superType();
Andreas Huber881227d2016-08-02 14:20:21 -0700201
Iliyan Malchev795dd432016-09-02 11:48:26 -0700202 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700203 bool haveCallbacks = false;
204 for (const auto &method : iface->methods()) {
205 const bool returnsValue = !method->results().empty();
206
207 if (!returnsValue) {
208 continue;
209 }
210
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700211 if (method->canElideCallback() != nullptr) {
212 continue;
213 }
214
Andreas Huber881227d2016-08-02 14:20:21 -0700215 haveCallbacks = true;
216
217 out << "using "
218 << method->name()
219 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700220 << Method::GetArgSignature(method->results(),
221 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700222 << ")>;\n";
223 }
224
225 if (haveCallbacks) {
226 out << "\n";
227 }
228
229 for (const auto &method : iface->methods()) {
230 const bool returnsValue = !method->results().empty();
231
Andreas Huber3599d922016-08-09 10:42:57 -0700232 method->dumpAnnotations(out);
233
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700234 const TypedVar *elidedReturn = method->canElideCallback();
235 if (elidedReturn) {
236 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700237 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700238 out << elidedReturn->type().getCppResultType(&extra) << "> ";
239 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700240 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700241 }
242
243 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700244 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700245 << Method::GetArgSignature(method->args(),
246 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700247
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700248 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700249 if (!method->args().empty()) {
250 out << ", ";
251 }
252
Iliyan Malchev549e2592016-08-10 08:59:12 -0700253 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700254 }
255
256 out << ") = 0;\n";
257 }
Steven Moreland40786312016-08-16 10:29:40 -0700258
259 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700260 }
261
262 if (isInterface) {
263 out.unindent();
264
265 out << "};\n";
266 }
267
268 out << "\n";
269 enterLeaveNamespace(out, false /* enter */);
270
271 out << "\n#endif // " << guard << "\n";
272
273 return OK;
274}
275
Steven Moreland40786312016-08-16 10:29:40 -0700276status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
277 std::string ifaceName;
278 if(!AST::isInterface(&ifaceName)) {
279 // types.hal does not get an HwBinder header.
280 return OK;
281 }
282
283 // cut off the leading 'I'.
284 const std::string baseName = ifaceName.substr(1);
285
286 const std::string klassName = "IHw" + baseName;
287
288 std::string path = outputPath;
289 path.append(mCoordinator->convertPackageRootToPath(mPackage));
290 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
291 path.append(klassName + ".h");
292
293 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(klassName);
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 for (const auto &item : mImportedNames) {
317 if (item.name() == "types") {
318 continue;
319 }
320
321 out << "#include <";
322
323 std::vector<std::string> components;
324 item.getPackageAndVersionComponents(
325 &components, false /* cpp_compatible */);
326
327 for (const auto &component : components) {
328 out << component << "/";
329 }
330
331 // cut off the leading I
332 const std::string itemBaseName = item.name().substr(1);
333
334 out << "Bn"
335 << itemBaseName
336 << ".h>\n";
337 }
338
339 out << "\n";
340
341 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200342 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700343 out << "#include <hwbinder/IBinder.h>\n";
344 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700345
346 out << "\n";
347
348 enterLeaveNamespace(out, true /* enter */);
349 out << "\n";
350
351 out << "struct "
352 << klassName
353 << " : public "
354 << ifaceName;
355
356 const Interface *iface = mRootScope->getInterface();
357 const Interface *superType = iface->superType();
358
359 out << ", public ::android::hardware::IInterface";
360
361 out << " {\n";
362
363 out.indent();
364
365 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
366
367 out << "enum Call {\n";
368 out.indent();
369
370 bool first = true;
371 for (const auto &method : iface->methods()) {
372 out << upcase(method->name());
373
374 if (first) {
375 out << " = ";
376 if (superType != NULL) {
377 out << superType->fqName().cppNamespace()
378 << "::IHw"
379 << superType->getBaseName()
380 << "::Call::CallCount";
381 } else {
382 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
383 }
384
385 first = false;
386 }
387
388 out << ",\n";
389 }
390
391 out << "CallCount\n";
392
393 out.unindent();
394 out << "};\n\n";
395
396 out.unindent();
397
398 out << "};\n\n";
399
400 enterLeaveNamespace(out, false /* enter */);
401
402 out << "\n#endif // " << guard << "\n";
403
404 return OK;
405}
406
Andreas Huber881227d2016-08-02 14:20:21 -0700407status_t AST::emitTypeDeclarations(Formatter &out) const {
408 return mRootScope->emitTypeDeclarations(out);
409}
410
Steven Morelanda7a421a2016-09-07 08:35:18 -0700411status_t AST::generateStubMethod(Formatter &out,
412 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700413 const Method *method,
414 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700415 out << "inline ";
416
Steven Moreland979e0992016-09-07 09:18:08 -0700417 method->generateCppSignature(out,
418 className,
419 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700420
421 const bool returnsValue = !method->results().empty();
422 const TypedVar *elidedReturn = method->canElideCallback();
423 out << " {\n";
424 out.indent();
425 out << "return mImpl->"
426 << method->name()
427 << "(";
428 bool first = true;
429 for (const auto &arg : method->args()) {
430 if (!first) {
431 out << ", ";
432 }
433 first = false;
434 out << arg->name();
435 }
436 if (returnsValue && elidedReturn == nullptr) {
437 if (!method->args().empty()) {
438 out << ", ";
439 }
440
441 out << "_hidl_cb";
442 }
443 out << ");\n";
444 out.unindent();
445 out << "}";
446
447 out << ";\n";
448
449 return OK;
450}
451
Steven Moreland9c387612016-09-07 09:54:26 -0700452status_t AST::generateProxyDeclaration(Formatter &out,
453 const std::string &className,
454 const Method *method,
455 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700456
Steven Moreland979e0992016-09-07 09:18:08 -0700457 method->generateCppSignature(out,
458 className,
459 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700460 out << " override;\n";
461
462 return OK;
463}
464
465status_t AST::generateMethods(
466 Formatter &out,
467 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700468 MethodLocation type,
469 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700470
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700471 const Interface *iface = mRootScope->getInterface();
472
473 std::vector<const Interface *> chain;
474 while (iface != NULL) {
475 chain.push_back(iface);
476 iface = iface->superType();
477 }
478
479 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
480 const Interface *superInterface = *it;
481
482 out << "// Methods from "
483 << superInterface->fullName()
484 << " follow.\n";
485
486 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700487 status_t err;
488 switch(type) {
489 case STUB_HEADER:
490 err = generateStubMethod(out,
491 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700492 method,
493 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700494 break;
495 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700496 err = generateProxyDeclaration(out,
497 className,
498 method,
499 specifyNamespaces);
500 break;
501 case IMPL_HEADER:
502 err = generateStubImplDeclaration(out,
503 className,
504 method,
505 specifyNamespaces);
506 break;
507 case IMPL_SOURCE:
508 err = generateStubImplMethod(out,
509 className,
510 method,
511 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700512 break;
513 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700514 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700515 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700516 }
517
Steven Morelanda7a421a2016-09-07 08:35:18 -0700518 if (err != OK) {
519 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700520 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700521 }
522
523 out << "\n";
524 }
525
526 return OK;
527}
528
Andreas Huberb82318c2016-08-02 14:45:54 -0700529status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700530 std::string ifaceName;
531 if (!AST::isInterface(&ifaceName)) {
532 // types.hal does not get a stub header.
533 return OK;
534 }
535
Andreas Huber881227d2016-08-02 14:20:21 -0700536 // cut off the leading 'I'.
537 const std::string baseName = ifaceName.substr(1);
Steven Moreland40786312016-08-16 10:29:40 -0700538 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700539
Andreas Huberb82318c2016-08-02 14:45:54 -0700540 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700541 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700542 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700543 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700544 path.append(".h");
545
Andreas Huberd2943e12016-08-05 11:59:31 -0700546 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700547 FILE *file = fopen(path.c_str(), "w");
548
549 if (file == NULL) {
550 return -errno;
551 }
552
553 Formatter out(file);
554
Steven Moreland40786312016-08-16 10:29:40 -0700555 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700556
557 out << "#ifndef " << guard << "\n";
558 out << "#define " << guard << "\n\n";
559
560 std::vector<std::string> packageComponents;
561 getPackageAndVersionComponents(
562 &packageComponents, false /* cpp_compatible */);
563
564 out << "#include <";
565 for (const auto &component : packageComponents) {
566 out << component << "/";
567 }
Steven Moreland40786312016-08-16 10:29:40 -0700568 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700569
570 enterLeaveNamespace(out, true /* enter */);
571 out << "\n";
572
573 out << "struct "
574 << "Bn"
575 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700576 << " : public ::android::hardware::BnInterface<I"
577 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700578 << "> {\n";
579
580 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700581 out << "explicit Bn"
582 << baseName
583 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
584 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700585 out << "::android::status_t onTransact(\n";
586 out.indent();
587 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700588 out << "uint32_t _hidl_code,\n";
589 out << "const ::android::hardware::Parcel &_hidl_data,\n";
590 out << "::android::hardware::Parcel *_hidl_reply,\n";
591 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700592 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700593 out.unindent();
594 out.unindent();
595
Steven Moreland9c387612016-09-07 09:54:26 -0700596 status_t err = generateMethods(out,
597 "" /* class name */,
598 MethodLocation::STUB_HEADER,
599 true /* specify namespaces */);
600
601 if (err != OK) {
602 return err;
603 }
604
Andreas Huber881227d2016-08-02 14:20:21 -0700605 out.unindent();
606
607 out << "};\n\n";
608
609 enterLeaveNamespace(out, false /* enter */);
610
611 out << "\n#endif // " << guard << "\n";
612
613 return OK;
614}
615
Andreas Huberb82318c2016-08-02 14:45:54 -0700616status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700617 std::string ifaceName;
618 if (!AST::isInterface(&ifaceName)) {
619 // types.hal does not get a proxy header.
620 return OK;
621 }
622
Andreas Huber881227d2016-08-02 14:20:21 -0700623 // cut off the leading 'I'.
624 const std::string baseName = ifaceName.substr(1);
625
Andreas Huberb82318c2016-08-02 14:45:54 -0700626 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700627 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700628 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700629 path.append("Bp");
630 path.append(baseName);
631 path.append(".h");
632
Andreas Huberd2943e12016-08-05 11:59:31 -0700633 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700634 FILE *file = fopen(path.c_str(), "w");
635
636 if (file == NULL) {
637 return -errno;
638 }
639
640 Formatter out(file);
641
642 const std::string guard = makeHeaderGuard("Bp" + baseName);
643
644 out << "#ifndef " << guard << "\n";
645 out << "#define " << guard << "\n\n";
646
647 std::vector<std::string> packageComponents;
648 getPackageAndVersionComponents(
649 &packageComponents, false /* cpp_compatible */);
650
651 out << "#include <";
652 for (const auto &component : packageComponents) {
653 out << component << "/";
654 }
Steven Moreland40786312016-08-16 10:29:40 -0700655 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700656
657 enterLeaveNamespace(out, true /* enter */);
658 out << "\n";
659
660 out << "struct "
661 << "Bp"
662 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700663 << " : public ::android::hardware::BpInterface<IHw"
664 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700665 << "> {\n";
666
667 out.indent();
668
669 out << "explicit Bp"
670 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700671 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700672 << "\n\n";
673
Iliyan Malchev795dd432016-09-02 11:48:26 -0700674 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700675
Steven Moreland9c387612016-09-07 09:54:26 -0700676 status_t err = generateMethods(out,
677 "" /* class name */,
678 MethodLocation::PROXY_HEADER,
679 true /* generate specify namespaces */);
680
681 if (err != OK) {
682 return err;
683 }
Andreas Huber881227d2016-08-02 14:20:21 -0700684
685 out.unindent();
686
687 out << "};\n\n";
688
689 enterLeaveNamespace(out, false /* enter */);
690
691 out << "\n#endif // " << guard << "\n";
692
693 return OK;
694}
695
Andreas Huberb82318c2016-08-02 14:45:54 -0700696status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700697
Andreas Huberb82318c2016-08-02 14:45:54 -0700698 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700699 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700700 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700701
702 std::string ifaceName;
703 std::string baseName;
704
705 bool isInterface = true;
706 if (!AST::isInterface(&ifaceName)) {
707 baseName = "types";
708 isInterface = false;
709 } else {
710 baseName = ifaceName.substr(1); // cut off the leading 'I'.
711 }
712
713 path.append(baseName);
714
715 if (baseName != "types") {
716 path.append("All");
717 }
718
719 path.append(".cpp");
720
Andreas Huberd2943e12016-08-05 11:59:31 -0700721 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700722 FILE *file = fopen(path.c_str(), "w");
723
724 if (file == NULL) {
725 return -errno;
726 }
727
728 Formatter out(file);
729
730 std::vector<std::string> packageComponents;
731 getPackageAndVersionComponents(
732 &packageComponents, false /* cpp_compatible */);
733
734 std::string prefix;
735 for (const auto &component : packageComponents) {
736 prefix += component;
737 prefix += "/";
738 }
739
740 if (isInterface) {
741 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
742 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
743 } else {
744 out << "#include <" << prefix << "types.h>\n";
745 }
746
747 out << "\n";
748
749 enterLeaveNamespace(out, true /* enter */);
750 out << "\n";
751
752 status_t err = generateTypeSource(out, ifaceName);
753
754 if (err == OK && isInterface) {
755 err = generateProxySource(out, baseName);
756 }
757
758 if (err == OK && isInterface) {
759 err = generateStubSource(out, baseName);
760 }
761
Steven Moreland40786312016-08-16 10:29:40 -0700762 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700763 const Interface *iface = mRootScope->getInterface();
764
765 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
766 << baseName << ", "
767 << "\"" << iface->fqName().package()
768 << iface->fqName().version() << ".impl.so\""
769 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700770 }
771
Andreas Huber881227d2016-08-02 14:20:21 -0700772 enterLeaveNamespace(out, false /* enter */);
773
774 return err;
775}
776
777status_t AST::generateTypeSource(
778 Formatter &out, const std::string &ifaceName) const {
779 return mRootScope->emitTypeDefinitions(out, ifaceName);
780}
781
Andreas Hubere7ff2282016-08-16 13:50:03 -0700782void AST::declareCppReaderLocals(
783 Formatter &out, const std::vector<TypedVar *> &args) const {
784 if (args.empty()) {
785 return;
786 }
787
788 for (const auto &arg : args) {
789 const Type &type = arg->type();
790
791 std::string extra;
792 out << type.getCppResultType(&extra)
793 << " "
794 << arg->name()
795 << extra
796 << ";\n";
797 }
798
799 out << "\n";
800}
801
Andreas Huber881227d2016-08-02 14:20:21 -0700802void AST::emitCppReaderWriter(
803 Formatter &out,
804 const std::string &parcelObj,
805 bool parcelObjIsPointer,
806 const TypedVar *arg,
807 bool isReader,
808 Type::ErrorMode mode) const {
809 const Type &type = arg->type();
810
Andreas Huber881227d2016-08-02 14:20:21 -0700811 type.emitReaderWriter(
812 out,
813 arg->name(),
814 parcelObj,
815 parcelObjIsPointer,
816 isReader,
817 mode);
818}
819
820status_t AST::generateProxySource(
821 Formatter &out, const std::string &baseName) const {
822 const std::string klassName = "Bp" + baseName;
823
824 out << klassName
825 << "::"
826 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700827 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700828
829 out.indent();
830 out.indent();
831
832 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700833 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700834 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700835 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700836
837 out.unindent();
838 out.unindent();
839 out << "}\n\n";
840
841 const Interface *iface = mRootScope->getInterface();
842
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700843 std::vector<const Interface *> chain;
844 while (iface != NULL) {
845 chain.push_back(iface);
846 iface = iface->superType();
847 }
Andreas Huber881227d2016-08-02 14:20:21 -0700848
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700849 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
850 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700851
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700852 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700853 method->generateCppSignature(out,
854 klassName,
855 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700856
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700857 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700858 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700859
Steven Morelanda7a421a2016-09-07 08:35:18 -0700860 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700861
862 out.indent();
863
Iliyan Malchev549e2592016-08-10 08:59:12 -0700864 out << "::android::hardware::Parcel _hidl_data;\n";
865 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700866 out << "::android::status_t _hidl_err;\n";
867 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700868 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700869
Iliyan Malchev549e2592016-08-10 08:59:12 -0700870 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700871 << superInterface->fqName().cppNamespace()
872 << "::IHw"
873 << superInterface->getBaseName()
874 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700875
Iliyan Malchev549e2592016-08-10 08:59:12 -0700876 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700877
878 for (const auto &arg : method->args()) {
879 emitCppReaderWriter(
880 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700881 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700882 false /* parcelObjIsPointer */,
883 arg,
884 false /* reader */,
885 Type::ErrorMode_Goto);
886 }
887
Steven Moreland40786312016-08-16 10:29:40 -0700888 out << "_hidl_err = remote()->transact("
889 << superInterface->fqName().cppNamespace()
890 << "::IHw"
891 << superInterface->getBaseName()
892 << "::Call::"
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700893 << upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700894 << ", _hidl_data, &_hidl_reply";
895 if (method->isOneway()) {
896 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700897 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700898 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700899
Iliyan Malchev639bff82016-08-13 14:24:11 -0700900 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700901
Iliyan Malchev639bff82016-08-13 14:24:11 -0700902 if (!method->isOneway()) {
903 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
904 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700905 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
906
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700907 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700908 emitCppReaderWriter(
909 out,
910 "_hidl_reply",
911 false /* parcelObjIsPointer */,
912 arg,
913 true /* reader */,
914 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700915 }
916
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700917 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700918 out << "if (_hidl_cb != nullptr) {\n";
919 out.indent();
920 out << "_hidl_cb(";
921
922 bool first = true;
923 for (const auto &arg : method->results()) {
924 if (!first) {
925 out << ", ";
926 }
927
928 if (arg->type().resultNeedsDeref()) {
929 out << "*";
930 }
931 out << arg->name();
932
933 first = false;
934 }
935
936 out << ");\n";
937 out.unindent();
938 out << "}\n\n";
939 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700940 }
941
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700942 if (elidedReturn != nullptr) {
943 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700944 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700945 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700946 out << elidedReturn->type().getCppResultType(&extra)
947 << ">(" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700948 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700949 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700950 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700951 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700952
Andreas Huber881227d2016-08-02 14:20:21 -0700953 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700954 out << "_hidl_error:\n";
955 out.indent();
956 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
957 out << "return ::android::hardware::Return<";
958 if (elidedReturn != nullptr) {
959 std::string extra;
960 out << method->results().at(0)->type().getCppResultType(&extra);
961 } else {
962 out << "void";
963 }
964 out << ">(_hidl_status);\n";
965
966 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700967 out << "}\n\n";
968 }
Andreas Huber881227d2016-08-02 14:20:21 -0700969 }
970
971 return OK;
972}
973
974status_t AST::generateStubSource(
975 Formatter &out, const std::string &baseName) const {
976 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
977 << baseName
978 << ", \""
979 << mPackage.string()
980 << "::I"
981 << baseName
982 << "\");\n\n";
983
984 const std::string klassName = "Bn" + baseName;
985
Steven Moreland40786312016-08-16 10:29:40 -0700986 out << klassName
987 << "::"
988 << klassName
989 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
990
991 out.indent();
992 out.indent();
993
994 out << ": BnInterface"
995 << "<I"
996 << baseName
997 << ", IHw"
998 << baseName
999 << ">(_hidl_impl) {\n";
1000
1001 out.unindent();
1002 out.unindent();
1003 out << "}\n\n";
1004
Andreas Huber881227d2016-08-02 14:20:21 -07001005 out << "::android::status_t " << klassName << "::onTransact(\n";
1006
1007 out.indent();
1008 out.indent();
1009
Iliyan Malchev549e2592016-08-10 08:59:12 -07001010 out << "uint32_t _hidl_code,\n"
1011 << "const ::android::hardware::Parcel &_hidl_data,\n"
1012 << "::android::hardware::Parcel *_hidl_reply,\n"
1013 << "uint32_t _hidl_flags,\n"
1014 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001015
1016 out.unindent();
1017
Iliyan Malchev549e2592016-08-10 08:59:12 -07001018 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001019 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001020 out.indent();
1021
1022 const Interface *iface = mRootScope->getInterface();
1023
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001024 std::vector<const Interface *> chain;
1025 while (iface != NULL) {
1026 chain.push_back(iface);
1027 iface = iface->superType();
1028 }
Andreas Huber881227d2016-08-02 14:20:21 -07001029
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001030 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1031 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001032
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001033 for (const auto &method : superInterface->methods()) {
1034 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001035 << superInterface->fqName().cppNamespace()
1036 << "::IHw"
1037 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001038 << "::Call::"
1039 << upcase(method->name())
1040 << ":\n{\n";
1041
1042 out.indent();
1043
1044 status_t err =
1045 generateStubSourceForMethod(out, superInterface, method);
1046
1047 if (err != OK) {
1048 return err;
1049 }
1050
1051 out.unindent();
1052 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001053 }
Andreas Huber881227d2016-08-02 14:20:21 -07001054 }
1055
1056 out << "default:\n{\n";
1057 out.indent();
1058
Andreas Huber8a82ff72016-08-04 10:29:39 -07001059 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001060 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001061 << ">::onTransact(\n";
1062
1063 out.indent();
1064 out.indent();
1065
Iliyan Malchev549e2592016-08-10 08:59:12 -07001066 out << "_hidl_code, _hidl_data, _hidl_reply, "
1067 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001068
1069 out.unindent();
1070 out.unindent();
1071
1072 out.unindent();
1073 out << "}\n";
1074
1075 out.unindent();
1076 out << "}\n\n";
1077
Iliyan Malchev549e2592016-08-10 08:59:12 -07001078 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001079 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001080 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001081 out.indent();
1082 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001083 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001084 out.indent();
1085 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001086 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001087 out.unindent();
1088 out.unindent();
1089 out.unindent();
1090 out.unindent();
1091
1092 out.unindent();
1093 out << "}\n\n";
1094
Iliyan Malchev549e2592016-08-10 08:59:12 -07001095 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001096
1097 out.unindent();
1098 out << "}\n\n";
1099
1100 return OK;
1101}
1102
1103status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001104 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001105 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001106 << iface->fqName().cppNamespace()
1107 << "::IHw"
1108 << iface->getBaseName()
1109 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001110
Andreas Huber881227d2016-08-02 14:20:21 -07001111 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001112 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001113 out << "break;\n";
1114 out.unindent();
1115 out << "}\n\n";
1116
Andreas Hubere7ff2282016-08-16 13:50:03 -07001117 declareCppReaderLocals(out, method->args());
1118
Andreas Huber881227d2016-08-02 14:20:21 -07001119 for (const auto &arg : method->args()) {
1120 emitCppReaderWriter(
1121 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001122 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001123 false /* parcelObjIsPointer */,
1124 arg,
1125 true /* reader */,
1126 Type::ErrorMode_Break);
1127 }
1128
1129 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001130 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001131
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001132 if (elidedReturn != nullptr) {
1133 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001134
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001135 out << elidedReturn->type().getCppResultType(&extra) << " ";
1136 out << elidedReturn->name() << " = ";
1137 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001138
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001139 bool first = true;
1140 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001141 if (!first) {
1142 out << ", ";
1143 }
1144
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001145 if (arg->type().resultNeedsDeref()) {
1146 out << "*";
1147 }
1148
1149 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001150
1151 first = false;
1152 }
1153
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001154 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001155 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001156 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001157
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001158 elidedReturn->type().emitReaderWriter(
1159 out,
1160 elidedReturn->name(),
1161 "_hidl_reply",
1162 true, /* parcelObjIsPointer */
1163 false, /* isReader */
1164 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001165
Iliyan Malchev549e2592016-08-10 08:59:12 -07001166 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001167 } else {
1168 if (returnsValue) {
1169 out << "bool _hidl_callbackCalled = false;\n\n";
1170 }
Andreas Huber881227d2016-08-02 14:20:21 -07001171
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001172 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001173
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001174 bool first = true;
1175 for (const auto &arg : method->args()) {
1176 if (!first) {
1177 out << ", ";
1178 }
Andreas Huber881227d2016-08-02 14:20:21 -07001179
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001180 if (arg->type().resultNeedsDeref()) {
1181 out << "*";
1182 }
1183
1184 out << arg->name();
1185
1186 first = false;
1187 }
1188
1189 if (returnsValue) {
1190 if (!first) {
1191 out << ", ";
1192 }
1193
1194 out << "[&](";
1195
1196 first = true;
1197 for (const auto &arg : method->results()) {
1198 if (!first) {
1199 out << ", ";
1200 }
1201
1202 out << "const auto &" << arg->name();
1203
1204 first = false;
1205 }
1206
1207 out << ") {\n";
1208 out.indent();
1209 out << "_hidl_callbackCalled = true;\n\n";
1210
1211 out << "::android::hardware::Status::ok()"
1212 << ".writeToParcel(_hidl_reply);\n\n";
1213
1214 for (const auto &arg : method->results()) {
1215 emitCppReaderWriter(
1216 out,
1217 "_hidl_reply",
1218 true /* parcelObjIsPointer */,
1219 arg,
1220 false /* reader */,
1221 Type::ErrorMode_Ignore);
1222 }
1223
1224 out << "_hidl_cb(*_hidl_reply);\n";
1225
1226 out.unindent();
1227 out << "}\n";
1228 }
1229
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001230 out << ");\n\n";
1231
1232 // What to do if the stub implementation has a synchronous callback
1233 // which does not get invoked? This is not a transport error but a
1234 // service error of sorts. For now, return OK to the caller, as this is
1235 // not a transport error.
1236 //
1237 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001238
1239 if (returnsValue) {
1240 out << "if (!_hidl_callbackCalled) {\n";
1241 out.indent();
1242 }
1243
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001244 out << "::android::hardware::Status::ok()"
1245 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001246
1247 if (returnsValue) {
1248 out.unindent();
1249 out << "}\n\n";
1250 }
Andreas Huber881227d2016-08-02 14:20:21 -07001251 }
1252
1253 out << "break;\n";
1254
1255 return OK;
1256}
1257
1258} // namespace android
1259