blob: 84001cff4726adec1e059f1e33dee8e0964f462f [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"
Steven Morelandaf440142016-09-07 10:09:11 -070026#include "StringHelper.h"
Andreas Huber881227d2016-08-02 14:20:21 -070027
Andreas Huberdca261f2016-08-04 13:47:51 -070028#include <algorithm>
Andreas Huber881227d2016-08-02 14:20:21 -070029#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070031#include <vector>
32
33namespace android {
34
Andreas Huberb82318c2016-08-02 14:45:54 -070035status_t AST::generateCpp(const std::string &outputPath) const {
36 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070037
38 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070039 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070040 }
41
42 if (err == OK) {
Steven Moreland40786312016-08-16 10:29:40 -070043 err = generateHwBinderHeader(outputPath);
44 }
45
46 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070047 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070048 }
49
50 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070051 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070052 }
53
54 return err;
55}
56
Andreas Huber737080b2016-08-02 15:38:04 -070057void AST::getPackageComponents(
58 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070059 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070060}
61
62void AST::getPackageAndVersionComponents(
63 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070064 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070065}
66
Andreas Huber881227d2016-08-02 14:20:21 -070067std::string AST::makeHeaderGuard(const std::string &baseName) const {
Steven Moreland9c387612016-09-07 09:54:26 -070068 std::string guard = "HIDL_GENERATED_";
69 guard += mPackage.tokenName();
Andreas Huber881227d2016-08-02 14:20:21 -070070
71 guard += "_";
72 guard += baseName;
73 guard += "_H_";
74
75 return guard;
76}
77
78void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
79 std::vector<std::string> packageComponents;
80 getPackageAndVersionComponents(
81 &packageComponents, true /* cpp_compatible */);
82
83 if (enter) {
84 for (const auto &component : packageComponents) {
85 out << "namespace " << component << " {\n";
86 }
Andreas Huber0e00de42016-08-03 09:56:02 -070087
Andreas Huber2831d512016-08-15 09:33:47 -070088 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -070089 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -070090 out.setNamespace(std::string());
91
Andreas Huber881227d2016-08-02 14:20:21 -070092 for (auto it = packageComponents.rbegin();
93 it != packageComponents.rend();
94 ++it) {
95 out << "} // namespace " << *it << "\n";
96 }
97 }
98}
99
Andreas Huberb82318c2016-08-02 14:45:54 -0700100status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700101
Andreas Huberb82318c2016-08-02 14:45:54 -0700102 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700103 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700104 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700105
106 std::string ifaceName;
107 bool isInterface = true;
108 if (!AST::isInterface(&ifaceName)) {
109 ifaceName = "types";
110 isInterface = false;
111 }
112 path.append(ifaceName);
113 path.append(".h");
114
Andreas Huberd2943e12016-08-05 11:59:31 -0700115 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700116 FILE *file = fopen(path.c_str(), "w");
117
118 if (file == NULL) {
119 return -errno;
120 }
121
122 Formatter out(file);
123
124 const std::string guard = makeHeaderGuard(ifaceName);
125
126 out << "#ifndef " << guard << "\n";
127 out << "#define " << guard << "\n\n";
128
Andreas Huber737080b2016-08-02 15:38:04 -0700129 for (const auto &item : mImportedNames) {
130 out << "#include <";
131
132 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700133 item.getPackageAndVersionComponents(
134 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700135
136 for (const auto &component : components) {
137 out << component << "/";
138 }
139
140 out << item.name()
141 << ".h>\n";
142 }
143
144 if (!mImportedNames.empty()) {
145 out << "\n";
146 }
147
Martijn Coenen7473fab2016-08-19 14:05:40 +0200148 out << "#include <hidl/HidlSupport.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700149 out << "#include <hidl/IServiceManager.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700150
151 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200152 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700153 }
154
155 out << "#include <utils/NativeHandle.h>\n\n";
156
157 enterLeaveNamespace(out, true /* enter */);
158 out << "\n";
159
Steven Moreland40786312016-08-16 10:29:40 -0700160 // cut off the leading 'I'.
161 const std::string baseName = ifaceName.substr(1);
162
Andreas Huber881227d2016-08-02 14:20:21 -0700163 if (isInterface) {
164 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700165 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700166
167 const Interface *iface = mRootScope->getInterface();
168 const Interface *superType = iface->superType();
169
Steven Moreland40786312016-08-16 10:29:40 -0700170 if (superType == NULL) {
171 out << " : virtual public RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700172 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700173 out << " : public "
174 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700175 }
176
177 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700178
179 out.indent();
180
Andreas Huber881227d2016-08-02 14:20:21 -0700181 }
182
183 status_t err = emitTypeDeclarations(out);
184
185 if (err != OK) {
186 return err;
187 }
188
189 if (isInterface) {
190 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700191 const Interface *superType = iface->superType();
Martijn Coenena21f1492016-09-08 15:55:14 +0200192 out << "constexpr static hidl_version version = {"
193 << mPackage.getPackageMajorVersion() << ","
194 << mPackage.getPackageMinorVersion() << "};\n";
195 out << "virtual const hidl_version& getInterfaceVersion() const {\n";
196 out.indent();
197 out << "return version;\n";
198 out.unindent();
199 out << "}\n\n";
Iliyan Malchev795dd432016-09-02 11:48:26 -0700200 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700201 bool haveCallbacks = false;
202 for (const auto &method : iface->methods()) {
203 const bool returnsValue = !method->results().empty();
204
205 if (!returnsValue) {
206 continue;
207 }
208
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700209 if (method->canElideCallback() != nullptr) {
210 continue;
211 }
212
Andreas Huber881227d2016-08-02 14:20:21 -0700213 haveCallbacks = true;
214
215 out << "using "
216 << method->name()
217 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700218 << Method::GetArgSignature(method->results(),
219 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700220 << ")>;\n";
221 }
222
223 if (haveCallbacks) {
224 out << "\n";
225 }
226
227 for (const auto &method : iface->methods()) {
228 const bool returnsValue = !method->results().empty();
229
Andreas Huber3599d922016-08-09 10:42:57 -0700230 method->dumpAnnotations(out);
231
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700232 const TypedVar *elidedReturn = method->canElideCallback();
233 if (elidedReturn) {
234 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700235 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700236 out << elidedReturn->type().getCppResultType(&extra) << "> ";
237 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700238 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700239 }
240
241 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700242 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700243 << Method::GetArgSignature(method->args(),
244 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700245
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700246 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700247 if (!method->args().empty()) {
248 out << ", ";
249 }
250
Iliyan Malchev549e2592016-08-10 08:59:12 -0700251 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700252 }
253
254 out << ") = 0;\n";
255 }
Steven Moreland40786312016-08-16 10:29:40 -0700256
257 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700258 }
259
260 if (isInterface) {
261 out.unindent();
262
263 out << "};\n";
264 }
265
266 out << "\n";
267 enterLeaveNamespace(out, false /* enter */);
268
269 out << "\n#endif // " << guard << "\n";
270
271 return OK;
272}
273
Steven Moreland40786312016-08-16 10:29:40 -0700274status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
275 std::string ifaceName;
276 if(!AST::isInterface(&ifaceName)) {
277 // types.hal does not get an HwBinder header.
278 return OK;
279 }
280
281 // cut off the leading 'I'.
282 const std::string baseName = ifaceName.substr(1);
283
284 const std::string klassName = "IHw" + baseName;
285
286 std::string path = outputPath;
287 path.append(mCoordinator->convertPackageRootToPath(mPackage));
288 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
289 path.append(klassName + ".h");
290
291 FILE* file = fopen(path.c_str(), "w");
292
293 if (file == NULL) {
294 return -errno;
295 }
296
297 Formatter out(file);
298
299 const std::string guard = makeHeaderGuard(klassName);
300
301 out << "#ifndef " << guard << "\n";
302 out << "#define " << guard << "\n\n";
303
304 std::vector<std::string> packageComponents;
305 getPackageAndVersionComponents(
306 &packageComponents, false /* cpp_compatible */);
307
308 out << "#include <";
309 for (const auto &component : packageComponents) {
310 out << component << "/";
311 }
312 out << ifaceName << ".h>\n\n";
313
314 for (const auto &item : mImportedNames) {
315 if (item.name() == "types") {
316 continue;
317 }
318
319 out << "#include <";
320
321 std::vector<std::string> components;
322 item.getPackageAndVersionComponents(
323 &components, false /* cpp_compatible */);
324
325 for (const auto &component : components) {
326 out << component << "/";
327 }
328
329 // cut off the leading I
330 const std::string itemBaseName = item.name().substr(1);
331
332 out << "Bn"
333 << itemBaseName
334 << ".h>\n";
335 }
336
337 out << "\n";
338
339 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200340 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700341 out << "#include <hwbinder/IBinder.h>\n";
342 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700343
344 out << "\n";
345
346 enterLeaveNamespace(out, true /* enter */);
347 out << "\n";
348
349 out << "struct "
350 << klassName
351 << " : public "
352 << ifaceName;
353
354 const Interface *iface = mRootScope->getInterface();
355 const Interface *superType = iface->superType();
356
357 out << ", public ::android::hardware::IInterface";
358
359 out << " {\n";
360
361 out.indent();
362
363 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
364
365 out << "enum Call {\n";
366 out.indent();
367
368 bool first = true;
369 for (const auto &method : iface->methods()) {
Steven Morelandaf440142016-09-07 10:09:11 -0700370 out << StringHelper::Upcase(method->name());
Steven Moreland40786312016-08-16 10:29:40 -0700371
372 if (first) {
373 out << " = ";
374 if (superType != NULL) {
375 out << superType->fqName().cppNamespace()
376 << "::IHw"
377 << superType->getBaseName()
378 << "::Call::CallCount";
379 } else {
380 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
381 }
382
383 first = false;
384 }
385
386 out << ",\n";
387 }
388
389 out << "CallCount\n";
390
391 out.unindent();
392 out << "};\n\n";
393
394 out.unindent();
395
396 out << "};\n\n";
397
398 enterLeaveNamespace(out, false /* enter */);
399
400 out << "\n#endif // " << guard << "\n";
401
402 return OK;
403}
404
Andreas Huber881227d2016-08-02 14:20:21 -0700405status_t AST::emitTypeDeclarations(Formatter &out) const {
406 return mRootScope->emitTypeDeclarations(out);
407}
408
Steven Morelanda7a421a2016-09-07 08:35:18 -0700409status_t AST::generateStubMethod(Formatter &out,
410 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700411 const Method *method,
412 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700413 out << "inline ";
414
Steven Moreland979e0992016-09-07 09:18:08 -0700415 method->generateCppSignature(out,
416 className,
417 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700418
419 const bool returnsValue = !method->results().empty();
420 const TypedVar *elidedReturn = method->canElideCallback();
421 out << " {\n";
422 out.indent();
423 out << "return mImpl->"
424 << method->name()
425 << "(";
426 bool first = true;
427 for (const auto &arg : method->args()) {
428 if (!first) {
429 out << ", ";
430 }
431 first = false;
432 out << arg->name();
433 }
434 if (returnsValue && elidedReturn == nullptr) {
435 if (!method->args().empty()) {
436 out << ", ";
437 }
438
439 out << "_hidl_cb";
440 }
441 out << ");\n";
442 out.unindent();
443 out << "}";
444
445 out << ";\n";
446
447 return OK;
448}
449
Steven Moreland9c387612016-09-07 09:54:26 -0700450status_t AST::generateProxyDeclaration(Formatter &out,
451 const std::string &className,
452 const Method *method,
453 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700454
Steven Moreland979e0992016-09-07 09:18:08 -0700455 method->generateCppSignature(out,
456 className,
457 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700458 out << " override;\n";
459
460 return OK;
461}
462
463status_t AST::generateMethods(
464 Formatter &out,
465 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700466 MethodLocation type,
467 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700468
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700469 const Interface *iface = mRootScope->getInterface();
470
471 std::vector<const Interface *> chain;
472 while (iface != NULL) {
473 chain.push_back(iface);
474 iface = iface->superType();
475 }
476
477 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
478 const Interface *superInterface = *it;
479
480 out << "// Methods from "
481 << superInterface->fullName()
482 << " follow.\n";
483
484 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700485 status_t err;
486 switch(type) {
487 case STUB_HEADER:
488 err = generateStubMethod(out,
489 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700490 method,
491 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700492 break;
493 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700494 err = generateProxyDeclaration(out,
495 className,
496 method,
497 specifyNamespaces);
498 break;
499 case IMPL_HEADER:
500 err = generateStubImplDeclaration(out,
501 className,
502 method,
503 specifyNamespaces);
504 break;
505 case IMPL_SOURCE:
506 err = generateStubImplMethod(out,
507 className,
508 method,
509 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700510 break;
511 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700512 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700513 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700514 }
515
Steven Morelanda7a421a2016-09-07 08:35:18 -0700516 if (err != OK) {
517 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700518 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700519 }
520
521 out << "\n";
522 }
523
524 return OK;
525}
526
Andreas Huberb82318c2016-08-02 14:45:54 -0700527status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700528 std::string ifaceName;
529 if (!AST::isInterface(&ifaceName)) {
530 // types.hal does not get a stub header.
531 return OK;
532 }
533
Andreas Huber881227d2016-08-02 14:20:21 -0700534 // cut off the leading 'I'.
535 const std::string baseName = ifaceName.substr(1);
Steven Moreland40786312016-08-16 10:29:40 -0700536 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700537
Andreas Huberb82318c2016-08-02 14:45:54 -0700538 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700539 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700540 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700541 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700542 path.append(".h");
543
Andreas Huberd2943e12016-08-05 11:59:31 -0700544 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700545 FILE *file = fopen(path.c_str(), "w");
546
547 if (file == NULL) {
548 return -errno;
549 }
550
551 Formatter out(file);
552
Steven Moreland40786312016-08-16 10:29:40 -0700553 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700554
555 out << "#ifndef " << guard << "\n";
556 out << "#define " << guard << "\n\n";
557
558 std::vector<std::string> packageComponents;
559 getPackageAndVersionComponents(
560 &packageComponents, false /* cpp_compatible */);
561
562 out << "#include <";
563 for (const auto &component : packageComponents) {
564 out << component << "/";
565 }
Steven Moreland40786312016-08-16 10:29:40 -0700566 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700567
568 enterLeaveNamespace(out, true /* enter */);
569 out << "\n";
570
571 out << "struct "
572 << "Bn"
573 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700574 << " : public ::android::hardware::BnInterface<I"
575 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700576 << "> {\n";
577
578 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700579 out << "explicit Bn"
580 << baseName
581 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
582 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700583 out << "::android::status_t onTransact(\n";
584 out.indent();
585 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700586 out << "uint32_t _hidl_code,\n";
587 out << "const ::android::hardware::Parcel &_hidl_data,\n";
588 out << "::android::hardware::Parcel *_hidl_reply,\n";
589 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700590 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700591 out.unindent();
592 out.unindent();
593
Steven Moreland9c387612016-09-07 09:54:26 -0700594 status_t err = generateMethods(out,
595 "" /* class name */,
596 MethodLocation::STUB_HEADER,
597 true /* specify namespaces */);
598
599 if (err != OK) {
600 return err;
601 }
602
Andreas Huber881227d2016-08-02 14:20:21 -0700603 out.unindent();
604
605 out << "};\n\n";
606
607 enterLeaveNamespace(out, false /* enter */);
608
609 out << "\n#endif // " << guard << "\n";
610
611 return OK;
612}
613
Andreas Huberb82318c2016-08-02 14:45:54 -0700614status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700615 std::string ifaceName;
616 if (!AST::isInterface(&ifaceName)) {
617 // types.hal does not get a proxy header.
618 return OK;
619 }
620
Andreas Huber881227d2016-08-02 14:20:21 -0700621 // cut off the leading 'I'.
622 const std::string baseName = ifaceName.substr(1);
623
Andreas Huberb82318c2016-08-02 14:45:54 -0700624 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700625 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700626 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700627 path.append("Bp");
628 path.append(baseName);
629 path.append(".h");
630
Andreas Huberd2943e12016-08-05 11:59:31 -0700631 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700632 FILE *file = fopen(path.c_str(), "w");
633
634 if (file == NULL) {
635 return -errno;
636 }
637
638 Formatter out(file);
639
640 const std::string guard = makeHeaderGuard("Bp" + baseName);
641
642 out << "#ifndef " << guard << "\n";
643 out << "#define " << guard << "\n\n";
644
645 std::vector<std::string> packageComponents;
646 getPackageAndVersionComponents(
647 &packageComponents, false /* cpp_compatible */);
648
649 out << "#include <";
650 for (const auto &component : packageComponents) {
651 out << component << "/";
652 }
Steven Moreland40786312016-08-16 10:29:40 -0700653 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700654
655 enterLeaveNamespace(out, true /* enter */);
656 out << "\n";
657
658 out << "struct "
659 << "Bp"
660 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700661 << " : public ::android::hardware::BpInterface<IHw"
662 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700663 << "> {\n";
664
665 out.indent();
666
667 out << "explicit Bp"
668 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700669 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700670 << "\n\n";
671
Iliyan Malchev795dd432016-09-02 11:48:26 -0700672 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700673
Steven Moreland9c387612016-09-07 09:54:26 -0700674 status_t err = generateMethods(out,
675 "" /* class name */,
676 MethodLocation::PROXY_HEADER,
677 true /* generate specify namespaces */);
678
679 if (err != OK) {
680 return err;
681 }
Andreas Huber881227d2016-08-02 14:20:21 -0700682
683 out.unindent();
684
685 out << "};\n\n";
686
687 enterLeaveNamespace(out, false /* enter */);
688
689 out << "\n#endif // " << guard << "\n";
690
691 return OK;
692}
693
Andreas Huberb82318c2016-08-02 14:45:54 -0700694status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700695
Andreas Huberb82318c2016-08-02 14:45:54 -0700696 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700697 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700698 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700699
700 std::string ifaceName;
701 std::string baseName;
702
703 bool isInterface = true;
704 if (!AST::isInterface(&ifaceName)) {
705 baseName = "types";
706 isInterface = false;
707 } else {
708 baseName = ifaceName.substr(1); // cut off the leading 'I'.
709 }
710
711 path.append(baseName);
712
713 if (baseName != "types") {
714 path.append("All");
715 }
716
717 path.append(".cpp");
718
Andreas Huberd2943e12016-08-05 11:59:31 -0700719 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700720 FILE *file = fopen(path.c_str(), "w");
721
722 if (file == NULL) {
723 return -errno;
724 }
725
726 Formatter out(file);
727
728 std::vector<std::string> packageComponents;
729 getPackageAndVersionComponents(
730 &packageComponents, false /* cpp_compatible */);
731
732 std::string prefix;
733 for (const auto &component : packageComponents) {
734 prefix += component;
735 prefix += "/";
736 }
737
738 if (isInterface) {
739 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
740 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
741 } else {
742 out << "#include <" << prefix << "types.h>\n";
743 }
744
745 out << "\n";
746
747 enterLeaveNamespace(out, true /* enter */);
748 out << "\n";
749
750 status_t err = generateTypeSource(out, ifaceName);
751
752 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200753 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700754 err = generateProxySource(out, baseName);
755 }
756
757 if (err == OK && isInterface) {
758 err = generateStubSource(out, baseName);
759 }
760
Steven Moreland40786312016-08-16 10:29:40 -0700761 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700762 const Interface *iface = mRootScope->getInterface();
763
764 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
765 << baseName << ", "
766 << "\"" << iface->fqName().package()
767 << iface->fqName().version() << ".impl.so\""
768 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700769 }
770
Andreas Huber881227d2016-08-02 14:20:21 -0700771 enterLeaveNamespace(out, false /* enter */);
772
773 return err;
774}
775
776status_t AST::generateTypeSource(
777 Formatter &out, const std::string &ifaceName) const {
778 return mRootScope->emitTypeDefinitions(out, ifaceName);
779}
780
Andreas Hubere7ff2282016-08-16 13:50:03 -0700781void AST::declareCppReaderLocals(
782 Formatter &out, const std::vector<TypedVar *> &args) const {
783 if (args.empty()) {
784 return;
785 }
786
787 for (const auto &arg : args) {
788 const Type &type = arg->type();
789
790 std::string extra;
791 out << type.getCppResultType(&extra)
792 << " "
793 << arg->name()
794 << extra
795 << ";\n";
796 }
797
798 out << "\n";
799}
800
Andreas Huber881227d2016-08-02 14:20:21 -0700801void AST::emitCppReaderWriter(
802 Formatter &out,
803 const std::string &parcelObj,
804 bool parcelObjIsPointer,
805 const TypedVar *arg,
806 bool isReader,
807 Type::ErrorMode mode) const {
808 const Type &type = arg->type();
809
Andreas Huber881227d2016-08-02 14:20:21 -0700810 type.emitReaderWriter(
811 out,
812 arg->name(),
813 parcelObj,
814 parcelObjIsPointer,
815 isReader,
816 mode);
817}
818
819status_t AST::generateProxySource(
820 Formatter &out, const std::string &baseName) const {
821 const std::string klassName = "Bp" + baseName;
822
823 out << klassName
824 << "::"
825 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700826 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700827
828 out.indent();
829 out.indent();
830
831 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700832 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700833 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700834 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700835
836 out.unindent();
837 out.unindent();
838 out << "}\n\n";
839
840 const Interface *iface = mRootScope->getInterface();
841
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700842 std::vector<const Interface *> chain;
843 while (iface != NULL) {
844 chain.push_back(iface);
845 iface = iface->superType();
846 }
Andreas Huber881227d2016-08-02 14:20:21 -0700847
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700848 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
849 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700850
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700851 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700852 method->generateCppSignature(out,
853 klassName,
854 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700855
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700856 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700857 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700858
Steven Morelanda7a421a2016-09-07 08:35:18 -0700859 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700860
861 out.indent();
862
Iliyan Malchev549e2592016-08-10 08:59:12 -0700863 out << "::android::hardware::Parcel _hidl_data;\n";
864 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700865 out << "::android::status_t _hidl_err;\n";
866 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700867 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700868
Iliyan Malchev549e2592016-08-10 08:59:12 -0700869 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700870 << superInterface->fqName().cppNamespace()
871 << "::IHw"
872 << superInterface->getBaseName()
873 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700874
Iliyan Malchev549e2592016-08-10 08:59:12 -0700875 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700876
877 for (const auto &arg : method->args()) {
878 emitCppReaderWriter(
879 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700880 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700881 false /* parcelObjIsPointer */,
882 arg,
883 false /* reader */,
884 Type::ErrorMode_Goto);
885 }
886
Steven Moreland40786312016-08-16 10:29:40 -0700887 out << "_hidl_err = remote()->transact("
888 << superInterface->fqName().cppNamespace()
889 << "::IHw"
890 << superInterface->getBaseName()
891 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -0700892 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700893 << ", _hidl_data, &_hidl_reply";
894 if (method->isOneway()) {
895 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700896 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700897 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700898
Iliyan Malchev639bff82016-08-13 14:24:11 -0700899 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700900
Iliyan Malchev639bff82016-08-13 14:24:11 -0700901 if (!method->isOneway()) {
902 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
903 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700904 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
905
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700906 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700907 emitCppReaderWriter(
908 out,
909 "_hidl_reply",
910 false /* parcelObjIsPointer */,
911 arg,
912 true /* reader */,
913 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700914 }
915
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700916 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700917 out << "if (_hidl_cb != nullptr) {\n";
918 out.indent();
919 out << "_hidl_cb(";
920
921 bool first = true;
922 for (const auto &arg : method->results()) {
923 if (!first) {
924 out << ", ";
925 }
926
927 if (arg->type().resultNeedsDeref()) {
928 out << "*";
929 }
930 out << arg->name();
931
932 first = false;
933 }
934
935 out << ");\n";
936 out.unindent();
937 out << "}\n\n";
938 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700939 }
940
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700941 if (elidedReturn != nullptr) {
942 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700943 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700944 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700945 out << elidedReturn->type().getCppResultType(&extra)
946 << ">(" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700947 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700948 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700949 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700950 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700951
Andreas Huber881227d2016-08-02 14:20:21 -0700952 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700953 out << "_hidl_error:\n";
954 out.indent();
955 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
956 out << "return ::android::hardware::Return<";
957 if (elidedReturn != nullptr) {
958 std::string extra;
959 out << method->results().at(0)->type().getCppResultType(&extra);
960 } else {
961 out << "void";
962 }
963 out << ">(_hidl_status);\n";
964
965 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700966 out << "}\n\n";
967 }
Andreas Huber881227d2016-08-02 14:20:21 -0700968 }
969
970 return OK;
971}
972
973status_t AST::generateStubSource(
974 Formatter &out, const std::string &baseName) const {
975 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
976 << baseName
977 << ", \""
978 << mPackage.string()
979 << "::I"
980 << baseName
981 << "\");\n\n";
982
983 const std::string klassName = "Bn" + baseName;
984
Steven Moreland40786312016-08-16 10:29:40 -0700985 out << klassName
986 << "::"
987 << klassName
988 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
989
990 out.indent();
991 out.indent();
992
993 out << ": BnInterface"
994 << "<I"
995 << baseName
996 << ", IHw"
997 << baseName
998 << ">(_hidl_impl) {\n";
999
1000 out.unindent();
1001 out.unindent();
1002 out << "}\n\n";
1003
Andreas Huber881227d2016-08-02 14:20:21 -07001004 out << "::android::status_t " << klassName << "::onTransact(\n";
1005
1006 out.indent();
1007 out.indent();
1008
Iliyan Malchev549e2592016-08-10 08:59:12 -07001009 out << "uint32_t _hidl_code,\n"
1010 << "const ::android::hardware::Parcel &_hidl_data,\n"
1011 << "::android::hardware::Parcel *_hidl_reply,\n"
1012 << "uint32_t _hidl_flags,\n"
1013 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001014
1015 out.unindent();
1016
Iliyan Malchev549e2592016-08-10 08:59:12 -07001017 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001018 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001019 out.indent();
1020
1021 const Interface *iface = mRootScope->getInterface();
1022
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001023 std::vector<const Interface *> chain;
1024 while (iface != NULL) {
1025 chain.push_back(iface);
1026 iface = iface->superType();
1027 }
Andreas Huber881227d2016-08-02 14:20:21 -07001028
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001029 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1030 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001031
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001032 for (const auto &method : superInterface->methods()) {
1033 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001034 << superInterface->fqName().cppNamespace()
1035 << "::IHw"
1036 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001037 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001038 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001039 << ":\n{\n";
1040
1041 out.indent();
1042
1043 status_t err =
1044 generateStubSourceForMethod(out, superInterface, method);
1045
1046 if (err != OK) {
1047 return err;
1048 }
1049
1050 out.unindent();
1051 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001052 }
Andreas Huber881227d2016-08-02 14:20:21 -07001053 }
1054
1055 out << "default:\n{\n";
1056 out.indent();
1057
Andreas Huber8a82ff72016-08-04 10:29:39 -07001058 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001059 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001060 << ">::onTransact(\n";
1061
1062 out.indent();
1063 out.indent();
1064
Iliyan Malchev549e2592016-08-10 08:59:12 -07001065 out << "_hidl_code, _hidl_data, _hidl_reply, "
1066 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001067
1068 out.unindent();
1069 out.unindent();
1070
1071 out.unindent();
1072 out << "}\n";
1073
1074 out.unindent();
1075 out << "}\n\n";
1076
Iliyan Malchev549e2592016-08-10 08:59:12 -07001077 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001078 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001079 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001080 out.indent();
1081 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001082 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001083 out.indent();
1084 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001085 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001086 out.unindent();
1087 out.unindent();
1088 out.unindent();
1089 out.unindent();
1090
1091 out.unindent();
1092 out << "}\n\n";
1093
Iliyan Malchev549e2592016-08-10 08:59:12 -07001094 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001095
1096 out.unindent();
1097 out << "}\n\n";
1098
1099 return OK;
1100}
1101
1102status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001103 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001104 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001105 << iface->fqName().cppNamespace()
1106 << "::IHw"
1107 << iface->getBaseName()
1108 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001109
Andreas Huber881227d2016-08-02 14:20:21 -07001110 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001111 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001112 out << "break;\n";
1113 out.unindent();
1114 out << "}\n\n";
1115
Andreas Hubere7ff2282016-08-16 13:50:03 -07001116 declareCppReaderLocals(out, method->args());
1117
Andreas Huber881227d2016-08-02 14:20:21 -07001118 for (const auto &arg : method->args()) {
1119 emitCppReaderWriter(
1120 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001121 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001122 false /* parcelObjIsPointer */,
1123 arg,
1124 true /* reader */,
1125 Type::ErrorMode_Break);
1126 }
1127
1128 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001129 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001130
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001131 if (elidedReturn != nullptr) {
1132 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001133
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001134 out << elidedReturn->type().getCppResultType(&extra) << " ";
1135 out << elidedReturn->name() << " = ";
1136 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001137
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001138 bool first = true;
1139 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001140 if (!first) {
1141 out << ", ";
1142 }
1143
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001144 if (arg->type().resultNeedsDeref()) {
1145 out << "*";
1146 }
1147
1148 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001149
1150 first = false;
1151 }
1152
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001153 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001154 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001155 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001156
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001157 elidedReturn->type().emitReaderWriter(
1158 out,
1159 elidedReturn->name(),
1160 "_hidl_reply",
1161 true, /* parcelObjIsPointer */
1162 false, /* isReader */
1163 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001164
Iliyan Malchev549e2592016-08-10 08:59:12 -07001165 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001166 } else {
1167 if (returnsValue) {
1168 out << "bool _hidl_callbackCalled = false;\n\n";
1169 }
Andreas Huber881227d2016-08-02 14:20:21 -07001170
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001171 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001172
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001173 bool first = true;
1174 for (const auto &arg : method->args()) {
1175 if (!first) {
1176 out << ", ";
1177 }
Andreas Huber881227d2016-08-02 14:20:21 -07001178
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001179 if (arg->type().resultNeedsDeref()) {
1180 out << "*";
1181 }
1182
1183 out << arg->name();
1184
1185 first = false;
1186 }
1187
1188 if (returnsValue) {
1189 if (!first) {
1190 out << ", ";
1191 }
1192
1193 out << "[&](";
1194
1195 first = true;
1196 for (const auto &arg : method->results()) {
1197 if (!first) {
1198 out << ", ";
1199 }
1200
1201 out << "const auto &" << arg->name();
1202
1203 first = false;
1204 }
1205
1206 out << ") {\n";
1207 out.indent();
1208 out << "_hidl_callbackCalled = true;\n\n";
1209
1210 out << "::android::hardware::Status::ok()"
1211 << ".writeToParcel(_hidl_reply);\n\n";
1212
1213 for (const auto &arg : method->results()) {
1214 emitCppReaderWriter(
1215 out,
1216 "_hidl_reply",
1217 true /* parcelObjIsPointer */,
1218 arg,
1219 false /* reader */,
1220 Type::ErrorMode_Ignore);
1221 }
1222
1223 out << "_hidl_cb(*_hidl_reply);\n";
1224
1225 out.unindent();
1226 out << "}\n";
1227 }
1228
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001229 out << ");\n\n";
1230
1231 // What to do if the stub implementation has a synchronous callback
1232 // which does not get invoked? This is not a transport error but a
1233 // service error of sorts. For now, return OK to the caller, as this is
1234 // not a transport error.
1235 //
1236 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001237
1238 if (returnsValue) {
1239 out << "if (!_hidl_callbackCalled) {\n";
1240 out.indent();
1241 }
1242
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001243 out << "::android::hardware::Status::ok()"
1244 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001245
1246 if (returnsValue) {
1247 out.unindent();
1248 out << "}\n\n";
1249 }
Andreas Huber881227d2016-08-02 14:20:21 -07001250 }
1251
1252 out << "break;\n";
1253
1254 return OK;
1255}
1256
1257} // namespace android
1258