blob: 3543e97fc1a3af2b7377aa41608a56be83c66a1b [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 "Interface.h"
22#include "Method.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070023#include "ScalarType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070024#include "Scope.h"
25
Andreas Huberdca261f2016-08-04 13:47:51 -070026#include <algorithm>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070027#include <hidl-util/StringHelper.h>
28#include <hidl-util/Formatter.h>
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 Huber4bcf97d2016-08-30 11:27:49 -0700150 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700151
152 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200153 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700154 }
155
156 out << "#include <utils/NativeHandle.h>\n\n";
157
158 enterLeaveNamespace(out, true /* enter */);
159 out << "\n";
160
Steven Moreland40786312016-08-16 10:29:40 -0700161 // cut off the leading 'I'.
162 const std::string baseName = ifaceName.substr(1);
163
Andreas Huber881227d2016-08-02 14:20:21 -0700164 if (isInterface) {
165 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700166 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700167
168 const Interface *iface = mRootScope->getInterface();
169 const Interface *superType = iface->superType();
170
Steven Moreland40786312016-08-16 10:29:40 -0700171 if (superType == NULL) {
172 out << " : virtual public RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700173 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700174 out << " : public "
175 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700176 }
177
178 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700179
180 out.indent();
181
Andreas Huber881227d2016-08-02 14:20:21 -0700182 }
183
184 status_t err = emitTypeDeclarations(out);
185
186 if (err != OK) {
187 return err;
188 }
189
190 if (isInterface) {
191 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700192 const Interface *superType = iface->superType();
Martijn Coenena21f1492016-09-08 15:55:14 +0200193 out << "constexpr static hidl_version version = {"
194 << mPackage.getPackageMajorVersion() << ","
195 << mPackage.getPackageMinorVersion() << "};\n";
196 out << "virtual const hidl_version& getInterfaceVersion() const {\n";
197 out.indent();
198 out << "return version;\n";
199 out.unindent();
200 out << "}\n\n";
Iliyan Malchev795dd432016-09-02 11:48:26 -0700201 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700202 bool haveCallbacks = false;
203 for (const auto &method : iface->methods()) {
204 const bool returnsValue = !method->results().empty();
205
206 if (!returnsValue) {
207 continue;
208 }
209
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700210 if (method->canElideCallback() != nullptr) {
211 continue;
212 }
213
Andreas Huber881227d2016-08-02 14:20:21 -0700214 haveCallbacks = true;
215
216 out << "using "
217 << method->name()
218 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700219 << Method::GetArgSignature(method->results(),
220 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700221 << ")>;\n";
222 }
223
224 if (haveCallbacks) {
225 out << "\n";
226 }
227
228 for (const auto &method : iface->methods()) {
229 const bool returnsValue = !method->results().empty();
230
Andreas Huber3599d922016-08-09 10:42:57 -0700231 method->dumpAnnotations(out);
232
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700233 const TypedVar *elidedReturn = method->canElideCallback();
234 if (elidedReturn) {
235 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700236 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700237 out << elidedReturn->type().getCppResultType(&extra) << "> ";
238 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700239 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700240 }
241
242 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700243 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700244 << Method::GetArgSignature(method->args(),
245 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700246
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700247 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700248 if (!method->args().empty()) {
249 out << ", ";
250 }
251
Iliyan Malchev549e2592016-08-10 08:59:12 -0700252 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700253 }
254
255 out << ") = 0;\n";
256 }
Steven Moreland40786312016-08-16 10:29:40 -0700257
258 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700259 }
260
261 if (isInterface) {
262 out.unindent();
263
264 out << "};\n";
265 }
266
267 out << "\n";
268 enterLeaveNamespace(out, false /* enter */);
269
270 out << "\n#endif // " << guard << "\n";
271
272 return OK;
273}
274
Steven Moreland40786312016-08-16 10:29:40 -0700275status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
276 std::string ifaceName;
277 if(!AST::isInterface(&ifaceName)) {
278 // types.hal does not get an HwBinder header.
279 return OK;
280 }
281
282 // cut off the leading 'I'.
283 const std::string baseName = ifaceName.substr(1);
284
285 const std::string klassName = "IHw" + baseName;
286
287 std::string path = outputPath;
288 path.append(mCoordinator->convertPackageRootToPath(mPackage));
289 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
290 path.append(klassName + ".h");
291
292 FILE* file = fopen(path.c_str(), "w");
293
294 if (file == NULL) {
295 return -errno;
296 }
297
298 Formatter out(file);
299
300 const std::string guard = makeHeaderGuard(klassName);
301
302 out << "#ifndef " << guard << "\n";
303 out << "#define " << guard << "\n\n";
304
305 std::vector<std::string> packageComponents;
306 getPackageAndVersionComponents(
307 &packageComponents, false /* cpp_compatible */);
308
309 out << "#include <";
310 for (const auto &component : packageComponents) {
311 out << component << "/";
312 }
313 out << ifaceName << ".h>\n\n";
314
315 for (const auto &item : mImportedNames) {
316 if (item.name() == "types") {
317 continue;
318 }
319
320 out << "#include <";
321
322 std::vector<std::string> components;
323 item.getPackageAndVersionComponents(
324 &components, false /* cpp_compatible */);
325
326 for (const auto &component : components) {
327 out << component << "/";
328 }
329
330 // cut off the leading I
331 const std::string itemBaseName = item.name().substr(1);
332
333 out << "Bn"
334 << itemBaseName
335 << ".h>\n";
336 }
337
338 out << "\n";
339
340 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200341 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700342 out << "#include <hwbinder/IBinder.h>\n";
343 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700344
345 out << "\n";
346
347 enterLeaveNamespace(out, true /* enter */);
348 out << "\n";
349
350 out << "struct "
351 << klassName
352 << " : public "
353 << ifaceName;
354
355 const Interface *iface = mRootScope->getInterface();
356 const Interface *superType = iface->superType();
357
358 out << ", public ::android::hardware::IInterface";
359
360 out << " {\n";
361
362 out.indent();
363
364 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
365
366 out << "enum Call {\n";
367 out.indent();
368
369 bool first = true;
370 for (const auto &method : iface->methods()) {
Steven Morelandaf440142016-09-07 10:09:11 -0700371 out << StringHelper::Upcase(method->name());
Steven Moreland40786312016-08-16 10:29:40 -0700372
373 if (first) {
374 out << " = ";
375 if (superType != NULL) {
376 out << superType->fqName().cppNamespace()
377 << "::IHw"
378 << superType->getBaseName()
379 << "::Call::CallCount";
380 } else {
381 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
382 }
383
384 first = false;
385 }
386
387 out << ",\n";
388 }
389
390 out << "CallCount\n";
391
392 out.unindent();
393 out << "};\n\n";
394
395 out.unindent();
396
397 out << "};\n\n";
398
399 enterLeaveNamespace(out, false /* enter */);
400
401 out << "\n#endif // " << guard << "\n";
402
403 return OK;
404}
405
Andreas Huber881227d2016-08-02 14:20:21 -0700406status_t AST::emitTypeDeclarations(Formatter &out) const {
407 return mRootScope->emitTypeDeclarations(out);
408}
409
Steven Morelanda7a421a2016-09-07 08:35:18 -0700410status_t AST::generateStubMethod(Formatter &out,
411 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700412 const Method *method,
413 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700414 out << "inline ";
415
Steven Moreland979e0992016-09-07 09:18:08 -0700416 method->generateCppSignature(out,
417 className,
418 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700419
420 const bool returnsValue = !method->results().empty();
421 const TypedVar *elidedReturn = method->canElideCallback();
422 out << " {\n";
423 out.indent();
424 out << "return mImpl->"
425 << method->name()
426 << "(";
427 bool first = true;
428 for (const auto &arg : method->args()) {
429 if (!first) {
430 out << ", ";
431 }
432 first = false;
433 out << arg->name();
434 }
435 if (returnsValue && elidedReturn == nullptr) {
436 if (!method->args().empty()) {
437 out << ", ";
438 }
439
440 out << "_hidl_cb";
441 }
442 out << ");\n";
443 out.unindent();
444 out << "}";
445
446 out << ";\n";
447
448 return OK;
449}
450
Steven Moreland9c387612016-09-07 09:54:26 -0700451status_t AST::generateProxyDeclaration(Formatter &out,
452 const std::string &className,
453 const Method *method,
454 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700455
Steven Moreland979e0992016-09-07 09:18:08 -0700456 method->generateCppSignature(out,
457 className,
458 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700459 out << " override;\n";
460
461 return OK;
462}
463
464status_t AST::generateMethods(
465 Formatter &out,
466 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700467 MethodLocation type,
468 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700469
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700470 const Interface *iface = mRootScope->getInterface();
471
472 std::vector<const Interface *> chain;
473 while (iface != NULL) {
474 chain.push_back(iface);
475 iface = iface->superType();
476 }
477
478 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
479 const Interface *superInterface = *it;
480
481 out << "// Methods from "
482 << superInterface->fullName()
483 << " follow.\n";
484
485 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700486 status_t err;
487 switch(type) {
488 case STUB_HEADER:
489 err = generateStubMethod(out,
490 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700491 method,
492 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700493 break;
494 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700495 err = generateProxyDeclaration(out,
496 className,
497 method,
498 specifyNamespaces);
499 break;
500 case IMPL_HEADER:
501 err = generateStubImplDeclaration(out,
502 className,
503 method,
504 specifyNamespaces);
505 break;
506 case IMPL_SOURCE:
507 err = generateStubImplMethod(out,
508 className,
509 method,
510 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700511 break;
512 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700513 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700514 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700515 }
516
Steven Morelanda7a421a2016-09-07 08:35:18 -0700517 if (err != OK) {
518 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700519 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700520 }
521
522 out << "\n";
523 }
524
525 return OK;
526}
527
Andreas Huberb82318c2016-08-02 14:45:54 -0700528status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700529 std::string ifaceName;
530 if (!AST::isInterface(&ifaceName)) {
531 // types.hal does not get a stub header.
532 return OK;
533 }
534
Andreas Huber881227d2016-08-02 14:20:21 -0700535 // cut off the leading 'I'.
536 const std::string baseName = ifaceName.substr(1);
Steven Moreland40786312016-08-16 10:29:40 -0700537 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700538
Andreas Huberb82318c2016-08-02 14:45:54 -0700539 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700540 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700541 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700542 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700543 path.append(".h");
544
Andreas Huberd2943e12016-08-05 11:59:31 -0700545 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700546 FILE *file = fopen(path.c_str(), "w");
547
548 if (file == NULL) {
549 return -errno;
550 }
551
552 Formatter out(file);
553
Steven Moreland40786312016-08-16 10:29:40 -0700554 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700555
556 out << "#ifndef " << guard << "\n";
557 out << "#define " << guard << "\n\n";
558
559 std::vector<std::string> packageComponents;
560 getPackageAndVersionComponents(
561 &packageComponents, false /* cpp_compatible */);
562
563 out << "#include <";
564 for (const auto &component : packageComponents) {
565 out << component << "/";
566 }
Steven Moreland40786312016-08-16 10:29:40 -0700567 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700568
569 enterLeaveNamespace(out, true /* enter */);
570 out << "\n";
571
572 out << "struct "
573 << "Bn"
574 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700575 << " : public ::android::hardware::BnInterface<I"
576 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700577 << "> {\n";
578
579 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700580 out << "explicit Bn"
581 << baseName
582 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
583 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700584 out << "::android::status_t onTransact(\n";
585 out.indent();
586 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700587 out << "uint32_t _hidl_code,\n";
588 out << "const ::android::hardware::Parcel &_hidl_data,\n";
589 out << "::android::hardware::Parcel *_hidl_reply,\n";
590 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700591 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700592 out.unindent();
593 out.unindent();
594
Steven Moreland9c387612016-09-07 09:54:26 -0700595 status_t err = generateMethods(out,
596 "" /* class name */,
597 MethodLocation::STUB_HEADER,
598 true /* specify namespaces */);
599
600 if (err != OK) {
601 return err;
602 }
603
Andreas Huber881227d2016-08-02 14:20:21 -0700604 out.unindent();
605
606 out << "};\n\n";
607
608 enterLeaveNamespace(out, false /* enter */);
609
610 out << "\n#endif // " << guard << "\n";
611
612 return OK;
613}
614
Andreas Huberb82318c2016-08-02 14:45:54 -0700615status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700616 std::string ifaceName;
617 if (!AST::isInterface(&ifaceName)) {
618 // types.hal does not get a proxy header.
619 return OK;
620 }
621
Andreas Huber881227d2016-08-02 14:20:21 -0700622 // cut off the leading 'I'.
623 const std::string baseName = ifaceName.substr(1);
624
Andreas Huberb82318c2016-08-02 14:45:54 -0700625 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700626 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700627 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700628 path.append("Bp");
629 path.append(baseName);
630 path.append(".h");
631
Andreas Huberd2943e12016-08-05 11:59:31 -0700632 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700633 FILE *file = fopen(path.c_str(), "w");
634
635 if (file == NULL) {
636 return -errno;
637 }
638
639 Formatter out(file);
640
641 const std::string guard = makeHeaderGuard("Bp" + baseName);
642
643 out << "#ifndef " << guard << "\n";
644 out << "#define " << guard << "\n\n";
645
646 std::vector<std::string> packageComponents;
647 getPackageAndVersionComponents(
648 &packageComponents, false /* cpp_compatible */);
649
650 out << "#include <";
651 for (const auto &component : packageComponents) {
652 out << component << "/";
653 }
Steven Moreland40786312016-08-16 10:29:40 -0700654 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700655
656 enterLeaveNamespace(out, true /* enter */);
657 out << "\n";
658
659 out << "struct "
660 << "Bp"
661 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700662 << " : public ::android::hardware::BpInterface<IHw"
663 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700664 << "> {\n";
665
666 out.indent();
667
668 out << "explicit Bp"
669 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700670 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700671 << "\n\n";
672
Iliyan Malchev795dd432016-09-02 11:48:26 -0700673 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700674
Steven Moreland9c387612016-09-07 09:54:26 -0700675 status_t err = generateMethods(out,
676 "" /* class name */,
677 MethodLocation::PROXY_HEADER,
678 true /* generate specify namespaces */);
679
680 if (err != OK) {
681 return err;
682 }
Andreas Huber881227d2016-08-02 14:20:21 -0700683
684 out.unindent();
685
686 out << "};\n\n";
687
688 enterLeaveNamespace(out, false /* enter */);
689
690 out << "\n#endif // " << guard << "\n";
691
692 return OK;
693}
694
Andreas Huberb82318c2016-08-02 14:45:54 -0700695status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700696
Andreas Huberb82318c2016-08-02 14:45:54 -0700697 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700698 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700699 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700700
701 std::string ifaceName;
702 std::string baseName;
703
704 bool isInterface = true;
705 if (!AST::isInterface(&ifaceName)) {
706 baseName = "types";
707 isInterface = false;
708 } else {
709 baseName = ifaceName.substr(1); // cut off the leading 'I'.
710 }
711
712 path.append(baseName);
713
714 if (baseName != "types") {
715 path.append("All");
716 }
717
718 path.append(".cpp");
719
Andreas Huberd2943e12016-08-05 11:59:31 -0700720 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700721 FILE *file = fopen(path.c_str(), "w");
722
723 if (file == NULL) {
724 return -errno;
725 }
726
727 Formatter out(file);
728
729 std::vector<std::string> packageComponents;
730 getPackageAndVersionComponents(
731 &packageComponents, false /* cpp_compatible */);
732
733 std::string prefix;
734 for (const auto &component : packageComponents) {
735 prefix += component;
736 prefix += "/";
737 }
738
739 if (isInterface) {
740 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
741 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
742 } else {
743 out << "#include <" << prefix << "types.h>\n";
744 }
745
746 out << "\n";
747
748 enterLeaveNamespace(out, true /* enter */);
749 out << "\n";
750
751 status_t err = generateTypeSource(out, ifaceName);
752
753 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200754 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700755 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()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700768 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700769 << ")\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::"
Steven Morelandaf440142016-09-07 10:09:11 -0700893 << StringHelper::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::"
Steven Morelandaf440142016-09-07 10:09:11 -07001039 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001040 << ":\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