blob: 680a7b830a469ebb81d5ec15841df3c75db7e4f3 [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
Steven Moreland67f67b42016-09-29 08:59:02 -0700254 out << method->name() << "_cb _hidl_cb";
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()) {
Yifan Hong42009032016-09-29 09:38:15 -0700371 out << StringHelper::Uppercase(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
Steven Moreland67f67b42016-09-29 08:59:02 -0700477 if (returnsValue && elidedReturn == nullptr) {
478 generateCheckNonNull(out, "_hidl_cb");
479 }
480
Steven Moreland69e7c702016-09-09 11:16:32 -0700481 out << "return ";
482
483 if (method->isOneway()) {
484 out << "addOnewayTask([this";
485 for (const auto &arg : method->args()) {
486 out << ", " << arg->name();
487 }
488 out << "] {this->";
489 }
490
491 out << "mImpl->"
492 << method->name()
493 << "(";
494
495 bool first = true;
496 for (const auto &arg : method->args()) {
497 if (!first) {
498 out << ", ";
499 }
500 first = false;
501 out << arg->name();
502 }
503 if (returnsValue && elidedReturn == nullptr) {
504 if (!method->args().empty()) {
505 out << ", ";
506 }
507
508 out << "_hidl_cb";
509 }
510 out << ")";
511
512 if (method->isOneway()) {
513 out << ";})";
514 }
515 out << ";\n";
516
517 out.unindent();
518 out << "}\n";
519
520 return OK;
521}
522
Steven Morelanda7a421a2016-09-07 08:35:18 -0700523status_t AST::generateMethods(
524 Formatter &out,
525 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700526 MethodLocation type,
527 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700528
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700529 const Interface *iface = mRootScope->getInterface();
530
531 std::vector<const Interface *> chain;
532 while (iface != NULL) {
533 chain.push_back(iface);
534 iface = iface->superType();
535 }
536
537 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
538 const Interface *superInterface = *it;
539
540 out << "// Methods from "
541 << superInterface->fullName()
542 << " follow.\n";
543
544 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700545 status_t err;
546 switch(type) {
547 case STUB_HEADER:
548 err = generateStubMethod(out,
549 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700550 method,
551 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700552 break;
553 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700554 err = generateProxyDeclaration(out,
555 className,
556 method,
557 specifyNamespaces);
558 break;
559 case IMPL_HEADER:
560 err = generateStubImplDeclaration(out,
561 className,
562 method,
563 specifyNamespaces);
564 break;
565 case IMPL_SOURCE:
566 err = generateStubImplMethod(out,
567 className,
568 method,
569 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700570 break;
Steven Moreland69e7c702016-09-09 11:16:32 -0700571 case PASSTHROUGH_HEADER:
572 err = generatePassthroughMethod(out,
573 className,
574 method,
575 specifyNamespaces);
576 break;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700577 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700578 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700579 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700580 }
581
Steven Morelanda7a421a2016-09-07 08:35:18 -0700582 if (err != OK) {
583 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700584 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700585 }
586
587 out << "\n";
588 }
589
590 return OK;
591}
592
Andreas Huberb82318c2016-08-02 14:45:54 -0700593status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700594 std::string ifaceName;
595 if (!AST::isInterface(&ifaceName)) {
596 // types.hal does not get a stub header.
597 return OK;
598 }
599
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700600 const Interface *iface = mRootScope->getInterface();
601 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700602 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700603
Andreas Huberb82318c2016-08-02 14:45:54 -0700604 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700605 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700606 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700607 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700608 path.append(".h");
609
Andreas Huberd2943e12016-08-05 11:59:31 -0700610 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700611 FILE *file = fopen(path.c_str(), "w");
612
613 if (file == NULL) {
614 return -errno;
615 }
616
617 Formatter out(file);
618
Steven Moreland40786312016-08-16 10:29:40 -0700619 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700620
621 out << "#ifndef " << guard << "\n";
622 out << "#define " << guard << "\n\n";
623
624 std::vector<std::string> packageComponents;
625 getPackageAndVersionComponents(
626 &packageComponents, false /* cpp_compatible */);
627
628 out << "#include <";
629 for (const auto &component : packageComponents) {
630 out << component << "/";
631 }
Steven Moreland40786312016-08-16 10:29:40 -0700632 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700633
634 enterLeaveNamespace(out, true /* enter */);
635 out << "\n";
636
637 out << "struct "
638 << "Bn"
639 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700640 << " : public ::android::hardware::BnInterface<I"
641 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700642 << "> {\n";
643
644 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700645 out << "explicit Bn"
646 << baseName
647 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
648 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700649 out << "::android::status_t onTransact(\n";
650 out.indent();
651 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700652 out << "uint32_t _hidl_code,\n";
653 out << "const ::android::hardware::Parcel &_hidl_data,\n";
654 out << "::android::hardware::Parcel *_hidl_reply,\n";
655 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700656 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700657 out.unindent();
658 out.unindent();
659
Steven Moreland9c387612016-09-07 09:54:26 -0700660 status_t err = generateMethods(out,
661 "" /* class name */,
662 MethodLocation::STUB_HEADER,
663 true /* specify namespaces */);
664
665 if (err != OK) {
666 return err;
667 }
668
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700669
Andreas Huber881227d2016-08-02 14:20:21 -0700670 out.unindent();
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700671 out << "private:\n";
672
673 out.indent();
674 emitCppInstrumentationDecl(out);
675 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700676
677 out << "};\n\n";
678
679 enterLeaveNamespace(out, false /* enter */);
680
681 out << "\n#endif // " << guard << "\n";
682
683 return OK;
684}
685
Andreas Huberb82318c2016-08-02 14:45:54 -0700686status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700687 std::string ifaceName;
688 if (!AST::isInterface(&ifaceName)) {
689 // types.hal does not get a proxy header.
690 return OK;
691 }
692
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700693 const Interface *iface = mRootScope->getInterface();
694 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700695
Andreas Huberb82318c2016-08-02 14:45:54 -0700696 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700697 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700698 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700699 path.append("Bp");
700 path.append(baseName);
701 path.append(".h");
702
Andreas Huberd2943e12016-08-05 11:59:31 -0700703 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700704 FILE *file = fopen(path.c_str(), "w");
705
706 if (file == NULL) {
707 return -errno;
708 }
709
710 Formatter out(file);
711
712 const std::string guard = makeHeaderGuard("Bp" + baseName);
713
714 out << "#ifndef " << guard << "\n";
715 out << "#define " << guard << "\n\n";
716
717 std::vector<std::string> packageComponents;
718 getPackageAndVersionComponents(
719 &packageComponents, false /* cpp_compatible */);
720
721 out << "#include <";
722 for (const auto &component : packageComponents) {
723 out << component << "/";
724 }
Steven Moreland40786312016-08-16 10:29:40 -0700725 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700726
727 enterLeaveNamespace(out, true /* enter */);
728 out << "\n";
729
730 out << "struct "
731 << "Bp"
732 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700733 << " : public ::android::hardware::BpInterface<IHw"
734 << baseName
Andreas Huber881227d2016-08-02 14:20:21 -0700735 << "> {\n";
736
737 out.indent();
738
739 out << "explicit Bp"
740 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700741 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700742 << "\n\n";
743
Iliyan Malchev795dd432016-09-02 11:48:26 -0700744 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700745
Steven Moreland9c387612016-09-07 09:54:26 -0700746 status_t err = generateMethods(out,
747 "" /* class name */,
748 MethodLocation::PROXY_HEADER,
749 true /* generate specify namespaces */);
750
751 if (err != OK) {
752 return err;
753 }
Andreas Huber881227d2016-08-02 14:20:21 -0700754
755 out.unindent();
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700756 out << "private:\n";
757
758 out.indent();
759 emitCppInstrumentationDecl(out);
760
761 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700762
763 out << "};\n\n";
764
765 enterLeaveNamespace(out, false /* enter */);
766
767 out << "\n#endif // " << guard << "\n";
768
769 return OK;
770}
771
Andreas Huberb82318c2016-08-02 14:45:54 -0700772status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700773
Andreas Huberb82318c2016-08-02 14:45:54 -0700774 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700775 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700776 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700777
778 std::string ifaceName;
779 std::string baseName;
780
781 bool isInterface = true;
782 if (!AST::isInterface(&ifaceName)) {
783 baseName = "types";
784 isInterface = false;
785 } else {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700786 const Interface *iface = mRootScope->getInterface();
787 baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700788 }
789
790 path.append(baseName);
791
792 if (baseName != "types") {
793 path.append("All");
794 }
795
796 path.append(".cpp");
797
Andreas Huberd2943e12016-08-05 11:59:31 -0700798 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700799 FILE *file = fopen(path.c_str(), "w");
800
801 if (file == NULL) {
802 return -errno;
803 }
804
805 Formatter out(file);
806
807 std::vector<std::string> packageComponents;
808 getPackageAndVersionComponents(
809 &packageComponents, false /* cpp_compatible */);
810
811 std::string prefix;
812 for (const auto &component : packageComponents) {
813 prefix += component;
814 prefix += "/";
815 }
816
817 if (isInterface) {
818 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
819 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700820 out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700821 out << "#include <cutils/properties.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700822 } else {
823 out << "#include <" << prefix << "types.h>\n";
824 }
825
826 out << "\n";
827
828 enterLeaveNamespace(out, true /* enter */);
829 out << "\n";
830
831 status_t err = generateTypeSource(out, ifaceName);
832
833 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200834 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700835 err = generateProxySource(out, baseName);
836 }
837
838 if (err == OK && isInterface) {
839 err = generateStubSource(out, baseName);
840 }
841
Steven Moreland40786312016-08-16 10:29:40 -0700842 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700843 err = generatePassthroughSource(out);
844 }
845
846 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700847 const Interface *iface = mRootScope->getInterface();
848
849 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
850 << baseName << ", "
851 << "\"" << iface->fqName().package()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700852 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700853 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700854 }
855
Andreas Huber881227d2016-08-02 14:20:21 -0700856 enterLeaveNamespace(out, false /* enter */);
857
858 return err;
859}
860
Steven Moreland67f67b42016-09-29 08:59:02 -0700861// static
862void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
863 out << "if (" << nonNull << " == nullptr) {\n";
864 out.indent();
865 out << "return ::android::hardware::Status::fromExceptionCode(\n";
866 out.indent();
867 out.indent();
868 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
869 out.unindent();
870 out.unindent();
871 out.unindent();
872 out << "}\n\n";
873}
874
Andreas Huber881227d2016-08-02 14:20:21 -0700875status_t AST::generateTypeSource(
876 Formatter &out, const std::string &ifaceName) const {
877 return mRootScope->emitTypeDefinitions(out, ifaceName);
878}
879
Andreas Hubere7ff2282016-08-16 13:50:03 -0700880void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700881 Formatter &out,
882 const std::vector<TypedVar *> &args,
883 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700884 if (args.empty()) {
885 return;
886 }
887
888 for (const auto &arg : args) {
889 const Type &type = arg->type();
890
891 std::string extra;
892 out << type.getCppResultType(&extra)
893 << " "
Andreas Huber5e44a292016-09-27 14:52:39 -0700894 << (forResults ? "_hidl_out_" : "")
Andreas Hubere7ff2282016-08-16 13:50:03 -0700895 << arg->name()
896 << extra
897 << ";\n";
898 }
899
900 out << "\n";
901}
902
Andreas Huber881227d2016-08-02 14:20:21 -0700903void AST::emitCppReaderWriter(
904 Formatter &out,
905 const std::string &parcelObj,
906 bool parcelObjIsPointer,
907 const TypedVar *arg,
908 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700909 Type::ErrorMode mode,
910 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700911 const Type &type = arg->type();
912
Andreas Huber881227d2016-08-02 14:20:21 -0700913 type.emitReaderWriter(
914 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700915 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700916 parcelObj,
917 parcelObjIsPointer,
918 isReader,
919 mode);
920}
921
Yifan Hongbf459bc2016-08-23 16:50:37 -0700922void AST::emitCppResolveReferences(
923 Formatter &out,
924 const std::string &parcelObj,
925 bool parcelObjIsPointer,
926 const TypedVar *arg,
927 bool isReader,
928 Type::ErrorMode mode,
929 bool addPrefixToName) const {
930 const Type &type = arg->type();
931 if(type.needsResolveReferences()) {
932 type.emitResolveReferences(
933 out,
934 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
935 isReader, // nameIsPointer
936 parcelObj,
937 parcelObjIsPointer,
938 isReader,
939 mode);
940 }
941}
942
Andreas Huber881227d2016-08-02 14:20:21 -0700943status_t AST::generateProxySource(
944 Formatter &out, const std::string &baseName) const {
945 const std::string klassName = "Bp" + baseName;
946
947 out << klassName
948 << "::"
949 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700950 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700951
952 out.indent();
953 out.indent();
954
955 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700956 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700957 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700958 << ">(_hidl_impl) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700959
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700960 emitCppInstrumentationInit(out, baseName);
961
Andreas Huber881227d2016-08-02 14:20:21 -0700962 out.unindent();
963 out.unindent();
964 out << "}\n\n";
965
966 const Interface *iface = mRootScope->getInterface();
967
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700968 std::vector<const Interface *> chain;
969 while (iface != NULL) {
970 chain.push_back(iface);
971 iface = iface->superType();
972 }
Andreas Huber881227d2016-08-02 14:20:21 -0700973
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700974 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
975 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700976
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700977 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700978 method->generateCppSignature(out,
979 klassName,
980 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700981
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700982 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700983 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700984
Steven Morelanda7a421a2016-09-07 08:35:18 -0700985 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700986
987 out.indent();
988
Steven Moreland67f67b42016-09-29 08:59:02 -0700989 if (returnsValue && elidedReturn == nullptr) {
990 generateCheckNonNull(out, "_hidl_cb");
991 }
992
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700993 status_t status = generateCppInstrumentationCall(
994 out,
995 InstrumentationEvent::CLIENT_API_ENTRY,
996 superInterface,
997 method);
998 if (status != OK) {
999 return status;
1000 }
1001
Iliyan Malchev549e2592016-08-10 08:59:12 -07001002 out << "::android::hardware::Parcel _hidl_data;\n";
1003 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -07001004 out << "::android::status_t _hidl_err;\n";
1005 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Huber5e44a292016-09-27 14:52:39 -07001006
1007 declareCppReaderLocals(
1008 out, method->results(), true /* forResults */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001009
Iliyan Malchev549e2592016-08-10 08:59:12 -07001010 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -07001011 << superInterface->fqName().cppNamespace()
1012 << "::IHw"
1013 << superInterface->getBaseName()
1014 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001015
Iliyan Malchev549e2592016-08-10 08:59:12 -07001016 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001017
Yifan Hongbf459bc2016-08-23 16:50:37 -07001018 // First DFS: write all buffers and resolve pointers for parent
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001019 for (const auto &arg : method->args()) {
1020 emitCppReaderWriter(
1021 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001022 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001023 false /* parcelObjIsPointer */,
1024 arg,
1025 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001026 Type::ErrorMode_Goto,
1027 false /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001028 }
1029
Yifan Hongbf459bc2016-08-23 16:50:37 -07001030 // Second DFS: resolve references.
1031 for (const auto &arg : method->args()) {
1032 emitCppResolveReferences(
1033 out,
1034 "_hidl_data",
1035 false /* parcelObjIsPointer */,
1036 arg,
1037 false /* reader */,
1038 Type::ErrorMode_Goto,
1039 false /* addPrefixToName */);
1040 }
1041
Steven Moreland40786312016-08-16 10:29:40 -07001042 out << "_hidl_err = remote()->transact("
1043 << superInterface->fqName().cppNamespace()
1044 << "::IHw"
1045 << superInterface->getBaseName()
1046 << "::Call::"
Yifan Hong42009032016-09-29 09:38:15 -07001047 << StringHelper::Uppercase(method->name())
Iliyan Malchev639bff82016-08-13 14:24:11 -07001048 << ", _hidl_data, &_hidl_reply";
1049 if (method->isOneway()) {
1050 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001051 }
Iliyan Malchev639bff82016-08-13 14:24:11 -07001052 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001053
Iliyan Malchev639bff82016-08-13 14:24:11 -07001054 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001055
Iliyan Malchev639bff82016-08-13 14:24:11 -07001056 if (!method->isOneway()) {
1057 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
1058 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -07001059 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1060
Yifan Hongbf459bc2016-08-23 16:50:37 -07001061
1062 // First DFS: write all buffers and resolve pointers for parent
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001063 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -07001064 emitCppReaderWriter(
1065 out,
1066 "_hidl_reply",
1067 false /* parcelObjIsPointer */,
1068 arg,
1069 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001070 Type::ErrorMode_Goto,
1071 true /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001072 }
1073
Yifan Hongbf459bc2016-08-23 16:50:37 -07001074 // Second DFS: resolve references.
1075 for (const auto &arg : method->results()) {
1076 emitCppResolveReferences(
1077 out,
1078 "_hidl_reply",
1079 false /* parcelObjIsPointer */,
1080 arg,
1081 true /* reader */,
1082 Type::ErrorMode_Goto,
1083 true /* addPrefixToName */);
1084 }
1085
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001086 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -07001087 out << "_hidl_cb(";
1088
1089 bool first = true;
1090 for (const auto &arg : method->results()) {
1091 if (!first) {
1092 out << ", ";
1093 }
1094
1095 if (arg->type().resultNeedsDeref()) {
1096 out << "*";
1097 }
Andreas Huber5e44a292016-09-27 14:52:39 -07001098 out << "_hidl_out_" << arg->name();
Iliyan Malchev639bff82016-08-13 14:24:11 -07001099
1100 first = false;
1101 }
1102
Steven Moreland67f67b42016-09-29 08:59:02 -07001103 out << ");\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -07001104 }
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001105 status_t status = generateCppInstrumentationCall(
1106 out,
1107 InstrumentationEvent::CLIENT_API_EXIT,
1108 superInterface,
1109 method);
1110 if (status != OK) {
1111 return status;
1112 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001113 }
1114
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001115 if (elidedReturn != nullptr) {
1116 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001117 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001118 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001119 out << elidedReturn->type().getCppResultType(&extra)
Andreas Huber5e44a292016-09-27 14:52:39 -07001120 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001121 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001122 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001123 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001124 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001125
Andreas Huber881227d2016-08-02 14:20:21 -07001126 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001127 out << "_hidl_error:\n";
1128 out.indent();
1129 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1130 out << "return ::android::hardware::Return<";
1131 if (elidedReturn != nullptr) {
1132 std::string extra;
1133 out << method->results().at(0)->type().getCppResultType(&extra);
1134 } else {
1135 out << "void";
1136 }
1137 out << ">(_hidl_status);\n";
1138
1139 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001140 out << "}\n\n";
1141 }
Andreas Huber881227d2016-08-02 14:20:21 -07001142 }
1143
1144 return OK;
1145}
1146
1147status_t AST::generateStubSource(
1148 Formatter &out, const std::string &baseName) const {
1149 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1150 << baseName
1151 << ", \""
1152 << mPackage.string()
1153 << "::I"
1154 << baseName
1155 << "\");\n\n";
1156
1157 const std::string klassName = "Bn" + baseName;
1158
Steven Moreland40786312016-08-16 10:29:40 -07001159 out << klassName
1160 << "::"
1161 << klassName
1162 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1163
1164 out.indent();
1165 out.indent();
1166
1167 out << ": BnInterface"
1168 << "<I"
1169 << baseName
1170 << ", IHw"
1171 << baseName
1172 << ">(_hidl_impl) {\n";
1173
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001174 emitCppInstrumentationInit(out, baseName);
Steven Moreland40786312016-08-16 10:29:40 -07001175 out.unindent();
1176 out.unindent();
1177 out << "}\n\n";
1178
Andreas Huber881227d2016-08-02 14:20:21 -07001179 out << "::android::status_t " << klassName << "::onTransact(\n";
1180
1181 out.indent();
1182 out.indent();
1183
Iliyan Malchev549e2592016-08-10 08:59:12 -07001184 out << "uint32_t _hidl_code,\n"
1185 << "const ::android::hardware::Parcel &_hidl_data,\n"
1186 << "::android::hardware::Parcel *_hidl_reply,\n"
1187 << "uint32_t _hidl_flags,\n"
1188 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001189
1190 out.unindent();
1191
Iliyan Malchev549e2592016-08-10 08:59:12 -07001192 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001193 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001194 out.indent();
1195
1196 const Interface *iface = mRootScope->getInterface();
1197
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001198 std::vector<const Interface *> chain;
1199 while (iface != NULL) {
1200 chain.push_back(iface);
1201 iface = iface->superType();
1202 }
Andreas Huber881227d2016-08-02 14:20:21 -07001203
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001204 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1205 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001206
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001207 for (const auto &method : superInterface->methods()) {
1208 out << "case "
Steven Moreland40786312016-08-16 10:29:40 -07001209 << superInterface->fqName().cppNamespace()
1210 << "::IHw"
1211 << superInterface->getBaseName()
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001212 << "::Call::"
Yifan Hong42009032016-09-29 09:38:15 -07001213 << StringHelper::Uppercase(method->name())
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001214 << ":\n{\n";
1215
1216 out.indent();
1217
1218 status_t err =
1219 generateStubSourceForMethod(out, superInterface, method);
1220
1221 if (err != OK) {
1222 return err;
1223 }
1224
1225 out.unindent();
1226 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001227 }
Andreas Huber881227d2016-08-02 14:20:21 -07001228 }
1229
1230 out << "default:\n{\n";
1231 out.indent();
1232
Andreas Huber8a82ff72016-08-04 10:29:39 -07001233 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001234 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001235 << ">::onTransact(\n";
1236
1237 out.indent();
1238 out.indent();
1239
Iliyan Malchev549e2592016-08-10 08:59:12 -07001240 out << "_hidl_code, _hidl_data, _hidl_reply, "
1241 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001242
1243 out.unindent();
1244 out.unindent();
1245
1246 out.unindent();
1247 out << "}\n";
1248
1249 out.unindent();
1250 out << "}\n\n";
1251
Iliyan Malchev549e2592016-08-10 08:59:12 -07001252 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001253 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001254 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001255 out.indent();
1256 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001257 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001258 out.indent();
1259 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001260 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001261 out.unindent();
1262 out.unindent();
1263 out.unindent();
1264 out.unindent();
1265
1266 out.unindent();
1267 out << "}\n\n";
1268
Iliyan Malchev549e2592016-08-10 08:59:12 -07001269 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001270
1271 out.unindent();
1272 out << "}\n\n";
1273
1274 return OK;
1275}
1276
1277status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001278 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001279 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001280 << iface->fqName().cppNamespace()
1281 << "::IHw"
1282 << iface->getBaseName()
1283 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001284
Andreas Huber881227d2016-08-02 14:20:21 -07001285 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001286 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001287 out << "break;\n";
1288 out.unindent();
1289 out << "}\n\n";
1290
Andreas Huber5e44a292016-09-27 14:52:39 -07001291 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001292
Yifan Hongbf459bc2016-08-23 16:50:37 -07001293 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001294 for (const auto &arg : method->args()) {
1295 emitCppReaderWriter(
1296 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001297 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001298 false /* parcelObjIsPointer */,
1299 arg,
1300 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001301 Type::ErrorMode_Break,
1302 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001303 }
1304
Yifan Hongbf459bc2016-08-23 16:50:37 -07001305 // Second DFS: resolve references
1306 for (const auto &arg : method->args()) {
1307 emitCppResolveReferences(
1308 out,
1309 "_hidl_data",
1310 false /* parcelObjIsPointer */,
1311 arg,
1312 true /* reader */,
1313 Type::ErrorMode_Break,
1314 false /* addPrefixToName */);
1315 }
1316
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001317 status_t status = generateCppInstrumentationCall(
1318 out,
1319 InstrumentationEvent::SERVER_API_ENTRY,
1320 iface,
1321 method);
1322 if (status != OK) {
1323 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001324 }
1325
Andreas Huber881227d2016-08-02 14:20:21 -07001326 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001327 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001328
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001329 if (elidedReturn != nullptr) {
1330 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001331
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001332 out << elidedReturn->type().getCppResultType(&extra) << " ";
1333 out << elidedReturn->name() << " = ";
1334 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001335
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001336 bool first = true;
1337 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001338 if (!first) {
1339 out << ", ";
1340 }
1341
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001342 if (arg->type().resultNeedsDeref()) {
1343 out << "*";
1344 }
1345
1346 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001347
1348 first = false;
1349 }
1350
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001351 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001352 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001353 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001354
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001355 elidedReturn->type().emitReaderWriter(
1356 out,
1357 elidedReturn->name(),
1358 "_hidl_reply",
1359 true, /* parcelObjIsPointer */
1360 false, /* isReader */
1361 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001362
Yifan Hongbf459bc2016-08-23 16:50:37 -07001363 emitCppResolveReferences(
1364 out,
1365 "_hidl_reply",
1366 true /* parcelObjIsPointer */,
1367 elidedReturn,
1368 false /* reader */,
1369 Type::ErrorMode_Ignore,
1370 false /* addPrefixToName */);
1371
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001372 status_t status = generateCppInstrumentationCall(
1373 out,
1374 InstrumentationEvent::SERVER_API_EXIT,
1375 iface,
1376 method);
1377 if (status != OK) {
1378 return status;
1379 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001380
Iliyan Malchev549e2592016-08-10 08:59:12 -07001381 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001382 } else {
1383 if (returnsValue) {
1384 out << "bool _hidl_callbackCalled = false;\n\n";
1385 }
Andreas Huber881227d2016-08-02 14:20:21 -07001386
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001387 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001388
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001389 bool first = true;
1390 for (const auto &arg : method->args()) {
1391 if (!first) {
1392 out << ", ";
1393 }
Andreas Huber881227d2016-08-02 14:20:21 -07001394
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001395 if (arg->type().resultNeedsDeref()) {
1396 out << "*";
1397 }
1398
1399 out << arg->name();
1400
1401 first = false;
1402 }
1403
1404 if (returnsValue) {
1405 if (!first) {
1406 out << ", ";
1407 }
1408
1409 out << "[&](";
1410
1411 first = true;
1412 for (const auto &arg : method->results()) {
1413 if (!first) {
1414 out << ", ";
1415 }
1416
1417 out << "const auto &" << arg->name();
1418
1419 first = false;
1420 }
1421
1422 out << ") {\n";
1423 out.indent();
1424 out << "_hidl_callbackCalled = true;\n\n";
1425
1426 out << "::android::hardware::Status::ok()"
1427 << ".writeToParcel(_hidl_reply);\n\n";
1428
Yifan Hongbf459bc2016-08-23 16:50:37 -07001429 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001430 for (const auto &arg : method->results()) {
1431 emitCppReaderWriter(
1432 out,
1433 "_hidl_reply",
1434 true /* parcelObjIsPointer */,
1435 arg,
1436 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001437 Type::ErrorMode_Ignore,
1438 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001439 }
1440
Yifan Hongbf459bc2016-08-23 16:50:37 -07001441 // Second DFS: resolve references
1442 for (const auto &arg : method->results()) {
1443 emitCppResolveReferences(
1444 out,
1445 "_hidl_reply",
1446 true /* parcelObjIsPointer */,
1447 arg,
1448 false /* reader */,
1449 Type::ErrorMode_Ignore,
1450 false /* addPrefixToName */);
1451 }
1452
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001453 status_t status = generateCppInstrumentationCall(
1454 out,
1455 InstrumentationEvent::SERVER_API_EXIT,
1456 iface,
1457 method);
1458 if (status != OK) {
1459 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001460 }
1461
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001462 out << "_hidl_cb(*_hidl_reply);\n";
1463
1464 out.unindent();
1465 out << "}\n";
1466 }
1467
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001468 out << ");\n\n";
1469
1470 // What to do if the stub implementation has a synchronous callback
1471 // which does not get invoked? This is not a transport error but a
1472 // service error of sorts. For now, return OK to the caller, as this is
1473 // not a transport error.
1474 //
1475 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001476
1477 if (returnsValue) {
1478 out << "if (!_hidl_callbackCalled) {\n";
1479 out.indent();
1480 }
1481
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001482 out << "::android::hardware::Status::ok()"
1483 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001484
1485 if (returnsValue) {
1486 out.unindent();
1487 out << "}\n\n";
1488 }
Andreas Huber881227d2016-08-02 14:20:21 -07001489 }
1490
1491 out << "break;\n";
1492
1493 return OK;
1494}
1495
Steven Moreland69e7c702016-09-09 11:16:32 -07001496status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1497 std::string ifaceName;
1498 if (!AST::isInterface(&ifaceName)) {
1499 // types.hal does not get a stub header.
1500 return OK;
1501 }
1502
1503 const Interface *iface = mRootScope->getInterface();
1504
1505 const std::string baseName = iface->getBaseName();
1506 const std::string klassName = "Bs" + baseName;
1507
1508 bool supportOneway = iface->hasOnewayMethods();
1509
1510 std::string path = outputPath;
1511 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1512 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1513 path.append(klassName);
1514 path.append(".h");
1515
1516 CHECK(Coordinator::MakeParentHierarchy(path));
1517 FILE *file = fopen(path.c_str(), "w");
1518
1519 if (file == NULL) {
1520 return -errno;
1521 }
1522
1523 Formatter out(file);
1524
1525 const std::string guard = makeHeaderGuard(klassName);
1526
1527 out << "#ifndef " << guard << "\n";
1528 out << "#define " << guard << "\n\n";
1529
1530 std::vector<std::string> packageComponents;
1531 getPackageAndVersionComponents(
1532 &packageComponents, false /* cpp_compatible */);
1533
1534 out << "#include <future>\n";
1535 out << "#include <";
1536 for (const auto &component : packageComponents) {
1537 out << component << "/";
1538 }
1539 out << ifaceName << ".h>\n\n";
1540
1541 if (supportOneway) {
1542 out << "#include <hidl/SynchronizedQueue.h>\n";
1543 }
1544
1545 enterLeaveNamespace(out, true /* enter */);
1546 out << "\n";
1547
1548 out << "struct "
1549 << klassName
1550 << " : " << ifaceName
1551 << " {\n";
1552
1553 out.indent();
1554 out << "explicit "
1555 << klassName
1556 << "(const sp<"
1557 << ifaceName
1558 << "> impl);\n";
1559
1560 status_t err = generateMethods(out,
1561 "" /* class name */,
1562 MethodLocation::PASSTHROUGH_HEADER,
1563 true /* specify namespaces */);
1564
1565 if (err != OK) {
1566 return err;
1567 }
1568
1569 out.unindent();
1570 out << "private:\n";
1571 out.indent();
1572 out << "const sp<" << ifaceName << "> mImpl;\n";
1573
1574 if (supportOneway) {
1575 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1576 out << "std::thread *mOnewayThread = nullptr;\n";
1577
1578 out << "\n";
1579
1580 out << "::android::hardware::Return<void> addOnewayTask("
1581 "std::function<void(void)>);\n\n";
1582
1583 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1584 }
1585
1586 out.unindent();
1587
1588 out << "};\n\n";
1589
1590 enterLeaveNamespace(out, false /* enter */);
1591
1592 out << "\n#endif // " << guard << "\n";
1593
1594 return OK;
1595}
1596
1597
1598status_t AST::generatePassthroughSource(Formatter &out) const {
1599 const Interface *iface = mRootScope->getInterface();
1600
1601 const std::string baseName = iface->getBaseName();
1602 const std::string klassName = "Bs" + baseName;
1603
1604 out << klassName
1605 << "::"
1606 << klassName
1607 << "(const sp<"
1608 << iface->fullName()
1609 << "> impl) : mImpl(impl) {}\n\n";
1610
1611 if (iface->hasOnewayMethods()) {
1612 out << "::android::hardware::Return<void> "
1613 << klassName
1614 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1615 out.indent();
1616 out << "if (mOnewayThread == nullptr) {\n";
1617 out.indent();
1618 out << "mOnewayThread = new std::thread([this]() {\n";
1619 out.indent();
1620 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1621 out.unindent();
1622 out << "});\n";
1623 out.unindent();
1624 out << "}\n\n";
1625
1626 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1627 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001628 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1629 out.indent();
1630 out.indent();
1631 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1632 out.unindent();
1633 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001634 out.unindent();
1635 out << "} else {\n";
1636 out.indent();
1637 out << "mOnewayQueue.push(fun);\n";
1638 out.unindent();
1639 out << "}\n";
1640
1641 out << "return Status();\n";
1642
1643 out.unindent();
1644 out << "}\n\n";
1645
1646
1647 }
1648
1649 return OK;
1650}
1651
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001652status_t AST::generateCppInstrumentationCall(
1653 Formatter &out,
1654 InstrumentationEvent event,
1655 const Interface *iface, const Method *method) const {
1656 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1657 out.indent();
1658 out << "std::vector<void *> args;\n";
1659 std::string event_str = "";
1660 switch (event) {
1661 case SERVER_API_ENTRY:
1662 {
1663 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1664 for (const auto &arg : method->args()) {
1665 out << "args.push_back((void *)"
1666 << (arg->type().resultNeedsDeref() ? "" : "&")
1667 << arg->name()
1668 << ");\n";
1669 }
1670 break;
1671 }
1672 case SERVER_API_EXIT:
1673 {
1674 event_str = "InstrumentationEvent::SERVER_API_EXIT";
1675 const TypedVar *elidedReturn = method->canElideCallback();
1676 if (elidedReturn != nullptr) {
1677 out << "args.push_back((void *)&" << elidedReturn->name()
1678 << ");\n";
1679 } else {
1680 for (const auto &arg : method->results()) {
1681 out << "args.push_back((void *)&" << arg->name()
1682 << ");\n";
1683 }
1684 }
1685 break;
1686 }
1687 case CLIENT_API_ENTRY:
1688 {
1689 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1690 for (const auto &arg : method->args()) {
1691 out << "args.push_back((void *)&" << arg->name() << ");\n";
1692 }
1693 break;
1694 }
1695 case CLIENT_API_EXIT:
1696 {
1697 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1698 for (const auto &arg : method->results()) {
1699 out << "args.push_back((void *)"
1700 << (arg->type().resultNeedsDeref() ? "" : "&")
1701 << "_hidl_out_" << arg->name()
1702 << ");\n";
1703 }
1704 break;
1705 }
1706 case SYNC_CALLBACK_ENTRY:
1707 case SYNC_CALLBACK_EXIT:
1708 case ASYNC_CALLBACK_ENTRY:
1709 case ASYNC_CALLBACK_EXIT:
1710 {
1711 LOG(ERROR) << "Not supported instrumentation event: " << event;
1712 return UNKNOWN_ERROR;
1713 }
1714 }
1715
1716 out << "for (auto callback: mInstrumentationCallbacks) {\n";
1717 out.indent();
1718 out << "callback("
1719 << event_str
1720 << ", \""
1721 << mPackage.package()
1722 << "\", \""
1723 << mPackage.getPackageFullVersion()
1724 << "\", \""
1725 << iface->localName()
1726 << "\", \""
1727 << method->name()
1728 << "\", &args);\n";
1729 out.unindent();
1730 out << "}\n";
1731 out.unindent();
1732 out << "}\n\n";
1733
1734 return OK;
1735}
1736
1737void AST::emitCppInstrumentationDecl(
1738 Formatter &out) const {
1739 out << "// for hidl instrumentation.\n";
1740 out << "std::vector<InstrumentationCallback> mInstrumentationCallbacks;\n";
1741 out << "bool mEnableInstrumentation;\n";
1742}
1743
1744void AST::emitCppInstrumentationInit(
1745 Formatter &out, const std::string &baseName) const {
1746 out << "mEnableInstrumentation = "
1747 "property_get_bool(\"hal.instrumentation.enable\", false);\n";
1748 out << "registerInstrumentationCallbacks(\""
1749 << mPackage.string()
1750 << "::I"
1751 << baseName
1752 << "\", &mInstrumentationCallbacks);\n";
1753}
1754
Andreas Huber881227d2016-08-02 14:20:21 -07001755} // namespace android
1756