blob: 9968635d455338471cd7cf02f9b6a772487e3a28 [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
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700665 // Generated code for instrumentation.
666 out << "// for hidl instrumentation.\n";
667 out << "std::vector<InstrumentationCallback> instrumentationCallbacks;\n\n";
668 out << "bool enableInstrumentation = false;\n";
669
Andreas Huber881227d2016-08-02 14:20:21 -0700670 out.unindent();
671
672 out << "};\n\n";
673
674 enterLeaveNamespace(out, false /* enter */);
675
676 out << "\n#endif // " << guard << "\n";
677
678 return OK;
679}
680
Andreas Huberb82318c2016-08-02 14:45:54 -0700681status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700682 std::string ifaceName;
683 if (!AST::isInterface(&ifaceName)) {
684 // types.hal does not get a proxy header.
685 return OK;
686 }
687
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700688 const Interface *iface = mRootScope->getInterface();
689 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700690
Andreas Huberb82318c2016-08-02 14:45:54 -0700691 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700692 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700693 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700694 path.append("Bp");
695 path.append(baseName);
696 path.append(".h");
697
Andreas Huberd2943e12016-08-05 11:59:31 -0700698 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700699 FILE *file = fopen(path.c_str(), "w");
700
701 if (file == NULL) {
702 return -errno;
703 }
704
705 Formatter out(file);
706
707 const std::string guard = makeHeaderGuard("Bp" + baseName);
708
709 out << "#ifndef " << guard << "\n";
710 out << "#define " << guard << "\n\n";
711
712 std::vector<std::string> packageComponents;
713 getPackageAndVersionComponents(
714 &packageComponents, false /* cpp_compatible */);
715
716 out << "#include <";
717 for (const auto &component : packageComponents) {
718 out << component << "/";
719 }
Steven Moreland40786312016-08-16 10:29:40 -0700720 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700721
722 enterLeaveNamespace(out, true /* enter */);
723 out << "\n";
724
725 out << "struct "
726 << "Bp"
727 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700728 << " : public ::android::hardware::BpInterface<IHw"
729 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700730 << "> {\n";
731
732 out.indent();
733
734 out << "explicit Bp"
735 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700736 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700737 << "\n\n";
738
Iliyan Malchev795dd432016-09-02 11:48:26 -0700739 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700740
Steven Moreland9c387612016-09-07 09:54:26 -0700741 status_t err = generateMethods(out,
742 "" /* class name */,
743 MethodLocation::PROXY_HEADER,
744 true /* generate specify namespaces */);
745
746 if (err != OK) {
747 return err;
748 }
Andreas Huber881227d2016-08-02 14:20:21 -0700749
750 out.unindent();
751
752 out << "};\n\n";
753
754 enterLeaveNamespace(out, false /* enter */);
755
756 out << "\n#endif // " << guard << "\n";
757
758 return OK;
759}
760
Andreas Huberb82318c2016-08-02 14:45:54 -0700761status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700762
Andreas Huberb82318c2016-08-02 14:45:54 -0700763 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700764 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700765 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700766
767 std::string ifaceName;
768 std::string baseName;
769
770 bool isInterface = true;
771 if (!AST::isInterface(&ifaceName)) {
772 baseName = "types";
773 isInterface = false;
774 } else {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700775 const Interface *iface = mRootScope->getInterface();
776 baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700777 }
778
779 path.append(baseName);
780
781 if (baseName != "types") {
782 path.append("All");
783 }
784
785 path.append(".cpp");
786
Andreas Huberd2943e12016-08-05 11:59:31 -0700787 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700788 FILE *file = fopen(path.c_str(), "w");
789
790 if (file == NULL) {
791 return -errno;
792 }
793
794 Formatter out(file);
795
796 std::vector<std::string> packageComponents;
797 getPackageAndVersionComponents(
798 &packageComponents, false /* cpp_compatible */);
799
800 std::string prefix;
801 for (const auto &component : packageComponents) {
802 prefix += component;
803 prefix += "/";
804 }
805
806 if (isInterface) {
807 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
808 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700809 out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700810 out << "#include <cutils/properties.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700811 } else {
812 out << "#include <" << prefix << "types.h>\n";
813 }
814
815 out << "\n";
816
817 enterLeaveNamespace(out, true /* enter */);
818 out << "\n";
819
820 status_t err = generateTypeSource(out, ifaceName);
821
822 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200823 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700824 err = generateProxySource(out, baseName);
825 }
826
827 if (err == OK && isInterface) {
828 err = generateStubSource(out, baseName);
829 }
830
Steven Moreland40786312016-08-16 10:29:40 -0700831 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700832 err = generatePassthroughSource(out);
833 }
834
835 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700836 const Interface *iface = mRootScope->getInterface();
837
838 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
839 << baseName << ", "
840 << "\"" << iface->fqName().package()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700841 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700842 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700843 }
844
Andreas Huber881227d2016-08-02 14:20:21 -0700845 enterLeaveNamespace(out, false /* enter */);
846
847 return err;
848}
849
850status_t AST::generateTypeSource(
851 Formatter &out, const std::string &ifaceName) const {
852 return mRootScope->emitTypeDefinitions(out, ifaceName);
853}
854
Andreas Hubere7ff2282016-08-16 13:50:03 -0700855void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700856 Formatter &out,
857 const std::vector<TypedVar *> &args,
858 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700859 if (args.empty()) {
860 return;
861 }
862
863 for (const auto &arg : args) {
864 const Type &type = arg->type();
865
866 std::string extra;
867 out << type.getCppResultType(&extra)
868 << " "
Andreas Huber5e44a292016-09-27 14:52:39 -0700869 << (forResults ? "_hidl_out_" : "")
Andreas Hubere7ff2282016-08-16 13:50:03 -0700870 << arg->name()
871 << extra
872 << ";\n";
873 }
874
875 out << "\n";
876}
877
Andreas Huber881227d2016-08-02 14:20:21 -0700878void AST::emitCppReaderWriter(
879 Formatter &out,
880 const std::string &parcelObj,
881 bool parcelObjIsPointer,
882 const TypedVar *arg,
883 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700884 Type::ErrorMode mode,
885 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700886 const Type &type = arg->type();
887
Andreas Huber881227d2016-08-02 14:20:21 -0700888 type.emitReaderWriter(
889 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700890 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700891 parcelObj,
892 parcelObjIsPointer,
893 isReader,
894 mode);
895}
896
897status_t AST::generateProxySource(
898 Formatter &out, const std::string &baseName) const {
899 const std::string klassName = "Bp" + baseName;
900
901 out << klassName
902 << "::"
903 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700904 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700905
906 out.indent();
907 out.indent();
908
909 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700910 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700911 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700912 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700913
914 out.unindent();
915 out.unindent();
916 out << "}\n\n";
917
918 const Interface *iface = mRootScope->getInterface();
919
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700920 std::vector<const Interface *> chain;
921 while (iface != NULL) {
922 chain.push_back(iface);
923 iface = iface->superType();
924 }
Andreas Huber881227d2016-08-02 14:20:21 -0700925
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700926 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
927 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700928
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700929 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700930 method->generateCppSignature(out,
931 klassName,
932 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700933
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700934 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700935 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700936
Steven Morelanda7a421a2016-09-07 08:35:18 -0700937 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700938
939 out.indent();
940
Iliyan Malchev549e2592016-08-10 08:59:12 -0700941 out << "::android::hardware::Parcel _hidl_data;\n";
942 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700943 out << "::android::status_t _hidl_err;\n";
944 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Huber5e44a292016-09-27 14:52:39 -0700945
946 declareCppReaderLocals(
947 out, method->results(), true /* forResults */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700948
Iliyan Malchev549e2592016-08-10 08:59:12 -0700949 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700950 << superInterface->fqName().cppNamespace()
951 << "::IHw"
952 << superInterface->getBaseName()
953 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700954
Iliyan Malchev549e2592016-08-10 08:59:12 -0700955 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700956
957 for (const auto &arg : method->args()) {
958 emitCppReaderWriter(
959 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700960 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700961 false /* parcelObjIsPointer */,
962 arg,
963 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -0700964 Type::ErrorMode_Goto,
965 false /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700966 }
967
Steven Moreland40786312016-08-16 10:29:40 -0700968 out << "_hidl_err = remote()->transact("
969 << superInterface->fqName().cppNamespace()
970 << "::IHw"
971 << superInterface->getBaseName()
972 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -0700973 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700974 << ", _hidl_data, &_hidl_reply";
975 if (method->isOneway()) {
976 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700977 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700978 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700979
Iliyan Malchev639bff82016-08-13 14:24:11 -0700980 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700981
Iliyan Malchev639bff82016-08-13 14:24:11 -0700982 if (!method->isOneway()) {
983 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
984 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700985 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
986
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700987 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700988 emitCppReaderWriter(
989 out,
990 "_hidl_reply",
991 false /* parcelObjIsPointer */,
992 arg,
993 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -0700994 Type::ErrorMode_Goto,
995 true /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700996 }
997
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700998 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700999 out << "if (_hidl_cb != nullptr) {\n";
1000 out.indent();
1001 out << "_hidl_cb(";
1002
1003 bool first = true;
1004 for (const auto &arg : method->results()) {
1005 if (!first) {
1006 out << ", ";
1007 }
1008
1009 if (arg->type().resultNeedsDeref()) {
1010 out << "*";
1011 }
Andreas Huber5e44a292016-09-27 14:52:39 -07001012 out << "_hidl_out_" << arg->name();
Iliyan Malchev639bff82016-08-13 14:24:11 -07001013
1014 first = false;
1015 }
1016
1017 out << ");\n";
1018 out.unindent();
1019 out << "}\n\n";
1020 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001021 }
1022
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001023 if (elidedReturn != nullptr) {
1024 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001025 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001026 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001027 out << elidedReturn->type().getCppResultType(&extra)
Andreas Huber5e44a292016-09-27 14:52:39 -07001028 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001029 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001030 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001031 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001032 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001033
Andreas Huber881227d2016-08-02 14:20:21 -07001034 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001035 out << "_hidl_error:\n";
1036 out.indent();
1037 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1038 out << "return ::android::hardware::Return<";
1039 if (elidedReturn != nullptr) {
1040 std::string extra;
1041 out << method->results().at(0)->type().getCppResultType(&extra);
1042 } else {
1043 out << "void";
1044 }
1045 out << ">(_hidl_status);\n";
1046
1047 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001048 out << "}\n\n";
1049 }
Andreas Huber881227d2016-08-02 14:20:21 -07001050 }
1051
1052 return OK;
1053}
1054
1055status_t AST::generateStubSource(
1056 Formatter &out, const std::string &baseName) const {
1057 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1058 << baseName
1059 << ", \""
1060 << mPackage.string()
1061 << "::I"
1062 << baseName
1063 << "\");\n\n";
1064
1065 const std::string klassName = "Bn" + baseName;
1066
Steven Moreland40786312016-08-16 10:29:40 -07001067 out << klassName
1068 << "::"
1069 << klassName
1070 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1071
1072 out.indent();
1073 out.indent();
1074
1075 out << ": BnInterface"
1076 << "<I"
1077 << baseName
1078 << ", IHw"
1079 << baseName
1080 << ">(_hidl_impl) {\n";
1081
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001082 out << "enableInstrumentation = "
1083 "property_get_bool(\"hal.instrumentation.enable\", false);\n";
1084 out << "registerInstrumentationCallbacks(\""
1085 << mPackage.string()
1086 << "::I"
1087 << baseName
1088 << "\", &instrumentationCallbacks);\n";
Steven Moreland40786312016-08-16 10:29:40 -07001089 out.unindent();
1090 out.unindent();
1091 out << "}\n\n";
1092
Andreas Huber881227d2016-08-02 14:20:21 -07001093 out << "::android::status_t " << klassName << "::onTransact(\n";
1094
1095 out.indent();
1096 out.indent();
1097
Iliyan Malchev549e2592016-08-10 08:59:12 -07001098 out << "uint32_t _hidl_code,\n"
1099 << "const ::android::hardware::Parcel &_hidl_data,\n"
1100 << "::android::hardware::Parcel *_hidl_reply,\n"
1101 << "uint32_t _hidl_flags,\n"
1102 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001103
1104 out.unindent();
1105
Iliyan Malchev549e2592016-08-10 08:59:12 -07001106 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001107 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001108 out.indent();
1109
1110 const Interface *iface = mRootScope->getInterface();
1111
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001112 std::vector<const Interface *> chain;
1113 while (iface != NULL) {
1114 chain.push_back(iface);
1115 iface = iface->superType();
1116 }
Andreas Huber881227d2016-08-02 14:20:21 -07001117
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001118 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1119 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001120
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001121 for (const auto &method : superInterface->methods()) {
1122 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001123 << superInterface->fqName().cppNamespace()
1124 << "::IHw"
1125 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001126 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001127 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001128 << ":\n{\n";
1129
1130 out.indent();
1131
1132 status_t err =
1133 generateStubSourceForMethod(out, superInterface, method);
1134
1135 if (err != OK) {
1136 return err;
1137 }
1138
1139 out.unindent();
1140 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001141 }
Andreas Huber881227d2016-08-02 14:20:21 -07001142 }
1143
1144 out << "default:\n{\n";
1145 out.indent();
1146
Andreas Huber8a82ff72016-08-04 10:29:39 -07001147 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001148 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001149 << ">::onTransact(\n";
1150
1151 out.indent();
1152 out.indent();
1153
Iliyan Malchev549e2592016-08-10 08:59:12 -07001154 out << "_hidl_code, _hidl_data, _hidl_reply, "
1155 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001156
1157 out.unindent();
1158 out.unindent();
1159
1160 out.unindent();
1161 out << "}\n";
1162
1163 out.unindent();
1164 out << "}\n\n";
1165
Iliyan Malchev549e2592016-08-10 08:59:12 -07001166 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001167 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001168 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001169 out.indent();
1170 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001171 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001172 out.indent();
1173 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001174 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001175 out.unindent();
1176 out.unindent();
1177 out.unindent();
1178 out.unindent();
1179
1180 out.unindent();
1181 out << "}\n\n";
1182
Iliyan Malchev549e2592016-08-10 08:59:12 -07001183 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001184
1185 out.unindent();
1186 out << "}\n\n";
1187
1188 return OK;
1189}
1190
1191status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001192 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001193 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001194 << iface->fqName().cppNamespace()
1195 << "::IHw"
1196 << iface->getBaseName()
1197 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001198
Andreas Huber881227d2016-08-02 14:20:21 -07001199 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001200 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001201 out << "break;\n";
1202 out.unindent();
1203 out << "}\n\n";
1204
Andreas Huber5e44a292016-09-27 14:52:39 -07001205 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001206
Andreas Huber881227d2016-08-02 14:20:21 -07001207 for (const auto &arg : method->args()) {
1208 emitCppReaderWriter(
1209 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001210 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001211 false /* parcelObjIsPointer */,
1212 arg,
1213 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001214 Type::ErrorMode_Break,
1215 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001216 }
1217
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001218 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1219 out.indent();
1220 out << "std::vector<void *> args;\n";
1221 for (const auto &arg : method->args()) {
1222 out << "args.push_back((void *)"
1223 << (arg->type().resultNeedsDeref() ? "" : "&")
1224 << arg->name()
1225 << ");\n";
1226 }
1227
1228 out << "for (auto callback: instrumentationCallbacks) {\n";
1229 out.indent();
1230 out << "callback(InstrumentationEvent::SERVER_API_ENTRY, \""
1231 << mPackage.package()
1232 << "\", \"" << mPackage.version().substr(1) << "\", \""
1233 << iface->localName() << "\", \"" << method->name() << "\", &args);\n";
1234 out.unindent();
1235 out << "}\n";
1236 out.unindent();
1237 out << "}\n\n";
1238
Andreas Huber881227d2016-08-02 14:20:21 -07001239 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001240 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001241
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001242 if (elidedReturn != nullptr) {
1243 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001244
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001245 out << elidedReturn->type().getCppResultType(&extra) << " ";
1246 out << elidedReturn->name() << " = ";
1247 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001248
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001249 bool first = true;
1250 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001251 if (!first) {
1252 out << ", ";
1253 }
1254
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001255 if (arg->type().resultNeedsDeref()) {
1256 out << "*";
1257 }
1258
1259 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001260
1261 first = false;
1262 }
1263
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001264 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001265 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001266 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001267
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001268 elidedReturn->type().emitReaderWriter(
1269 out,
1270 elidedReturn->name(),
1271 "_hidl_reply",
1272 true, /* parcelObjIsPointer */
1273 false, /* isReader */
1274 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001275
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001276 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1277 out.indent();
1278 out << "std::vector<void *> results;\n";
1279 out << "results.push_back((void *)&" << elidedReturn->name() << ");\n";
1280
1281 out << "for (auto callback: instrumentationCallbacks) {\n";
1282 out.indent();
1283 out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
1284 << mPackage.package()
1285 << "\", \"" << mPackage.version().substr(1) << "\", \""
1286 << iface->localName() << "\", \"" << method->name()
1287 << "\", &results);\n";
1288 out.unindent();
1289 out << "}\n";
1290 out.unindent();
1291 out << "}\n\n";
1292
Iliyan Malchev549e2592016-08-10 08:59:12 -07001293 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001294 } else {
1295 if (returnsValue) {
1296 out << "bool _hidl_callbackCalled = false;\n\n";
1297 }
Andreas Huber881227d2016-08-02 14:20:21 -07001298
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001299 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001300
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001301 bool first = true;
1302 for (const auto &arg : method->args()) {
1303 if (!first) {
1304 out << ", ";
1305 }
Andreas Huber881227d2016-08-02 14:20:21 -07001306
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001307 if (arg->type().resultNeedsDeref()) {
1308 out << "*";
1309 }
1310
1311 out << arg->name();
1312
1313 first = false;
1314 }
1315
1316 if (returnsValue) {
1317 if (!first) {
1318 out << ", ";
1319 }
1320
1321 out << "[&](";
1322
1323 first = true;
1324 for (const auto &arg : method->results()) {
1325 if (!first) {
1326 out << ", ";
1327 }
1328
1329 out << "const auto &" << arg->name();
1330
1331 first = false;
1332 }
1333
1334 out << ") {\n";
1335 out.indent();
1336 out << "_hidl_callbackCalled = true;\n\n";
1337
1338 out << "::android::hardware::Status::ok()"
1339 << ".writeToParcel(_hidl_reply);\n\n";
1340
1341 for (const auto &arg : method->results()) {
1342 emitCppReaderWriter(
1343 out,
1344 "_hidl_reply",
1345 true /* parcelObjIsPointer */,
1346 arg,
1347 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001348 Type::ErrorMode_Ignore,
1349 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001350 }
1351
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001352 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1353 out.indent();
1354 out << "std::vector<void *> results;\n";
1355 for (const auto &arg : method->results()) {
1356 out << "results.push_back((void *)&" << arg->name() << ");\n";
1357 }
1358
1359 out << "for (auto callback: instrumentationCallbacks) {\n";
1360 out.indent();
1361 out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
1362 << mPackage.package()
1363 << "\", \"" << mPackage.version().substr(1) << "\", \""
1364 << iface->localName() << "\", \"" << method->name()
1365 << "\", &results);\n";
1366 out.unindent();
1367 out << "}\n";
1368 out.unindent();
1369 out << "}\n\n";
1370
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001371 out << "_hidl_cb(*_hidl_reply);\n";
1372
1373 out.unindent();
1374 out << "}\n";
1375 }
1376
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001377 out << ");\n\n";
1378
1379 // What to do if the stub implementation has a synchronous callback
1380 // which does not get invoked? This is not a transport error but a
1381 // service error of sorts. For now, return OK to the caller, as this is
1382 // not a transport error.
1383 //
1384 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001385
1386 if (returnsValue) {
1387 out << "if (!_hidl_callbackCalled) {\n";
1388 out.indent();
1389 }
1390
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001391 out << "::android::hardware::Status::ok()"
1392 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001393
1394 if (returnsValue) {
1395 out.unindent();
1396 out << "}\n\n";
1397 }
Andreas Huber881227d2016-08-02 14:20:21 -07001398 }
1399
1400 out << "break;\n";
1401
1402 return OK;
1403}
1404
Steven Moreland69e7c702016-09-09 11:16:32 -07001405status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1406 std::string ifaceName;
1407 if (!AST::isInterface(&ifaceName)) {
1408 // types.hal does not get a stub header.
1409 return OK;
1410 }
1411
1412 const Interface *iface = mRootScope->getInterface();
1413
1414 const std::string baseName = iface->getBaseName();
1415 const std::string klassName = "Bs" + baseName;
1416
1417 bool supportOneway = iface->hasOnewayMethods();
1418
1419 std::string path = outputPath;
1420 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1421 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1422 path.append(klassName);
1423 path.append(".h");
1424
1425 CHECK(Coordinator::MakeParentHierarchy(path));
1426 FILE *file = fopen(path.c_str(), "w");
1427
1428 if (file == NULL) {
1429 return -errno;
1430 }
1431
1432 Formatter out(file);
1433
1434 const std::string guard = makeHeaderGuard(klassName);
1435
1436 out << "#ifndef " << guard << "\n";
1437 out << "#define " << guard << "\n\n";
1438
1439 std::vector<std::string> packageComponents;
1440 getPackageAndVersionComponents(
1441 &packageComponents, false /* cpp_compatible */);
1442
1443 out << "#include <future>\n";
1444 out << "#include <";
1445 for (const auto &component : packageComponents) {
1446 out << component << "/";
1447 }
1448 out << ifaceName << ".h>\n\n";
1449
1450 if (supportOneway) {
1451 out << "#include <hidl/SynchronizedQueue.h>\n";
1452 }
1453
1454 enterLeaveNamespace(out, true /* enter */);
1455 out << "\n";
1456
1457 out << "struct "
1458 << klassName
1459 << " : " << ifaceName
1460 << " {\n";
1461
1462 out.indent();
1463 out << "explicit "
1464 << klassName
1465 << "(const sp<"
1466 << ifaceName
1467 << "> impl);\n";
1468
1469 status_t err = generateMethods(out,
1470 "" /* class name */,
1471 MethodLocation::PASSTHROUGH_HEADER,
1472 true /* specify namespaces */);
1473
1474 if (err != OK) {
1475 return err;
1476 }
1477
1478 out.unindent();
1479 out << "private:\n";
1480 out.indent();
1481 out << "const sp<" << ifaceName << "> mImpl;\n";
1482
1483 if (supportOneway) {
1484 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1485 out << "std::thread *mOnewayThread = nullptr;\n";
1486
1487 out << "\n";
1488
1489 out << "::android::hardware::Return<void> addOnewayTask("
1490 "std::function<void(void)>);\n\n";
1491
1492 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1493 }
1494
1495 out.unindent();
1496
1497 out << "};\n\n";
1498
1499 enterLeaveNamespace(out, false /* enter */);
1500
1501 out << "\n#endif // " << guard << "\n";
1502
1503 return OK;
1504}
1505
1506
1507status_t AST::generatePassthroughSource(Formatter &out) const {
1508 const Interface *iface = mRootScope->getInterface();
1509
1510 const std::string baseName = iface->getBaseName();
1511 const std::string klassName = "Bs" + baseName;
1512
1513 out << klassName
1514 << "::"
1515 << klassName
1516 << "(const sp<"
1517 << iface->fullName()
1518 << "> impl) : mImpl(impl) {}\n\n";
1519
1520 if (iface->hasOnewayMethods()) {
1521 out << "::android::hardware::Return<void> "
1522 << klassName
1523 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1524 out.indent();
1525 out << "if (mOnewayThread == nullptr) {\n";
1526 out.indent();
1527 out << "mOnewayThread = new std::thread([this]() {\n";
1528 out.indent();
1529 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1530 out.unindent();
1531 out << "});\n";
1532 out.unindent();
1533 out << "}\n\n";
1534
1535 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1536 out.indent();
1537 out << "return Status::fromExceptionCode(Status::EX_TRANSACTION_FAILED);\n";
1538 out.unindent();
1539 out << "} else {\n";
1540 out.indent();
1541 out << "mOnewayQueue.push(fun);\n";
1542 out.unindent();
1543 out << "}\n";
1544
1545 out << "return Status();\n";
1546
1547 out.unindent();
1548 out << "}\n\n";
1549
1550
1551 }
1552
1553 return OK;
1554}
1555
Andreas Huber881227d2016-08-02 14:20:21 -07001556} // namespace android
1557