blob: 215d1eb02a5962e0a3cac398474648ad4b3d81ac [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
Steven Moreland69e7c702016-09-09 11:16:32 -070054 if (err == OK) {
55 generatePassthroughHeader(outputPath);
56 }
57
Andreas Huber881227d2016-08-02 14:20:21 -070058 return err;
59}
60
Andreas Huber737080b2016-08-02 15:38:04 -070061void AST::getPackageComponents(
62 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070063 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070064}
65
66void AST::getPackageAndVersionComponents(
67 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070068 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070069}
70
Andreas Huber881227d2016-08-02 14:20:21 -070071std::string AST::makeHeaderGuard(const std::string &baseName) const {
Steven Moreland9c387612016-09-07 09:54:26 -070072 std::string guard = "HIDL_GENERATED_";
73 guard += mPackage.tokenName();
Andreas Huber881227d2016-08-02 14:20:21 -070074
75 guard += "_";
76 guard += baseName;
77 guard += "_H_";
78
79 return guard;
80}
81
82void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
83 std::vector<std::string> packageComponents;
84 getPackageAndVersionComponents(
85 &packageComponents, true /* cpp_compatible */);
86
87 if (enter) {
88 for (const auto &component : packageComponents) {
89 out << "namespace " << component << " {\n";
90 }
Andreas Huber0e00de42016-08-03 09:56:02 -070091
Andreas Huber2831d512016-08-15 09:33:47 -070092 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -070093 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -070094 out.setNamespace(std::string());
95
Andreas Huber881227d2016-08-02 14:20:21 -070096 for (auto it = packageComponents.rbegin();
97 it != packageComponents.rend();
98 ++it) {
99 out << "} // namespace " << *it << "\n";
100 }
101 }
102}
103
Andreas Huberb82318c2016-08-02 14:45:54 -0700104status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700105
Andreas Huberb82318c2016-08-02 14:45:54 -0700106 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700107 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700108 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700109
110 std::string ifaceName;
111 bool isInterface = true;
112 if (!AST::isInterface(&ifaceName)) {
113 ifaceName = "types";
114 isInterface = false;
115 }
116 path.append(ifaceName);
117 path.append(".h");
118
Andreas Huberd2943e12016-08-05 11:59:31 -0700119 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700120 FILE *file = fopen(path.c_str(), "w");
121
122 if (file == NULL) {
123 return -errno;
124 }
125
126 Formatter out(file);
127
128 const std::string guard = makeHeaderGuard(ifaceName);
129
130 out << "#ifndef " << guard << "\n";
131 out << "#define " << guard << "\n\n";
132
Andreas Huber737080b2016-08-02 15:38:04 -0700133 for (const auto &item : mImportedNames) {
134 out << "#include <";
135
136 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700137 item.getPackageAndVersionComponents(
138 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700139
140 for (const auto &component : components) {
141 out << component << "/";
142 }
143
144 out << item.name()
145 << ".h>\n";
146 }
147
148 if (!mImportedNames.empty()) {
149 out << "\n";
150 }
151
Martijn Coenen7473fab2016-08-19 14:05:40 +0200152 out << "#include <hidl/HidlSupport.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700153 out << "#include <hidl/IServiceManager.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700154 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700155
156 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200157 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700158 }
159
160 out << "#include <utils/NativeHandle.h>\n\n";
161
162 enterLeaveNamespace(out, true /* enter */);
163 out << "\n";
164
Steven Moreland40786312016-08-16 10:29:40 -0700165 // cut off the leading 'I'.
166 const std::string baseName = ifaceName.substr(1);
167
Andreas Huber881227d2016-08-02 14:20:21 -0700168 if (isInterface) {
169 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700170 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700171
172 const Interface *iface = mRootScope->getInterface();
173 const Interface *superType = iface->superType();
174
Steven Moreland40786312016-08-16 10:29:40 -0700175 if (superType == NULL) {
176 out << " : virtual public RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700177 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700178 out << " : public "
179 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700180 }
181
182 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700183
184 out.indent();
185
Andreas Huber881227d2016-08-02 14:20:21 -0700186 }
187
188 status_t err = emitTypeDeclarations(out);
189
190 if (err != OK) {
191 return err;
192 }
193
194 if (isInterface) {
195 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700196 const Interface *superType = iface->superType();
Martijn Coenena21f1492016-09-08 15:55:14 +0200197 out << "constexpr static hidl_version version = {"
198 << mPackage.getPackageMajorVersion() << ","
199 << mPackage.getPackageMinorVersion() << "};\n";
200 out << "virtual const hidl_version& getInterfaceVersion() const {\n";
201 out.indent();
202 out << "return version;\n";
203 out.unindent();
204 out << "}\n\n";
Iliyan Malchev795dd432016-09-02 11:48:26 -0700205 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700206 bool haveCallbacks = false;
207 for (const auto &method : iface->methods()) {
208 const bool returnsValue = !method->results().empty();
209
210 if (!returnsValue) {
211 continue;
212 }
213
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700214 if (method->canElideCallback() != nullptr) {
215 continue;
216 }
217
Andreas Huber881227d2016-08-02 14:20:21 -0700218 haveCallbacks = true;
219
220 out << "using "
221 << method->name()
222 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700223 << Method::GetArgSignature(method->results(),
224 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700225 << ")>;\n";
226 }
227
228 if (haveCallbacks) {
229 out << "\n";
230 }
231
232 for (const auto &method : iface->methods()) {
233 const bool returnsValue = !method->results().empty();
234
Andreas Huber3599d922016-08-09 10:42:57 -0700235 method->dumpAnnotations(out);
236
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700237 const TypedVar *elidedReturn = method->canElideCallback();
238 if (elidedReturn) {
239 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700240 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700241 out << elidedReturn->type().getCppResultType(&extra) << "> ";
242 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700243 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700244 }
245
246 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700247 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700248 << Method::GetArgSignature(method->args(),
249 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700250
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700251 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700252 if (!method->args().empty()) {
253 out << ", ";
254 }
255
Iliyan Malchev549e2592016-08-10 08:59:12 -0700256 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700257 }
258
259 out << ") = 0;\n";
260 }
Steven Moreland40786312016-08-16 10:29:40 -0700261
262 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700263 }
264
265 if (isInterface) {
266 out.unindent();
267
268 out << "};\n";
269 }
270
271 out << "\n";
272 enterLeaveNamespace(out, false /* enter */);
273
274 out << "\n#endif // " << guard << "\n";
275
276 return OK;
277}
278
Steven Moreland40786312016-08-16 10:29:40 -0700279status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
280 std::string ifaceName;
281 if(!AST::isInterface(&ifaceName)) {
282 // types.hal does not get an HwBinder header.
283 return OK;
284 }
285
286 // cut off the leading 'I'.
287 const std::string baseName = ifaceName.substr(1);
288
289 const std::string klassName = "IHw" + baseName;
290
291 std::string path = outputPath;
292 path.append(mCoordinator->convertPackageRootToPath(mPackage));
293 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
294 path.append(klassName + ".h");
295
296 FILE* file = fopen(path.c_str(), "w");
297
298 if (file == NULL) {
299 return -errno;
300 }
301
302 Formatter out(file);
303
304 const std::string guard = makeHeaderGuard(klassName);
305
306 out << "#ifndef " << guard << "\n";
307 out << "#define " << guard << "\n\n";
308
309 std::vector<std::string> packageComponents;
310 getPackageAndVersionComponents(
311 &packageComponents, false /* cpp_compatible */);
312
313 out << "#include <";
314 for (const auto &component : packageComponents) {
315 out << component << "/";
316 }
317 out << ifaceName << ".h>\n\n";
318
319 for (const auto &item : mImportedNames) {
320 if (item.name() == "types") {
321 continue;
322 }
323
324 out << "#include <";
325
326 std::vector<std::string> components;
327 item.getPackageAndVersionComponents(
328 &components, false /* cpp_compatible */);
329
330 for (const auto &component : components) {
331 out << component << "/";
332 }
333
334 // cut off the leading I
335 const std::string itemBaseName = item.name().substr(1);
336
337 out << "Bn"
338 << itemBaseName
339 << ".h>\n";
340 }
341
342 out << "\n";
343
344 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200345 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700346 out << "#include <hwbinder/IBinder.h>\n";
347 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700348
349 out << "\n";
350
351 enterLeaveNamespace(out, true /* enter */);
352 out << "\n";
353
354 out << "struct "
355 << klassName
356 << " : public "
357 << ifaceName;
358
359 const Interface *iface = mRootScope->getInterface();
360 const Interface *superType = iface->superType();
361
362 out << ", public ::android::hardware::IInterface";
363
364 out << " {\n";
365
366 out.indent();
367
368 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
369
370 out << "enum Call {\n";
371 out.indent();
372
373 bool first = true;
374 for (const auto &method : iface->methods()) {
Steven Morelandaf440142016-09-07 10:09:11 -0700375 out << StringHelper::Upcase(method->name());
Steven Moreland40786312016-08-16 10:29:40 -0700376
377 if (first) {
378 out << " = ";
379 if (superType != NULL) {
380 out << superType->fqName().cppNamespace()
381 << "::IHw"
382 << superType->getBaseName()
383 << "::Call::CallCount";
384 } else {
385 out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
386 }
387
388 first = false;
389 }
390
391 out << ",\n";
392 }
393
394 out << "CallCount\n";
395
396 out.unindent();
397 out << "};\n\n";
398
399 out.unindent();
400
401 out << "};\n\n";
402
403 enterLeaveNamespace(out, false /* enter */);
404
405 out << "\n#endif // " << guard << "\n";
406
407 return OK;
408}
409
Andreas Huber881227d2016-08-02 14:20:21 -0700410status_t AST::emitTypeDeclarations(Formatter &out) const {
411 return mRootScope->emitTypeDeclarations(out);
412}
413
Steven Morelanda7a421a2016-09-07 08:35:18 -0700414status_t AST::generateStubMethod(Formatter &out,
415 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700416 const Method *method,
417 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700418 out << "inline ";
419
Steven Moreland979e0992016-09-07 09:18:08 -0700420 method->generateCppSignature(out,
421 className,
422 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700423
424 const bool returnsValue = !method->results().empty();
425 const TypedVar *elidedReturn = method->canElideCallback();
426 out << " {\n";
427 out.indent();
428 out << "return mImpl->"
429 << method->name()
430 << "(";
431 bool first = true;
432 for (const auto &arg : method->args()) {
433 if (!first) {
434 out << ", ";
435 }
436 first = false;
437 out << arg->name();
438 }
439 if (returnsValue && elidedReturn == nullptr) {
440 if (!method->args().empty()) {
441 out << ", ";
442 }
443
444 out << "_hidl_cb";
445 }
446 out << ");\n";
447 out.unindent();
448 out << "}";
449
450 out << ";\n";
451
452 return OK;
453}
454
Steven Moreland9c387612016-09-07 09:54:26 -0700455status_t AST::generateProxyDeclaration(Formatter &out,
456 const std::string &className,
457 const Method *method,
458 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700459
Steven Moreland979e0992016-09-07 09:18:08 -0700460 method->generateCppSignature(out,
461 className,
462 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700463 out << " override;\n";
464
465 return OK;
466}
467
Steven Moreland69e7c702016-09-09 11:16:32 -0700468
469status_t AST::generatePassthroughMethod(Formatter &out,
470 const std::string &className,
471 const Method *method,
472 bool specifyNamespaces) const {
473 method->generateCppSignature(out, className, specifyNamespaces);
474
475 out << " {\n";
476 out.indent();
477
478 const bool returnsValue = !method->results().empty();
479 const TypedVar *elidedReturn = method->canElideCallback();
480
481 out << "return ";
482
483 if (method->isOneway()) {
484 out << "addOnewayTask([this";
485 for (const auto &arg : method->args()) {
486 out << ", " << arg->name();
487 }
488 out << "] {this->";
489 }
490
491 out << "mImpl->"
492 << method->name()
493 << "(";
494
495 bool first = true;
496 for (const auto &arg : method->args()) {
497 if (!first) {
498 out << ", ";
499 }
500 first = false;
501 out << arg->name();
502 }
503 if (returnsValue && elidedReturn == nullptr) {
504 if (!method->args().empty()) {
505 out << ", ";
506 }
507
508 out << "_hidl_cb";
509 }
510 out << ")";
511
512 if (method->isOneway()) {
513 out << ";})";
514 }
515 out << ";\n";
516
517 out.unindent();
518 out << "}\n";
519
520 return OK;
521}
522
Steven Morelanda7a421a2016-09-07 08:35:18 -0700523status_t AST::generateMethods(
524 Formatter &out,
525 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700526 MethodLocation type,
527 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700528
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700529 const Interface *iface = mRootScope->getInterface();
530
531 std::vector<const Interface *> chain;
532 while (iface != NULL) {
533 chain.push_back(iface);
534 iface = iface->superType();
535 }
536
537 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
538 const Interface *superInterface = *it;
539
540 out << "// Methods from "
541 << superInterface->fullName()
542 << " follow.\n";
543
544 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700545 status_t err;
546 switch(type) {
547 case STUB_HEADER:
548 err = generateStubMethod(out,
549 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700550 method,
551 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700552 break;
553 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700554 err = generateProxyDeclaration(out,
555 className,
556 method,
557 specifyNamespaces);
558 break;
559 case IMPL_HEADER:
560 err = generateStubImplDeclaration(out,
561 className,
562 method,
563 specifyNamespaces);
564 break;
565 case IMPL_SOURCE:
566 err = generateStubImplMethod(out,
567 className,
568 method,
569 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700570 break;
Steven Moreland69e7c702016-09-09 11:16:32 -0700571 case PASSTHROUGH_HEADER:
572 err = generatePassthroughMethod(out,
573 className,
574 method,
575 specifyNamespaces);
576 break;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700577 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700578 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700579 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700580 }
581
Steven Morelanda7a421a2016-09-07 08:35:18 -0700582 if (err != OK) {
583 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700584 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700585 }
586
587 out << "\n";
588 }
589
590 return OK;
591}
592
Andreas Huberb82318c2016-08-02 14:45:54 -0700593status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700594 std::string ifaceName;
595 if (!AST::isInterface(&ifaceName)) {
596 // types.hal does not get a stub header.
597 return OK;
598 }
599
Andreas Huber881227d2016-08-02 14:20:21 -0700600 // cut off the leading 'I'.
601 const std::string baseName = ifaceName.substr(1);
Steven Moreland40786312016-08-16 10:29:40 -0700602 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700603
Andreas Huberb82318c2016-08-02 14:45:54 -0700604 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700605 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700606 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700607 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700608 path.append(".h");
609
Andreas Huberd2943e12016-08-05 11:59:31 -0700610 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700611 FILE *file = fopen(path.c_str(), "w");
612
613 if (file == NULL) {
614 return -errno;
615 }
616
617 Formatter out(file);
618
Steven Moreland40786312016-08-16 10:29:40 -0700619 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700620
621 out << "#ifndef " << guard << "\n";
622 out << "#define " << guard << "\n\n";
623
624 std::vector<std::string> packageComponents;
625 getPackageAndVersionComponents(
626 &packageComponents, false /* cpp_compatible */);
627
628 out << "#include <";
629 for (const auto &component : packageComponents) {
630 out << component << "/";
631 }
Steven Moreland40786312016-08-16 10:29:40 -0700632 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700633
634 enterLeaveNamespace(out, true /* enter */);
635 out << "\n";
636
637 out << "struct "
638 << "Bn"
639 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700640 << " : public ::android::hardware::BnInterface<I"
641 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700642 << "> {\n";
643
644 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700645 out << "explicit Bn"
646 << baseName
647 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
648 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700649 out << "::android::status_t onTransact(\n";
650 out.indent();
651 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700652 out << "uint32_t _hidl_code,\n";
653 out << "const ::android::hardware::Parcel &_hidl_data,\n";
654 out << "::android::hardware::Parcel *_hidl_reply,\n";
655 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700656 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700657 out.unindent();
658 out.unindent();
659
Steven Moreland9c387612016-09-07 09:54:26 -0700660 status_t err = generateMethods(out,
661 "" /* class name */,
662 MethodLocation::STUB_HEADER,
663 true /* specify namespaces */);
664
665 if (err != OK) {
666 return err;
667 }
668
Andreas Huber881227d2016-08-02 14:20:21 -0700669 out.unindent();
670
671 out << "};\n\n";
672
673 enterLeaveNamespace(out, false /* enter */);
674
675 out << "\n#endif // " << guard << "\n";
676
677 return OK;
678}
679
Andreas Huberb82318c2016-08-02 14:45:54 -0700680status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700681 std::string ifaceName;
682 if (!AST::isInterface(&ifaceName)) {
683 // types.hal does not get a proxy header.
684 return OK;
685 }
686
Andreas Huber881227d2016-08-02 14:20:21 -0700687 // cut off the leading 'I'.
688 const std::string baseName = ifaceName.substr(1);
689
Andreas Huberb82318c2016-08-02 14:45:54 -0700690 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700691 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700692 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700693 path.append("Bp");
694 path.append(baseName);
695 path.append(".h");
696
Andreas Huberd2943e12016-08-05 11:59:31 -0700697 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700698 FILE *file = fopen(path.c_str(), "w");
699
700 if (file == NULL) {
701 return -errno;
702 }
703
704 Formatter out(file);
705
706 const std::string guard = makeHeaderGuard("Bp" + baseName);
707
708 out << "#ifndef " << guard << "\n";
709 out << "#define " << guard << "\n\n";
710
711 std::vector<std::string> packageComponents;
712 getPackageAndVersionComponents(
713 &packageComponents, false /* cpp_compatible */);
714
715 out << "#include <";
716 for (const auto &component : packageComponents) {
717 out << component << "/";
718 }
Steven Moreland40786312016-08-16 10:29:40 -0700719 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700720
721 enterLeaveNamespace(out, true /* enter */);
722 out << "\n";
723
724 out << "struct "
725 << "Bp"
726 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700727 << " : public ::android::hardware::BpInterface<IHw"
728 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700729 << "> {\n";
730
731 out.indent();
732
733 out << "explicit Bp"
734 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700735 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700736 << "\n\n";
737
Iliyan Malchev795dd432016-09-02 11:48:26 -0700738 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700739
Steven Moreland9c387612016-09-07 09:54:26 -0700740 status_t err = generateMethods(out,
741 "" /* class name */,
742 MethodLocation::PROXY_HEADER,
743 true /* generate specify namespaces */);
744
745 if (err != OK) {
746 return err;
747 }
Andreas Huber881227d2016-08-02 14:20:21 -0700748
749 out.unindent();
750
751 out << "};\n\n";
752
753 enterLeaveNamespace(out, false /* enter */);
754
755 out << "\n#endif // " << guard << "\n";
756
757 return OK;
758}
759
Andreas Huberb82318c2016-08-02 14:45:54 -0700760status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700761
Andreas Huberb82318c2016-08-02 14:45:54 -0700762 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700763 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700764 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700765
766 std::string ifaceName;
767 std::string baseName;
768
769 bool isInterface = true;
770 if (!AST::isInterface(&ifaceName)) {
771 baseName = "types";
772 isInterface = false;
773 } else {
774 baseName = ifaceName.substr(1); // cut off the leading 'I'.
775 }
776
777 path.append(baseName);
778
779 if (baseName != "types") {
780 path.append("All");
781 }
782
783 path.append(".cpp");
784
Andreas Huberd2943e12016-08-05 11:59:31 -0700785 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700786 FILE *file = fopen(path.c_str(), "w");
787
788 if (file == NULL) {
789 return -errno;
790 }
791
792 Formatter out(file);
793
794 std::vector<std::string> packageComponents;
795 getPackageAndVersionComponents(
796 &packageComponents, false /* cpp_compatible */);
797
798 std::string prefix;
799 for (const auto &component : packageComponents) {
800 prefix += component;
801 prefix += "/";
802 }
803
804 if (isInterface) {
805 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
806 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700807 out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700808 } else {
809 out << "#include <" << prefix << "types.h>\n";
810 }
811
812 out << "\n";
813
814 enterLeaveNamespace(out, true /* enter */);
815 out << "\n";
816
817 status_t err = generateTypeSource(out, ifaceName);
818
819 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200820 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700821 err = generateProxySource(out, baseName);
822 }
823
824 if (err == OK && isInterface) {
825 err = generateStubSource(out, baseName);
826 }
827
Steven Moreland40786312016-08-16 10:29:40 -0700828 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700829 err = generatePassthroughSource(out);
830 }
831
832 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700833 const Interface *iface = mRootScope->getInterface();
834
835 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
836 << baseName << ", "
837 << "\"" << iface->fqName().package()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700838 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700839 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700840 }
841
Andreas Huber881227d2016-08-02 14:20:21 -0700842 enterLeaveNamespace(out, false /* enter */);
843
844 return err;
845}
846
847status_t AST::generateTypeSource(
848 Formatter &out, const std::string &ifaceName) const {
849 return mRootScope->emitTypeDefinitions(out, ifaceName);
850}
851
Andreas Hubere7ff2282016-08-16 13:50:03 -0700852void AST::declareCppReaderLocals(
853 Formatter &out, const std::vector<TypedVar *> &args) const {
854 if (args.empty()) {
855 return;
856 }
857
858 for (const auto &arg : args) {
859 const Type &type = arg->type();
860
861 std::string extra;
862 out << type.getCppResultType(&extra)
863 << " "
864 << arg->name()
865 << extra
866 << ";\n";
867 }
868
869 out << "\n";
870}
871
Andreas Huber881227d2016-08-02 14:20:21 -0700872void AST::emitCppReaderWriter(
873 Formatter &out,
874 const std::string &parcelObj,
875 bool parcelObjIsPointer,
876 const TypedVar *arg,
877 bool isReader,
878 Type::ErrorMode mode) const {
879 const Type &type = arg->type();
880
Andreas Huber881227d2016-08-02 14:20:21 -0700881 type.emitReaderWriter(
882 out,
883 arg->name(),
884 parcelObj,
885 parcelObjIsPointer,
886 isReader,
887 mode);
888}
889
890status_t AST::generateProxySource(
891 Formatter &out, const std::string &baseName) const {
892 const std::string klassName = "Bp" + baseName;
893
894 out << klassName
895 << "::"
896 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700897 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700898
899 out.indent();
900 out.indent();
901
902 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700903 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700904 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700905 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700906
907 out.unindent();
908 out.unindent();
909 out << "}\n\n";
910
911 const Interface *iface = mRootScope->getInterface();
912
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700913 std::vector<const Interface *> chain;
914 while (iface != NULL) {
915 chain.push_back(iface);
916 iface = iface->superType();
917 }
Andreas Huber881227d2016-08-02 14:20:21 -0700918
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700919 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
920 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700921
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700922 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700923 method->generateCppSignature(out,
924 klassName,
925 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700926
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700927 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700928 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700929
Steven Morelanda7a421a2016-09-07 08:35:18 -0700930 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700931
932 out.indent();
933
Iliyan Malchev549e2592016-08-10 08:59:12 -0700934 out << "::android::hardware::Parcel _hidl_data;\n";
935 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700936 out << "::android::status_t _hidl_err;\n";
937 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700938 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700939
Iliyan Malchev549e2592016-08-10 08:59:12 -0700940 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700941 << superInterface->fqName().cppNamespace()
942 << "::IHw"
943 << superInterface->getBaseName()
944 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700945
Iliyan Malchev549e2592016-08-10 08:59:12 -0700946 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700947
948 for (const auto &arg : method->args()) {
949 emitCppReaderWriter(
950 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700951 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700952 false /* parcelObjIsPointer */,
953 arg,
954 false /* reader */,
955 Type::ErrorMode_Goto);
956 }
957
Steven Moreland40786312016-08-16 10:29:40 -0700958 out << "_hidl_err = remote()->transact("
959 << superInterface->fqName().cppNamespace()
960 << "::IHw"
961 << superInterface->getBaseName()
962 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -0700963 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700964 << ", _hidl_data, &_hidl_reply";
965 if (method->isOneway()) {
966 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700967 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700968 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700969
Iliyan Malchev639bff82016-08-13 14:24:11 -0700970 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700971
Iliyan Malchev639bff82016-08-13 14:24:11 -0700972 if (!method->isOneway()) {
973 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
974 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700975 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
976
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700977 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700978 emitCppReaderWriter(
979 out,
980 "_hidl_reply",
981 false /* parcelObjIsPointer */,
982 arg,
983 true /* reader */,
984 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700985 }
986
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700987 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700988 out << "if (_hidl_cb != nullptr) {\n";
989 out.indent();
990 out << "_hidl_cb(";
991
992 bool first = true;
993 for (const auto &arg : method->results()) {
994 if (!first) {
995 out << ", ";
996 }
997
998 if (arg->type().resultNeedsDeref()) {
999 out << "*";
1000 }
1001 out << arg->name();
1002
1003 first = false;
1004 }
1005
1006 out << ");\n";
1007 out.unindent();
1008 out << "}\n\n";
1009 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001010 }
1011
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001012 if (elidedReturn != nullptr) {
1013 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001014 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001015 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001016 out << elidedReturn->type().getCppResultType(&extra)
1017 << ">(" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001018 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001019 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001020 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001021 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001022
Andreas Huber881227d2016-08-02 14:20:21 -07001023 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001024 out << "_hidl_error:\n";
1025 out.indent();
1026 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1027 out << "return ::android::hardware::Return<";
1028 if (elidedReturn != nullptr) {
1029 std::string extra;
1030 out << method->results().at(0)->type().getCppResultType(&extra);
1031 } else {
1032 out << "void";
1033 }
1034 out << ">(_hidl_status);\n";
1035
1036 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001037 out << "}\n\n";
1038 }
Andreas Huber881227d2016-08-02 14:20:21 -07001039 }
1040
1041 return OK;
1042}
1043
1044status_t AST::generateStubSource(
1045 Formatter &out, const std::string &baseName) const {
1046 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1047 << baseName
1048 << ", \""
1049 << mPackage.string()
1050 << "::I"
1051 << baseName
1052 << "\");\n\n";
1053
1054 const std::string klassName = "Bn" + baseName;
1055
Steven Moreland40786312016-08-16 10:29:40 -07001056 out << klassName
1057 << "::"
1058 << klassName
1059 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1060
1061 out.indent();
1062 out.indent();
1063
1064 out << ": BnInterface"
1065 << "<I"
1066 << baseName
1067 << ", IHw"
1068 << baseName
1069 << ">(_hidl_impl) {\n";
1070
1071 out.unindent();
1072 out.unindent();
1073 out << "}\n\n";
1074
Andreas Huber881227d2016-08-02 14:20:21 -07001075 out << "::android::status_t " << klassName << "::onTransact(\n";
1076
1077 out.indent();
1078 out.indent();
1079
Iliyan Malchev549e2592016-08-10 08:59:12 -07001080 out << "uint32_t _hidl_code,\n"
1081 << "const ::android::hardware::Parcel &_hidl_data,\n"
1082 << "::android::hardware::Parcel *_hidl_reply,\n"
1083 << "uint32_t _hidl_flags,\n"
1084 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001085
1086 out.unindent();
1087
Iliyan Malchev549e2592016-08-10 08:59:12 -07001088 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001089 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001090 out.indent();
1091
1092 const Interface *iface = mRootScope->getInterface();
1093
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001094 std::vector<const Interface *> chain;
1095 while (iface != NULL) {
1096 chain.push_back(iface);
1097 iface = iface->superType();
1098 }
Andreas Huber881227d2016-08-02 14:20:21 -07001099
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001100 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1101 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001102
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001103 for (const auto &method : superInterface->methods()) {
1104 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001105 << superInterface->fqName().cppNamespace()
1106 << "::IHw"
1107 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001108 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001109 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001110 << ":\n{\n";
1111
1112 out.indent();
1113
1114 status_t err =
1115 generateStubSourceForMethod(out, superInterface, method);
1116
1117 if (err != OK) {
1118 return err;
1119 }
1120
1121 out.unindent();
1122 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001123 }
Andreas Huber881227d2016-08-02 14:20:21 -07001124 }
1125
1126 out << "default:\n{\n";
1127 out.indent();
1128
Andreas Huber8a82ff72016-08-04 10:29:39 -07001129 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001130 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001131 << ">::onTransact(\n";
1132
1133 out.indent();
1134 out.indent();
1135
Iliyan Malchev549e2592016-08-10 08:59:12 -07001136 out << "_hidl_code, _hidl_data, _hidl_reply, "
1137 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001138
1139 out.unindent();
1140 out.unindent();
1141
1142 out.unindent();
1143 out << "}\n";
1144
1145 out.unindent();
1146 out << "}\n\n";
1147
Iliyan Malchev549e2592016-08-10 08:59:12 -07001148 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001149 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001150 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001151 out.indent();
1152 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001153 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001154 out.indent();
1155 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001156 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001157 out.unindent();
1158 out.unindent();
1159 out.unindent();
1160 out.unindent();
1161
1162 out.unindent();
1163 out << "}\n\n";
1164
Iliyan Malchev549e2592016-08-10 08:59:12 -07001165 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001166
1167 out.unindent();
1168 out << "}\n\n";
1169
1170 return OK;
1171}
1172
1173status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001174 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001175 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001176 << iface->fqName().cppNamespace()
1177 << "::IHw"
1178 << iface->getBaseName()
1179 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001180
Andreas Huber881227d2016-08-02 14:20:21 -07001181 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001182 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001183 out << "break;\n";
1184 out.unindent();
1185 out << "}\n\n";
1186
Andreas Hubere7ff2282016-08-16 13:50:03 -07001187 declareCppReaderLocals(out, method->args());
1188
Andreas Huber881227d2016-08-02 14:20:21 -07001189 for (const auto &arg : method->args()) {
1190 emitCppReaderWriter(
1191 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001192 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001193 false /* parcelObjIsPointer */,
1194 arg,
1195 true /* reader */,
1196 Type::ErrorMode_Break);
1197 }
1198
1199 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001200 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001201
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001202 if (elidedReturn != nullptr) {
1203 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001204
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001205 out << elidedReturn->type().getCppResultType(&extra) << " ";
1206 out << elidedReturn->name() << " = ";
1207 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001208
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001209 bool first = true;
1210 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001211 if (!first) {
1212 out << ", ";
1213 }
1214
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001215 if (arg->type().resultNeedsDeref()) {
1216 out << "*";
1217 }
1218
1219 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001220
1221 first = false;
1222 }
1223
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001224 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001225 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001226 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001227
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001228 elidedReturn->type().emitReaderWriter(
1229 out,
1230 elidedReturn->name(),
1231 "_hidl_reply",
1232 true, /* parcelObjIsPointer */
1233 false, /* isReader */
1234 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001235
Iliyan Malchev549e2592016-08-10 08:59:12 -07001236 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001237 } else {
1238 if (returnsValue) {
1239 out << "bool _hidl_callbackCalled = false;\n\n";
1240 }
Andreas Huber881227d2016-08-02 14:20:21 -07001241
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001242 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001243
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001244 bool first = true;
1245 for (const auto &arg : method->args()) {
1246 if (!first) {
1247 out << ", ";
1248 }
Andreas Huber881227d2016-08-02 14:20:21 -07001249
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001250 if (arg->type().resultNeedsDeref()) {
1251 out << "*";
1252 }
1253
1254 out << arg->name();
1255
1256 first = false;
1257 }
1258
1259 if (returnsValue) {
1260 if (!first) {
1261 out << ", ";
1262 }
1263
1264 out << "[&](";
1265
1266 first = true;
1267 for (const auto &arg : method->results()) {
1268 if (!first) {
1269 out << ", ";
1270 }
1271
1272 out << "const auto &" << arg->name();
1273
1274 first = false;
1275 }
1276
1277 out << ") {\n";
1278 out.indent();
1279 out << "_hidl_callbackCalled = true;\n\n";
1280
1281 out << "::android::hardware::Status::ok()"
1282 << ".writeToParcel(_hidl_reply);\n\n";
1283
1284 for (const auto &arg : method->results()) {
1285 emitCppReaderWriter(
1286 out,
1287 "_hidl_reply",
1288 true /* parcelObjIsPointer */,
1289 arg,
1290 false /* reader */,
1291 Type::ErrorMode_Ignore);
1292 }
1293
1294 out << "_hidl_cb(*_hidl_reply);\n";
1295
1296 out.unindent();
1297 out << "}\n";
1298 }
1299
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001300 out << ");\n\n";
1301
1302 // What to do if the stub implementation has a synchronous callback
1303 // which does not get invoked? This is not a transport error but a
1304 // service error of sorts. For now, return OK to the caller, as this is
1305 // not a transport error.
1306 //
1307 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001308
1309 if (returnsValue) {
1310 out << "if (!_hidl_callbackCalled) {\n";
1311 out.indent();
1312 }
1313
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001314 out << "::android::hardware::Status::ok()"
1315 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001316
1317 if (returnsValue) {
1318 out.unindent();
1319 out << "}\n\n";
1320 }
Andreas Huber881227d2016-08-02 14:20:21 -07001321 }
1322
1323 out << "break;\n";
1324
1325 return OK;
1326}
1327
Steven Moreland69e7c702016-09-09 11:16:32 -07001328status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1329 std::string ifaceName;
1330 if (!AST::isInterface(&ifaceName)) {
1331 // types.hal does not get a stub header.
1332 return OK;
1333 }
1334
1335 const Interface *iface = mRootScope->getInterface();
1336
1337 const std::string baseName = iface->getBaseName();
1338 const std::string klassName = "Bs" + baseName;
1339
1340 bool supportOneway = iface->hasOnewayMethods();
1341
1342 std::string path = outputPath;
1343 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1344 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1345 path.append(klassName);
1346 path.append(".h");
1347
1348 CHECK(Coordinator::MakeParentHierarchy(path));
1349 FILE *file = fopen(path.c_str(), "w");
1350
1351 if (file == NULL) {
1352 return -errno;
1353 }
1354
1355 Formatter out(file);
1356
1357 const std::string guard = makeHeaderGuard(klassName);
1358
1359 out << "#ifndef " << guard << "\n";
1360 out << "#define " << guard << "\n\n";
1361
1362 std::vector<std::string> packageComponents;
1363 getPackageAndVersionComponents(
1364 &packageComponents, false /* cpp_compatible */);
1365
1366 out << "#include <future>\n";
1367 out << "#include <";
1368 for (const auto &component : packageComponents) {
1369 out << component << "/";
1370 }
1371 out << ifaceName << ".h>\n\n";
1372
1373 if (supportOneway) {
1374 out << "#include <hidl/SynchronizedQueue.h>\n";
1375 }
1376
1377 enterLeaveNamespace(out, true /* enter */);
1378 out << "\n";
1379
1380 out << "struct "
1381 << klassName
1382 << " : " << ifaceName
1383 << " {\n";
1384
1385 out.indent();
1386 out << "explicit "
1387 << klassName
1388 << "(const sp<"
1389 << ifaceName
1390 << "> impl);\n";
1391
1392 status_t err = generateMethods(out,
1393 "" /* class name */,
1394 MethodLocation::PASSTHROUGH_HEADER,
1395 true /* specify namespaces */);
1396
1397 if (err != OK) {
1398 return err;
1399 }
1400
1401 out.unindent();
1402 out << "private:\n";
1403 out.indent();
1404 out << "const sp<" << ifaceName << "> mImpl;\n";
1405
1406 if (supportOneway) {
1407 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1408 out << "std::thread *mOnewayThread = nullptr;\n";
1409
1410 out << "\n";
1411
1412 out << "::android::hardware::Return<void> addOnewayTask("
1413 "std::function<void(void)>);\n\n";
1414
1415 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1416 }
1417
1418 out.unindent();
1419
1420 out << "};\n\n";
1421
1422 enterLeaveNamespace(out, false /* enter */);
1423
1424 out << "\n#endif // " << guard << "\n";
1425
1426 return OK;
1427}
1428
1429
1430status_t AST::generatePassthroughSource(Formatter &out) const {
1431 const Interface *iface = mRootScope->getInterface();
1432
1433 const std::string baseName = iface->getBaseName();
1434 const std::string klassName = "Bs" + baseName;
1435
1436 out << klassName
1437 << "::"
1438 << klassName
1439 << "(const sp<"
1440 << iface->fullName()
1441 << "> impl) : mImpl(impl) {}\n\n";
1442
1443 if (iface->hasOnewayMethods()) {
1444 out << "::android::hardware::Return<void> "
1445 << klassName
1446 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1447 out.indent();
1448 out << "if (mOnewayThread == nullptr) {\n";
1449 out.indent();
1450 out << "mOnewayThread = new std::thread([this]() {\n";
1451 out.indent();
1452 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1453 out.unindent();
1454 out << "});\n";
1455 out.unindent();
1456 out << "}\n\n";
1457
1458 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1459 out.indent();
1460 out << "return Status::fromExceptionCode(Status::EX_TRANSACTION_FAILED);\n";
1461 out.unindent();
1462 out << "} else {\n";
1463 out.indent();
1464 out << "mOnewayQueue.push(fun);\n";
1465 out.unindent();
1466 out << "}\n";
1467
1468 out << "return Status();\n";
1469
1470 out.unindent();
1471 out << "}\n\n";
1472
1473
1474 }
1475
1476 return OK;
1477}
1478
Andreas Huber881227d2016-08-02 14:20:21 -07001479} // namespace android
1480