blob: 4987cc1fb58e2d1c716502f98984d0c1087de8c1 [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
165 if (isInterface) {
166 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700167 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700168
169 const Interface *iface = mRootScope->getInterface();
170 const Interface *superType = iface->superType();
171
Steven Moreland40786312016-08-16 10:29:40 -0700172 if (superType == NULL) {
173 out << " : virtual public RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700174 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700175 out << " : public "
176 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700177 }
178
179 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700180
181 out.indent();
182
Andreas Huber881227d2016-08-02 14:20:21 -0700183 }
184
185 status_t err = emitTypeDeclarations(out);
186
187 if (err != OK) {
188 return err;
189 }
190
191 if (isInterface) {
192 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700193 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700194 const std::string baseName = iface->getBaseName();
Martijn Coenena21f1492016-09-08 15:55:14 +0200195 out << "constexpr static hidl_version version = {"
196 << mPackage.getPackageMajorVersion() << ","
197 << mPackage.getPackageMinorVersion() << "};\n";
198 out << "virtual const hidl_version& getInterfaceVersion() const {\n";
199 out.indent();
200 out << "return version;\n";
201 out.unindent();
202 out << "}\n\n";
Iliyan Malchev795dd432016-09-02 11:48:26 -0700203 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700204 bool haveCallbacks = false;
205 for (const auto &method : iface->methods()) {
206 const bool returnsValue = !method->results().empty();
207
208 if (!returnsValue) {
209 continue;
210 }
211
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700212 if (method->canElideCallback() != nullptr) {
213 continue;
214 }
215
Andreas Huber881227d2016-08-02 14:20:21 -0700216 haveCallbacks = true;
217
218 out << "using "
219 << method->name()
220 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700221 << Method::GetArgSignature(method->results(),
222 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700223 << ")>;\n";
224 }
225
226 if (haveCallbacks) {
227 out << "\n";
228 }
229
230 for (const auto &method : iface->methods()) {
231 const bool returnsValue = !method->results().empty();
232
Andreas Huber3599d922016-08-09 10:42:57 -0700233 method->dumpAnnotations(out);
234
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700235 const TypedVar *elidedReturn = method->canElideCallback();
236 if (elidedReturn) {
237 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700238 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700239 out << elidedReturn->type().getCppResultType(&extra) << "> ";
240 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700241 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700242 }
243
244 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700245 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700246 << Method::GetArgSignature(method->args(),
247 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700248
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700249 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700250 if (!method->args().empty()) {
251 out << ", ";
252 }
253
Iliyan Malchev549e2592016-08-10 08:59:12 -0700254 out << method->name() << "_cb _hidl_cb = nullptr";
Andreas Huber881227d2016-08-02 14:20:21 -0700255 }
256
257 out << ") = 0;\n";
258 }
Steven Moreland40786312016-08-16 10:29:40 -0700259
260 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700261 }
262
263 if (isInterface) {
264 out.unindent();
265
266 out << "};\n";
267 }
268
269 out << "\n";
270 enterLeaveNamespace(out, false /* enter */);
271
272 out << "\n#endif // " << guard << "\n";
273
274 return OK;
275}
276
Steven Moreland40786312016-08-16 10:29:40 -0700277status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
278 std::string ifaceName;
279 if(!AST::isInterface(&ifaceName)) {
280 // types.hal does not get an HwBinder header.
281 return OK;
282 }
283
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700284 const Interface *iface = mRootScope->getInterface();
285 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700286
287 const std::string klassName = "IHw" + baseName;
288
289 std::string path = outputPath;
290 path.append(mCoordinator->convertPackageRootToPath(mPackage));
291 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
292 path.append(klassName + ".h");
293
294 FILE* file = fopen(path.c_str(), "w");
295
296 if (file == NULL) {
297 return -errno;
298 }
299
300 Formatter out(file);
301
302 const std::string guard = makeHeaderGuard(klassName);
303
304 out << "#ifndef " << guard << "\n";
305 out << "#define " << guard << "\n\n";
306
307 std::vector<std::string> packageComponents;
308 getPackageAndVersionComponents(
309 &packageComponents, false /* cpp_compatible */);
310
311 out << "#include <";
312 for (const auto &component : packageComponents) {
313 out << component << "/";
314 }
315 out << ifaceName << ".h>\n\n";
316
317 for (const auto &item : mImportedNames) {
318 if (item.name() == "types") {
319 continue;
320 }
321
322 out << "#include <";
323
324 std::vector<std::string> components;
325 item.getPackageAndVersionComponents(
326 &components, false /* cpp_compatible */);
327
328 for (const auto &component : components) {
329 out << component << "/";
330 }
331
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700332 const std::string itemBaseName = item.getInterfaceBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700333
334 out << "Bn"
335 << itemBaseName
336 << ".h>\n";
337 }
338
339 out << "\n";
340
341 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200342 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700343 out << "#include <hwbinder/IBinder.h>\n";
344 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700345
346 out << "\n";
347
348 enterLeaveNamespace(out, true /* enter */);
349 out << "\n";
350
351 out << "struct "
352 << klassName
353 << " : public "
354 << ifaceName;
355
Steven Moreland40786312016-08-16 10:29:40 -0700356 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
Steven Moreland69e7c702016-09-09 11:16:32 -0700464
465status_t AST::generatePassthroughMethod(Formatter &out,
466 const std::string &className,
467 const Method *method,
468 bool specifyNamespaces) const {
469 method->generateCppSignature(out, className, specifyNamespaces);
470
471 out << " {\n";
472 out.indent();
473
474 const bool returnsValue = !method->results().empty();
475 const TypedVar *elidedReturn = method->canElideCallback();
476
477 out << "return ";
478
479 if (method->isOneway()) {
480 out << "addOnewayTask([this";
481 for (const auto &arg : method->args()) {
482 out << ", " << arg->name();
483 }
484 out << "] {this->";
485 }
486
487 out << "mImpl->"
488 << method->name()
489 << "(";
490
491 bool first = true;
492 for (const auto &arg : method->args()) {
493 if (!first) {
494 out << ", ";
495 }
496 first = false;
497 out << arg->name();
498 }
499 if (returnsValue && elidedReturn == nullptr) {
500 if (!method->args().empty()) {
501 out << ", ";
502 }
503
504 out << "_hidl_cb";
505 }
506 out << ")";
507
508 if (method->isOneway()) {
509 out << ";})";
510 }
511 out << ";\n";
512
513 out.unindent();
514 out << "}\n";
515
516 return OK;
517}
518
Steven Morelanda7a421a2016-09-07 08:35:18 -0700519status_t AST::generateMethods(
520 Formatter &out,
521 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700522 MethodLocation type,
523 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700524
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700525 const Interface *iface = mRootScope->getInterface();
526
527 std::vector<const Interface *> chain;
528 while (iface != NULL) {
529 chain.push_back(iface);
530 iface = iface->superType();
531 }
532
533 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
534 const Interface *superInterface = *it;
535
536 out << "// Methods from "
537 << superInterface->fullName()
538 << " follow.\n";
539
540 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700541 status_t err;
542 switch(type) {
543 case STUB_HEADER:
544 err = generateStubMethod(out,
545 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700546 method,
547 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700548 break;
549 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700550 err = generateProxyDeclaration(out,
551 className,
552 method,
553 specifyNamespaces);
554 break;
555 case IMPL_HEADER:
556 err = generateStubImplDeclaration(out,
557 className,
558 method,
559 specifyNamespaces);
560 break;
561 case IMPL_SOURCE:
562 err = generateStubImplMethod(out,
563 className,
564 method,
565 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700566 break;
Steven Moreland69e7c702016-09-09 11:16:32 -0700567 case PASSTHROUGH_HEADER:
568 err = generatePassthroughMethod(out,
569 className,
570 method,
571 specifyNamespaces);
572 break;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700573 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700574 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700575 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700576 }
577
Steven Morelanda7a421a2016-09-07 08:35:18 -0700578 if (err != OK) {
579 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700580 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700581 }
582
583 out << "\n";
584 }
585
586 return OK;
587}
588
Andreas Huberb82318c2016-08-02 14:45:54 -0700589status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700590 std::string ifaceName;
591 if (!AST::isInterface(&ifaceName)) {
592 // types.hal does not get a stub header.
593 return OK;
594 }
595
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700596 const Interface *iface = mRootScope->getInterface();
597 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700598 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700599
Andreas Huberb82318c2016-08-02 14:45:54 -0700600 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700601 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700602 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700603 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700604 path.append(".h");
605
Andreas Huberd2943e12016-08-05 11:59:31 -0700606 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700607 FILE *file = fopen(path.c_str(), "w");
608
609 if (file == NULL) {
610 return -errno;
611 }
612
613 Formatter out(file);
614
Steven Moreland40786312016-08-16 10:29:40 -0700615 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700616
617 out << "#ifndef " << guard << "\n";
618 out << "#define " << guard << "\n\n";
619
620 std::vector<std::string> packageComponents;
621 getPackageAndVersionComponents(
622 &packageComponents, false /* cpp_compatible */);
623
624 out << "#include <";
625 for (const auto &component : packageComponents) {
626 out << component << "/";
627 }
Steven Moreland40786312016-08-16 10:29:40 -0700628 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700629
630 enterLeaveNamespace(out, true /* enter */);
631 out << "\n";
632
633 out << "struct "
634 << "Bn"
635 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700636 << " : public ::android::hardware::BnInterface<I"
637 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700638 << "> {\n";
639
640 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700641 out << "explicit Bn"
642 << baseName
643 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
644 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700645 out << "::android::status_t onTransact(\n";
646 out.indent();
647 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700648 out << "uint32_t _hidl_code,\n";
649 out << "const ::android::hardware::Parcel &_hidl_data,\n";
650 out << "::android::hardware::Parcel *_hidl_reply,\n";
651 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700652 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700653 out.unindent();
654 out.unindent();
655
Steven Moreland9c387612016-09-07 09:54:26 -0700656 status_t err = generateMethods(out,
657 "" /* class name */,
658 MethodLocation::STUB_HEADER,
659 true /* specify namespaces */);
660
661 if (err != OK) {
662 return err;
663 }
664
Andreas Huber881227d2016-08-02 14:20:21 -0700665 out.unindent();
666
667 out << "};\n\n";
668
669 enterLeaveNamespace(out, false /* enter */);
670
671 out << "\n#endif // " << guard << "\n";
672
673 return OK;
674}
675
Andreas Huberb82318c2016-08-02 14:45:54 -0700676status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700677 std::string ifaceName;
678 if (!AST::isInterface(&ifaceName)) {
679 // types.hal does not get a proxy header.
680 return OK;
681 }
682
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700683 const Interface *iface = mRootScope->getInterface();
684 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700685
Andreas Huberb82318c2016-08-02 14:45:54 -0700686 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700687 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700688 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700689 path.append("Bp");
690 path.append(baseName);
691 path.append(".h");
692
Andreas Huberd2943e12016-08-05 11:59:31 -0700693 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700694 FILE *file = fopen(path.c_str(), "w");
695
696 if (file == NULL) {
697 return -errno;
698 }
699
700 Formatter out(file);
701
702 const std::string guard = makeHeaderGuard("Bp" + baseName);
703
704 out << "#ifndef " << guard << "\n";
705 out << "#define " << guard << "\n\n";
706
707 std::vector<std::string> packageComponents;
708 getPackageAndVersionComponents(
709 &packageComponents, false /* cpp_compatible */);
710
711 out << "#include <";
712 for (const auto &component : packageComponents) {
713 out << component << "/";
714 }
Steven Moreland40786312016-08-16 10:29:40 -0700715 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700716
717 enterLeaveNamespace(out, true /* enter */);
718 out << "\n";
719
720 out << "struct "
721 << "Bp"
722 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700723 << " : public ::android::hardware::BpInterface<IHw"
724 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700725 << "> {\n";
726
727 out.indent();
728
729 out << "explicit Bp"
730 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700731 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700732 << "\n\n";
733
Iliyan Malchev795dd432016-09-02 11:48:26 -0700734 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700735
Steven Moreland9c387612016-09-07 09:54:26 -0700736 status_t err = generateMethods(out,
737 "" /* class name */,
738 MethodLocation::PROXY_HEADER,
739 true /* generate specify namespaces */);
740
741 if (err != OK) {
742 return err;
743 }
Andreas Huber881227d2016-08-02 14:20:21 -0700744
745 out.unindent();
746
747 out << "};\n\n";
748
749 enterLeaveNamespace(out, false /* enter */);
750
751 out << "\n#endif // " << guard << "\n";
752
753 return OK;
754}
755
Andreas Huberb82318c2016-08-02 14:45:54 -0700756status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700757
Andreas Huberb82318c2016-08-02 14:45:54 -0700758 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700759 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700760 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700761
762 std::string ifaceName;
763 std::string baseName;
764
765 bool isInterface = true;
766 if (!AST::isInterface(&ifaceName)) {
767 baseName = "types";
768 isInterface = false;
769 } else {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700770 const Interface *iface = mRootScope->getInterface();
771 baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700772 }
773
774 path.append(baseName);
775
776 if (baseName != "types") {
777 path.append("All");
778 }
779
780 path.append(".cpp");
781
Andreas Huberd2943e12016-08-05 11:59:31 -0700782 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700783 FILE *file = fopen(path.c_str(), "w");
784
785 if (file == NULL) {
786 return -errno;
787 }
788
789 Formatter out(file);
790
791 std::vector<std::string> packageComponents;
792 getPackageAndVersionComponents(
793 &packageComponents, false /* cpp_compatible */);
794
795 std::string prefix;
796 for (const auto &component : packageComponents) {
797 prefix += component;
798 prefix += "/";
799 }
800
801 if (isInterface) {
802 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
803 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700804 out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700805 } else {
806 out << "#include <" << prefix << "types.h>\n";
807 }
808
809 out << "\n";
810
811 enterLeaveNamespace(out, true /* enter */);
812 out << "\n";
813
814 status_t err = generateTypeSource(out, ifaceName);
815
816 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200817 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700818 err = generateProxySource(out, baseName);
819 }
820
821 if (err == OK && isInterface) {
822 err = generateStubSource(out, baseName);
823 }
824
Steven Moreland40786312016-08-16 10:29:40 -0700825 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700826 err = generatePassthroughSource(out);
827 }
828
829 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700830 const Interface *iface = mRootScope->getInterface();
831
832 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
833 << baseName << ", "
834 << "\"" << iface->fqName().package()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700835 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700836 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700837 }
838
Andreas Huber881227d2016-08-02 14:20:21 -0700839 enterLeaveNamespace(out, false /* enter */);
840
841 return err;
842}
843
844status_t AST::generateTypeSource(
845 Formatter &out, const std::string &ifaceName) const {
846 return mRootScope->emitTypeDefinitions(out, ifaceName);
847}
848
Andreas Hubere7ff2282016-08-16 13:50:03 -0700849void AST::declareCppReaderLocals(
850 Formatter &out, const std::vector<TypedVar *> &args) const {
851 if (args.empty()) {
852 return;
853 }
854
855 for (const auto &arg : args) {
856 const Type &type = arg->type();
857
858 std::string extra;
859 out << type.getCppResultType(&extra)
860 << " "
861 << arg->name()
862 << extra
863 << ";\n";
864 }
865
866 out << "\n";
867}
868
Andreas Huber881227d2016-08-02 14:20:21 -0700869void AST::emitCppReaderWriter(
870 Formatter &out,
871 const std::string &parcelObj,
872 bool parcelObjIsPointer,
873 const TypedVar *arg,
874 bool isReader,
875 Type::ErrorMode mode) const {
876 const Type &type = arg->type();
877
Andreas Huber881227d2016-08-02 14:20:21 -0700878 type.emitReaderWriter(
879 out,
880 arg->name(),
881 parcelObj,
882 parcelObjIsPointer,
883 isReader,
884 mode);
885}
886
887status_t AST::generateProxySource(
888 Formatter &out, const std::string &baseName) const {
889 const std::string klassName = "Bp" + baseName;
890
891 out << klassName
892 << "::"
893 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700894 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700895
896 out.indent();
897 out.indent();
898
899 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700900 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700901 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700902 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700903
904 out.unindent();
905 out.unindent();
906 out << "}\n\n";
907
908 const Interface *iface = mRootScope->getInterface();
909
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700910 std::vector<const Interface *> chain;
911 while (iface != NULL) {
912 chain.push_back(iface);
913 iface = iface->superType();
914 }
Andreas Huber881227d2016-08-02 14:20:21 -0700915
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700916 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
917 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700918
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700919 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700920 method->generateCppSignature(out,
921 klassName,
922 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700923
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700924 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700925 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700926
Steven Morelanda7a421a2016-09-07 08:35:18 -0700927 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700928
929 out.indent();
930
Iliyan Malchev549e2592016-08-10 08:59:12 -0700931 out << "::android::hardware::Parcel _hidl_data;\n";
932 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700933 out << "::android::status_t _hidl_err;\n";
934 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700935 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700936
Iliyan Malchev549e2592016-08-10 08:59:12 -0700937 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700938 << superInterface->fqName().cppNamespace()
939 << "::IHw"
940 << superInterface->getBaseName()
941 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700942
Iliyan Malchev549e2592016-08-10 08:59:12 -0700943 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700944
945 for (const auto &arg : method->args()) {
946 emitCppReaderWriter(
947 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700948 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700949 false /* parcelObjIsPointer */,
950 arg,
951 false /* reader */,
952 Type::ErrorMode_Goto);
953 }
954
Steven Moreland40786312016-08-16 10:29:40 -0700955 out << "_hidl_err = remote()->transact("
956 << superInterface->fqName().cppNamespace()
957 << "::IHw"
958 << superInterface->getBaseName()
959 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -0700960 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700961 << ", _hidl_data, &_hidl_reply";
962 if (method->isOneway()) {
963 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700964 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700965 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700966
Iliyan Malchev639bff82016-08-13 14:24:11 -0700967 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700968
Iliyan Malchev639bff82016-08-13 14:24:11 -0700969 if (!method->isOneway()) {
970 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
971 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700972 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
973
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700974 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700975 emitCppReaderWriter(
976 out,
977 "_hidl_reply",
978 false /* parcelObjIsPointer */,
979 arg,
980 true /* reader */,
981 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700982 }
983
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700984 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700985 out << "if (_hidl_cb != nullptr) {\n";
986 out.indent();
987 out << "_hidl_cb(";
988
989 bool first = true;
990 for (const auto &arg : method->results()) {
991 if (!first) {
992 out << ", ";
993 }
994
995 if (arg->type().resultNeedsDeref()) {
996 out << "*";
997 }
998 out << arg->name();
999
1000 first = false;
1001 }
1002
1003 out << ");\n";
1004 out.unindent();
1005 out << "}\n\n";
1006 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001007 }
1008
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001009 if (elidedReturn != nullptr) {
1010 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001011 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001012 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001013 out << elidedReturn->type().getCppResultType(&extra)
1014 << ">(" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001015 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001016 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001017 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001018 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001019
Andreas Huber881227d2016-08-02 14:20:21 -07001020 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001021 out << "_hidl_error:\n";
1022 out.indent();
1023 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1024 out << "return ::android::hardware::Return<";
1025 if (elidedReturn != nullptr) {
1026 std::string extra;
1027 out << method->results().at(0)->type().getCppResultType(&extra);
1028 } else {
1029 out << "void";
1030 }
1031 out << ">(_hidl_status);\n";
1032
1033 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001034 out << "}\n\n";
1035 }
Andreas Huber881227d2016-08-02 14:20:21 -07001036 }
1037
1038 return OK;
1039}
1040
1041status_t AST::generateStubSource(
1042 Formatter &out, const std::string &baseName) const {
1043 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1044 << baseName
1045 << ", \""
1046 << mPackage.string()
1047 << "::I"
1048 << baseName
1049 << "\");\n\n";
1050
1051 const std::string klassName = "Bn" + baseName;
1052
Steven Moreland40786312016-08-16 10:29:40 -07001053 out << klassName
1054 << "::"
1055 << klassName
1056 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1057
1058 out.indent();
1059 out.indent();
1060
1061 out << ": BnInterface"
1062 << "<I"
1063 << baseName
1064 << ", IHw"
1065 << baseName
1066 << ">(_hidl_impl) {\n";
1067
1068 out.unindent();
1069 out.unindent();
1070 out << "}\n\n";
1071
Andreas Huber881227d2016-08-02 14:20:21 -07001072 out << "::android::status_t " << klassName << "::onTransact(\n";
1073
1074 out.indent();
1075 out.indent();
1076
Iliyan Malchev549e2592016-08-10 08:59:12 -07001077 out << "uint32_t _hidl_code,\n"
1078 << "const ::android::hardware::Parcel &_hidl_data,\n"
1079 << "::android::hardware::Parcel *_hidl_reply,\n"
1080 << "uint32_t _hidl_flags,\n"
1081 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001082
1083 out.unindent();
1084
Iliyan Malchev549e2592016-08-10 08:59:12 -07001085 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001086 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001087 out.indent();
1088
1089 const Interface *iface = mRootScope->getInterface();
1090
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001091 std::vector<const Interface *> chain;
1092 while (iface != NULL) {
1093 chain.push_back(iface);
1094 iface = iface->superType();
1095 }
Andreas Huber881227d2016-08-02 14:20:21 -07001096
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001097 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1098 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001099
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001100 for (const auto &method : superInterface->methods()) {
1101 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001102 << superInterface->fqName().cppNamespace()
1103 << "::IHw"
1104 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001105 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001106 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001107 << ":\n{\n";
1108
1109 out.indent();
1110
1111 status_t err =
1112 generateStubSourceForMethod(out, superInterface, method);
1113
1114 if (err != OK) {
1115 return err;
1116 }
1117
1118 out.unindent();
1119 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001120 }
Andreas Huber881227d2016-08-02 14:20:21 -07001121 }
1122
1123 out << "default:\n{\n";
1124 out.indent();
1125
Andreas Huber8a82ff72016-08-04 10:29:39 -07001126 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001127 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001128 << ">::onTransact(\n";
1129
1130 out.indent();
1131 out.indent();
1132
Iliyan Malchev549e2592016-08-10 08:59:12 -07001133 out << "_hidl_code, _hidl_data, _hidl_reply, "
1134 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001135
1136 out.unindent();
1137 out.unindent();
1138
1139 out.unindent();
1140 out << "}\n";
1141
1142 out.unindent();
1143 out << "}\n\n";
1144
Iliyan Malchev549e2592016-08-10 08:59:12 -07001145 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001146 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001147 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001148 out.indent();
1149 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001150 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001151 out.indent();
1152 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001153 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001154 out.unindent();
1155 out.unindent();
1156 out.unindent();
1157 out.unindent();
1158
1159 out.unindent();
1160 out << "}\n\n";
1161
Iliyan Malchev549e2592016-08-10 08:59:12 -07001162 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001163
1164 out.unindent();
1165 out << "}\n\n";
1166
1167 return OK;
1168}
1169
1170status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001171 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001172 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001173 << iface->fqName().cppNamespace()
1174 << "::IHw"
1175 << iface->getBaseName()
1176 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001177
Andreas Huber881227d2016-08-02 14:20:21 -07001178 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001179 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001180 out << "break;\n";
1181 out.unindent();
1182 out << "}\n\n";
1183
Andreas Hubere7ff2282016-08-16 13:50:03 -07001184 declareCppReaderLocals(out, method->args());
1185
Andreas Huber881227d2016-08-02 14:20:21 -07001186 for (const auto &arg : method->args()) {
1187 emitCppReaderWriter(
1188 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001189 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001190 false /* parcelObjIsPointer */,
1191 arg,
1192 true /* reader */,
1193 Type::ErrorMode_Break);
1194 }
1195
1196 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001197 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001198
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001199 if (elidedReturn != nullptr) {
1200 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001201
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001202 out << elidedReturn->type().getCppResultType(&extra) << " ";
1203 out << elidedReturn->name() << " = ";
1204 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001205
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001206 bool first = true;
1207 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001208 if (!first) {
1209 out << ", ";
1210 }
1211
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001212 if (arg->type().resultNeedsDeref()) {
1213 out << "*";
1214 }
1215
1216 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001217
1218 first = false;
1219 }
1220
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001221 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001222 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001223 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001224
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001225 elidedReturn->type().emitReaderWriter(
1226 out,
1227 elidedReturn->name(),
1228 "_hidl_reply",
1229 true, /* parcelObjIsPointer */
1230 false, /* isReader */
1231 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001232
Iliyan Malchev549e2592016-08-10 08:59:12 -07001233 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001234 } else {
1235 if (returnsValue) {
1236 out << "bool _hidl_callbackCalled = false;\n\n";
1237 }
Andreas Huber881227d2016-08-02 14:20:21 -07001238
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001239 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001240
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001241 bool first = true;
1242 for (const auto &arg : method->args()) {
1243 if (!first) {
1244 out << ", ";
1245 }
Andreas Huber881227d2016-08-02 14:20:21 -07001246
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001247 if (arg->type().resultNeedsDeref()) {
1248 out << "*";
1249 }
1250
1251 out << arg->name();
1252
1253 first = false;
1254 }
1255
1256 if (returnsValue) {
1257 if (!first) {
1258 out << ", ";
1259 }
1260
1261 out << "[&](";
1262
1263 first = true;
1264 for (const auto &arg : method->results()) {
1265 if (!first) {
1266 out << ", ";
1267 }
1268
1269 out << "const auto &" << arg->name();
1270
1271 first = false;
1272 }
1273
1274 out << ") {\n";
1275 out.indent();
1276 out << "_hidl_callbackCalled = true;\n\n";
1277
1278 out << "::android::hardware::Status::ok()"
1279 << ".writeToParcel(_hidl_reply);\n\n";
1280
1281 for (const auto &arg : method->results()) {
1282 emitCppReaderWriter(
1283 out,
1284 "_hidl_reply",
1285 true /* parcelObjIsPointer */,
1286 arg,
1287 false /* reader */,
1288 Type::ErrorMode_Ignore);
1289 }
1290
1291 out << "_hidl_cb(*_hidl_reply);\n";
1292
1293 out.unindent();
1294 out << "}\n";
1295 }
1296
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001297 out << ");\n\n";
1298
1299 // What to do if the stub implementation has a synchronous callback
1300 // which does not get invoked? This is not a transport error but a
1301 // service error of sorts. For now, return OK to the caller, as this is
1302 // not a transport error.
1303 //
1304 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001305
1306 if (returnsValue) {
1307 out << "if (!_hidl_callbackCalled) {\n";
1308 out.indent();
1309 }
1310
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001311 out << "::android::hardware::Status::ok()"
1312 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001313
1314 if (returnsValue) {
1315 out.unindent();
1316 out << "}\n\n";
1317 }
Andreas Huber881227d2016-08-02 14:20:21 -07001318 }
1319
1320 out << "break;\n";
1321
1322 return OK;
1323}
1324
Steven Moreland69e7c702016-09-09 11:16:32 -07001325status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1326 std::string ifaceName;
1327 if (!AST::isInterface(&ifaceName)) {
1328 // types.hal does not get a stub header.
1329 return OK;
1330 }
1331
1332 const Interface *iface = mRootScope->getInterface();
1333
1334 const std::string baseName = iface->getBaseName();
1335 const std::string klassName = "Bs" + baseName;
1336
1337 bool supportOneway = iface->hasOnewayMethods();
1338
1339 std::string path = outputPath;
1340 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1341 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1342 path.append(klassName);
1343 path.append(".h");
1344
1345 CHECK(Coordinator::MakeParentHierarchy(path));
1346 FILE *file = fopen(path.c_str(), "w");
1347
1348 if (file == NULL) {
1349 return -errno;
1350 }
1351
1352 Formatter out(file);
1353
1354 const std::string guard = makeHeaderGuard(klassName);
1355
1356 out << "#ifndef " << guard << "\n";
1357 out << "#define " << guard << "\n\n";
1358
1359 std::vector<std::string> packageComponents;
1360 getPackageAndVersionComponents(
1361 &packageComponents, false /* cpp_compatible */);
1362
1363 out << "#include <future>\n";
1364 out << "#include <";
1365 for (const auto &component : packageComponents) {
1366 out << component << "/";
1367 }
1368 out << ifaceName << ".h>\n\n";
1369
1370 if (supportOneway) {
1371 out << "#include <hidl/SynchronizedQueue.h>\n";
1372 }
1373
1374 enterLeaveNamespace(out, true /* enter */);
1375 out << "\n";
1376
1377 out << "struct "
1378 << klassName
1379 << " : " << ifaceName
1380 << " {\n";
1381
1382 out.indent();
1383 out << "explicit "
1384 << klassName
1385 << "(const sp<"
1386 << ifaceName
1387 << "> impl);\n";
1388
1389 status_t err = generateMethods(out,
1390 "" /* class name */,
1391 MethodLocation::PASSTHROUGH_HEADER,
1392 true /* specify namespaces */);
1393
1394 if (err != OK) {
1395 return err;
1396 }
1397
1398 out.unindent();
1399 out << "private:\n";
1400 out.indent();
1401 out << "const sp<" << ifaceName << "> mImpl;\n";
1402
1403 if (supportOneway) {
1404 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1405 out << "std::thread *mOnewayThread = nullptr;\n";
1406
1407 out << "\n";
1408
1409 out << "::android::hardware::Return<void> addOnewayTask("
1410 "std::function<void(void)>);\n\n";
1411
1412 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1413 }
1414
1415 out.unindent();
1416
1417 out << "};\n\n";
1418
1419 enterLeaveNamespace(out, false /* enter */);
1420
1421 out << "\n#endif // " << guard << "\n";
1422
1423 return OK;
1424}
1425
1426
1427status_t AST::generatePassthroughSource(Formatter &out) const {
1428 const Interface *iface = mRootScope->getInterface();
1429
1430 const std::string baseName = iface->getBaseName();
1431 const std::string klassName = "Bs" + baseName;
1432
1433 out << klassName
1434 << "::"
1435 << klassName
1436 << "(const sp<"
1437 << iface->fullName()
1438 << "> impl) : mImpl(impl) {}\n\n";
1439
1440 if (iface->hasOnewayMethods()) {
1441 out << "::android::hardware::Return<void> "
1442 << klassName
1443 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1444 out.indent();
1445 out << "if (mOnewayThread == nullptr) {\n";
1446 out.indent();
1447 out << "mOnewayThread = new std::thread([this]() {\n";
1448 out.indent();
1449 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1450 out.unindent();
1451 out << "});\n";
1452 out.unindent();
1453 out << "}\n\n";
1454
1455 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1456 out.indent();
1457 out << "return Status::fromExceptionCode(Status::EX_TRANSACTION_FAILED);\n";
1458 out.unindent();
1459 out << "} else {\n";
1460 out.indent();
1461 out << "mOnewayQueue.push(fun);\n";
1462 out.unindent();
1463 out << "}\n";
1464
1465 out << "return Status();\n";
1466
1467 out.unindent();
1468 out << "}\n\n";
1469
1470
1471 }
1472
1473 return OK;
1474}
1475
Andreas Huber881227d2016-08-02 14:20:21 -07001476} // namespace android
1477