blob: 8e63349240da085da6c74f922fbb7d938104b2f5 [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) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700172 out << " : virtual public IHidlInterfaceBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700173 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000174 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700175 << 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";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700202 out << "virtual bool isRemote() const override { 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
Yifan Hong10fe0b52016-10-19 14:20:17 -0700256 out << ")";
257 if (method->isHidlReserved()) {
258 out << " override";
259 out << " {\n";
260 out.indent();
261 method->cppImpl(out);
262 out.unindent();
263 out << "\n}\n";
264 } else {
265 out << " = 0;\n";
266 }
Andreas Huber881227d2016-08-02 14:20:21 -0700267 }
Steven Moreland40786312016-08-16 10:29:40 -0700268
Yifan Hong10fe0b52016-10-19 14:20:17 -0700269 out << "\nstatic const ::android::String16 descriptor;\n\n";
270
Steven Moreland40786312016-08-16 10:29:40 -0700271 out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700272 }
273
274 if (isInterface) {
275 out.unindent();
276
Andreas Hubere3f769a2016-10-10 10:54:44 -0700277 out << "};\n\n";
278 }
279
280 err = mRootScope->emitGlobalTypeDeclarations(out);
281
282 if (err != OK) {
283 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700284 }
285
286 out << "\n";
287 enterLeaveNamespace(out, false /* enter */);
288
289 out << "\n#endif // " << guard << "\n";
290
291 return OK;
292}
293
Steven Moreland40786312016-08-16 10:29:40 -0700294status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
295 std::string ifaceName;
296 if(!AST::isInterface(&ifaceName)) {
297 // types.hal does not get an HwBinder header.
298 return OK;
299 }
300
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700301 const Interface *iface = mRootScope->getInterface();
302 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700303
304 const std::string klassName = "IHw" + baseName;
305
306 std::string path = outputPath;
307 path.append(mCoordinator->convertPackageRootToPath(mPackage));
308 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
309 path.append(klassName + ".h");
310
311 FILE* file = fopen(path.c_str(), "w");
312
313 if (file == NULL) {
314 return -errno;
315 }
316
317 Formatter out(file);
318
319 const std::string guard = makeHeaderGuard(klassName);
320
321 out << "#ifndef " << guard << "\n";
322 out << "#define " << guard << "\n\n";
323
324 std::vector<std::string> packageComponents;
325 getPackageAndVersionComponents(
326 &packageComponents, false /* cpp_compatible */);
327
328 out << "#include <";
329 for (const auto &component : packageComponents) {
330 out << component << "/";
331 }
332 out << ifaceName << ".h>\n\n";
333
334 for (const auto &item : mImportedNames) {
335 if (item.name() == "types") {
336 continue;
337 }
338
339 out << "#include <";
340
341 std::vector<std::string> components;
342 item.getPackageAndVersionComponents(
343 &components, false /* cpp_compatible */);
344
345 for (const auto &component : components) {
346 out << component << "/";
347 }
348
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700349 const std::string itemBaseName = item.getInterfaceBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700350
351 out << "Bn"
352 << itemBaseName
353 << ".h>\n";
354 }
355
356 out << "\n";
357
358 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200359 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700360 out << "#include <hwbinder/IBinder.h>\n";
361 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700362
363 out << "\n";
364
365 enterLeaveNamespace(out, true /* enter */);
366 out << "\n";
367
368 out << "struct "
369 << klassName
370 << " : public "
371 << ifaceName;
372
Steven Moreland40786312016-08-16 10:29:40 -0700373 const Interface *superType = iface->superType();
374
375 out << ", public ::android::hardware::IInterface";
376
377 out << " {\n";
378
379 out.indent();
380
381 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
382
Steven Moreland40786312016-08-16 10:29:40 -0700383 out.unindent();
384
385 out << "};\n\n";
386
387 enterLeaveNamespace(out, false /* enter */);
388
389 out << "\n#endif // " << guard << "\n";
390
391 return OK;
392}
393
Andreas Huber881227d2016-08-02 14:20:21 -0700394status_t AST::emitTypeDeclarations(Formatter &out) const {
395 return mRootScope->emitTypeDeclarations(out);
396}
397
Steven Morelanda7a421a2016-09-07 08:35:18 -0700398status_t AST::generateStubMethod(Formatter &out,
399 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700400 const Method *method,
401 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700402 out << "inline ";
403
Steven Moreland979e0992016-09-07 09:18:08 -0700404 method->generateCppSignature(out,
405 className,
406 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700407
408 const bool returnsValue = !method->results().empty();
409 const TypedVar *elidedReturn = method->canElideCallback();
410 out << " {\n";
411 out.indent();
412 out << "return mImpl->"
413 << method->name()
414 << "(";
415 bool first = true;
416 for (const auto &arg : method->args()) {
417 if (!first) {
418 out << ", ";
419 }
420 first = false;
421 out << arg->name();
422 }
423 if (returnsValue && elidedReturn == nullptr) {
424 if (!method->args().empty()) {
425 out << ", ";
426 }
427
428 out << "_hidl_cb";
429 }
430 out << ");\n";
431 out.unindent();
432 out << "}";
433
434 out << ";\n";
435
436 return OK;
437}
438
Steven Moreland9c387612016-09-07 09:54:26 -0700439status_t AST::generateProxyDeclaration(Formatter &out,
440 const std::string &className,
441 const Method *method,
442 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700443
Steven Moreland979e0992016-09-07 09:18:08 -0700444 method->generateCppSignature(out,
445 className,
446 specifyNamespaces);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700447 out << " override;\n";
448
449 return OK;
450}
451
Steven Moreland69e7c702016-09-09 11:16:32 -0700452
453status_t AST::generatePassthroughMethod(Formatter &out,
454 const std::string &className,
455 const Method *method,
456 bool specifyNamespaces) const {
457 method->generateCppSignature(out, className, specifyNamespaces);
458
459 out << " {\n";
460 out.indent();
461
462 const bool returnsValue = !method->results().empty();
463 const TypedVar *elidedReturn = method->canElideCallback();
464
Steven Moreland67f67b42016-09-29 08:59:02 -0700465 if (returnsValue && elidedReturn == nullptr) {
466 generateCheckNonNull(out, "_hidl_cb");
467 }
468
Steven Moreland69e7c702016-09-09 11:16:32 -0700469 out << "return ";
470
471 if (method->isOneway()) {
472 out << "addOnewayTask([this";
473 for (const auto &arg : method->args()) {
474 out << ", " << arg->name();
475 }
476 out << "] {this->";
477 }
478
479 out << "mImpl->"
480 << method->name()
481 << "(";
482
483 bool first = true;
484 for (const auto &arg : method->args()) {
485 if (!first) {
486 out << ", ";
487 }
488 first = false;
489 out << arg->name();
490 }
491 if (returnsValue && elidedReturn == nullptr) {
492 if (!method->args().empty()) {
493 out << ", ";
494 }
495
496 out << "_hidl_cb";
497 }
498 out << ")";
499
500 if (method->isOneway()) {
501 out << ";})";
502 }
503 out << ";\n";
504
505 out.unindent();
506 out << "}\n";
507
508 return OK;
509}
510
Steven Morelanda7a421a2016-09-07 08:35:18 -0700511status_t AST::generateMethods(
512 Formatter &out,
513 const std::string &className,
Steven Moreland979e0992016-09-07 09:18:08 -0700514 MethodLocation type,
515 bool specifyNamespaces) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700516
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700517 const Interface *iface = mRootScope->getInterface();
518
Yifan Hong10fe0b52016-10-19 14:20:17 -0700519 const Interface *prevIterface = nullptr;
520 for (const auto &tuple : iface->allMethodsFromRoot()) {
521 const Method *method = tuple.method();
522 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700523
Yifan Hong10fe0b52016-10-19 14:20:17 -0700524 if(prevIterface != superInterface) {
525 if (prevIterface != nullptr) {
526 out << "\n";
527 }
528 out << "// Methods from "
529 << superInterface->fullName()
530 << " follow.\n";
531 prevIterface = superInterface;
532 }
533 status_t err;
534 switch(type) {
535 case STUB_HEADER:
536 err = generateStubMethod(out,
537 className,
538 method,
539 specifyNamespaces);
540 break;
541 case PROXY_HEADER:
542 err = generateProxyDeclaration(out,
543 className,
544 method,
545 specifyNamespaces);
546 break;
547 case IMPL_HEADER:
548 err = generateStubImplDeclaration(out,
549 className,
550 method,
551 specifyNamespaces);
552 break;
553 case IMPL_SOURCE:
554 err = generateStubImplMethod(out,
Steven Morelanda7a421a2016-09-07 08:35:18 -0700555 className,
Steven Moreland979e0992016-09-07 09:18:08 -0700556 method,
557 specifyNamespaces);
Yifan Hong10fe0b52016-10-19 14:20:17 -0700558 break;
559 case PASSTHROUGH_HEADER:
560 err = generatePassthroughMethod(out,
561 className,
562 method,
563 specifyNamespaces);
564 break;
565 default:
566 LOG(ERROR) << "Unkown method type: " << type;
567 err = UNKNOWN_ERROR;
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700568 }
569
Yifan Hong10fe0b52016-10-19 14:20:17 -0700570 if (err != OK) {
571 return err;
572 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700573 }
574
Yifan Hong10fe0b52016-10-19 14:20:17 -0700575 out << "\n";
576
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700577 return OK;
578}
579
Andreas Huberb82318c2016-08-02 14:45:54 -0700580status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700581 std::string ifaceName;
582 if (!AST::isInterface(&ifaceName)) {
583 // types.hal does not get a stub header.
584 return OK;
585 }
586
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700587 const Interface *iface = mRootScope->getInterface();
588 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700589 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700590
Andreas Huberb82318c2016-08-02 14:45:54 -0700591 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700592 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700593 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700594 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700595 path.append(".h");
596
Andreas Huberd2943e12016-08-05 11:59:31 -0700597 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700598 FILE *file = fopen(path.c_str(), "w");
599
600 if (file == NULL) {
601 return -errno;
602 }
603
604 Formatter out(file);
605
Steven Moreland40786312016-08-16 10:29:40 -0700606 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700607
608 out << "#ifndef " << guard << "\n";
609 out << "#define " << guard << "\n\n";
610
611 std::vector<std::string> packageComponents;
612 getPackageAndVersionComponents(
613 &packageComponents, false /* cpp_compatible */);
614
615 out << "#include <";
616 for (const auto &component : packageComponents) {
617 out << component << "/";
618 }
Steven Moreland40786312016-08-16 10:29:40 -0700619 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700620
621 enterLeaveNamespace(out, true /* enter */);
622 out << "\n";
623
624 out << "struct "
625 << "Bn"
626 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700627 << " : public ::android::hardware::BnInterface<I"
628 << baseName << ", IHw" << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700629 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700630
631 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700632 out << "explicit Bn"
633 << baseName
634 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
635 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700636 out << "::android::status_t onTransact(\n";
637 out.indent();
638 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700639 out << "uint32_t _hidl_code,\n";
640 out << "const ::android::hardware::Parcel &_hidl_data,\n";
641 out << "::android::hardware::Parcel *_hidl_reply,\n";
642 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700643 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700644 out.unindent();
645 out.unindent();
646
Steven Moreland9c387612016-09-07 09:54:26 -0700647 status_t err = generateMethods(out,
648 "" /* class name */,
649 MethodLocation::STUB_HEADER,
650 true /* specify namespaces */);
651
652 if (err != OK) {
653 return err;
654 }
655
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700656
Andreas Huber881227d2016-08-02 14:20:21 -0700657 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700658 out << "};\n\n";
659
660 enterLeaveNamespace(out, false /* enter */);
661
662 out << "\n#endif // " << guard << "\n";
663
664 return OK;
665}
666
Andreas Huberb82318c2016-08-02 14:45:54 -0700667status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700668 std::string ifaceName;
669 if (!AST::isInterface(&ifaceName)) {
670 // types.hal does not get a proxy header.
671 return OK;
672 }
673
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700674 const Interface *iface = mRootScope->getInterface();
675 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700676
Andreas Huberb82318c2016-08-02 14:45:54 -0700677 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700678 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700679 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700680 path.append("Bp");
681 path.append(baseName);
682 path.append(".h");
683
Andreas Huberd2943e12016-08-05 11:59:31 -0700684 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700685 FILE *file = fopen(path.c_str(), "w");
686
687 if (file == NULL) {
688 return -errno;
689 }
690
691 Formatter out(file);
692
693 const std::string guard = makeHeaderGuard("Bp" + baseName);
694
695 out << "#ifndef " << guard << "\n";
696 out << "#define " << guard << "\n\n";
697
698 std::vector<std::string> packageComponents;
699 getPackageAndVersionComponents(
700 &packageComponents, false /* cpp_compatible */);
701
702 out << "#include <";
703 for (const auto &component : packageComponents) {
704 out << component << "/";
705 }
Steven Moreland40786312016-08-16 10:29:40 -0700706 out << "IHw" << baseName << ".h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700707
708 enterLeaveNamespace(out, true /* enter */);
709 out << "\n";
710
711 out << "struct "
712 << "Bp"
713 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700714 << " : public ::android::hardware::BpInterface<IHw"
715 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700716 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700717
718 out.indent();
719
720 out << "explicit Bp"
721 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700722 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700723 << "\n\n";
724
Yifan Hong10fe0b52016-10-19 14:20:17 -0700725 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700726
Steven Moreland9c387612016-09-07 09:54:26 -0700727 status_t err = generateMethods(out,
728 "" /* class name */,
729 MethodLocation::PROXY_HEADER,
730 true /* generate specify namespaces */);
731
732 if (err != OK) {
733 return err;
734 }
Andreas Huber881227d2016-08-02 14:20:21 -0700735
736 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700737 out << "};\n\n";
738
739 enterLeaveNamespace(out, false /* enter */);
740
741 out << "\n#endif // " << guard << "\n";
742
743 return OK;
744}
745
Andreas Huberb82318c2016-08-02 14:45:54 -0700746status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700747
Andreas Huberb82318c2016-08-02 14:45:54 -0700748 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700749 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700750 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700751
752 std::string ifaceName;
753 std::string baseName;
754
755 bool isInterface = true;
756 if (!AST::isInterface(&ifaceName)) {
757 baseName = "types";
758 isInterface = false;
759 } else {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700760 const Interface *iface = mRootScope->getInterface();
761 baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700762 }
763
764 path.append(baseName);
765
766 if (baseName != "types") {
767 path.append("All");
768 }
769
770 path.append(".cpp");
771
Andreas Huberd2943e12016-08-05 11:59:31 -0700772 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700773 FILE *file = fopen(path.c_str(), "w");
774
775 if (file == NULL) {
776 return -errno;
777 }
778
779 Formatter out(file);
780
781 std::vector<std::string> packageComponents;
782 getPackageAndVersionComponents(
783 &packageComponents, false /* cpp_compatible */);
784
785 std::string prefix;
786 for (const auto &component : packageComponents) {
787 prefix += component;
788 prefix += "/";
789 }
790
791 if (isInterface) {
792 out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
793 out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700794 out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700795 } else {
796 out << "#include <" << prefix << "types.h>\n";
797 }
798
799 out << "\n";
800
801 enterLeaveNamespace(out, true /* enter */);
802 out << "\n";
803
804 status_t err = generateTypeSource(out, ifaceName);
805
806 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700807 const Interface *iface = mRootScope->getInterface();
Martijn Coenena21f1492016-09-08 15:55:14 +0200808 out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700809
810 // need to be put here, generateStubSource is using this.
811 out << "const ::android::String16 I"
812 << iface->getBaseName()
813 << "::descriptor(\""
814 << iface->fqName().string()
815 << "\");\n\n";
816
Andreas Huber881227d2016-08-02 14:20:21 -0700817 err = generateProxySource(out, baseName);
818 }
819
820 if (err == OK && isInterface) {
821 err = generateStubSource(out, baseName);
822 }
823
Steven Moreland40786312016-08-16 10:29:40 -0700824 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700825 err = generatePassthroughSource(out);
826 }
827
828 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700829 const Interface *iface = mRootScope->getInterface();
830
831 out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
832 << baseName << ", "
833 << "\"" << iface->fqName().package()
Iliyan Malchev4923f932016-09-09 13:04:59 -0700834 << iface->fqName().version() << "-impl.so\""
Steven Moreland9c387612016-09-07 09:54:26 -0700835 << ")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700836 }
837
Andreas Huber881227d2016-08-02 14:20:21 -0700838 enterLeaveNamespace(out, false /* enter */);
839
840 return err;
841}
842
Steven Moreland67f67b42016-09-29 08:59:02 -0700843// static
844void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
845 out << "if (" << nonNull << " == nullptr) {\n";
846 out.indent();
847 out << "return ::android::hardware::Status::fromExceptionCode(\n";
848 out.indent();
849 out.indent();
850 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
851 out.unindent();
852 out.unindent();
853 out.unindent();
854 out << "}\n\n";
855}
856
Andreas Huber881227d2016-08-02 14:20:21 -0700857status_t AST::generateTypeSource(
858 Formatter &out, const std::string &ifaceName) const {
859 return mRootScope->emitTypeDefinitions(out, ifaceName);
860}
861
Andreas Hubere7ff2282016-08-16 13:50:03 -0700862void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700863 Formatter &out,
864 const std::vector<TypedVar *> &args,
865 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700866 if (args.empty()) {
867 return;
868 }
869
870 for (const auto &arg : args) {
871 const Type &type = arg->type();
872
873 std::string extra;
874 out << type.getCppResultType(&extra)
875 << " "
Andreas Huber5e44a292016-09-27 14:52:39 -0700876 << (forResults ? "_hidl_out_" : "")
Andreas Hubere7ff2282016-08-16 13:50:03 -0700877 << arg->name()
878 << extra
879 << ";\n";
880 }
881
882 out << "\n";
883}
884
Andreas Huber881227d2016-08-02 14:20:21 -0700885void AST::emitCppReaderWriter(
886 Formatter &out,
887 const std::string &parcelObj,
888 bool parcelObjIsPointer,
889 const TypedVar *arg,
890 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700891 Type::ErrorMode mode,
892 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700893 const Type &type = arg->type();
894
Andreas Huber881227d2016-08-02 14:20:21 -0700895 type.emitReaderWriter(
896 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700897 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700898 parcelObj,
899 parcelObjIsPointer,
900 isReader,
901 mode);
902}
903
Yifan Hongbf459bc2016-08-23 16:50:37 -0700904void AST::emitCppResolveReferences(
905 Formatter &out,
906 const std::string &parcelObj,
907 bool parcelObjIsPointer,
908 const TypedVar *arg,
909 bool isReader,
910 Type::ErrorMode mode,
911 bool addPrefixToName) const {
912 const Type &type = arg->type();
913 if(type.needsResolveReferences()) {
914 type.emitResolveReferences(
915 out,
916 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
917 isReader, // nameIsPointer
918 parcelObj,
919 parcelObjIsPointer,
920 isReader,
921 mode);
922 }
923}
924
Andreas Huber881227d2016-08-02 14:20:21 -0700925status_t AST::generateProxySource(
926 Formatter &out, const std::string &baseName) const {
927 const std::string klassName = "Bp" + baseName;
928
929 out << klassName
930 << "::"
931 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700932 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700933
934 out.indent();
935 out.indent();
936
937 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -0700938 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -0700939 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700940 << ">(_hidl_impl),\n"
941 << " HidlInstrumentor(\""
942 << mPackage.string()
943 << "::I"
944 << baseName
945 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700946
Andreas Huber881227d2016-08-02 14:20:21 -0700947 out.unindent();
948 out.unindent();
949 out << "}\n\n";
950
951 const Interface *iface = mRootScope->getInterface();
952
Yifan Hong10fe0b52016-10-19 14:20:17 -0700953 for (const auto &tuple : iface->allMethodsFromRoot()) {
954 const Method *method = tuple.method();
955 const Interface *superInterface = tuple.interface();
956 method->generateCppSignature(out,
957 klassName,
958 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700959
Yifan Hong10fe0b52016-10-19 14:20:17 -0700960 const bool returnsValue = !method->results().empty();
961 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -0700962
Yifan Hong10fe0b52016-10-19 14:20:17 -0700963 out << "{\n";
Steven Morelanda7a421a2016-09-07 08:35:18 -0700964
Yifan Hong10fe0b52016-10-19 14:20:17 -0700965 out.indent();
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700966
Yifan Hong10fe0b52016-10-19 14:20:17 -0700967 if (returnsValue && elidedReturn == nullptr) {
968 generateCheckNonNull(out, "_hidl_cb");
969 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700970
Yifan Hong10fe0b52016-10-19 14:20:17 -0700971 status_t status = generateCppInstrumentationCall(
972 out,
973 InstrumentationEvent::CLIENT_API_ENTRY,
974 superInterface,
975 method);
976 if (status != OK) {
977 return status;
978 }
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700979
Yifan Hong10fe0b52016-10-19 14:20:17 -0700980 out << "::android::hardware::Parcel _hidl_data;\n";
981 out << "::android::hardware::Parcel _hidl_reply;\n";
982 out << "::android::status_t _hidl_err;\n";
983 out << "::android::hardware::Status _hidl_status;\n\n";
984
985 declareCppReaderLocals(
986 out, method->results(), true /* forResults */);
987
988 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
989 if (!method->isHidlReserved()) {
990 out << superInterface->fqName().cppNamespace()
991 << "::IHw"
992 << superInterface->getBaseName();
993 } else {
994 out << "::android::hardware::IHidlInterfaceBase";
995 }
996 out << "::descriptor);\n";
997
998 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
999
1000 // First DFS: write all buffers and resolve pointers for parent
1001 for (const auto &arg : method->args()) {
1002 emitCppReaderWriter(
1003 out,
1004 "_hidl_data",
1005 false /* parcelObjIsPointer */,
1006 arg,
1007 false /* reader */,
1008 Type::ErrorMode_Goto,
1009 false /* addPrefixToName */);
1010 }
1011
1012 // Second DFS: resolve references.
1013 for (const auto &arg : method->args()) {
1014 emitCppResolveReferences(
1015 out,
1016 "_hidl_data",
1017 false /* parcelObjIsPointer */,
1018 arg,
1019 false /* reader */,
1020 Type::ErrorMode_Goto,
1021 false /* addPrefixToName */);
1022 }
1023
1024 out << "_hidl_err = remote()->transact("
1025 << method->getSerialId()
1026 << " /* "
1027 << method->name()
1028 << " */, _hidl_data, &_hidl_reply";
1029
1030 if (method->isOneway()) {
1031 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1032 }
1033 out << ");\n";
1034
1035 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1036
1037 if (!method->isOneway()) {
1038 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
1039 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1040 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1041
1042
1043 // First DFS: write all buffers and resolve pointers for parent
1044 for (const auto &arg : method->results()) {
1045 emitCppReaderWriter(
1046 out,
1047 "_hidl_reply",
1048 false /* parcelObjIsPointer */,
1049 arg,
1050 true /* reader */,
1051 Type::ErrorMode_Goto,
1052 true /* addPrefixToName */);
Steven Moreland67f67b42016-09-29 08:59:02 -07001053 }
1054
Yifan Hong10fe0b52016-10-19 14:20:17 -07001055 // Second DFS: resolve references.
1056 for (const auto &arg : method->results()) {
1057 emitCppResolveReferences(
1058 out,
1059 "_hidl_reply",
1060 false /* parcelObjIsPointer */,
1061 arg,
1062 true /* reader */,
1063 Type::ErrorMode_Goto,
1064 true /* addPrefixToName */);
1065 }
1066
1067 if (returnsValue && elidedReturn == nullptr) {
1068 out << "_hidl_cb(";
1069
1070 bool first = true;
1071 for (const auto &arg : method->results()) {
1072 if (!first) {
1073 out << ", ";
1074 }
1075
1076 if (arg->type().resultNeedsDeref()) {
1077 out << "*";
1078 }
1079 out << "_hidl_out_" << arg->name();
1080
1081 first = false;
1082 }
1083
1084 out << ");\n\n";
1085 }
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001086 status_t status = generateCppInstrumentationCall(
1087 out,
Yifan Hong10fe0b52016-10-19 14:20:17 -07001088 InstrumentationEvent::CLIENT_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001089 superInterface,
1090 method);
1091 if (status != OK) {
1092 return status;
1093 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001094 }
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001095
Yifan Hong10fe0b52016-10-19 14:20:17 -07001096 if (elidedReturn != nullptr) {
1097 std::string extra;
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001098 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1099 out << "return ::android::hardware::Return<";
Yifan Hong10fe0b52016-10-19 14:20:17 -07001100 out << elidedReturn->type().getCppResultType(&extra)
1101 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1102 } else {
1103 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1104 out << "return ::android::hardware::Return<void>();\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001105 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001106
1107 out.unindent();
1108 out << "_hidl_error:\n";
1109 out.indent();
1110 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1111 out << "return ::android::hardware::Return<";
1112 if (elidedReturn != nullptr) {
1113 std::string extra;
1114 out << method->results().at(0)->type().getCppResultType(&extra);
1115 } else {
1116 out << "void";
1117 }
1118 out << ">(_hidl_status);\n";
1119
1120 out.unindent();
1121 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001122 }
1123
Yifan Hong10fe0b52016-10-19 14:20:17 -07001124
Andreas Huber881227d2016-08-02 14:20:21 -07001125 return OK;
1126}
1127
1128status_t AST::generateStubSource(
1129 Formatter &out, const std::string &baseName) const {
1130 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1131 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001132 << ", "
1133 << mPackage.cppNamespace()
Andreas Huber881227d2016-08-02 14:20:21 -07001134 << "::I"
1135 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001136 << "::descriptor);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001137
1138 const std::string klassName = "Bn" + baseName;
1139
Steven Moreland40786312016-08-16 10:29:40 -07001140 out << klassName
1141 << "::"
1142 << klassName
1143 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1144
1145 out.indent();
1146 out.indent();
1147
1148 out << ": BnInterface"
1149 << "<I"
1150 << baseName
1151 << ", IHw"
1152 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001153 << ">(_hidl_impl),\n"
1154 << " HidlInstrumentor(\""
1155 << mPackage.string()
1156 << "::I"
1157 << baseName
1158 << "\") {\n";
Steven Moreland40786312016-08-16 10:29:40 -07001159
1160 out.unindent();
1161 out.unindent();
1162 out << "}\n\n";
1163
Andreas Huber881227d2016-08-02 14:20:21 -07001164 out << "::android::status_t " << klassName << "::onTransact(\n";
1165
1166 out.indent();
1167 out.indent();
1168
Iliyan Malchev549e2592016-08-10 08:59:12 -07001169 out << "uint32_t _hidl_code,\n"
1170 << "const ::android::hardware::Parcel &_hidl_data,\n"
1171 << "::android::hardware::Parcel *_hidl_reply,\n"
1172 << "uint32_t _hidl_flags,\n"
1173 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001174
1175 out.unindent();
1176
Iliyan Malchev549e2592016-08-10 08:59:12 -07001177 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001178 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001179 out.indent();
1180
1181 const Interface *iface = mRootScope->getInterface();
1182
Yifan Hong10fe0b52016-10-19 14:20:17 -07001183 for (const auto &tuple : iface->allMethodsFromRoot()) {
1184 const Method *method = tuple.method();
1185 const Interface *superInterface = tuple.interface();
1186 out << "case "
1187 << method->getSerialId()
1188 << " /* "
1189 << method->name()
1190 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001191
Yifan Hong10fe0b52016-10-19 14:20:17 -07001192 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001193
Yifan Hong10fe0b52016-10-19 14:20:17 -07001194 status_t err =
1195 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001196
Yifan Hong10fe0b52016-10-19 14:20:17 -07001197 if (err != OK) {
1198 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001199 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001200
1201 out.unindent();
1202 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001203 }
1204
1205 out << "default:\n{\n";
1206 out.indent();
1207
Andreas Huber8a82ff72016-08-04 10:29:39 -07001208 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001209 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001210 << ">::onTransact(\n";
1211
1212 out.indent();
1213 out.indent();
1214
Iliyan Malchev549e2592016-08-10 08:59:12 -07001215 out << "_hidl_code, _hidl_data, _hidl_reply, "
1216 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001217
1218 out.unindent();
1219 out.unindent();
1220
1221 out.unindent();
1222 out << "}\n";
1223
1224 out.unindent();
1225 out << "}\n\n";
1226
Iliyan Malchev549e2592016-08-10 08:59:12 -07001227 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001228 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001229 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001230 out.indent();
1231 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001232 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001233 out.indent();
1234 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001235 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001236 out.unindent();
1237 out.unindent();
1238 out.unindent();
1239 out.unindent();
1240
1241 out.unindent();
1242 out << "}\n\n";
1243
Iliyan Malchev549e2592016-08-10 08:59:12 -07001244 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001245
1246 out.unindent();
1247 out << "}\n\n";
1248
1249 return OK;
1250}
1251
1252status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001253 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001254 out << "if (!_hidl_data.enforceInterface(";
1255
1256 if (!method->isHidlReserved()) {
1257 out << iface->fqName().cppNamespace()
1258 << "::IHw"
1259 << iface->getBaseName();
1260 } else {
1261 out << "::android::hardware::IHidlInterfaceBase";
1262 }
1263
1264 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001265
Andreas Huber881227d2016-08-02 14:20:21 -07001266 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001267 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001268 out << "break;\n";
1269 out.unindent();
1270 out << "}\n\n";
1271
Andreas Huber5e44a292016-09-27 14:52:39 -07001272 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001273
Yifan Hongbf459bc2016-08-23 16:50:37 -07001274 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001275 for (const auto &arg : method->args()) {
1276 emitCppReaderWriter(
1277 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001278 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001279 false /* parcelObjIsPointer */,
1280 arg,
1281 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001282 Type::ErrorMode_Break,
1283 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001284 }
1285
Yifan Hongbf459bc2016-08-23 16:50:37 -07001286 // Second DFS: resolve references
1287 for (const auto &arg : method->args()) {
1288 emitCppResolveReferences(
1289 out,
1290 "_hidl_data",
1291 false /* parcelObjIsPointer */,
1292 arg,
1293 true /* reader */,
1294 Type::ErrorMode_Break,
1295 false /* addPrefixToName */);
1296 }
1297
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001298 status_t status = generateCppInstrumentationCall(
1299 out,
1300 InstrumentationEvent::SERVER_API_ENTRY,
1301 iface,
1302 method);
1303 if (status != OK) {
1304 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001305 }
1306
Andreas Huber881227d2016-08-02 14:20:21 -07001307 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001308 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001309
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001310 if (elidedReturn != nullptr) {
1311 std::string extra;
Andreas Huber881227d2016-08-02 14:20:21 -07001312
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001313 out << elidedReturn->type().getCppResultType(&extra) << " ";
1314 out << elidedReturn->name() << " = ";
1315 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001316
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001317 bool first = true;
1318 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001319 if (!first) {
1320 out << ", ";
1321 }
1322
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001323 if (arg->type().resultNeedsDeref()) {
1324 out << "*";
1325 }
1326
1327 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001328
1329 first = false;
1330 }
1331
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001332 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001333 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001334 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001335
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001336 elidedReturn->type().emitReaderWriter(
1337 out,
1338 elidedReturn->name(),
1339 "_hidl_reply",
1340 true, /* parcelObjIsPointer */
1341 false, /* isReader */
1342 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001343
Yifan Hongbf459bc2016-08-23 16:50:37 -07001344 emitCppResolveReferences(
1345 out,
1346 "_hidl_reply",
1347 true /* parcelObjIsPointer */,
1348 elidedReturn,
1349 false /* reader */,
1350 Type::ErrorMode_Ignore,
1351 false /* addPrefixToName */);
1352
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001353 status_t status = generateCppInstrumentationCall(
1354 out,
1355 InstrumentationEvent::SERVER_API_EXIT,
1356 iface,
1357 method);
1358 if (status != OK) {
1359 return status;
1360 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001361
Iliyan Malchev549e2592016-08-10 08:59:12 -07001362 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001363 } else {
1364 if (returnsValue) {
1365 out << "bool _hidl_callbackCalled = false;\n\n";
1366 }
Andreas Huber881227d2016-08-02 14:20:21 -07001367
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001368 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001369
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001370 bool first = true;
1371 for (const auto &arg : method->args()) {
1372 if (!first) {
1373 out << ", ";
1374 }
Andreas Huber881227d2016-08-02 14:20:21 -07001375
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001376 if (arg->type().resultNeedsDeref()) {
1377 out << "*";
1378 }
1379
1380 out << arg->name();
1381
1382 first = false;
1383 }
1384
1385 if (returnsValue) {
1386 if (!first) {
1387 out << ", ";
1388 }
1389
1390 out << "[&](";
1391
1392 first = true;
1393 for (const auto &arg : method->results()) {
1394 if (!first) {
1395 out << ", ";
1396 }
1397
1398 out << "const auto &" << arg->name();
1399
1400 first = false;
1401 }
1402
1403 out << ") {\n";
1404 out.indent();
1405 out << "_hidl_callbackCalled = true;\n\n";
1406
1407 out << "::android::hardware::Status::ok()"
1408 << ".writeToParcel(_hidl_reply);\n\n";
1409
Yifan Hongbf459bc2016-08-23 16:50:37 -07001410 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001411 for (const auto &arg : method->results()) {
1412 emitCppReaderWriter(
1413 out,
1414 "_hidl_reply",
1415 true /* parcelObjIsPointer */,
1416 arg,
1417 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001418 Type::ErrorMode_Ignore,
1419 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001420 }
1421
Yifan Hongbf459bc2016-08-23 16:50:37 -07001422 // Second DFS: resolve references
1423 for (const auto &arg : method->results()) {
1424 emitCppResolveReferences(
1425 out,
1426 "_hidl_reply",
1427 true /* parcelObjIsPointer */,
1428 arg,
1429 false /* reader */,
1430 Type::ErrorMode_Ignore,
1431 false /* addPrefixToName */);
1432 }
1433
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001434 status_t status = generateCppInstrumentationCall(
1435 out,
1436 InstrumentationEvent::SERVER_API_EXIT,
1437 iface,
1438 method);
1439 if (status != OK) {
1440 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001441 }
1442
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001443 out << "_hidl_cb(*_hidl_reply);\n";
1444
1445 out.unindent();
1446 out << "}\n";
1447 }
1448
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001449 out << ");\n\n";
1450
1451 // What to do if the stub implementation has a synchronous callback
1452 // which does not get invoked? This is not a transport error but a
1453 // service error of sorts. For now, return OK to the caller, as this is
1454 // not a transport error.
1455 //
1456 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001457
1458 if (returnsValue) {
1459 out << "if (!_hidl_callbackCalled) {\n";
1460 out.indent();
1461 }
1462
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001463 out << "::android::hardware::Status::ok()"
1464 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001465
1466 if (returnsValue) {
1467 out.unindent();
1468 out << "}\n\n";
1469 }
Andreas Huber881227d2016-08-02 14:20:21 -07001470 }
1471
1472 out << "break;\n";
1473
1474 return OK;
1475}
1476
Steven Moreland69e7c702016-09-09 11:16:32 -07001477status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1478 std::string ifaceName;
1479 if (!AST::isInterface(&ifaceName)) {
1480 // types.hal does not get a stub header.
1481 return OK;
1482 }
1483
1484 const Interface *iface = mRootScope->getInterface();
1485
1486 const std::string baseName = iface->getBaseName();
1487 const std::string klassName = "Bs" + baseName;
1488
1489 bool supportOneway = iface->hasOnewayMethods();
1490
1491 std::string path = outputPath;
1492 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1493 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1494 path.append(klassName);
1495 path.append(".h");
1496
1497 CHECK(Coordinator::MakeParentHierarchy(path));
1498 FILE *file = fopen(path.c_str(), "w");
1499
1500 if (file == NULL) {
1501 return -errno;
1502 }
1503
1504 Formatter out(file);
1505
1506 const std::string guard = makeHeaderGuard(klassName);
1507
1508 out << "#ifndef " << guard << "\n";
1509 out << "#define " << guard << "\n\n";
1510
1511 std::vector<std::string> packageComponents;
1512 getPackageAndVersionComponents(
1513 &packageComponents, false /* cpp_compatible */);
1514
1515 out << "#include <future>\n";
1516 out << "#include <";
1517 for (const auto &component : packageComponents) {
1518 out << component << "/";
1519 }
1520 out << ifaceName << ".h>\n\n";
1521
1522 if (supportOneway) {
1523 out << "#include <hidl/SynchronizedQueue.h>\n";
1524 }
1525
1526 enterLeaveNamespace(out, true /* enter */);
1527 out << "\n";
1528
1529 out << "struct "
1530 << klassName
1531 << " : " << ifaceName
1532 << " {\n";
1533
1534 out.indent();
1535 out << "explicit "
1536 << klassName
1537 << "(const sp<"
1538 << ifaceName
1539 << "> impl);\n";
1540
1541 status_t err = generateMethods(out,
1542 "" /* class name */,
1543 MethodLocation::PASSTHROUGH_HEADER,
1544 true /* specify namespaces */);
1545
1546 if (err != OK) {
1547 return err;
1548 }
1549
1550 out.unindent();
1551 out << "private:\n";
1552 out.indent();
1553 out << "const sp<" << ifaceName << "> mImpl;\n";
1554
1555 if (supportOneway) {
1556 out << "SynchronizedQueue<std::function<void(void)>> mOnewayQueue;\n";
1557 out << "std::thread *mOnewayThread = nullptr;\n";
1558
1559 out << "\n";
1560
1561 out << "::android::hardware::Return<void> addOnewayTask("
1562 "std::function<void(void)>);\n\n";
1563
1564 out << "static const int kOnewayQueueMaxSize = 3000;\n";
1565 }
1566
1567 out.unindent();
1568
1569 out << "};\n\n";
1570
1571 enterLeaveNamespace(out, false /* enter */);
1572
1573 out << "\n#endif // " << guard << "\n";
1574
1575 return OK;
1576}
1577
1578
1579status_t AST::generatePassthroughSource(Formatter &out) const {
1580 const Interface *iface = mRootScope->getInterface();
1581
1582 const std::string baseName = iface->getBaseName();
1583 const std::string klassName = "Bs" + baseName;
1584
1585 out << klassName
1586 << "::"
1587 << klassName
1588 << "(const sp<"
1589 << iface->fullName()
1590 << "> impl) : mImpl(impl) {}\n\n";
1591
1592 if (iface->hasOnewayMethods()) {
1593 out << "::android::hardware::Return<void> "
1594 << klassName
1595 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1596 out.indent();
1597 out << "if (mOnewayThread == nullptr) {\n";
1598 out.indent();
1599 out << "mOnewayThread = new std::thread([this]() {\n";
1600 out.indent();
1601 out << "while(true) { (this->mOnewayQueue.wait_pop())(); }";
1602 out.unindent();
1603 out << "});\n";
1604 out.unindent();
1605 out << "}\n\n";
1606
1607 out << "if (mOnewayQueue.size() > kOnewayQueueMaxSize) {\n";
1608 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001609 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1610 out.indent();
1611 out.indent();
1612 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1613 out.unindent();
1614 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001615 out.unindent();
1616 out << "} else {\n";
1617 out.indent();
1618 out << "mOnewayQueue.push(fun);\n";
1619 out.unindent();
1620 out << "}\n";
1621
Steven Morelandd366c262016-10-11 15:29:10 -07001622 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001623
1624 out.unindent();
1625 out << "}\n\n";
1626
1627
1628 }
1629
1630 return OK;
1631}
1632
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001633status_t AST::generateCppInstrumentationCall(
1634 Formatter &out,
1635 InstrumentationEvent event,
1636 const Interface *iface, const Method *method) const {
1637 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1638 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001639 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001640 std::string event_str = "";
1641 switch (event) {
1642 case SERVER_API_ENTRY:
1643 {
1644 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1645 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001646 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001647 << (arg->type().resultNeedsDeref() ? "" : "&")
1648 << arg->name()
1649 << ");\n";
1650 }
1651 break;
1652 }
1653 case SERVER_API_EXIT:
1654 {
1655 event_str = "InstrumentationEvent::SERVER_API_EXIT";
1656 const TypedVar *elidedReturn = method->canElideCallback();
1657 if (elidedReturn != nullptr) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001658 out << "_hidl_args.push_back((void *)&"
1659 << elidedReturn->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001660 << ");\n";
1661 } else {
1662 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001663 out << "_hidl_args.push_back((void *)&"
1664 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001665 << ");\n";
1666 }
1667 }
1668 break;
1669 }
1670 case CLIENT_API_ENTRY:
1671 {
1672 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1673 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001674 out << "_hidl_args.push_back((void *)&"
1675 << arg->name()
1676 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001677 }
1678 break;
1679 }
1680 case CLIENT_API_EXIT:
1681 {
1682 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1683 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001684 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001685 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001686 << "_hidl_out_"
1687 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001688 << ");\n";
1689 }
1690 break;
1691 }
1692 case SYNC_CALLBACK_ENTRY:
1693 case SYNC_CALLBACK_EXIT:
1694 case ASYNC_CALLBACK_ENTRY:
1695 case ASYNC_CALLBACK_EXIT:
1696 {
1697 LOG(ERROR) << "Not supported instrumentation event: " << event;
1698 return UNKNOWN_ERROR;
1699 }
1700 }
1701
1702 out << "for (auto callback: mInstrumentationCallbacks) {\n";
1703 out.indent();
1704 out << "callback("
1705 << event_str
1706 << ", \""
1707 << mPackage.package()
1708 << "\", \""
1709 << mPackage.getPackageFullVersion()
1710 << "\", \""
1711 << iface->localName()
1712 << "\", \""
1713 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001714 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001715 out.unindent();
1716 out << "}\n";
1717 out.unindent();
1718 out << "}\n\n";
1719
1720 return OK;
1721}
1722
Andreas Huber881227d2016-08-02 14:20:21 -07001723} // namespace android
1724