blob: 3b9320a68411d6d8b70e97ae55646e9b3c810c2e [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
Yifan Hongbf459bc2016-08-23 16:50:37 -0700897void AST::emitCppResolveReferences(
898 Formatter &out,
899 const std::string &parcelObj,
900 bool parcelObjIsPointer,
901 const TypedVar *arg,
902 bool isReader,
903 Type::ErrorMode mode,
904 bool addPrefixToName) const {
905 const Type &type = arg->type();
906 if(type.needsResolveReferences()) {
907 type.emitResolveReferences(
908 out,
909 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
910 isReader, // nameIsPointer
911 parcelObj,
912 parcelObjIsPointer,
913 isReader,
914 mode);
915 }
916}
917
Andreas Huber881227d2016-08-02 14:20:21 -0700918status_t AST::generateProxySource(
919 Formatter &out, const std::string &baseName) const {
920 const std::string klassName = "Bp" + baseName;
921
922 out << klassName
923 << "::"
924 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700925 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700926
927 out.indent();
928 out.indent();
929
930 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700931 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700932 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700933 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700934
935 out.unindent();
936 out.unindent();
937 out << "}\n\n";
938
939 const Interface *iface = mRootScope->getInterface();
940
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700941 std::vector<const Interface *> chain;
942 while (iface != NULL) {
943 chain.push_back(iface);
944 iface = iface->superType();
945 }
Andreas Huber881227d2016-08-02 14:20:21 -0700946
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700947 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
948 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700949
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700950 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700951 method->generateCppSignature(out,
952 klassName,
953 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700954
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700955 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700956 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700957
Steven Morelanda7a421a2016-09-07 08:35:18 -0700958 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700959
960 out.indent();
961
Iliyan Malchev549e2592016-08-10 08:59:12 -0700962 out << "::android::hardware::Parcel _hidl_data;\n";
963 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700964 out << "::android::status_t _hidl_err;\n";
965 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Huber5e44a292016-09-27 14:52:39 -0700966
967 declareCppReaderLocals(
968 out, method->results(), true /* forResults */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700969
Iliyan Malchev549e2592016-08-10 08:59:12 -0700970 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700971 << superInterface->fqName().cppNamespace()
972 << "::IHw"
973 << superInterface->getBaseName()
974 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700975
Iliyan Malchev549e2592016-08-10 08:59:12 -0700976 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700977
Yifan Hongbf459bc2016-08-23 16:50:37 -0700978 // First DFS: write all buffers and resolve pointers for parent
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700979 for (const auto &arg : method->args()) {
980 emitCppReaderWriter(
981 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700982 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700983 false /* parcelObjIsPointer */,
984 arg,
985 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -0700986 Type::ErrorMode_Goto,
987 false /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700988 }
989
Yifan Hongbf459bc2016-08-23 16:50:37 -0700990 // Second DFS: resolve references.
991 for (const auto &arg : method->args()) {
992 emitCppResolveReferences(
993 out,
994 "_hidl_data",
995 false /* parcelObjIsPointer */,
996 arg,
997 false /* reader */,
998 Type::ErrorMode_Goto,
999 false /* addPrefixToName */);
1000 }
1001
Steven Moreland40786312016-08-16 10:29:40 -07001002 out << "_hidl_err = remote()->transact("
1003 << superInterface->fqName().cppNamespace()
1004 << "::IHw"
1005 << superInterface->getBaseName()
1006 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001007 << StringHelper::Upcase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -07001008 << ", _hidl_data, &_hidl_reply";
1009 if (method->isOneway()) {
1010 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001011 }
Iliyan Malchev639bff82016-08-13 14:24:11 -07001012 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001013
Iliyan Malchev639bff82016-08-13 14:24:11 -07001014 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001015
Iliyan Malchev639bff82016-08-13 14:24:11 -07001016 if (!method->isOneway()) {
1017 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
1018 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -07001019 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1020
Yifan Hongbf459bc2016-08-23 16:50:37 -07001021
1022 // First DFS: write all buffers and resolve pointers for parent
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001023 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -07001024 emitCppReaderWriter(
1025 out,
1026 "_hidl_reply",
1027 false /* parcelObjIsPointer */,
1028 arg,
1029 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001030 Type::ErrorMode_Goto,
1031 true /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001032 }
1033
Yifan Hongbf459bc2016-08-23 16:50:37 -07001034 // Second DFS: resolve references.
1035 for (const auto &arg : method->results()) {
1036 emitCppResolveReferences(
1037 out,
1038 "_hidl_reply",
1039 false /* parcelObjIsPointer */,
1040 arg,
1041 true /* reader */,
1042 Type::ErrorMode_Goto,
1043 true /* addPrefixToName */);
1044 }
1045
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001046 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -07001047 out << "if (_hidl_cb != nullptr) {\n";
1048 out.indent();
1049 out << "_hidl_cb(";
1050
1051 bool first = true;
1052 for (const auto &arg : method->results()) {
1053 if (!first) {
1054 out << ", ";
1055 }
1056
1057 if (arg->type().resultNeedsDeref()) {
1058 out << "*";
1059 }
Andreas Huber5e44a292016-09-27 14:52:39 -07001060 out << "_hidl_out_" << arg->name();
Iliyan Malchev639bff82016-08-13 14:24:11 -07001061
1062 first = false;
1063 }
1064
1065 out << ");\n";
1066 out.unindent();
1067 out << "}\n\n";
1068 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001069 }
1070
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001071 if (elidedReturn != nullptr) {
1072 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001073 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001074 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001075 out << elidedReturn->type().getCppResultType(&extra)
Andreas Huber5e44a292016-09-27 14:52:39 -07001076 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001077 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001078 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001079 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001080 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001081
Andreas Huber881227d2016-08-02 14:20:21 -07001082 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001083 out << "_hidl_error:\n";
1084 out.indent();
1085 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1086 out << "return ::android::hardware::Return<";
1087 if (elidedReturn != nullptr) {
1088 std::string extra;
1089 out << method->results().at(0)->type().getCppResultType(&extra);
1090 } else {
1091 out << "void";
1092 }
1093 out << ">(_hidl_status);\n";
1094
1095 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001096 out << "}\n\n";
1097 }
Andreas Huber881227d2016-08-02 14:20:21 -07001098 }
1099
1100 return OK;
1101}
1102
1103status_t AST::generateStubSource(
1104 Formatter &out, const std::string &baseName) const {
1105 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1106 << baseName
1107 << ", \""
1108 << mPackage.string()
1109 << "::I"
1110 << baseName
1111 << "\");\n\n";
1112
1113 const std::string klassName = "Bn" + baseName;
1114
Steven Moreland40786312016-08-16 10:29:40 -07001115 out << klassName
1116 << "::"
1117 << klassName
1118 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1119
1120 out.indent();
1121 out.indent();
1122
1123 out << ": BnInterface"
1124 << "<I"
1125 << baseName
1126 << ", IHw"
1127 << baseName
1128 << ">(_hidl_impl) {\n";
1129
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001130 out << "enableInstrumentation = "
1131 "property_get_bool(\"hal.instrumentation.enable\", false);\n";
1132 out << "registerInstrumentationCallbacks(\""
1133 << mPackage.string()
1134 << "::I"
1135 << baseName
1136 << "\", &instrumentationCallbacks);\n";
Steven Moreland40786312016-08-16 10:29:40 -07001137 out.unindent();
1138 out.unindent();
1139 out << "}\n\n";
1140
Andreas Huber881227d2016-08-02 14:20:21 -07001141 out << "::android::status_t " << klassName << "::onTransact(\n";
1142
1143 out.indent();
1144 out.indent();
1145
Iliyan Malchev549e2592016-08-10 08:59:12 -07001146 out << "uint32_t _hidl_code,\n"
1147 << "const ::android::hardware::Parcel &_hidl_data,\n"
1148 << "::android::hardware::Parcel *_hidl_reply,\n"
1149 << "uint32_t _hidl_flags,\n"
1150 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001151
1152 out.unindent();
1153
Iliyan Malchev549e2592016-08-10 08:59:12 -07001154 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001155 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001156 out.indent();
1157
1158 const Interface *iface = mRootScope->getInterface();
1159
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001160 std::vector<const Interface *> chain;
1161 while (iface != NULL) {
1162 chain.push_back(iface);
1163 iface = iface->superType();
1164 }
Andreas Huber881227d2016-08-02 14:20:21 -07001165
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001166 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1167 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001168
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001169 for (const auto &method : superInterface->methods()) {
1170 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001171 << superInterface->fqName().cppNamespace()
1172 << "::IHw"
1173 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001174 << "::Call::"
Steven Morelandaf440142016-09-07 10:09:11 -07001175 << StringHelper::Upcase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001176 << ":\n{\n";
1177
1178 out.indent();
1179
1180 status_t err =
1181 generateStubSourceForMethod(out, superInterface, method);
1182
1183 if (err != OK) {
1184 return err;
1185 }
1186
1187 out.unindent();
1188 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001189 }
Andreas Huber881227d2016-08-02 14:20:21 -07001190 }
1191
1192 out << "default:\n{\n";
1193 out.indent();
1194
Andreas Huber8a82ff72016-08-04 10:29:39 -07001195 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001196 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001197 << ">::onTransact(\n";
1198
1199 out.indent();
1200 out.indent();
1201
Iliyan Malchev549e2592016-08-10 08:59:12 -07001202 out << "_hidl_code, _hidl_data, _hidl_reply, "
1203 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001204
1205 out.unindent();
1206 out.unindent();
1207
1208 out.unindent();
1209 out << "}\n";
1210
1211 out.unindent();
1212 out << "}\n\n";
1213
Iliyan Malchev549e2592016-08-10 08:59:12 -07001214 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001215 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001216 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001217 out.indent();
1218 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001219 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001220 out.indent();
1221 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001222 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001223 out.unindent();
1224 out.unindent();
1225 out.unindent();
1226 out.unindent();
1227
1228 out.unindent();
1229 out << "}\n\n";
1230
Iliyan Malchev549e2592016-08-10 08:59:12 -07001231 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001232
1233 out.unindent();
1234 out << "}\n\n";
1235
1236 return OK;
1237}
1238
1239status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001240 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001241 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001242 << iface->fqName().cppNamespace()
1243 << "::IHw"
1244 << iface->getBaseName()
1245 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001246
Andreas Huber881227d2016-08-02 14:20:21 -07001247 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001248 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001249 out << "break;\n";
1250 out.unindent();
1251 out << "}\n\n";
1252
Andreas Huber5e44a292016-09-27 14:52:39 -07001253 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001254
Yifan Hongbf459bc2016-08-23 16:50:37 -07001255 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001256 for (const auto &arg : method->args()) {
1257 emitCppReaderWriter(
1258 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001259 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001260 false /* parcelObjIsPointer */,
1261 arg,
1262 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001263 Type::ErrorMode_Break,
1264 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001265 }
1266
Yifan Hongbf459bc2016-08-23 16:50:37 -07001267 // Second DFS: resolve references
1268 for (const auto &arg : method->args()) {
1269 emitCppResolveReferences(
1270 out,
1271 "_hidl_data",
1272 false /* parcelObjIsPointer */,
1273 arg,
1274 true /* reader */,
1275 Type::ErrorMode_Break,
1276 false /* addPrefixToName */);
1277 }
1278
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001279 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1280 out.indent();
1281 out << "std::vector<void *> args;\n";
1282 for (const auto &arg : method->args()) {
1283 out << "args.push_back((void *)"
1284 << (arg->type().resultNeedsDeref() ? "" : "&")
1285 << arg->name()
1286 << ");\n";
1287 }
1288
1289 out << "for (auto callback: instrumentationCallbacks) {\n";
1290 out.indent();
1291 out << "callback(InstrumentationEvent::SERVER_API_ENTRY, \""
1292 << mPackage.package()
1293 << "\", \"" << mPackage.version().substr(1) << "\", \""
1294 << iface->localName() << "\", \"" << method->name() << "\", &args);\n";
1295 out.unindent();
1296 out << "}\n";
1297 out.unindent();
1298 out << "}\n\n";
1299
Andreas Huber881227d2016-08-02 14:20:21 -07001300 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001301 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001302
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001303 if (elidedReturn != nullptr) {
1304 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001305
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001306 out << elidedReturn->type().getCppResultType(&extra) << " ";
1307 out << elidedReturn->name() << " = ";
1308 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001309
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001310 bool first = true;
1311 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001312 if (!first) {
1313 out << ", ";
1314 }
1315
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001316 if (arg->type().resultNeedsDeref()) {
1317 out << "*";
1318 }
1319
1320 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001321
1322 first = false;
1323 }
1324
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001325 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001326 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001327 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001328
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001329 elidedReturn->type().emitReaderWriter(
1330 out,
1331 elidedReturn->name(),
1332 "_hidl_reply",
1333 true, /* parcelObjIsPointer */
1334 false, /* isReader */
1335 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001336
Yifan Hongbf459bc2016-08-23 16:50:37 -07001337 emitCppResolveReferences(
1338 out,
1339 "_hidl_reply",
1340 true /* parcelObjIsPointer */,
1341 elidedReturn,
1342 false /* reader */,
1343 Type::ErrorMode_Ignore,
1344 false /* addPrefixToName */);
1345
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001346 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1347 out.indent();
1348 out << "std::vector<void *> results;\n";
1349 out << "results.push_back((void *)&" << elidedReturn->name() << ");\n";
1350
1351 out << "for (auto callback: instrumentationCallbacks) {\n";
1352 out.indent();
1353 out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
1354 << mPackage.package()
1355 << "\", \"" << mPackage.version().substr(1) << "\", \""
1356 << iface->localName() << "\", \"" << method->name()
1357 << "\", &results);\n";
1358 out.unindent();
1359 out << "}\n";
1360 out.unindent();
1361 out << "}\n\n";
1362
Iliyan Malchev549e2592016-08-10 08:59:12 -07001363 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001364 } else {
1365 if (returnsValue) {
1366 out << "bool _hidl_callbackCalled = false;\n\n";
1367 }
Andreas Huber881227d2016-08-02 14:20:21 -07001368
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001369 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001370
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001371 bool first = true;
1372 for (const auto &arg : method->args()) {
1373 if (!first) {
1374 out << ", ";
1375 }
Andreas Huber881227d2016-08-02 14:20:21 -07001376
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001377 if (arg->type().resultNeedsDeref()) {
1378 out << "*";
1379 }
1380
1381 out << arg->name();
1382
1383 first = false;
1384 }
1385
1386 if (returnsValue) {
1387 if (!first) {
1388 out << ", ";
1389 }
1390
1391 out << "[&](";
1392
1393 first = true;
1394 for (const auto &arg : method->results()) {
1395 if (!first) {
1396 out << ", ";
1397 }
1398
1399 out << "const auto &" << arg->name();
1400
1401 first = false;
1402 }
1403
1404 out << ") {\n";
1405 out.indent();
1406 out << "_hidl_callbackCalled = true;\n\n";
1407
1408 out << "::android::hardware::Status::ok()"
1409 << ".writeToParcel(_hidl_reply);\n\n";
1410
Yifan Hongbf459bc2016-08-23 16:50:37 -07001411 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001412 for (const auto &arg : method->results()) {
1413 emitCppReaderWriter(
1414 out,
1415 "_hidl_reply",
1416 true /* parcelObjIsPointer */,
1417 arg,
1418 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001419 Type::ErrorMode_Ignore,
1420 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001421 }
1422
Yifan Hongbf459bc2016-08-23 16:50:37 -07001423 // Second DFS: resolve references
1424 for (const auto &arg : method->results()) {
1425 emitCppResolveReferences(
1426 out,
1427 "_hidl_reply",
1428 true /* parcelObjIsPointer */,
1429 arg,
1430 false /* reader */,
1431 Type::ErrorMode_Ignore,
1432 false /* addPrefixToName */);
1433 }
1434
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001435 out << "if (UNLIKELY(enableInstrumentation)) {\n";
1436 out.indent();
1437 out << "std::vector<void *> results;\n";
1438 for (const auto &arg : method->results()) {
1439 out << "results.push_back((void *)&" << arg->name() << ");\n";
1440 }
1441
1442 out << "for (auto callback: instrumentationCallbacks) {\n";
1443 out.indent();
1444 out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
1445 << mPackage.package()
1446 << "\", \"" << mPackage.version().substr(1) << "\", \""
1447 << iface->localName() << "\", \"" << method->name()
1448 << "\", &results);\n";
1449 out.unindent();
1450 out << "}\n";
1451 out.unindent();
1452 out << "}\n\n";
1453
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001454 out << "_hidl_cb(*_hidl_reply);\n";
1455
1456 out.unindent();
1457 out << "}\n";
1458 }
1459
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001460 out << ");\n\n";
1461
1462 // What to do if the stub implementation has a synchronous callback
1463 // which does not get invoked? This is not a transport error but a
1464 // service error of sorts. For now, return OK to the caller, as this is
1465 // not a transport error.
1466 //
1467 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001468
1469 if (returnsValue) {
1470 out << "if (!_hidl_callbackCalled) {\n";
1471 out.indent();
1472 }
1473
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001474 out << "::android::hardware::Status::ok()"
1475 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001476
1477 if (returnsValue) {
1478 out.unindent();
1479 out << "}\n\n";
1480 }
Andreas Huber881227d2016-08-02 14:20:21 -07001481 }
1482
1483 out << "break;\n";
1484
1485 return OK;
1486}
1487
Steven Moreland69e7c702016-09-09 11:16:32 -07001488status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1489 std::string ifaceName;
1490 if (!AST::isInterface(&ifaceName)) {
1491 // types.hal does not get a stub header.
1492 return OK;
1493 }
1494
1495 const Interface *iface = mRootScope->getInterface();
1496
1497 const std::string baseName = iface->getBaseName();
1498 const std::string klassName = "Bs" + baseName;
1499
1500 bool supportOneway = iface->hasOnewayMethods();
1501
1502 std::string path = outputPath;
1503 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1504 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1505 path.append(klassName);
1506 path.append(".h");
1507
1508 CHECK(Coordinator::MakeParentHierarchy(path));
1509 FILE *file = fopen(path.c_str(), "w");
1510
1511 if (file == NULL) {
1512 return -errno;
1513 }
1514
1515 Formatter out(file);
1516
1517 const std::string guard = makeHeaderGuard(klassName);
1518
1519 out << "#ifndef " << guard << "\n";
1520 out << "#define " << guard << "\n\n";
1521
1522 std::vector<std::string> packageComponents;
1523 getPackageAndVersionComponents(
1524 &packageComponents, false /* cpp_compatible */);
1525
1526 out << "#include <future>\n";
1527 out << "#include <";
1528 for (const auto &component : packageComponents) {
1529 out << component << "/";
1530 }
1531 out << ifaceName << ".h>\n\n";
1532
1533 if (supportOneway) {
1534 out << "#include <hidl/SynchronizedQueue.h>\n";
1535 }
1536
1537 enterLeaveNamespace(out, true /* enter */);
1538 out << "\n";
1539
1540 out << "struct "
1541 << klassName
1542 << " : " << ifaceName
1543 << " {\n";
1544
1545 out.indent();
1546 out << "explicit "
1547 << klassName
1548 << "(const sp<"
1549 << ifaceName
1550 << "> impl);\n";
1551
1552 status_t err = generateMethods(out,
1553 "" /* class name */,
1554 MethodLocation::PASSTHROUGH_HEADER,
1555 true /* specify namespaces */);
1556
1557 if (err != OK) {
1558 return err;
1559 }
1560
1561 out.unindent();
1562 out << "private:\n";
1563 out.indent();
1564 out << "const sp<" << ifaceName << "> mImpl;\n";
1565
1566 if (supportOneway) {
1567 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1568 out << "std::thread *mOnewayThread = nullptr;\n";
1569
1570 out << "\n";
1571
1572 out << "::android::hardware::Return<void> addOnewayTask("
1573 "std::function<void(void)>);\n\n";
1574
1575 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1576 }
1577
1578 out.unindent();
1579
1580 out << "};\n\n";
1581
1582 enterLeaveNamespace(out, false /* enter */);
1583
1584 out << "\n#endif // " << guard << "\n";
1585
1586 return OK;
1587}
1588
1589
1590status_t AST::generatePassthroughSource(Formatter &out) const {
1591 const Interface *iface = mRootScope->getInterface();
1592
1593 const std::string baseName = iface->getBaseName();
1594 const std::string klassName = "Bs" + baseName;
1595
1596 out << klassName
1597 << "::"
1598 << klassName
1599 << "(const sp<"
1600 << iface->fullName()
1601 << "> impl) : mImpl(impl) {}\n\n";
1602
1603 if (iface->hasOnewayMethods()) {
1604 out << "::android::hardware::Return<void> "
1605 << klassName
1606 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1607 out.indent();
1608 out << "if (mOnewayThread == nullptr) {\n";
1609 out.indent();
1610 out << "mOnewayThread = new std::thread([this]() {\n";
1611 out.indent();
1612 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1613 out.unindent();
1614 out << "});\n";
1615 out.unindent();
1616 out << "}\n\n";
1617
1618 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1619 out.indent();
1620 out << "return Status::fromExceptionCode(Status::EX_TRANSACTION_FAILED);\n";
1621 out.unindent();
1622 out << "} else {\n";
1623 out.indent();
1624 out << "mOnewayQueue.push(fun);\n";
1625 out.unindent();
1626 out << "}\n";
1627
1628 out << "return Status();\n";
1629
1630 out.unindent();
1631 out << "}\n\n";
1632
1633
1634 }
1635
1636 return OK;
1637}
1638
Andreas Huber881227d2016-08-02 14:20:21 -07001639} // namespace android
1640