blob: 2ad8019bd6d8ca3c8b6e16a7b226457447f3927d [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();
Andreas Huber881227d2016-08-02 14:20:21 -0700192
Iliyan Malchev795dd432016-09-02 11:48:26 -0700193 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700194 bool haveCallbacks = false;
195 for (const auto &method : iface->methods()) {
196 const bool returnsValue = !method->results().empty();
197
198 if (!returnsValue) {
199 continue;
200 }
201
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700202 if (method->canElideCallback() != nullptr) {
203 continue;
204 }
205
Andreas Huber881227d2016-08-02 14:20:21 -0700206 haveCallbacks = true;
207
208 out << "using "
209 << method->name()
210 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700211 << Method::GetArgSignature(method->results(),
212 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700213 << ")>;\n";
214 }
215
216 if (haveCallbacks) {
217 out << "\n";
218 }
219
220 for (const auto &method : iface->methods()) {
221 const bool returnsValue = !method->results().empty();
222
Andreas Huber3599d922016-08-09 10:42:57 -0700223 method->dumpAnnotations(out);
224
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700225 const TypedVar *elidedReturn = method->canElideCallback();
226 if (elidedReturn) {
227 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700228 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700229 out << elidedReturn->type().getCppResultType(&extra) << "> ";
230 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700231 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700232 }
233
234 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700235 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700236 << Method::GetArgSignature(method->args(),
237 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700238
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700239 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700240 if (!method->args().empty()) {
241 out << ", ";
242 }
243
Iliyan Malchev549e2592016-08-10 08:59:12 -0700244 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700245 }
246
247 out << ") = 0;\n";
248 }
Steven Moreland40786312016-08-16 10:29:40 -0700249
250 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700251 }
252
253 if (isInterface) {
254 out.unindent();
255
256 out << "};\n";
257 }
258
259 out << "\n";
260 enterLeaveNamespace(out, false /* enter */);
261
262 out << "\n#endif // " << guard << "\n";
263
264 return OK;
265}
266
Steven Moreland40786312016-08-16 10:29:40 -0700267status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
268 std::string ifaceName;
269 if(!AST::isInterface(&ifaceName)) {
270 // types.hal does not get an HwBinder header.
271 return OK;
272 }
273
274 // cut off the leading 'I'.
275 const std::string baseName = ifaceName.substr(1);
276
277 const std::string klassName = "IHw" + baseName;
278
279 std::string path = outputPath;
280 path.append(mCoordinator->convertPackageRootToPath(mPackage));
281 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
282 path.append(klassName + ".h");
283
284 FILE* file = fopen(path.c_str(), "w");
285
286 if (file == NULL) {
287 return -errno;
288 }
289
290 Formatter out(file);
291
292 const std::string guard = makeHeaderGuard(klassName);
293
294 out << "#ifndef " << guard << "\n";
295 out << "#define " << guard << "\n\n";
296
297 std::vector<std::string> packageComponents;
298 getPackageAndVersionComponents(
299 &packageComponents, false /* cpp_compatible */);
300
301 out << "#include <";
302 for (const auto &component : packageComponents) {
303 out << component << "/";
304 }
305 out << ifaceName << ".h>\n\n";
306
307 for (const auto &item : mImportedNames) {
308 if (item.name() == "types") {
309 continue;
310 }
311
312 out << "#include <";
313
314 std::vector<std::string> components;
315 item.getPackageAndVersionComponents(
316 &components, false /* cpp_compatible */);
317
318 for (const auto &component : components) {
319 out << component << "/";
320 }
321
322 // cut off the leading I
323 const std::string itemBaseName = item.name().substr(1);
324
325 out << "Bn"
326 << itemBaseName
327 << ".h>\n";
328 }
329
330 out << "\n";
331
332 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200333 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700334 out << "#include <hwbinder/IBinder.h>\n";
335 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700336
337 out << "\n";
338
339 enterLeaveNamespace(out, true /* enter */);
340 out << "\n";
341
342 out << "struct "
343 << klassName
344 << " : public "
345 << ifaceName;
346
347 const Interface *iface = mRootScope->getInterface();
348 const Interface *superType = iface->superType();
349
350 out << ", public ::android::hardware::IInterface";
351
352 out << " {\n";
353
354 out.indent();
355
356 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
357
358 out << "enum Call {\n";
359 out.indent();
360
361 bool first = true;
362 for (const auto &method : iface->methods()) {
Steven Morelandaf440142016-09-07 10:09:11 -0700363 out << StringHelper::Upcase(method->name());
Steven Moreland40786312016-08-16 10:29:40 -0700364
365 if (first) {
366 out << " = ";
367 if (superType != NULL) {
368 out << superType->fqName().cppNamespace()
369 << "::IHw"
370 << superType->getBaseName()
371 << "::Call::CallCount";
372 } else {
373 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
374 }
375
376 first = false;
377 }
378
379 out << ",\n";
380 }
381
382 out << "CallCount\n";
383
384 out.unindent();
385 out << "};\n\n";
386
387 out.unindent();
388
389 out << "};\n\n";
390
391 enterLeaveNamespace(out, false /* enter */);
392
393 out << "\n#endif // " << guard << "\n";
394
395 return OK;
396}
397
Andreas Huber881227d2016-08-02 14:20:21 -0700398status_t AST::emitTypeDeclarations(Formatter &out) const {
399 return mRootScope->emitTypeDeclarations(out);
400}
401
Steven Morelanda7a421a2016-09-07 08:35:18 -0700402status_t AST::generateStubMethod(Formatter &out,
403 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700404 const Method *method,
405 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700406 out << "inline ";
407
Steven Moreland979e0992016-09-07 09:18:08 -0700408 method->generateCppSignature(out,
409 className,
410 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700411
412 const bool returnsValue = !method->results().empty();
413 const TypedVar *elidedReturn = method->canElideCallback();
414 out << " {\n";
415 out.indent();
416 out << "return mImpl->"
417 << method->name()
418 << "(";
419 bool first = true;
420 for (const auto &arg : method->args()) {
421 if (!first) {
422 out << ", ";
423 }
424 first = false;
425 out << arg->name();
426 }
427 if (returnsValue && elidedReturn == nullptr) {
428 if (!method->args().empty()) {
429 out << ", ";
430 }
431
432 out << "_hidl_cb";
433 }
434 out << ");\n";
435 out.unindent();
436 out << "}";
437
438 out << ";\n";
439
440 return OK;
441}
442
Steven Moreland9c387612016-09-07 09:54:26 -0700443status_t AST::generateProxyDeclaration(Formatter &out,
444 const std::string &className,
445 const Method *method,
446 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700447
Steven Moreland979e0992016-09-07 09:18:08 -0700448 method->generateCppSignature(out,
449 className,
450 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700451 out << " override;\n";
452
453 return OK;
454}
455
456status_t AST::generateMethods(
457 Formatter &out,
458 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700459 MethodLocation type,
460 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700461
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700462 const Interface *iface = mRootScope->getInterface();
463
464 std::vector<const Interface *> chain;
465 while (iface != NULL) {
466 chain.push_back(iface);
467 iface = iface->superType();
468 }
469
470 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
471 const Interface *superInterface = *it;
472
473 out << "// Methods from "
474 << superInterface->fullName()
475 << " follow.\n";
476
477 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700478 status_t err;
479 switch(type) {
480 case STUB_HEADER:
481 err = generateStubMethod(out,
482 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700483 method,
484 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700485 break;
486 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700487 err = generateProxyDeclaration(out,
488 className,
489 method,
490 specifyNamespaces);
491 break;
492 case IMPL_HEADER:
493 err = generateStubImplDeclaration(out,
494 className,
495 method,
496 specifyNamespaces);
497 break;
498 case IMPL_SOURCE:
499 err = generateStubImplMethod(out,
500 className,
501 method,
502 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700503 break;
504 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700505 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700506 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700507 }
508
Steven Morelanda7a421a2016-09-07 08:35:18 -0700509 if (err != OK) {
510 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700511 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700512 }
513
514 out << "\n";
515 }
516
517 return OK;
518}
519
Andreas Huberb82318c2016-08-02 14:45:54 -0700520status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700521 std::string ifaceName;
522 if (!AST::isInterface(&ifaceName)) {
523 // types.hal does not get a stub header.
524 return OK;
525 }
526
Andreas Huber881227d2016-08-02 14:20:21 -0700527 // cut off the leading 'I'.
528 const std::string baseName = ifaceName.substr(1);
Steven Moreland40786312016-08-16 10:29:40 -0700529 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700530
Andreas Huberb82318c2016-08-02 14:45:54 -0700531 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700532 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700533 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700534 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700535 path.append(".h");
536
Andreas Huberd2943e12016-08-05 11:59:31 -0700537 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700538 FILE *file = fopen(path.c_str(), "w");
539
540 if (file == NULL) {
541 return -errno;
542 }
543
544 Formatter out(file);
545
Steven Moreland40786312016-08-16 10:29:40 -0700546 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700547
548 out << "#ifndef " << guard << "\n";
549 out << "#define " << guard << "\n\n";
550
551 std::vector<std::string> packageComponents;
552 getPackageAndVersionComponents(
553 &packageComponents, false /* cpp_compatible */);
554
555 out << "#include <";
556 for (const auto &component : packageComponents) {
557 out << component << "/";
558 }
Steven Moreland40786312016-08-16 10:29:40 -0700559 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700560
561 enterLeaveNamespace(out, true /* enter */);
562 out << "\n";
563
564 out << "struct "
565 << "Bn"
566 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700567 << " : public ::android::hardware::BnInterface<I"
568 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700569 << "> {\n";
570
571 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700572 out << "explicit Bn"
573 << baseName
574 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
575 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700576 out << "::android::status_t onTransact(\n";
577 out.indent();
578 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700579 out << "uint32_t _hidl_code,\n";
580 out << "const ::android::hardware::Parcel &_hidl_data,\n";
581 out << "::android::hardware::Parcel *_hidl_reply,\n";
582 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700583 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700584 out.unindent();
585 out.unindent();
586
Steven Moreland9c387612016-09-07 09:54:26 -0700587 status_t err = generateMethods(out,
588 "" /* class name */,
589 MethodLocation::STUB_HEADER,
590 true /* specify namespaces */);
591
592 if (err != OK) {
593 return err;
594 }
595
Andreas Huber881227d2016-08-02 14:20:21 -0700596 out.unindent();
597
598 out << "};\n\n";
599
600 enterLeaveNamespace(out, false /* enter */);
601
602 out << "\n#endif // " << guard << "\n";
603
604 return OK;
605}
606
Andreas Huberb82318c2016-08-02 14:45:54 -0700607status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700608 std::string ifaceName;
609 if (!AST::isInterface(&ifaceName)) {
610 // types.hal does not get a proxy header.
611 return OK;
612 }
613
Andreas Huber881227d2016-08-02 14:20:21 -0700614 // cut off the leading 'I'.
615 const std::string baseName = ifaceName.substr(1);
616
Andreas Huberb82318c2016-08-02 14:45:54 -0700617 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700618 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700619 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700620 path.append("Bp");
621 path.append(baseName);
622 path.append(".h");
623
Andreas Huberd2943e12016-08-05 11:59:31 -0700624 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700625 FILE *file = fopen(path.c_str(), "w");
626
627 if (file == NULL) {
628 return -errno;
629 }
630
631 Formatter out(file);
632
633 const std::string guard = makeHeaderGuard("Bp" + baseName);
634
635 out << "#ifndef " << guard << "\n";
636 out << "#define " << guard << "\n\n";
637
638 std::vector<std::string> packageComponents;
639 getPackageAndVersionComponents(
640 &packageComponents, false /* cpp_compatible */);
641
642 out << "#include <";
643 for (const auto &component : packageComponents) {
644 out << component << "/";
645 }
Steven Moreland40786312016-08-16 10:29:40 -0700646 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700647
648 enterLeaveNamespace(out, true /* enter */);
649 out << "\n";
650
651 out << "struct "
652 << "Bp"
653 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700654 << " : public ::android::hardware::BpInterface<IHw"
655 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700656 << "> {\n";
657
658 out.indent();
659
660 out << "explicit Bp"
661 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700662 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700663 << "\n\n";
664
Iliyan Malchev795dd432016-09-02 11:48:26 -0700665 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700666
Steven Moreland9c387612016-09-07 09:54:26 -0700667 status_t err = generateMethods(out,
668 "" /* class name */,
669 MethodLocation::PROXY_HEADER,
670 true /* generate specify namespaces */);
671
672 if (err != OK) {
673 return err;
674 }
Andreas Huber881227d2016-08-02 14:20:21 -0700675
676 out.unindent();
677
678 out << "};\n\n";
679
680 enterLeaveNamespace(out, false /* enter */);
681
682 out << "\n#endif // " << guard << "\n";
683
684 return OK;
685}
686
Andreas Huberb82318c2016-08-02 14:45:54 -0700687status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700688
Andreas Huberb82318c2016-08-02 14:45:54 -0700689 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700690 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700691 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700692
693 std::string ifaceName;
694 std::string baseName;
695
696 bool isInterface = true;
697 if (!AST::isInterface(&ifaceName)) {
698 baseName = "types";
699 isInterface = false;
700 } else {
701 baseName = ifaceName.substr(1); // cut off the leading 'I'.
702 }
703
704 path.append(baseName);
705
706 if (baseName != "types") {
707 path.append("All");
708 }
709
710 path.append(".cpp");
711
Andreas Huberd2943e12016-08-05 11:59:31 -0700712 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700713 FILE *file = fopen(path.c_str(), "w");
714
715 if (file == NULL) {
716 return -errno;
717 }
718
719 Formatter out(file);
720
721 std::vector<std::string> packageComponents;
722 getPackageAndVersionComponents(
723 &packageComponents, false /* cpp_compatible */);
724
725 std::string prefix;
726 for (const auto &component : packageComponents) {
727 prefix += component;
728 prefix += "/";
729 }
730
731 if (isInterface) {
732 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
733 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
734 } else {
735 out << "#include <" << prefix << "types.h>\n";
736 }
737
738 out << "\n";
739
740 enterLeaveNamespace(out, true /* enter */);
741 out << "\n";
742
743 status_t err = generateTypeSource(out, ifaceName);
744
745 if (err == OK && isInterface) {
746 err = generateProxySource(out, baseName);
747 }
748
749 if (err == OK && isInterface) {
750 err = generateStubSource(out, baseName);
751 }
752
Steven Moreland40786312016-08-16 10:29:40 -0700753 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700754 const Interface *iface = mRootScope->getInterface();
755
756 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
757 << baseName << ", "
758 << "\"" << iface->fqName().package()
759 << iface->fqName().version() << ".impl.so\""
760 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700761 }
762
Andreas Huber881227d2016-08-02 14:20:21 -0700763 enterLeaveNamespace(out, false /* enter */);
764
765 return err;
766}
767
768status_t AST::generateTypeSource(
769 Formatter &out, const std::string &ifaceName) const {
770 return mRootScope->emitTypeDefinitions(out, ifaceName);
771}
772
Andreas Hubere7ff2282016-08-16 13:50:03 -0700773void AST::declareCppReaderLocals(
774 Formatter &out, const std::vector<TypedVar *> &args) const {
775 if (args.empty()) {
776 return;
777 }
778
779 for (const auto &arg : args) {
780 const Type &type = arg->type();
781
782 std::string extra;
783 out << type.getCppResultType(&extra)
784 << " "
785 << arg->name()
786 << extra
787 << ";\n";
788 }
789
790 out << "\n";
791}
792
Andreas Huber881227d2016-08-02 14:20:21 -0700793void AST::emitCppReaderWriter(
794 Formatter &out,
795 const std::string &parcelObj,
796 bool parcelObjIsPointer,
797 const TypedVar *arg,
798 bool isReader,
799 Type::ErrorMode mode) const {
800 const Type &type = arg->type();
801
Andreas Huber881227d2016-08-02 14:20:21 -0700802 type.emitReaderWriter(
803 out,
804 arg->name(),
805 parcelObj,
806 parcelObjIsPointer,
807 isReader,
808 mode);
809}
810
811status_t AST::generateProxySource(
812 Formatter &out, const std::string &baseName) const {
813 const std::string klassName = "Bp" + baseName;
814
815 out << klassName
816 << "::"
817 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700818 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700819
820 out.indent();
821 out.indent();
822
823 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700824 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700825 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700826 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700827
828 out.unindent();
829 out.unindent();
830 out << "}\n\n";
831
832 const Interface *iface = mRootScope->getInterface();
833
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700834 std::vector<const Interface *> chain;
835 while (iface != NULL) {
836 chain.push_back(iface);
837 iface = iface->superType();
838 }
Andreas Huber881227d2016-08-02 14:20:21 -0700839
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700840 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
841 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700842
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700843 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700844 method->generateCppSignature(out,
845 klassName,
846 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700847
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700848 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700849 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700850
Steven Morelanda7a421a2016-09-07 08:35:18 -0700851 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700852
853 out.indent();
854
Iliyan Malchev549e2592016-08-10 08:59:12 -0700855 out << "::android::hardware::Parcel _hidl_data;\n";
856 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700857 out << "::android::status_t _hidl_err;\n";
858 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700859 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700860
Iliyan Malchev549e2592016-08-10 08:59:12 -0700861 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700862 << superInterface->fqName().cppNamespace()
863 << "::IHw"
864 << superInterface->getBaseName()
865 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700866
Iliyan Malchev549e2592016-08-10 08:59:12 -0700867 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700868
869 for (const auto &arg : method->args()) {
870 emitCppReaderWriter(
871 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700872 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700873 false /* parcelObjIsPointer */,
874 arg,
875 false /* reader */,
876 Type::ErrorMode_Goto);
877 }
878
Steven Moreland40786312016-08-16 10:29:40 -0700879 out << "_hidl_err = remote()->transact("
880 << superInterface->fqName().cppNamespace()
881 << "::IHw"
882 << superInterface->getBaseName()
883 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -0700884 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700885 << ", _hidl_data, &_hidl_reply";
886 if (method->isOneway()) {
887 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700888 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700889 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700890
Iliyan Malchev639bff82016-08-13 14:24:11 -0700891 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700892
Iliyan Malchev639bff82016-08-13 14:24:11 -0700893 if (!method->isOneway()) {
894 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
895 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700896 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
897
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700898 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700899 emitCppReaderWriter(
900 out,
901 "_hidl_reply",
902 false /* parcelObjIsPointer */,
903 arg,
904 true /* reader */,
905 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700906 }
907
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700908 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700909 out << "if (_hidl_cb != nullptr) {\n";
910 out.indent();
911 out << "_hidl_cb(";
912
913 bool first = true;
914 for (const auto &arg : method->results()) {
915 if (!first) {
916 out << ", ";
917 }
918
919 if (arg->type().resultNeedsDeref()) {
920 out << "*";
921 }
922 out << arg->name();
923
924 first = false;
925 }
926
927 out << ");\n";
928 out.unindent();
929 out << "}\n\n";
930 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700931 }
932
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700933 if (elidedReturn != nullptr) {
934 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700935 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700936 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700937 out << elidedReturn->type().getCppResultType(&extra)
938 << ">(" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700939 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700940 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700941 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700942 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700943
Andreas Huber881227d2016-08-02 14:20:21 -0700944 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700945 out << "_hidl_error:\n";
946 out.indent();
947 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
948 out << "return ::android::hardware::Return<";
949 if (elidedReturn != nullptr) {
950 std::string extra;
951 out << method->results().at(0)->type().getCppResultType(&extra);
952 } else {
953 out << "void";
954 }
955 out << ">(_hidl_status);\n";
956
957 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700958 out << "}\n\n";
959 }
Andreas Huber881227d2016-08-02 14:20:21 -0700960 }
961
962 return OK;
963}
964
965status_t AST::generateStubSource(
966 Formatter &out, const std::string &baseName) const {
967 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
968 << baseName
969 << ", \""
970 << mPackage.string()
971 << "::I"
972 << baseName
973 << "\");\n\n";
974
975 const std::string klassName = "Bn" + baseName;
976
Steven Moreland40786312016-08-16 10:29:40 -0700977 out << klassName
978 << "::"
979 << klassName
980 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
981
982 out.indent();
983 out.indent();
984
985 out << ": BnInterface"
986 << "<I"
987 << baseName
988 << ", IHw"
989 << baseName
990 << ">(_hidl_impl) {\n";
991
992 out.unindent();
993 out.unindent();
994 out << "}\n\n";
995
Andreas Huber881227d2016-08-02 14:20:21 -0700996 out << "::android::status_t " << klassName << "::onTransact(\n";
997
998 out.indent();
999 out.indent();
1000
Iliyan Malchev549e2592016-08-10 08:59:12 -07001001 out << "uint32_t _hidl_code,\n"
1002 << "const ::android::hardware::Parcel &_hidl_data,\n"
1003 << "::android::hardware::Parcel *_hidl_reply,\n"
1004 << "uint32_t _hidl_flags,\n"
1005 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001006
1007 out.unindent();
1008
Iliyan Malchev549e2592016-08-10 08:59:12 -07001009 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001010 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001011 out.indent();
1012
1013 const Interface *iface = mRootScope->getInterface();
1014
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001015 std::vector<const Interface *> chain;
1016 while (iface != NULL) {
1017 chain.push_back(iface);
1018 iface = iface->superType();
1019 }
Andreas Huber881227d2016-08-02 14:20:21 -07001020
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001021 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1022 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001023
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001024 for (const auto &method : superInterface->methods()) {
1025 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001026 << superInterface->fqName().cppNamespace()
1027 << "::IHw"
1028 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001029 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001030 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001031 << ":\n{\n";
1032
1033 out.indent();
1034
1035 status_t err =
1036 generateStubSourceForMethod(out, superInterface, method);
1037
1038 if (err != OK) {
1039 return err;
1040 }
1041
1042 out.unindent();
1043 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001044 }
Andreas Huber881227d2016-08-02 14:20:21 -07001045 }
1046
1047 out << "default:\n{\n";
1048 out.indent();
1049
Andreas Huber8a82ff72016-08-04 10:29:39 -07001050 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001051 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001052 << ">::onTransact(\n";
1053
1054 out.indent();
1055 out.indent();
1056
Iliyan Malchev549e2592016-08-10 08:59:12 -07001057 out << "_hidl_code, _hidl_data, _hidl_reply, "
1058 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001059
1060 out.unindent();
1061 out.unindent();
1062
1063 out.unindent();
1064 out << "}\n";
1065
1066 out.unindent();
1067 out << "}\n\n";
1068
Iliyan Malchev549e2592016-08-10 08:59:12 -07001069 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001070 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001071 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001072 out.indent();
1073 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001074 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001075 out.indent();
1076 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001077 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001078 out.unindent();
1079 out.unindent();
1080 out.unindent();
1081 out.unindent();
1082
1083 out.unindent();
1084 out << "}\n\n";
1085
Iliyan Malchev549e2592016-08-10 08:59:12 -07001086 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001087
1088 out.unindent();
1089 out << "}\n\n";
1090
1091 return OK;
1092}
1093
1094status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001095 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001096 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001097 << iface->fqName().cppNamespace()
1098 << "::IHw"
1099 << iface->getBaseName()
1100 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001101
Andreas Huber881227d2016-08-02 14:20:21 -07001102 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001103 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001104 out << "break;\n";
1105 out.unindent();
1106 out << "}\n\n";
1107
Andreas Hubere7ff2282016-08-16 13:50:03 -07001108 declareCppReaderLocals(out, method->args());
1109
Andreas Huber881227d2016-08-02 14:20:21 -07001110 for (const auto &arg : method->args()) {
1111 emitCppReaderWriter(
1112 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001113 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001114 false /* parcelObjIsPointer */,
1115 arg,
1116 true /* reader */,
1117 Type::ErrorMode_Break);
1118 }
1119
1120 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001121 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001122
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001123 if (elidedReturn != nullptr) {
1124 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001125
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001126 out << elidedReturn->type().getCppResultType(&extra) << " ";
1127 out << elidedReturn->name() << " = ";
1128 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001129
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001130 bool first = true;
1131 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001132 if (!first) {
1133 out << ", ";
1134 }
1135
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001136 if (arg->type().resultNeedsDeref()) {
1137 out << "*";
1138 }
1139
1140 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001141
1142 first = false;
1143 }
1144
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001145 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001146 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001147 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001148
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001149 elidedReturn->type().emitReaderWriter(
1150 out,
1151 elidedReturn->name(),
1152 "_hidl_reply",
1153 true, /* parcelObjIsPointer */
1154 false, /* isReader */
1155 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001156
Iliyan Malchev549e2592016-08-10 08:59:12 -07001157 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001158 } else {
1159 if (returnsValue) {
1160 out << "bool _hidl_callbackCalled = false;\n\n";
1161 }
Andreas Huber881227d2016-08-02 14:20:21 -07001162
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001163 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001164
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001165 bool first = true;
1166 for (const auto &arg : method->args()) {
1167 if (!first) {
1168 out << ", ";
1169 }
Andreas Huber881227d2016-08-02 14:20:21 -07001170
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001171 if (arg->type().resultNeedsDeref()) {
1172 out << "*";
1173 }
1174
1175 out << arg->name();
1176
1177 first = false;
1178 }
1179
1180 if (returnsValue) {
1181 if (!first) {
1182 out << ", ";
1183 }
1184
1185 out << "[&](";
1186
1187 first = true;
1188 for (const auto &arg : method->results()) {
1189 if (!first) {
1190 out << ", ";
1191 }
1192
1193 out << "const auto &" << arg->name();
1194
1195 first = false;
1196 }
1197
1198 out << ") {\n";
1199 out.indent();
1200 out << "_hidl_callbackCalled = true;\n\n";
1201
1202 out << "::android::hardware::Status::ok()"
1203 << ".writeToParcel(_hidl_reply);\n\n";
1204
1205 for (const auto &arg : method->results()) {
1206 emitCppReaderWriter(
1207 out,
1208 "_hidl_reply",
1209 true /* parcelObjIsPointer */,
1210 arg,
1211 false /* reader */,
1212 Type::ErrorMode_Ignore);
1213 }
1214
1215 out << "_hidl_cb(*_hidl_reply);\n";
1216
1217 out.unindent();
1218 out << "}\n";
1219 }
1220
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001221 out << ");\n\n";
1222
1223 // What to do if the stub implementation has a synchronous callback
1224 // which does not get invoked? This is not a transport error but a
1225 // service error of sorts. For now, return OK to the caller, as this is
1226 // not a transport error.
1227 //
1228 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001229
1230 if (returnsValue) {
1231 out << "if (!_hidl_callbackCalled) {\n";
1232 out.indent();
1233 }
1234
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001235 out << "::android::hardware::Status::ok()"
1236 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001237
1238 if (returnsValue) {
1239 out.unindent();
1240 out << "}\n\n";
1241 }
Andreas Huber881227d2016-08-02 14:20:21 -07001242 }
1243
1244 out << "break;\n";
1245
1246 return OK;
1247}
1248
1249} // namespace android
1250