blob: fdca7fcb6ae80d49fabf1a3359b81dfd954c40e8 [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/Formatter.h>
Andreas Huber881227d2016-08-02 14:20:21 -070028#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070029#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070030#include <vector>
31
32namespace android {
33
Andreas Huberb82318c2016-08-02 14:45:54 -070034status_t AST::generateCpp(const std::string &outputPath) const {
35 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070036
37 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070038 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070039 }
40
41 if (err == OK) {
Steven Moreland40786312016-08-16 10:29:40 -070042 err = generateHwBinderHeader(outputPath);
43 }
44
45 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070046 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070047 }
48
49 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070050 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070051 }
52
Steven Moreland69e7c702016-09-09 11:16:32 -070053 if (err == OK) {
54 generatePassthroughHeader(outputPath);
55 }
56
Andreas Huber881227d2016-08-02 14:20:21 -070057 return err;
58}
59
Andreas Huber737080b2016-08-02 15:38:04 -070060void AST::getPackageComponents(
61 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070062 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070063}
64
65void AST::getPackageAndVersionComponents(
66 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070067 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070068}
69
Andreas Huber881227d2016-08-02 14:20:21 -070070std::string AST::makeHeaderGuard(const std::string &baseName) const {
Steven Moreland9c387612016-09-07 09:54:26 -070071 std::string guard = "HIDL_GENERATED_";
72 guard += mPackage.tokenName();
Andreas Huber881227d2016-08-02 14:20:21 -070073
74 guard += "_";
75 guard += baseName;
76 guard += "_H_";
77
78 return guard;
79}
80
81void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
82 std::vector<std::string> packageComponents;
83 getPackageAndVersionComponents(
84 &packageComponents, true /* cpp_compatible */);
85
86 if (enter) {
87 for (const auto &component : packageComponents) {
88 out << "namespace " << component << " {\n";
89 }
Andreas Huber0e00de42016-08-03 09:56:02 -070090
Andreas Huber2831d512016-08-15 09:33:47 -070091 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -070092 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -070093 out.setNamespace(std::string());
94
Andreas Huber881227d2016-08-02 14:20:21 -070095 for (auto it = packageComponents.rbegin();
96 it != packageComponents.rend();
97 ++it) {
98 out << "} // namespace " << *it << "\n";
99 }
100 }
101}
102
Andreas Huberb82318c2016-08-02 14:45:54 -0700103status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700104
Andreas Huberb82318c2016-08-02 14:45:54 -0700105 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700106 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700107 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700108
109 std::string ifaceName;
110 bool isInterface = true;
111 if (!AST::isInterface(&ifaceName)) {
112 ifaceName = "types";
113 isInterface = false;
114 }
115 path.append(ifaceName);
116 path.append(".h");
117
Andreas Huberd2943e12016-08-05 11:59:31 -0700118 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700119 FILE *file = fopen(path.c_str(), "w");
120
121 if (file == NULL) {
122 return -errno;
123 }
124
125 Formatter out(file);
126
127 const std::string guard = makeHeaderGuard(ifaceName);
128
129 out << "#ifndef " << guard << "\n";
130 out << "#define " << guard << "\n\n";
131
Andreas Huber737080b2016-08-02 15:38:04 -0700132 for (const auto &item : mImportedNames) {
133 out << "#include <";
134
135 std::vector<std::string> components;
Andreas Huber0e00de42016-08-03 09:56:02 -0700136 item.getPackageAndVersionComponents(
137 &components, false /* cpp_compatible */);
Andreas Huber737080b2016-08-02 15:38:04 -0700138
139 for (const auto &component : components) {
140 out << component << "/";
141 }
142
143 out << item.name()
144 << ".h>\n";
145 }
146
147 if (!mImportedNames.empty()) {
148 out << "\n";
149 }
150
Martijn Coenen7473fab2016-08-19 14:05:40 +0200151 out << "#include <hidl/HidlSupport.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700152 out << "#include <hidl/IServiceManager.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700153 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700154
155 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200156 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700157 }
158
159 out << "#include <utils/NativeHandle.h>\n\n";
160
161 enterLeaveNamespace(out, true /* enter */);
162 out << "\n";
163
164 if (isInterface) {
165 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700166 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700167
168 const Interface *iface = mRootScope->getInterface();
169 const Interface *superType = iface->superType();
170
Steven Moreland40786312016-08-16 10:29:40 -0700171 if (superType == NULL) {
172 out << " : virtual public RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700173 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700174 out << " : public "
175 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700176 }
177
178 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700179
180 out.indent();
181
Andreas Huber881227d2016-08-02 14:20:21 -0700182 }
183
184 status_t err = emitTypeDeclarations(out);
185
186 if (err != OK) {
187 return err;
188 }
189
190 if (isInterface) {
191 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700192 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700193 const std::string baseName = iface->getBaseName();
Martijn Coenena21f1492016-09-08 15:55:14 +0200194 out << "constexpr static hidl_version version = {"
195 << mPackage.getPackageMajorVersion() << ","
196 << mPackage.getPackageMinorVersion() << "};\n";
197 out << "virtual const hidl_version& getInterfaceVersion() const {\n";
198 out.indent();
199 out << "return version;\n";
200 out.unindent();
201 out << "}\n\n";
Iliyan Malchev795dd432016-09-02 11:48:26 -0700202 out << "virtual bool isRemote() const { return false; }\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700203 bool haveCallbacks = false;
204 for (const auto &method : iface->methods()) {
205 const bool returnsValue = !method->results().empty();
206
207 if (!returnsValue) {
208 continue;
209 }
210
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700211 if (method->canElideCallback() != nullptr) {
212 continue;
213 }
214
Andreas Huber881227d2016-08-02 14:20:21 -0700215 haveCallbacks = true;
216
217 out << "using "
218 << method->name()
219 << "_cb = std::function<void("
Steven Moreland979e0992016-09-07 09:18:08 -0700220 << Method::GetArgSignature(method->results(),
221 true /* specify namespaces */)
Andreas Huber881227d2016-08-02 14:20:21 -0700222 << ")>;\n";
223 }
224
225 if (haveCallbacks) {
226 out << "\n";
227 }
228
229 for (const auto &method : iface->methods()) {
230 const bool returnsValue = !method->results().empty();
231
Andreas Huber3599d922016-08-09 10:42:57 -0700232 method->dumpAnnotations(out);
233
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700234 const TypedVar *elidedReturn = method->canElideCallback();
235 if (elidedReturn) {
236 std::string extra;
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700237 out << "virtual ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700238 out << elidedReturn->type().getCppResultType(&extra) << "> ";
239 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700240 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700241 }
242
243 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700244 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700245 << Method::GetArgSignature(method->args(),
246 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700247
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700248 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700249 if (!method->args().empty()) {
250 out << ", ";
251 }
252
Steven Moreland67f67b42016-09-29 08:59:02 -0700253 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700254 }
255
256 out << ") = 0;\n";
257 }
Steven Moreland40786312016-08-16 10:29:40 -0700258
259 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700260 }
261
262 if (isInterface) {
263 out.unindent();
264
Andreas Hubere3f769a2016-10-10 10:54:44 -0700265 out << "};\n\n";
266 }
267
268 err = mRootScope->emitGlobalTypeDeclarations(out);
269
270 if (err != OK) {
271 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700272 }
273
274 out << "\n";
275 enterLeaveNamespace(out, false /* enter */);
276
277 out << "\n#endif // " << guard << "\n";
278
279 return OK;
280}
281
Steven Moreland40786312016-08-16 10:29:40 -0700282status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
283 std::string ifaceName;
284 if(!AST::isInterface(&ifaceName)) {
285 // types.hal does not get an HwBinder header.
286 return OK;
287 }
288
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700289 const Interface *iface = mRootScope->getInterface();
290 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700291
292 const std::string klassName = "IHw" + baseName;
293
294 std::string path = outputPath;
295 path.append(mCoordinator->convertPackageRootToPath(mPackage));
296 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
297 path.append(klassName + ".h");
298
299 FILE* file = fopen(path.c_str(), "w");
300
301 if (file == NULL) {
302 return -errno;
303 }
304
305 Formatter out(file);
306
307 const std::string guard = makeHeaderGuard(klassName);
308
309 out << "#ifndef " << guard << "\n";
310 out << "#define " << guard << "\n\n";
311
312 std::vector<std::string> packageComponents;
313 getPackageAndVersionComponents(
314 &packageComponents, false /* cpp_compatible */);
315
316 out << "#include <";
317 for (const auto &component : packageComponents) {
318 out << component << "/";
319 }
320 out << ifaceName << ".h>\n\n";
321
322 for (const auto &item : mImportedNames) {
323 if (item.name() == "types") {
324 continue;
325 }
326
327 out << "#include <";
328
329 std::vector<std::string> components;
330 item.getPackageAndVersionComponents(
331 &components, false /* cpp_compatible */);
332
333 for (const auto &component : components) {
334 out << component << "/";
335 }
336
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700337 const std::string itemBaseName = item.getInterfaceBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700338
339 out << "Bn"
340 << itemBaseName
341 << ".h>\n";
342 }
343
344 out << "\n";
345
346 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200347 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700348 out << "#include <hwbinder/IBinder.h>\n";
349 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700350
351 out << "\n";
352
353 enterLeaveNamespace(out, true /* enter */);
354 out << "\n";
355
356 out << "struct "
357 << klassName
358 << " : public "
359 << ifaceName;
360
Steven Moreland40786312016-08-16 10:29:40 -0700361 const Interface *superType = iface->superType();
362
363 out << ", public ::android::hardware::IInterface";
364
365 out << " {\n";
366
367 out.indent();
368
369 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
370
Steven Moreland40786312016-08-16 10:29:40 -0700371 out.unindent();
372
373 out << "};\n\n";
374
375 enterLeaveNamespace(out, false /* enter */);
376
377 out << "\n#endif // " << guard << "\n";
378
379 return OK;
380}
381
Andreas Huber881227d2016-08-02 14:20:21 -0700382status_t AST::emitTypeDeclarations(Formatter &out) const {
383 return mRootScope->emitTypeDeclarations(out);
384}
385
Steven Morelanda7a421a2016-09-07 08:35:18 -0700386status_t AST::generateStubMethod(Formatter &out,
387 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700388 const Method *method,
389 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700390 out << "inline ";
391
Steven Moreland979e0992016-09-07 09:18:08 -0700392 method->generateCppSignature(out,
393 className,
394 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700395
396 const bool returnsValue = !method->results().empty();
397 const TypedVar *elidedReturn = method->canElideCallback();
398 out << " {\n";
399 out.indent();
400 out << "return mImpl->"
401 << method->name()
402 << "(";
403 bool first = true;
404 for (const auto &arg : method->args()) {
405 if (!first) {
406 out << ", ";
407 }
408 first = false;
409 out << arg->name();
410 }
411 if (returnsValue && elidedReturn == nullptr) {
412 if (!method->args().empty()) {
413 out << ", ";
414 }
415
416 out << "_hidl_cb";
417 }
418 out << ");\n";
419 out.unindent();
420 out << "}";
421
422 out << ";\n";
423
424 return OK;
425}
426
Steven Moreland9c387612016-09-07 09:54:26 -0700427status_t AST::generateProxyDeclaration(Formatter &out,
428 const std::string &className,
429 const Method *method,
430 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700431
Steven Moreland979e0992016-09-07 09:18:08 -0700432 method->generateCppSignature(out,
433 className,
434 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700435 out << " override;\n";
436
437 return OK;
438}
439
Steven Moreland69e7c702016-09-09 11:16:32 -0700440
441status_t AST::generatePassthroughMethod(Formatter &out,
442 const std::string &className,
443 const Method *method,
444 bool specifyNamespaces) const {
445 method->generateCppSignature(out, className, specifyNamespaces);
446
447 out << " {\n";
448 out.indent();
449
450 const bool returnsValue = !method->results().empty();
451 const TypedVar *elidedReturn = method->canElideCallback();
452
Steven Moreland67f67b42016-09-29 08:59:02 -0700453 if (returnsValue && elidedReturn == nullptr) {
454 generateCheckNonNull(out, "_hidl_cb");
455 }
456
Steven Moreland69e7c702016-09-09 11:16:32 -0700457 out << "return ";
458
459 if (method->isOneway()) {
460 out << "addOnewayTask([this";
461 for (const auto &arg : method->args()) {
462 out << ", " << arg->name();
463 }
464 out << "] {this->";
465 }
466
467 out << "mImpl->"
468 << method->name()
469 << "(";
470
471 bool first = true;
472 for (const auto &arg : method->args()) {
473 if (!first) {
474 out << ", ";
475 }
476 first = false;
477 out << arg->name();
478 }
479 if (returnsValue && elidedReturn == nullptr) {
480 if (!method->args().empty()) {
481 out << ", ";
482 }
483
484 out << "_hidl_cb";
485 }
486 out << ")";
487
488 if (method->isOneway()) {
489 out << ";})";
490 }
491 out << ";\n";
492
493 out.unindent();
494 out << "}\n";
495
496 return OK;
497}
498
Steven Morelanda7a421a2016-09-07 08:35:18 -0700499status_t AST::generateMethods(
500 Formatter &out,
501 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700502 MethodLocation type,
503 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700504
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700505 const Interface *iface = mRootScope->getInterface();
506
507 std::vector<const Interface *> chain;
508 while (iface != NULL) {
509 chain.push_back(iface);
510 iface = iface->superType();
511 }
512
513 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
514 const Interface *superInterface = *it;
515
516 out << "// Methods from "
517 << superInterface->fullName()
518 << " follow.\n";
519
520 for (const auto &method : superInterface->methods()) {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700521 status_t err;
522 switch(type) {
523 case STUB_HEADER:
524 err = generateStubMethod(out,
525 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700526 method,
527 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700528 break;
529 case PROXY_HEADER:
Steven Moreland9c387612016-09-07 09:54:26 -0700530 err = generateProxyDeclaration(out,
531 className,
532 method,
533 specifyNamespaces);
534 break;
535 case IMPL_HEADER:
536 err = generateStubImplDeclaration(out,
537 className,
538 method,
539 specifyNamespaces);
540 break;
541 case IMPL_SOURCE:
542 err = generateStubImplMethod(out,
543 className,
544 method,
545 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700546 break;
Steven Moreland69e7c702016-09-09 11:16:32 -0700547 case PASSTHROUGH_HEADER:
548 err = generatePassthroughMethod(out,
549 className,
550 method,
551 specifyNamespaces);
552 break;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700553 default:
Steven Moreland9c387612016-09-07 09:54:26 -0700554 LOG(ERROR) << "Unkown method type: " << type;
Steven Morelanda7a421a2016-09-07 08:35:18 -0700555 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700556 }
557
Steven Morelanda7a421a2016-09-07 08:35:18 -0700558 if (err != OK) {
559 return err;
Steven Moreland40786312016-08-16 10:29:40 -0700560 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700561 }
562
563 out << "\n";
564 }
565
566 return OK;
567}
568
Andreas Huberb82318c2016-08-02 14:45:54 -0700569status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700570 std::string ifaceName;
571 if (!AST::isInterface(&ifaceName)) {
572 // types.hal does not get a stub header.
573 return OK;
574 }
575
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700576 const Interface *iface = mRootScope->getInterface();
577 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700578 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700579
Andreas Huberb82318c2016-08-02 14:45:54 -0700580 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700581 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700582 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700583 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700584 path.append(".h");
585
Andreas Huberd2943e12016-08-05 11:59:31 -0700586 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700587 FILE *file = fopen(path.c_str(), "w");
588
589 if (file == NULL) {
590 return -errno;
591 }
592
593 Formatter out(file);
594
Steven Moreland40786312016-08-16 10:29:40 -0700595 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700596
597 out << "#ifndef " << guard << "\n";
598 out << "#define " << guard << "\n\n";
599
600 std::vector<std::string> packageComponents;
601 getPackageAndVersionComponents(
602 &packageComponents, false /* cpp_compatible */);
603
604 out << "#include <";
605 for (const auto &component : packageComponents) {
606 out << component << "/";
607 }
Steven Moreland40786312016-08-16 10:29:40 -0700608 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700609
610 enterLeaveNamespace(out, true /* enter */);
611 out << "\n";
612
613 out << "struct "
614 << "Bn"
615 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700616 << " : public ::android::hardware::BnInterface<I"
617 << baseName << ", IHw" << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700618 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700619
620 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700621 out << "explicit Bn"
622 << baseName
623 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
624 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700625 out << "::android::status_t onTransact(\n";
626 out.indent();
627 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700628 out << "uint32_t _hidl_code,\n";
629 out << "const ::android::hardware::Parcel &_hidl_data,\n";
630 out << "::android::hardware::Parcel *_hidl_reply,\n";
631 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700632 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700633 out.unindent();
634 out.unindent();
635
Steven Moreland9c387612016-09-07 09:54:26 -0700636 status_t err = generateMethods(out,
637 "" /* class name */,
638 MethodLocation::STUB_HEADER,
639 true /* specify namespaces */);
640
641 if (err != OK) {
642 return err;
643 }
644
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700645
Andreas Huber881227d2016-08-02 14:20:21 -0700646 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700647 out << "};\n\n";
648
649 enterLeaveNamespace(out, false /* enter */);
650
651 out << "\n#endif // " << guard << "\n";
652
653 return OK;
654}
655
Andreas Huberb82318c2016-08-02 14:45:54 -0700656status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700657 std::string ifaceName;
658 if (!AST::isInterface(&ifaceName)) {
659 // types.hal does not get a proxy header.
660 return OK;
661 }
662
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700663 const Interface *iface = mRootScope->getInterface();
664 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700665
Andreas Huberb82318c2016-08-02 14:45:54 -0700666 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700667 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700668 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700669 path.append("Bp");
670 path.append(baseName);
671 path.append(".h");
672
Andreas Huberd2943e12016-08-05 11:59:31 -0700673 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700674 FILE *file = fopen(path.c_str(), "w");
675
676 if (file == NULL) {
677 return -errno;
678 }
679
680 Formatter out(file);
681
682 const std::string guard = makeHeaderGuard("Bp" + baseName);
683
684 out << "#ifndef " << guard << "\n";
685 out << "#define " << guard << "\n\n";
686
687 std::vector<std::string> packageComponents;
688 getPackageAndVersionComponents(
689 &packageComponents, false /* cpp_compatible */);
690
691 out << "#include <";
692 for (const auto &component : packageComponents) {
693 out << component << "/";
694 }
Steven Moreland40786312016-08-16 10:29:40 -0700695 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700696
697 enterLeaveNamespace(out, true /* enter */);
698 out << "\n";
699
700 out << "struct "
701 << "Bp"
702 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700703 << " : public ::android::hardware::BpInterface<IHw"
704 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700705 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700706
707 out.indent();
708
709 out << "explicit Bp"
710 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700711 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700712 << "\n\n";
713
Iliyan Malchev795dd432016-09-02 11:48:26 -0700714 out << "virtual bool isRemote() const { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700715
Steven Moreland9c387612016-09-07 09:54:26 -0700716 status_t err = generateMethods(out,
717 "" /* class name */,
718 MethodLocation::PROXY_HEADER,
719 true /* generate specify namespaces */);
720
721 if (err != OK) {
722 return err;
723 }
Andreas Huber881227d2016-08-02 14:20:21 -0700724
725 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700726 out << "};\n\n";
727
728 enterLeaveNamespace(out, false /* enter */);
729
730 out << "\n#endif // " << guard << "\n";
731
732 return OK;
733}
734
Andreas Huberb82318c2016-08-02 14:45:54 -0700735status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700736
Andreas Huberb82318c2016-08-02 14:45:54 -0700737 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700738 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700739 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700740
741 std::string ifaceName;
742 std::string baseName;
743
744 bool isInterface = true;
745 if (!AST::isInterface(&ifaceName)) {
746 baseName = "types";
747 isInterface = false;
748 } else {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700749 const Interface *iface = mRootScope->getInterface();
750 baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700751 }
752
753 path.append(baseName);
754
755 if (baseName != "types") {
756 path.append("All");
757 }
758
759 path.append(".cpp");
760
Andreas Huberd2943e12016-08-05 11:59:31 -0700761 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700762 FILE *file = fopen(path.c_str(), "w");
763
764 if (file == NULL) {
765 return -errno;
766 }
767
768 Formatter out(file);
769
770 std::vector<std::string> packageComponents;
771 getPackageAndVersionComponents(
772 &packageComponents, false /* cpp_compatible */);
773
774 std::string prefix;
775 for (const auto &component : packageComponents) {
776 prefix += component;
777 prefix += "/";
778 }
779
780 if (isInterface) {
781 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
782 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700783 out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700784 } else {
785 out << "#include <" << prefix << "types.h>\n";
786 }
787
788 out << "\n";
789
790 enterLeaveNamespace(out, true /* enter */);
791 out << "\n";
792
793 status_t err = generateTypeSource(out, ifaceName);
794
795 if (err == OK && isInterface) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200796 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700797 err = generateProxySource(out, baseName);
798 }
799
800 if (err == OK && isInterface) {
801 err = generateStubSource(out, baseName);
802 }
803
Steven Moreland40786312016-08-16 10:29:40 -0700804 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700805 err = generatePassthroughSource(out);
806 }
807
808 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700809 const Interface *iface = mRootScope->getInterface();
810
811 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
812 << baseName << ", "
813 << "\"" << iface->fqName().package()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700814 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700815 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700816 }
817
Andreas Huber881227d2016-08-02 14:20:21 -0700818 enterLeaveNamespace(out, false /* enter */);
819
820 return err;
821}
822
Steven Moreland67f67b42016-09-29 08:59:02 -0700823// static
824void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
825 out << "if (" << nonNull << " == nullptr) {\n";
826 out.indent();
827 out << "return ::android::hardware::Status::fromExceptionCode(\n";
828 out.indent();
829 out.indent();
830 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
831 out.unindent();
832 out.unindent();
833 out.unindent();
834 out << "}\n\n";
835}
836
Andreas Huber881227d2016-08-02 14:20:21 -0700837status_t AST::generateTypeSource(
838 Formatter &out, const std::string &ifaceName) const {
839 return mRootScope->emitTypeDefinitions(out, ifaceName);
840}
841
Andreas Hubere7ff2282016-08-16 13:50:03 -0700842void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700843 Formatter &out,
844 const std::vector<TypedVar *> &args,
845 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700846 if (args.empty()) {
847 return;
848 }
849
850 for (const auto &arg : args) {
851 const Type &type = arg->type();
852
853 std::string extra;
854 out << type.getCppResultType(&extra)
855 << " "
Andreas Huber5e44a292016-09-27 14:52:39 -0700856 << (forResults ? "_hidl_out_" : "")
Andreas Hubere7ff2282016-08-16 13:50:03 -0700857 << arg->name()
858 << extra
859 << ";\n";
860 }
861
862 out << "\n";
863}
864
Andreas Huber881227d2016-08-02 14:20:21 -0700865void AST::emitCppReaderWriter(
866 Formatter &out,
867 const std::string &parcelObj,
868 bool parcelObjIsPointer,
869 const TypedVar *arg,
870 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700871 Type::ErrorMode mode,
872 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700873 const Type &type = arg->type();
874
Andreas Huber881227d2016-08-02 14:20:21 -0700875 type.emitReaderWriter(
876 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700877 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700878 parcelObj,
879 parcelObjIsPointer,
880 isReader,
881 mode);
882}
883
Yifan Hongbf459bc2016-08-23 16:50:37 -0700884void AST::emitCppResolveReferences(
885 Formatter &out,
886 const std::string &parcelObj,
887 bool parcelObjIsPointer,
888 const TypedVar *arg,
889 bool isReader,
890 Type::ErrorMode mode,
891 bool addPrefixToName) const {
892 const Type &type = arg->type();
893 if(type.needsResolveReferences()) {
894 type.emitResolveReferences(
895 out,
896 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
897 isReader, // nameIsPointer
898 parcelObj,
899 parcelObjIsPointer,
900 isReader,
901 mode);
902 }
903}
904
Andreas Huber881227d2016-08-02 14:20:21 -0700905status_t AST::generateProxySource(
906 Formatter &out, const std::string &baseName) const {
907 const std::string klassName = "Bp" + baseName;
908
909 out << klassName
910 << "::"
911 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700912 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700913
914 out.indent();
915 out.indent();
916
917 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700918 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700919 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700920 << ">(_hidl_impl),\n"
921 << " HidlInstrumentor(\""
922 << mPackage.string()
923 << "::I"
924 << baseName
925 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700926
Andreas Huber881227d2016-08-02 14:20:21 -0700927 out.unindent();
928 out.unindent();
929 out << "}\n\n";
930
931 const Interface *iface = mRootScope->getInterface();
932
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700933 std::vector<const Interface *> chain;
934 while (iface != NULL) {
935 chain.push_back(iface);
936 iface = iface->superType();
937 }
Andreas Huber881227d2016-08-02 14:20:21 -0700938
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700939 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
940 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -0700941
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700942 for (const auto &method : superInterface->methods()) {
Steven Moreland979e0992016-09-07 09:18:08 -0700943 method->generateCppSignature(out,
944 klassName,
945 true /* specify namespaces */);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700946
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700947 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700948 const TypedVar *elidedReturn = method->canElideCallback();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700949
Steven Morelanda7a421a2016-09-07 08:35:18 -0700950 out << "{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700951
952 out.indent();
953
Steven Moreland67f67b42016-09-29 08:59:02 -0700954 if (returnsValue && elidedReturn == nullptr) {
955 generateCheckNonNull(out, "_hidl_cb");
956 }
957
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700958 status_t status = generateCppInstrumentationCall(
959 out,
960 InstrumentationEvent::CLIENT_API_ENTRY,
961 superInterface,
962 method);
963 if (status != OK) {
964 return status;
965 }
966
Iliyan Malchev549e2592016-08-10 08:59:12 -0700967 out << "::android::hardware::Parcel _hidl_data;\n";
968 out << "::android::hardware::Parcel _hidl_reply;\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700969 out << "::android::status_t _hidl_err;\n";
970 out << "::android::hardware::Status _hidl_status;\n\n";
Andreas Huber5e44a292016-09-27 14:52:39 -0700971
972 declareCppReaderLocals(
973 out, method->results(), true /* forResults */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700974
Iliyan Malchev549e2592016-08-10 08:59:12 -0700975 out << "_hidl_err = _hidl_data.writeInterfaceToken("
Steven Moreland40786312016-08-16 10:29:40 -0700976 << superInterface->fqName().cppNamespace()
977 << "::IHw"
978 << superInterface->getBaseName()
979 << "::descriptor);\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700980
Iliyan Malchev549e2592016-08-10 08:59:12 -0700981 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700982
Yifan Hongbf459bc2016-08-23 16:50:37 -0700983 // First DFS: write all buffers and resolve pointers for parent
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700984 for (const auto &arg : method->args()) {
985 emitCppReaderWriter(
986 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -0700987 "_hidl_data",
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700988 false /* parcelObjIsPointer */,
989 arg,
990 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -0700991 Type::ErrorMode_Goto,
992 false /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700993 }
994
Yifan Hongbf459bc2016-08-23 16:50:37 -0700995 // Second DFS: resolve references.
996 for (const auto &arg : method->args()) {
997 emitCppResolveReferences(
998 out,
999 "_hidl_data",
1000 false /* parcelObjIsPointer */,
1001 arg,
1002 false /* reader */,
1003 Type::ErrorMode_Goto,
1004 false /* addPrefixToName */);
1005 }
1006
Steven Moreland40786312016-08-16 10:29:40 -07001007 out << "_hidl_err = remote()->transact("
Steven Morelandef1a9fe2016-10-06 17:19:09 -07001008 << method->getSerialId()
1009 << " /* "
1010 << method->name()
1011 << " */, _hidl_data, &_hidl_reply";
1012
Iliyan Malchev639bff82016-08-13 14:24:11 -07001013 if (method->isOneway()) {
1014 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001015 }
Iliyan Malchev639bff82016-08-13 14:24:11 -07001016 out << ");\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001017
Iliyan Malchev639bff82016-08-13 14:24:11 -07001018 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001019
Iliyan Malchev639bff82016-08-13 14:24:11 -07001020 if (!method->isOneway()) {
1021 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
1022 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -07001023 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1024
Yifan Hongbf459bc2016-08-23 16:50:37 -07001025
1026 // First DFS: write all buffers and resolve pointers for parent
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001027 for (const auto &arg : method->results()) {
Iliyan Malchev639bff82016-08-13 14:24:11 -07001028 emitCppReaderWriter(
1029 out,
1030 "_hidl_reply",
1031 false /* parcelObjIsPointer */,
1032 arg,
1033 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001034 Type::ErrorMode_Goto,
1035 true /* addPrefixToName */);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001036 }
1037
Yifan Hongbf459bc2016-08-23 16:50:37 -07001038 // Second DFS: resolve references.
1039 for (const auto &arg : method->results()) {
1040 emitCppResolveReferences(
1041 out,
1042 "_hidl_reply",
1043 false /* parcelObjIsPointer */,
1044 arg,
1045 true /* reader */,
1046 Type::ErrorMode_Goto,
1047 true /* addPrefixToName */);
1048 }
1049
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001050 if (returnsValue && elidedReturn == nullptr) {
Iliyan Malchev639bff82016-08-13 14:24:11 -07001051 out << "_hidl_cb(";
1052
1053 bool first = true;
1054 for (const auto &arg : method->results()) {
1055 if (!first) {
1056 out << ", ";
1057 }
1058
1059 if (arg->type().resultNeedsDeref()) {
1060 out << "*";
1061 }
Andreas Huber5e44a292016-09-27 14:52:39 -07001062 out << "_hidl_out_" << arg->name();
Iliyan Malchev639bff82016-08-13 14:24:11 -07001063
1064 first = false;
1065 }
1066
Steven Moreland67f67b42016-09-29 08:59:02 -07001067 out << ");\n\n";
Iliyan Malchev639bff82016-08-13 14:24:11 -07001068 }
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001069 status_t status = generateCppInstrumentationCall(
1070 out,
1071 InstrumentationEvent::CLIENT_API_EXIT,
1072 superInterface,
1073 method);
1074 if (status != OK) {
1075 return status;
1076 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001077 }
1078
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001079 if (elidedReturn != nullptr) {
1080 std::string extra;
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001081 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchev2b6591b2016-08-18 19:15:19 -07001082 out << "return ::android::hardware::Return<";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001083 out << elidedReturn->type().getCppResultType(&extra)
Andreas Huber5e44a292016-09-27 14:52:39 -07001084 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001085 } else {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001086 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001087 out << "return ::android::hardware::Return<void>();\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001088 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001089
Andreas Huber881227d2016-08-02 14:20:21 -07001090 out.unindent();
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001091 out << "_hidl_error:\n";
1092 out.indent();
1093 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1094 out << "return ::android::hardware::Return<";
1095 if (elidedReturn != nullptr) {
1096 std::string extra;
1097 out << method->results().at(0)->type().getCppResultType(&extra);
1098 } else {
1099 out << "void";
1100 }
1101 out << ">(_hidl_status);\n";
1102
1103 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -07001104 out << "}\n\n";
1105 }
Andreas Huber881227d2016-08-02 14:20:21 -07001106 }
1107
1108 return OK;
1109}
1110
1111status_t AST::generateStubSource(
1112 Formatter &out, const std::string &baseName) const {
1113 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1114 << baseName
1115 << ", \""
1116 << mPackage.string()
1117 << "::I"
1118 << baseName
1119 << "\");\n\n";
1120
1121 const std::string klassName = "Bn" + baseName;
1122
Steven Moreland40786312016-08-16 10:29:40 -07001123 out << klassName
1124 << "::"
1125 << klassName
1126 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1127
1128 out.indent();
1129 out.indent();
1130
1131 out << ": BnInterface"
1132 << "<I"
1133 << baseName
1134 << ", IHw"
1135 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001136 << ">(_hidl_impl),\n"
1137 << " HidlInstrumentor(\""
1138 << mPackage.string()
1139 << "::I"
1140 << baseName
1141 << "\") {\n";
Steven Moreland40786312016-08-16 10:29:40 -07001142
1143 out.unindent();
1144 out.unindent();
1145 out << "}\n\n";
1146
Andreas Huber881227d2016-08-02 14:20:21 -07001147 out << "::android::status_t " << klassName << "::onTransact(\n";
1148
1149 out.indent();
1150 out.indent();
1151
Iliyan Malchev549e2592016-08-10 08:59:12 -07001152 out << "uint32_t _hidl_code,\n"
1153 << "const ::android::hardware::Parcel &_hidl_data,\n"
1154 << "::android::hardware::Parcel *_hidl_reply,\n"
1155 << "uint32_t _hidl_flags,\n"
1156 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001157
1158 out.unindent();
1159
Iliyan Malchev549e2592016-08-10 08:59:12 -07001160 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001161 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001162 out.indent();
1163
1164 const Interface *iface = mRootScope->getInterface();
1165
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001166 std::vector<const Interface *> chain;
1167 while (iface != NULL) {
1168 chain.push_back(iface);
1169 iface = iface->superType();
1170 }
Andreas Huber881227d2016-08-02 14:20:21 -07001171
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001172 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
1173 const Interface *superInterface = *it;
Andreas Huber881227d2016-08-02 14:20:21 -07001174
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001175 for (const auto &method : superInterface->methods()) {
1176 out << "case "
Steven Morelandef1a9fe2016-10-06 17:19:09 -07001177 << method->getSerialId()
1178 << " /* "
1179 << method->name()
1180 << " */:\n{\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001181
1182 out.indent();
1183
1184 status_t err =
1185 generateStubSourceForMethod(out, superInterface, method);
1186
1187 if (err != OK) {
1188 return err;
1189 }
1190
1191 out.unindent();
1192 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001193 }
Andreas Huber881227d2016-08-02 14:20:21 -07001194 }
1195
1196 out << "default:\n{\n";
1197 out.indent();
1198
Andreas Huber8a82ff72016-08-04 10:29:39 -07001199 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001200 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001201 << ">::onTransact(\n";
1202
1203 out.indent();
1204 out.indent();
1205
Iliyan Malchev549e2592016-08-10 08:59:12 -07001206 out << "_hidl_code, _hidl_data, _hidl_reply, "
1207 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001208
1209 out.unindent();
1210 out.unindent();
1211
1212 out.unindent();
1213 out << "}\n";
1214
1215 out.unindent();
1216 out << "}\n\n";
1217
Iliyan Malchev549e2592016-08-10 08:59:12 -07001218 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001219 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001220 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001221 out.indent();
1222 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001223 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001224 out.indent();
1225 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001226 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001227 out.unindent();
1228 out.unindent();
1229 out.unindent();
1230 out.unindent();
1231
1232 out.unindent();
1233 out << "}\n\n";
1234
Iliyan Malchev549e2592016-08-10 08:59:12 -07001235 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001236
1237 out.unindent();
1238 out << "}\n\n";
1239
1240 return OK;
1241}
1242
1243status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001244 Formatter &out, const Interface *iface, const Method *method) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -07001245 out << "if (!_hidl_data.enforceInterface("
Steven Moreland40786312016-08-16 10:29:40 -07001246 << iface->fqName().cppNamespace()
1247 << "::IHw"
1248 << iface->getBaseName()
1249 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001250
Andreas Huber881227d2016-08-02 14:20:21 -07001251 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001252 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001253 out << "break;\n";
1254 out.unindent();
1255 out << "}\n\n";
1256
Andreas Huber5e44a292016-09-27 14:52:39 -07001257 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001258
Yifan Hongbf459bc2016-08-23 16:50:37 -07001259 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001260 for (const auto &arg : method->args()) {
1261 emitCppReaderWriter(
1262 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001263 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001264 false /* parcelObjIsPointer */,
1265 arg,
1266 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001267 Type::ErrorMode_Break,
1268 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001269 }
1270
Yifan Hongbf459bc2016-08-23 16:50:37 -07001271 // Second DFS: resolve references
1272 for (const auto &arg : method->args()) {
1273 emitCppResolveReferences(
1274 out,
1275 "_hidl_data",
1276 false /* parcelObjIsPointer */,
1277 arg,
1278 true /* reader */,
1279 Type::ErrorMode_Break,
1280 false /* addPrefixToName */);
1281 }
1282
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001283 status_t status = generateCppInstrumentationCall(
1284 out,
1285 InstrumentationEvent::SERVER_API_ENTRY,
1286 iface,
1287 method);
1288 if (status != OK) {
1289 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001290 }
1291
Andreas Huber881227d2016-08-02 14:20:21 -07001292 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001293 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001294
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001295 if (elidedReturn != nullptr) {
1296 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001297
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001298 out << elidedReturn->type().getCppResultType(&extra) << " ";
1299 out << elidedReturn->name() << " = ";
1300 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001301
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001302 bool first = true;
1303 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001304 if (!first) {
1305 out << ", ";
1306 }
1307
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001308 if (arg->type().resultNeedsDeref()) {
1309 out << "*";
1310 }
1311
1312 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001313
1314 first = false;
1315 }
1316
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001317 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001318 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001319 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001320
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001321 elidedReturn->type().emitReaderWriter(
1322 out,
1323 elidedReturn->name(),
1324 "_hidl_reply",
1325 true, /* parcelObjIsPointer */
1326 false, /* isReader */
1327 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001328
Yifan Hongbf459bc2016-08-23 16:50:37 -07001329 emitCppResolveReferences(
1330 out,
1331 "_hidl_reply",
1332 true /* parcelObjIsPointer */,
1333 elidedReturn,
1334 false /* reader */,
1335 Type::ErrorMode_Ignore,
1336 false /* addPrefixToName */);
1337
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001338 status_t status = generateCppInstrumentationCall(
1339 out,
1340 InstrumentationEvent::SERVER_API_EXIT,
1341 iface,
1342 method);
1343 if (status != OK) {
1344 return status;
1345 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001346
Iliyan Malchev549e2592016-08-10 08:59:12 -07001347 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001348 } else {
1349 if (returnsValue) {
1350 out << "bool _hidl_callbackCalled = false;\n\n";
1351 }
Andreas Huber881227d2016-08-02 14:20:21 -07001352
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001353 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001354
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001355 bool first = true;
1356 for (const auto &arg : method->args()) {
1357 if (!first) {
1358 out << ", ";
1359 }
Andreas Huber881227d2016-08-02 14:20:21 -07001360
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001361 if (arg->type().resultNeedsDeref()) {
1362 out << "*";
1363 }
1364
1365 out << arg->name();
1366
1367 first = false;
1368 }
1369
1370 if (returnsValue) {
1371 if (!first) {
1372 out << ", ";
1373 }
1374
1375 out << "[&](";
1376
1377 first = true;
1378 for (const auto &arg : method->results()) {
1379 if (!first) {
1380 out << ", ";
1381 }
1382
1383 out << "const auto &" << arg->name();
1384
1385 first = false;
1386 }
1387
1388 out << ") {\n";
1389 out.indent();
1390 out << "_hidl_callbackCalled = true;\n\n";
1391
1392 out << "::android::hardware::Status::ok()"
1393 << ".writeToParcel(_hidl_reply);\n\n";
1394
Yifan Hongbf459bc2016-08-23 16:50:37 -07001395 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001396 for (const auto &arg : method->results()) {
1397 emitCppReaderWriter(
1398 out,
1399 "_hidl_reply",
1400 true /* parcelObjIsPointer */,
1401 arg,
1402 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001403 Type::ErrorMode_Ignore,
1404 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001405 }
1406
Yifan Hongbf459bc2016-08-23 16:50:37 -07001407 // Second DFS: resolve references
1408 for (const auto &arg : method->results()) {
1409 emitCppResolveReferences(
1410 out,
1411 "_hidl_reply",
1412 true /* parcelObjIsPointer */,
1413 arg,
1414 false /* reader */,
1415 Type::ErrorMode_Ignore,
1416 false /* addPrefixToName */);
1417 }
1418
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001419 status_t status = generateCppInstrumentationCall(
1420 out,
1421 InstrumentationEvent::SERVER_API_EXIT,
1422 iface,
1423 method);
1424 if (status != OK) {
1425 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001426 }
1427
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001428 out << "_hidl_cb(*_hidl_reply);\n";
1429
1430 out.unindent();
1431 out << "}\n";
1432 }
1433
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001434 out << ");\n\n";
1435
1436 // What to do if the stub implementation has a synchronous callback
1437 // which does not get invoked? This is not a transport error but a
1438 // service error of sorts. For now, return OK to the caller, as this is
1439 // not a transport error.
1440 //
1441 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001442
1443 if (returnsValue) {
1444 out << "if (!_hidl_callbackCalled) {\n";
1445 out.indent();
1446 }
1447
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001448 out << "::android::hardware::Status::ok()"
1449 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001450
1451 if (returnsValue) {
1452 out.unindent();
1453 out << "}\n\n";
1454 }
Andreas Huber881227d2016-08-02 14:20:21 -07001455 }
1456
1457 out << "break;\n";
1458
1459 return OK;
1460}
1461
Steven Moreland69e7c702016-09-09 11:16:32 -07001462status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1463 std::string ifaceName;
1464 if (!AST::isInterface(&ifaceName)) {
1465 // types.hal does not get a stub header.
1466 return OK;
1467 }
1468
1469 const Interface *iface = mRootScope->getInterface();
1470
1471 const std::string baseName = iface->getBaseName();
1472 const std::string klassName = "Bs" + baseName;
1473
1474 bool supportOneway = iface->hasOnewayMethods();
1475
1476 std::string path = outputPath;
1477 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1478 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1479 path.append(klassName);
1480 path.append(".h");
1481
1482 CHECK(Coordinator::MakeParentHierarchy(path));
1483 FILE *file = fopen(path.c_str(), "w");
1484
1485 if (file == NULL) {
1486 return -errno;
1487 }
1488
1489 Formatter out(file);
1490
1491 const std::string guard = makeHeaderGuard(klassName);
1492
1493 out << "#ifndef " << guard << "\n";
1494 out << "#define " << guard << "\n\n";
1495
1496 std::vector<std::string> packageComponents;
1497 getPackageAndVersionComponents(
1498 &packageComponents, false /* cpp_compatible */);
1499
1500 out << "#include <future>\n";
1501 out << "#include <";
1502 for (const auto &component : packageComponents) {
1503 out << component << "/";
1504 }
1505 out << ifaceName << ".h>\n\n";
1506
1507 if (supportOneway) {
1508 out << "#include <hidl/SynchronizedQueue.h>\n";
1509 }
1510
1511 enterLeaveNamespace(out, true /* enter */);
1512 out << "\n";
1513
1514 out << "struct "
1515 << klassName
1516 << " : " << ifaceName
1517 << " {\n";
1518
1519 out.indent();
1520 out << "explicit "
1521 << klassName
1522 << "(const sp<"
1523 << ifaceName
1524 << "> impl);\n";
1525
1526 status_t err = generateMethods(out,
1527 "" /* class name */,
1528 MethodLocation::PASSTHROUGH_HEADER,
1529 true /* specify namespaces */);
1530
1531 if (err != OK) {
1532 return err;
1533 }
1534
1535 out.unindent();
1536 out << "private:\n";
1537 out.indent();
1538 out << "const sp<" << ifaceName << "> mImpl;\n";
1539
1540 if (supportOneway) {
1541 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1542 out << "std::thread *mOnewayThread = nullptr;\n";
1543
1544 out << "\n";
1545
1546 out << "::android::hardware::Return<void> addOnewayTask("
1547 "std::function<void(void)>);\n\n";
1548
1549 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1550 }
1551
1552 out.unindent();
1553
1554 out << "};\n\n";
1555
1556 enterLeaveNamespace(out, false /* enter */);
1557
1558 out << "\n#endif // " << guard << "\n";
1559
1560 return OK;
1561}
1562
1563
1564status_t AST::generatePassthroughSource(Formatter &out) const {
1565 const Interface *iface = mRootScope->getInterface();
1566
1567 const std::string baseName = iface->getBaseName();
1568 const std::string klassName = "Bs" + baseName;
1569
1570 out << klassName
1571 << "::"
1572 << klassName
1573 << "(const sp<"
1574 << iface->fullName()
1575 << "> impl) : mImpl(impl) {}\n\n";
1576
1577 if (iface->hasOnewayMethods()) {
1578 out << "::android::hardware::Return<void> "
1579 << klassName
1580 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1581 out.indent();
1582 out << "if (mOnewayThread == nullptr) {\n";
1583 out.indent();
1584 out << "mOnewayThread = new std::thread([this]() {\n";
1585 out.indent();
1586 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1587 out.unindent();
1588 out << "});\n";
1589 out.unindent();
1590 out << "}\n\n";
1591
1592 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1593 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001594 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1595 out.indent();
1596 out.indent();
1597 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1598 out.unindent();
1599 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001600 out.unindent();
1601 out << "} else {\n";
1602 out.indent();
1603 out << "mOnewayQueue.push(fun);\n";
1604 out.unindent();
1605 out << "}\n";
1606
Steven Morelandd366c262016-10-11 15:29:10 -07001607 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001608
1609 out.unindent();
1610 out << "}\n\n";
1611
1612
1613 }
1614
1615 return OK;
1616}
1617
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001618status_t AST::generateCppInstrumentationCall(
1619 Formatter &out,
1620 InstrumentationEvent event,
1621 const Interface *iface, const Method *method) const {
1622 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1623 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001624 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001625 std::string event_str = "";
1626 switch (event) {
1627 case SERVER_API_ENTRY:
1628 {
1629 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1630 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001631 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001632 << (arg->type().resultNeedsDeref() ? "" : "&")
1633 << arg->name()
1634 << ");\n";
1635 }
1636 break;
1637 }
1638 case SERVER_API_EXIT:
1639 {
1640 event_str = "InstrumentationEvent::SERVER_API_EXIT";
1641 const TypedVar *elidedReturn = method->canElideCallback();
1642 if (elidedReturn != nullptr) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001643 out << "_hidl_args.push_back((void *)&"
1644 << elidedReturn->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001645 << ");\n";
1646 } else {
1647 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001648 out << "_hidl_args.push_back((void *)&"
1649 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001650 << ");\n";
1651 }
1652 }
1653 break;
1654 }
1655 case CLIENT_API_ENTRY:
1656 {
1657 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1658 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001659 out << "_hidl_args.push_back((void *)&"
1660 << arg->name()
1661 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001662 }
1663 break;
1664 }
1665 case CLIENT_API_EXIT:
1666 {
1667 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1668 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001669 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001670 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001671 << "_hidl_out_"
1672 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001673 << ");\n";
1674 }
1675 break;
1676 }
1677 case SYNC_CALLBACK_ENTRY:
1678 case SYNC_CALLBACK_EXIT:
1679 case ASYNC_CALLBACK_ENTRY:
1680 case ASYNC_CALLBACK_EXIT:
1681 {
1682 LOG(ERROR) << "Not supported instrumentation event: " << event;
1683 return UNKNOWN_ERROR;
1684 }
1685 }
1686
1687 out << "for (auto callback: mInstrumentationCallbacks) {\n";
1688 out.indent();
1689 out << "callback("
1690 << event_str
1691 << ", \""
1692 << mPackage.package()
1693 << "\", \""
1694 << mPackage.getPackageFullVersion()
1695 << "\", \""
1696 << iface->localName()
1697 << "\", \""
1698 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001699 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001700 out.unindent();
1701 out << "}\n";
1702 out.unindent();
1703 out << "}\n\n";
1704
1705 return OK;
1706}
1707
Andreas Huber881227d2016-08-02 14:20:21 -07001708} // namespace android
1709