blob: 72c8e6b9188d35a578ddbf1a58f9fc8afa0a060d [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(
856 Formatter &out, const std::vector<TypedVar *> &args) const {
857 if (args.empty()) {
858 return;
859 }
860
861 for (const auto &arg : args) {
862 const Type &type = arg->type();
863
864 std::string extra;
865 out << type.getCppResultType(&extra)
866 << " "
867 << arg->name()
868 << extra
869 << ";\n";
870 }
871
872 out << "\n";
873}
874
Andreas Huber881227d2016-08-02 14:20:21 -0700875void AST::emitCppReaderWriter(
876 Formatter &out,
877 const std::string &parcelObj,
878 bool parcelObjIsPointer,
879 const TypedVar *arg,
880 bool isReader,
881 Type::ErrorMode mode) const {
882 const Type &type = arg->type();
883
Andreas Huber881227d2016-08-02 14:20:21 -0700884 type.emitReaderWriter(
885 out,
886 arg->name(),
887 parcelObj,
888 parcelObjIsPointer,
889 isReader,
890 mode);
891}
892
893status_t AST::generateProxySource(
894 Formatter &out, const std::string &baseName) const {
895 const std::string klassName = "Bp" + baseName;
896
897 out << klassName
898 << "::"
899 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700900 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700901
902 out.indent();
903 out.indent();
904
905 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700906 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700907 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700908 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700909
910 out.unindent();
911 out.unindent();
912 out << "}\n\n";
913
914 const Interface *iface = mRootScope->getInterface();
915
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700916 std::vector<const Interface *> chain;
917 while (iface != NULL) {
918 chain.push_back(iface);
919 iface = iface->superType();
920 }
Andreas Huber881227d2016-08-02 14:20:21 -0700921
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700922 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
923 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700924
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700925 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700926 method->generateCppSignature(out,
927 klassName,
928 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700929
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700930 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700931 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700932
Steven Morelanda7a421a2016-09-07 08:35:18 -0700933 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700934
935 out.indent();
936
Iliyan Malchev549e2592016-08-10 08:59:12 -0700937 out << "::android::hardware::Parcel _hidl_data;\n";
938 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700939 out << "::android::status_t _hidl_err;\n";
940 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700941 declareCppReaderLocals(out, method->results());
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700942
Iliyan Malchev549e2592016-08-10 08:59:12 -0700943 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700944 << superInterface->fqName().cppNamespace()
945 << "::IHw"
946 << superInterface->getBaseName()
947 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700948
Iliyan Malchev549e2592016-08-10 08:59:12 -0700949 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700950
951 for (const auto &arg : method->args()) {
952 emitCppReaderWriter(
953 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700954 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700955 false /* parcelObjIsPointer */,
956 arg,
957 false /* reader */,
958 Type::ErrorMode_Goto);
959 }
960
Steven Moreland40786312016-08-16 10:29:40 -0700961 out << "_hidl_err = remote()->transact("
962 << superInterface->fqName().cppNamespace()
963 << "::IHw"
964 << superInterface->getBaseName()
965 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -0700966 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -0700967 << ", _hidl_data, &_hidl_reply";
968 if (method->isOneway()) {
969 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700970 }
Iliyan Malchev639bff82016-08-13 14:24:11 -0700971 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700972
Iliyan Malchev639bff82016-08-13 14:24:11 -0700973 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700974
Iliyan Malchev639bff82016-08-13 14:24:11 -0700975 if (!method->isOneway()) {
976 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
977 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -0700978 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
979
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700980 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700981 emitCppReaderWriter(
982 out,
983 "_hidl_reply",
984 false /* parcelObjIsPointer */,
985 arg,
986 true /* reader */,
987 Type::ErrorMode_Goto);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700988 }
989
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700990 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -0700991 out << "if (_hidl_cb != nullptr) {\n";
992 out.indent();
993 out << "_hidl_cb(";
994
995 bool first = true;
996 for (const auto &arg : method->results()) {
997 if (!first) {
998 out << ", ";
999 }
1000
1001 if (arg->type().resultNeedsDeref()) {
1002 out << "*";
1003 }
1004 out << arg->name();
1005
1006 first = false;
1007 }
1008
1009 out << ");\n";
1010 out.unindent();
1011 out << "}\n\n";
1012 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001013 }
1014
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001015 if (elidedReturn != nullptr) {
1016 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001017 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001018 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001019 out << elidedReturn->type().getCppResultType(&extra)
1020 << ">(" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001021 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001022 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001023 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001024 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001025
Andreas Huber881227d2016-08-02 14:20:21 -07001026 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001027 out << "_hidl_error:\n";
1028 out.indent();
1029 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1030 out << "return ::android::hardware::Return<";
1031 if (elidedReturn != nullptr) {
1032 std::string extra;
1033 out << method->results().at(0)->type().getCppResultType(&extra);
1034 } else {
1035 out << "void";
1036 }
1037 out << ">(_hidl_status);\n";
1038
1039 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001040 out << "}\n\n";
1041 }
Andreas Huber881227d2016-08-02 14:20:21 -07001042 }
1043
1044 return OK;
1045}
1046
1047status_t AST::generateStubSource(
1048 Formatter &out, const std::string &baseName) const {
1049 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1050 << baseName
1051 << ", \""
1052 << mPackage.string()
1053 << "::I"
1054 << baseName
1055 << "\");\n\n";
1056
1057 const std::string klassName = "Bn" + baseName;
1058
Steven Moreland40786312016-08-16 10:29:40 -07001059 out << klassName
1060 << "::"
1061 << klassName
1062 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1063
1064 out.indent();
1065 out.indent();
1066
1067 out << ": BnInterface"
1068 << "<I"
1069 << baseName
1070 << ", IHw"
1071 << baseName
1072 << ">(_hidl_impl) {\n";
1073
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001074 out << "enableInstrumentation = "
1075 "property_get_bool(\"hal.instrumentation.enable\", false);\n";
1076 out << "registerInstrumentationCallbacks(\""
1077 << mPackage.string()
1078 << "::I"
1079 << baseName
1080 << "\", &instrumentationCallbacks);\n";
Steven Moreland40786312016-08-16 10:29:40 -07001081 out.unindent();
1082 out.unindent();
1083 out << "}\n\n";
1084
Andreas Huber881227d2016-08-02 14:20:21 -07001085 out << "::android::status_t " << klassName << "::onTransact(\n";
1086
1087 out.indent();
1088 out.indent();
1089
Iliyan Malchev549e2592016-08-10 08:59:12 -07001090 out << "uint32_t _hidl_code,\n"
1091 << "const ::android::hardware::Parcel &_hidl_data,\n"
1092 << "::android::hardware::Parcel *_hidl_reply,\n"
1093 << "uint32_t _hidl_flags,\n"
1094 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001095
1096 out.unindent();
1097
Iliyan Malchev549e2592016-08-10 08:59:12 -07001098 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001099 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001100 out.indent();
1101
1102 const Interface *iface = mRootScope->getInterface();
1103
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001104 std::vector<const Interface *> chain;
1105 while (iface != NULL) {
1106 chain.push_back(iface);
1107 iface = iface->superType();
1108 }
Andreas Huber881227d2016-08-02 14:20:21 -07001109
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001110 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1111 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001112
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001113 for (const auto &method : superInterface->methods()) {
1114 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001115 << superInterface->fqName().cppNamespace()
1116 << "::IHw"
1117 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001118 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001119 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001120 << ":\n{\n";
1121
1122 out.indent();
1123
1124 status_t err =
1125 generateStubSourceForMethod(out, superInterface, method);
1126
1127 if (err != OK) {
1128 return err;
1129 }
1130
1131 out.unindent();
1132 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001133 }
Andreas Huber881227d2016-08-02 14:20:21 -07001134 }
1135
1136 out << "default:\n{\n";
1137 out.indent();
1138
Andreas Huber8a82ff72016-08-04 10:29:39 -07001139 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001140 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001141 << ">::onTransact(\n";
1142
1143 out.indent();
1144 out.indent();
1145
Iliyan Malchev549e2592016-08-10 08:59:12 -07001146 out << "_hidl_code, _hidl_data, _hidl_reply, "
1147 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001148
1149 out.unindent();
1150 out.unindent();
1151
1152 out.unindent();
1153 out << "}\n";
1154
1155 out.unindent();
1156 out << "}\n\n";
1157
Iliyan Malchev549e2592016-08-10 08:59:12 -07001158 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001159 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001160 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001161 out.indent();
1162 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001163 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001164 out.indent();
1165 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001166 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001167 out.unindent();
1168 out.unindent();
1169 out.unindent();
1170 out.unindent();
1171
1172 out.unindent();
1173 out << "}\n\n";
1174
Iliyan Malchev549e2592016-08-10 08:59:12 -07001175 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001176
1177 out.unindent();
1178 out << "}\n\n";
1179
1180 return OK;
1181}
1182
1183status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001184 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001185 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001186 << iface->fqName().cppNamespace()
1187 << "::IHw"
1188 << iface->getBaseName()
1189 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001190
Andreas Huber881227d2016-08-02 14:20:21 -07001191 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001192 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001193 out << "break;\n";
1194 out.unindent();
1195 out << "}\n\n";
1196
Andreas Hubere7ff2282016-08-16 13:50:03 -07001197 declareCppReaderLocals(out, method->args());
1198
Andreas Huber881227d2016-08-02 14:20:21 -07001199 for (const auto &arg : method->args()) {
1200 emitCppReaderWriter(
1201 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001202 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001203 false /* parcelObjIsPointer */,
1204 arg,
1205 true /* reader */,
1206 Type::ErrorMode_Break);
1207 }
1208
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001209 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1210 out.indent();
1211 out << "std::vector<void *> args;\n";
1212 for (const auto &arg : method->args()) {
1213 out << "args.push_back((void *)"
1214 << (arg->type().resultNeedsDeref() ? "" : "&")
1215 << arg->name()
1216 << ");\n";
1217 }
1218
1219 out << "for (auto callback: instrumentationCallbacks) {\n";
1220 out.indent();
1221 out << "callback(InstrumentationEvent::SERVER_API_ENTRY, \""
1222 << mPackage.package()
1223 << "\", \"" << mPackage.version().substr(1) << "\", \""
1224 << iface->localName() << "\", \"" << method->name() << "\", &args);\n";
1225 out.unindent();
1226 out << "}\n";
1227 out.unindent();
1228 out << "}\n\n";
1229
Andreas Huber881227d2016-08-02 14:20:21 -07001230 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001231 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001232
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001233 if (elidedReturn != nullptr) {
1234 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001235
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001236 out << elidedReturn->type().getCppResultType(&extra) << " ";
1237 out << elidedReturn->name() << " = ";
1238 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001239
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001240 bool first = true;
1241 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001242 if (!first) {
1243 out << ", ";
1244 }
1245
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001246 if (arg->type().resultNeedsDeref()) {
1247 out << "*";
1248 }
1249
1250 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001251
1252 first = false;
1253 }
1254
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001255 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001256 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001257 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001258
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001259 elidedReturn->type().emitReaderWriter(
1260 out,
1261 elidedReturn->name(),
1262 "_hidl_reply",
1263 true, /* parcelObjIsPointer */
1264 false, /* isReader */
1265 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001266
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001267 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1268 out.indent();
1269 out << "std::vector<void *> results;\n";
1270 out << "results.push_back((void *)&" << elidedReturn->name() << ");\n";
1271
1272 out << "for (auto callback: instrumentationCallbacks) {\n";
1273 out.indent();
1274 out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
1275 << mPackage.package()
1276 << "\", \"" << mPackage.version().substr(1) << "\", \""
1277 << iface->localName() << "\", \"" << method->name()
1278 << "\", &results);\n";
1279 out.unindent();
1280 out << "}\n";
1281 out.unindent();
1282 out << "}\n\n";
1283
Iliyan Malchev549e2592016-08-10 08:59:12 -07001284 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001285 } else {
1286 if (returnsValue) {
1287 out << "bool _hidl_callbackCalled = false;\n\n";
1288 }
Andreas Huber881227d2016-08-02 14:20:21 -07001289
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001290 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001291
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001292 bool first = true;
1293 for (const auto &arg : method->args()) {
1294 if (!first) {
1295 out << ", ";
1296 }
Andreas Huber881227d2016-08-02 14:20:21 -07001297
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001298 if (arg->type().resultNeedsDeref()) {
1299 out << "*";
1300 }
1301
1302 out << arg->name();
1303
1304 first = false;
1305 }
1306
1307 if (returnsValue) {
1308 if (!first) {
1309 out << ", ";
1310 }
1311
1312 out << "[&](";
1313
1314 first = true;
1315 for (const auto &arg : method->results()) {
1316 if (!first) {
1317 out << ", ";
1318 }
1319
1320 out << "const auto &" << arg->name();
1321
1322 first = false;
1323 }
1324
1325 out << ") {\n";
1326 out.indent();
1327 out << "_hidl_callbackCalled = true;\n\n";
1328
1329 out << "::android::hardware::Status::ok()"
1330 << ".writeToParcel(_hidl_reply);\n\n";
1331
1332 for (const auto &arg : method->results()) {
1333 emitCppReaderWriter(
1334 out,
1335 "_hidl_reply",
1336 true /* parcelObjIsPointer */,
1337 arg,
1338 false /* reader */,
1339 Type::ErrorMode_Ignore);
1340 }
1341
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001342 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1343 out.indent();
1344 out << "std::vector<void *> results;\n";
1345 for (const auto &arg : method->results()) {
1346 out << "results.push_back((void *)&" << arg->name() << ");\n";
1347 }
1348
1349 out << "for (auto callback: instrumentationCallbacks) {\n";
1350 out.indent();
1351 out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
1352 << mPackage.package()
1353 << "\", \"" << mPackage.version().substr(1) << "\", \""
1354 << iface->localName() << "\", \"" << method->name()
1355 << "\", &results);\n";
1356 out.unindent();
1357 out << "}\n";
1358 out.unindent();
1359 out << "}\n\n";
1360
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001361 out << "_hidl_cb(*_hidl_reply);\n";
1362
1363 out.unindent();
1364 out << "}\n";
1365 }
1366
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001367 out << ");\n\n";
1368
1369 // What to do if the stub implementation has a synchronous callback
1370 // which does not get invoked? This is not a transport error but a
1371 // service error of sorts. For now, return OK to the caller, as this is
1372 // not a transport error.
1373 //
1374 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001375
1376 if (returnsValue) {
1377 out << "if (!_hidl_callbackCalled) {\n";
1378 out.indent();
1379 }
1380
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001381 out << "::android::hardware::Status::ok()"
1382 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001383
1384 if (returnsValue) {
1385 out.unindent();
1386 out << "}\n\n";
1387 }
Andreas Huber881227d2016-08-02 14:20:21 -07001388 }
1389
1390 out << "break;\n";
1391
1392 return OK;
1393}
1394
Steven Moreland69e7c702016-09-09 11:16:32 -07001395status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1396 std::string ifaceName;
1397 if (!AST::isInterface(&ifaceName)) {
1398 // types.hal does not get a stub header.
1399 return OK;
1400 }
1401
1402 const Interface *iface = mRootScope->getInterface();
1403
1404 const std::string baseName = iface->getBaseName();
1405 const std::string klassName = "Bs" + baseName;
1406
1407 bool supportOneway = iface->hasOnewayMethods();
1408
1409 std::string path = outputPath;
1410 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1411 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1412 path.append(klassName);
1413 path.append(".h");
1414
1415 CHECK(Coordinator::MakeParentHierarchy(path));
1416 FILE *file = fopen(path.c_str(), "w");
1417
1418 if (file == NULL) {
1419 return -errno;
1420 }
1421
1422 Formatter out(file);
1423
1424 const std::string guard = makeHeaderGuard(klassName);
1425
1426 out << "#ifndef " << guard << "\n";
1427 out << "#define " << guard << "\n\n";
1428
1429 std::vector<std::string> packageComponents;
1430 getPackageAndVersionComponents(
1431 &packageComponents, false /* cpp_compatible */);
1432
1433 out << "#include <future>\n";
1434 out << "#include <";
1435 for (const auto &component : packageComponents) {
1436 out << component << "/";
1437 }
1438 out << ifaceName << ".h>\n\n";
1439
1440 if (supportOneway) {
1441 out << "#include <hidl/SynchronizedQueue.h>\n";
1442 }
1443
1444 enterLeaveNamespace(out, true /* enter */);
1445 out << "\n";
1446
1447 out << "struct "
1448 << klassName
1449 << " : " << ifaceName
1450 << " {\n";
1451
1452 out.indent();
1453 out << "explicit "
1454 << klassName
1455 << "(const sp<"
1456 << ifaceName
1457 << "> impl);\n";
1458
1459 status_t err = generateMethods(out,
1460 "" /* class name */,
1461 MethodLocation::PASSTHROUGH_HEADER,
1462 true /* specify namespaces */);
1463
1464 if (err != OK) {
1465 return err;
1466 }
1467
1468 out.unindent();
1469 out << "private:\n";
1470 out.indent();
1471 out << "const sp<" << ifaceName << "> mImpl;\n";
1472
1473 if (supportOneway) {
1474 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1475 out << "std::thread *mOnewayThread = nullptr;\n";
1476
1477 out << "\n";
1478
1479 out << "::android::hardware::Return<void> addOnewayTask("
1480 "std::function<void(void)>);\n\n";
1481
1482 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1483 }
1484
1485 out.unindent();
1486
1487 out << "};\n\n";
1488
1489 enterLeaveNamespace(out, false /* enter */);
1490
1491 out << "\n#endif // " << guard << "\n";
1492
1493 return OK;
1494}
1495
1496
1497status_t AST::generatePassthroughSource(Formatter &out) const {
1498 const Interface *iface = mRootScope->getInterface();
1499
1500 const std::string baseName = iface->getBaseName();
1501 const std::string klassName = "Bs" + baseName;
1502
1503 out << klassName
1504 << "::"
1505 << klassName
1506 << "(const sp<"
1507 << iface->fullName()
1508 << "> impl) : mImpl(impl) {}\n\n";
1509
1510 if (iface->hasOnewayMethods()) {
1511 out << "::android::hardware::Return<void> "
1512 << klassName
1513 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1514 out.indent();
1515 out << "if (mOnewayThread == nullptr) {\n";
1516 out.indent();
1517 out << "mOnewayThread = new std::thread([this]() {\n";
1518 out.indent();
1519 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1520 out.unindent();
1521 out << "});\n";
1522 out.unindent();
1523 out << "}\n\n";
1524
1525 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1526 out.indent();
1527 out << "return Status::fromExceptionCode(Status::EX_TRANSACTION_FAILED);\n";
1528 out.unindent();
1529 out << "} else {\n";
1530 out.indent();
1531 out << "mOnewayQueue.push(fun);\n";
1532 out.unindent();
1533 out << "}\n";
1534
1535 out << "return Status();\n";
1536
1537 out.unindent();
1538 out << "}\n\n";
1539
1540
1541 }
1542
1543 return OK;
1544}
1545
Andreas Huber881227d2016-08-02 14:20:21 -07001546} // namespace android
1547