blob: ec7905985d9d0971688b1ff8fc29fefbb69a297e [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>
Steven Moreland5708edf2016-11-04 15:33:31 +000028#include <hidl-util/StringHelper.h>
Andreas Huber881227d2016-08-02 14:20:21 -070029#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070031#include <vector>
32
33namespace android {
34
Andreas Huberb82318c2016-08-02 14:45:54 -070035status_t AST::generateCpp(const std::string &outputPath) const {
36 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070037
38 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070039 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070040 }
41
42 if (err == OK) {
Steven Moreland40786312016-08-16 10:29:40 -070043 err = generateHwBinderHeader(outputPath);
44 }
45
46 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070047 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070048 }
49
50 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070051 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070052 }
53
Steven Moreland69e7c702016-09-09 11:16:32 -070054 if (err == OK) {
55 generatePassthroughHeader(outputPath);
56 }
57
Andreas Huber881227d2016-08-02 14:20:21 -070058 return err;
59}
60
Andreas Huber737080b2016-08-02 15:38:04 -070061void AST::getPackageComponents(
62 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070063 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070064}
65
66void AST::getPackageAndVersionComponents(
67 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070068 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070069}
70
Steven Moreland5708edf2016-11-04 15:33:31 +000071std::string AST::makeHeaderGuard(const std::string &baseName,
72 bool indicateGenerated) const {
73 std::string guard;
Andreas Huber881227d2016-08-02 14:20:21 -070074
Steven Moreland5708edf2016-11-04 15:33:31 +000075 if (indicateGenerated) {
76 guard += "HIDL_GENERATED_";
77 }
78
79 guard += StringHelper::Uppercase(mPackage.tokenName());
Andreas Huber881227d2016-08-02 14:20:21 -070080 guard += "_";
Steven Moreland5708edf2016-11-04 15:33:31 +000081 guard += StringHelper::Uppercase(baseName);
82 guard += "_H";
Andreas Huber881227d2016-08-02 14:20:21 -070083
84 return guard;
85}
86
Steven Morelandee88eed2016-10-31 17:49:00 -070087// static
88void AST::generateCppPackageInclude(
89 Formatter &out,
90 const FQName &package,
91 const std::string &klass) {
92
93 out << "#include <";
94
95 std::vector<std::string> components;
96 package.getPackageAndVersionComponents(&components, false /* cpp_compatible */);
97
98 for (const auto &component : components) {
99 out << component << "/";
100 }
101
102 out << klass
103 << ".h>\n";
104}
105
Andreas Huber881227d2016-08-02 14:20:21 -0700106void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
107 std::vector<std::string> packageComponents;
108 getPackageAndVersionComponents(
109 &packageComponents, true /* cpp_compatible */);
110
111 if (enter) {
112 for (const auto &component : packageComponents) {
113 out << "namespace " << component << " {\n";
114 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700115
Andreas Huber2831d512016-08-15 09:33:47 -0700116 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -0700117 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700118 out.setNamespace(std::string());
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120 for (auto it = packageComponents.rbegin();
121 it != packageComponents.rend();
122 ++it) {
123 out << "} // namespace " << *it << "\n";
124 }
125 }
126}
127
Andreas Huberb82318c2016-08-02 14:45:54 -0700128status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700129
Andreas Huberb82318c2016-08-02 14:45:54 -0700130 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700131 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700132 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700133
134 std::string ifaceName;
135 bool isInterface = true;
136 if (!AST::isInterface(&ifaceName)) {
137 ifaceName = "types";
138 isInterface = false;
139 }
140 path.append(ifaceName);
141 path.append(".h");
142
Andreas Huberd2943e12016-08-05 11:59:31 -0700143 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700144 FILE *file = fopen(path.c_str(), "w");
145
146 if (file == NULL) {
147 return -errno;
148 }
149
150 Formatter out(file);
151
152 const std::string guard = makeHeaderGuard(ifaceName);
153
154 out << "#ifndef " << guard << "\n";
155 out << "#define " << guard << "\n\n";
156
Andreas Huber737080b2016-08-02 15:38:04 -0700157 for (const auto &item : mImportedNames) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700158 generateCppPackageInclude(out, item, item.name());
Andreas Huber737080b2016-08-02 15:38:04 -0700159 }
160
161 if (!mImportedNames.empty()) {
162 out << "\n";
163 }
164
Steven Moreland0693f312016-11-09 15:06:14 -0800165 if (isInterface) {
Yifan Hongc8934042016-11-17 17:10:52 -0800166 if (isIBase()) {
167 out << "// skipped #include IServiceNotification.h\n\n";
168 } else {
169 out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
170 }
Steven Moreland0693f312016-11-09 15:06:14 -0800171 }
172
Yifan Hongc8934042016-11-17 17:10:52 -0800173 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700174 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700175
176 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200177 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700178 }
179
Martijn Coenenaf712c02016-11-16 15:26:27 +0100180 out << "#include <utils/NativeHandle.h>\n";
181 out << "#include <utils/misc.h>\n\n"; /* for report_sysprop_change() */
Andreas Huber881227d2016-08-02 14:20:21 -0700182
183 enterLeaveNamespace(out, true /* enter */);
184 out << "\n";
185
186 if (isInterface) {
187 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700188 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700189
190 const Interface *iface = mRootScope->getInterface();
191 const Interface *superType = iface->superType();
192
Steven Moreland40786312016-08-16 10:29:40 -0700193 if (superType == NULL) {
Yifan Hongc8934042016-11-17 17:10:52 -0800194 out << " : virtual public ::android::RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700195 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000196 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700197 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700198 }
199
200 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700201
202 out.indent();
203
Andreas Huber881227d2016-08-02 14:20:21 -0700204 }
205
206 status_t err = emitTypeDeclarations(out);
207
208 if (err != OK) {
209 return err;
210 }
211
212 if (isInterface) {
213 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700214 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700215 const std::string baseName = iface->getBaseName();
Steven Moreland19d5c172016-10-20 19:20:25 -0700216 out << "constexpr static ::android::hardware::hidl_version version = {"
Martijn Coenena21f1492016-09-08 15:55:14 +0200217 << mPackage.getPackageMajorVersion() << ","
218 << mPackage.getPackageMinorVersion() << "};\n";
Steven Moreland19d5c172016-10-20 19:20:25 -0700219 out << "virtual const ::android::hardware::hidl_version&"
220 << "getInterfaceVersion() const {\n";
Martijn Coenena21f1492016-09-08 15:55:14 +0200221 out.indent();
222 out << "return version;\n";
223 out.unindent();
224 out << "}\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800225 out << "virtual bool isRemote() const ";
226 if (!isIBase()) {
227 out << "override ";
228 }
229 out << "{ return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800230
Andreas Huber881227d2016-08-02 14:20:21 -0700231 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700232 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700233
Andreas Huber881227d2016-08-02 14:20:21 -0700234 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800235 const TypedVar *elidedReturn = method->canElideCallback();
236
237 if (elidedReturn == nullptr && returnsValue) {
238 out << "using "
239 << method->name()
240 << "_cb = std::function<void("
241 << Method::GetArgSignature(method->results(),
242 true /* specify namespaces */)
243 << ")>;\n";
244 }
Andreas Huber881227d2016-08-02 14:20:21 -0700245
Andreas Huber3599d922016-08-09 10:42:57 -0700246 method->dumpAnnotations(out);
247
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700248 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700249 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700250 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700251 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700252 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700253 }
254
255 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700256 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700257 << Method::GetArgSignature(method->args(),
258 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700259
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700260 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700261 if (!method->args().empty()) {
262 out << ", ";
263 }
264
Steven Moreland67f67b42016-09-29 08:59:02 -0700265 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700266 }
267
Yifan Hong10fe0b52016-10-19 14:20:17 -0700268 out << ")";
269 if (method->isHidlReserved()) {
Yifan Hongc8934042016-11-17 17:10:52 -0800270 if (!isIBase()) {
271 out << " override";
272 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700273 out << " {\n";
274 out.indent();
275 method->cppImpl(out);
276 out.unindent();
277 out << "\n}\n";
278 } else {
279 out << " = 0;\n";
280 }
Andreas Huber881227d2016-08-02 14:20:21 -0700281 }
Steven Moreland40786312016-08-16 10:29:40 -0700282
Yifan Hong3d746092016-12-07 14:26:33 -0800283 out << "// cast static functions\n";
284 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700285
Yifan Hong3d746092016-12-07 14:26:33 -0800286 for (const Interface *superType : iface->typeChain()) {
287 out << "static "
288 << childTypeResult
289 << " castFrom("
290 << superType->getCppArgumentType()
291 << " parent"
292 << ");\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -0700293 }
294
Steven Morelandd39133b2016-11-11 12:30:08 -0800295 out << "\nstatic const char* descriptor;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700296
Yifan Hongc8934042016-11-17 17:10:52 -0800297 if (isIBase()) {
298 out << "// skipped DECLARE_SERVICE_MANAGER_INTERACTIONS\n\n";
299 } else {
300 out << "DECLARE_SERVICE_MANAGER_INTERACTIONS(" << baseName << ")\n\n";
301 }
Yifan Hong158655a2016-11-08 12:34:07 -0800302
303 out << "private: static int hidlStaticBlock;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700304 }
305
306 if (isInterface) {
307 out.unindent();
308
Andreas Hubere3f769a2016-10-10 10:54:44 -0700309 out << "};\n\n";
310 }
311
312 err = mRootScope->emitGlobalTypeDeclarations(out);
313
314 if (err != OK) {
315 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700316 }
317
318 out << "\n";
319 enterLeaveNamespace(out, false /* enter */);
320
321 out << "\n#endif // " << guard << "\n";
322
323 return OK;
324}
325
Steven Moreland40786312016-08-16 10:29:40 -0700326status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
327 std::string ifaceName;
Yifan Hong244e82d2016-11-11 11:13:57 -0800328 bool isInterface = AST::isInterface(&ifaceName);
329 const Interface *iface = nullptr;
330 std::string baseName{};
331 std::string klassName{};
332
333 if(isInterface) {
334 iface = mRootScope->getInterface();
335 baseName = iface->getBaseName();
336 klassName = "IHw" + baseName;
337 } else {
338 klassName = "hwtypes";
Steven Moreland40786312016-08-16 10:29:40 -0700339 }
340
Steven Moreland40786312016-08-16 10:29:40 -0700341 std::string path = outputPath;
342 path.append(mCoordinator->convertPackageRootToPath(mPackage));
343 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
344 path.append(klassName + ".h");
345
Yifan Hong244e82d2016-11-11 11:13:57 -0800346 FILE *file = fopen(path.c_str(), "w");
Steven Moreland40786312016-08-16 10:29:40 -0700347
348 if (file == NULL) {
349 return -errno;
350 }
351
352 Formatter out(file);
353
354 const std::string guard = makeHeaderGuard(klassName);
355
356 out << "#ifndef " << guard << "\n";
357 out << "#define " << guard << "\n\n";
358
Yifan Hong244e82d2016-11-11 11:13:57 -0800359 if (isInterface) {
360 generateCppPackageInclude(out, mPackage, ifaceName);
361 } else {
362 generateCppPackageInclude(out, mPackage, "types");
363 }
Steven Moreland40786312016-08-16 10:29:40 -0700364
Steven Morelandee88eed2016-10-31 17:49:00 -0700365 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700366
367 for (const auto &item : mImportedNames) {
368 if (item.name() == "types") {
Yifan Hong244e82d2016-11-11 11:13:57 -0800369 generateCppPackageInclude(out, item, "hwtypes");
370 } else {
371 generateCppPackageInclude(out, item, "Bn" + item.getInterfaceBaseName());
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100372 generateCppPackageInclude(out, item, "Bp" + item.getInterfaceBaseName());
Steven Moreland40786312016-08-16 10:29:40 -0700373 }
Steven Moreland40786312016-08-16 10:29:40 -0700374 }
375
376 out << "\n";
377
Martijn Coenen93915102016-09-01 01:35:52 +0200378 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700379 out << "#include <hwbinder/IBinder.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100380 out << "#include <hwbinder/Parcel.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700381
382 out << "\n";
383
384 enterLeaveNamespace(out, true /* enter */);
Steven Moreland40786312016-08-16 10:29:40 -0700385
Yifan Hong244e82d2016-11-11 11:13:57 -0800386 status_t err = mRootScope->emitGlobalHwDeclarations(out);
387 if (err != OK) {
388 return err;
389 }
Steven Moreland40786312016-08-16 10:29:40 -0700390
391 enterLeaveNamespace(out, false /* enter */);
392
393 out << "\n#endif // " << guard << "\n";
394
395 return OK;
396}
397
Andreas Huber881227d2016-08-02 14:20:21 -0700398status_t AST::emitTypeDeclarations(Formatter &out) const {
399 return mRootScope->emitTypeDeclarations(out);
400}
401
Steven Moreland69e7c702016-09-09 11:16:32 -0700402status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700403 const Method *method) const {
404 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700405
406 out << " {\n";
407 out.indent();
408
409 const bool returnsValue = !method->results().empty();
410 const TypedVar *elidedReturn = method->canElideCallback();
411
Steven Moreland67f67b42016-09-29 08:59:02 -0700412 if (returnsValue && elidedReturn == nullptr) {
413 generateCheckNonNull(out, "_hidl_cb");
414 }
415
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700416 generateCppInstrumentationCall(
417 out,
418 InstrumentationEvent::PASSTHROUGH_ENTRY,
419 method);
420
421 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700422
423 if (method->isOneway()) {
424 out << "addOnewayTask([this";
425 for (const auto &arg : method->args()) {
426 out << ", " << arg->name();
427 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700428 out << "] {\n";
429 out.indent();
430 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700431 }
432
433 out << "mImpl->"
434 << method->name()
435 << "(";
436
437 bool first = true;
438 for (const auto &arg : method->args()) {
439 if (!first) {
440 out << ", ";
441 }
442 first = false;
443 out << arg->name();
444 }
445 if (returnsValue && elidedReturn == nullptr) {
446 if (!method->args().empty()) {
447 out << ", ";
448 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800449 out << "[&](";
450 first = true;
451 for (const auto &arg : method->results()) {
452 if (!first) {
453 out << ", ";
454 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700455
Yifan Honga47eef32016-12-12 10:38:54 -0800456 out << "const auto &_hidl_out_" << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800457
458 first = false;
459 }
460
461 out << ") {\n";
462 out.indent();
463 status_t status = generateCppInstrumentationCall(
464 out,
465 InstrumentationEvent::PASSTHROUGH_EXIT,
466 method);
467 if (status != OK) {
468 return status;
469 }
470
471 out << "_hidl_cb(";
472 first = true;
473 for (const auto &arg : method->results()) {
474 if (!first) {
475 out << ", ";
476 }
477
Yifan Honga47eef32016-12-12 10:38:54 -0800478 out << "_hidl_out_" << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800479
480 first = false;
481 }
482 out << ");\n";
483 out.unindent();
484 out << "});\n\n";
485 } else {
486 out << ");\n\n";
487 if (elidedReturn != nullptr) {
488 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -0800489 << " _hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800490 << elidedReturn->name()
Steven Moreland2ae5bca2016-12-01 05:56:49 +0000491 << " = _hidl_return;\n";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800492 }
493 status_t status = generateCppInstrumentationCall(
494 out,
495 InstrumentationEvent::PASSTHROUGH_EXIT,
496 method);
497 if (status != OK) {
498 return status;
499 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700500 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700501
502 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700503 out.unindent();
504 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700505 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700506
507 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700508
509 out.unindent();
510 out << "}\n";
511
512 return OK;
513}
514
Yifan Hong068c5522016-10-31 14:07:25 -0700515status_t AST::generateMethods(Formatter &out, MethodGenerator gen) 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 }
Yifan Hong068c5522016-10-31 14:07:25 -0700533 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700534
Yifan Hong10fe0b52016-10-19 14:20:17 -0700535 if (err != OK) {
536 return err;
537 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700538 }
539
Yifan Hong10fe0b52016-10-19 14:20:17 -0700540 out << "\n";
541
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700542 return OK;
543}
544
Andreas Huberb82318c2016-08-02 14:45:54 -0700545status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700546 std::string ifaceName;
547 if (!AST::isInterface(&ifaceName)) {
548 // types.hal does not get a stub header.
549 return OK;
550 }
551
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700552 const Interface *iface = mRootScope->getInterface();
553 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700554 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700555
Andreas Huberb82318c2016-08-02 14:45:54 -0700556 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700557 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700558 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700559 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700560 path.append(".h");
561
Andreas Huberd2943e12016-08-05 11:59:31 -0700562 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700563 FILE *file = fopen(path.c_str(), "w");
564
565 if (file == NULL) {
566 return -errno;
567 }
568
569 Formatter out(file);
570
Steven Moreland40786312016-08-16 10:29:40 -0700571 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700572
573 out << "#ifndef " << guard << "\n";
574 out << "#define " << guard << "\n\n";
575
Steven Morelandee88eed2016-10-31 17:49:00 -0700576 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
577 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700578
579 enterLeaveNamespace(out, true /* enter */);
580 out << "\n";
581
582 out << "struct "
583 << "Bn"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100584 << baseName;
585 if (iface->isIBase()) {
586 out << " : public ::android::hardware::BBinder";
587 out << ", public ::android::hardware::HidlInstrumentor {\n";
588 } else {
589 out << " : public ::android::hidl::base::V1_0::BnBase {\n";
590 }
Andreas Huber881227d2016-08-02 14:20:21 -0700591
592 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700593 out << "explicit Bn"
594 << baseName
595 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100596 << "\n";
597 out << "explicit Bn"
598 << baseName
599 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl,"
600 << " const std::string& prefix);"
Steven Moreland40786312016-08-16 10:29:40 -0700601 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700602 out << "::android::status_t onTransact(\n";
603 out.indent();
604 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700605 out << "uint32_t _hidl_code,\n";
606 out << "const ::android::hardware::Parcel &_hidl_data,\n";
607 out << "::android::hardware::Parcel *_hidl_reply,\n";
608 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700609 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700610 out.unindent();
611 out.unindent();
612
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100613 out << "::android::sp<" << ifaceName << "> getImpl() { return _hidl_mImpl; };\n";
614 out.unindent();
615 out << "private:\n";
616 out.indent();
617 out << "::android::sp<" << ifaceName << "> _hidl_mImpl;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700618 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700619 out << "};\n\n";
620
621 enterLeaveNamespace(out, false /* enter */);
622
623 out << "\n#endif // " << guard << "\n";
624
625 return OK;
626}
627
Andreas Huberb82318c2016-08-02 14:45:54 -0700628status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700629 std::string ifaceName;
630 if (!AST::isInterface(&ifaceName)) {
631 // types.hal does not get a proxy header.
632 return OK;
633 }
634
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700635 const Interface *iface = mRootScope->getInterface();
636 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700637
Andreas Huberb82318c2016-08-02 14:45:54 -0700638 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700639 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700640 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700641 path.append("Bp");
642 path.append(baseName);
643 path.append(".h");
644
Andreas Huberd2943e12016-08-05 11:59:31 -0700645 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700646 FILE *file = fopen(path.c_str(), "w");
647
648 if (file == NULL) {
649 return -errno;
650 }
651
652 Formatter out(file);
653
654 const std::string guard = makeHeaderGuard("Bp" + baseName);
655
656 out << "#ifndef " << guard << "\n";
657 out << "#define " << guard << "\n\n";
658
659 std::vector<std::string> packageComponents;
660 getPackageAndVersionComponents(
661 &packageComponents, false /* cpp_compatible */);
662
Steven Morelandee88eed2016-10-31 17:49:00 -0700663 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
664 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700665
666 enterLeaveNamespace(out, true /* enter */);
667 out << "\n";
668
669 out << "struct "
670 << "Bp"
671 << baseName
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100672 << " : public ::android::hardware::BpInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -0700673 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700674 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700675
676 out.indent();
677
678 out << "explicit Bp"
679 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700680 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700681 << "\n\n";
682
Yifan Hong10fe0b52016-10-19 14:20:17 -0700683 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700684
Yifan Hong068c5522016-10-31 14:07:25 -0700685 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
686 method->generateCppSignature(out);
687 out << " override;\n";
688 return OK;
689 });
Steven Moreland9c387612016-09-07 09:54:26 -0700690
691 if (err != OK) {
692 return err;
693 }
Andreas Huber881227d2016-08-02 14:20:21 -0700694
695 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700696 out << "};\n\n";
697
698 enterLeaveNamespace(out, false /* enter */);
699
700 out << "\n#endif // " << guard << "\n";
701
702 return OK;
703}
704
Andreas Huberb82318c2016-08-02 14:45:54 -0700705status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700706
Andreas Huberb82318c2016-08-02 14:45:54 -0700707 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700708 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700709 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700710
711 std::string ifaceName;
712 std::string baseName;
713
Yifan Hongfe95aa22016-10-19 17:26:45 -0700714 const Interface *iface = nullptr;
715 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700716 if (!AST::isInterface(&ifaceName)) {
717 baseName = "types";
718 isInterface = false;
719 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700720 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700721 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700722 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700723 }
724
725 path.append(baseName);
726
727 if (baseName != "types") {
728 path.append("All");
729 }
730
731 path.append(".cpp");
732
Andreas Huberd2943e12016-08-05 11:59:31 -0700733 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700734 FILE *file = fopen(path.c_str(), "w");
735
736 if (file == NULL) {
737 return -errno;
738 }
739
740 Formatter out(file);
741
Steven Moreland05cd4232016-11-21 16:01:12 -0800742 out << "#include <android/log.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100743 out << "#include <cutils/trace.h>\n";
744 out << "#include <hidl/HidlTransportSupport.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700745 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700746 // This is a no-op for IServiceManager itself.
747 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
748
Steven Morelandee88eed2016-10-31 17:49:00 -0700749 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
750 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
751 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700752
753 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700754 generateCppPackageInclude(out,
755 superType->fqName(),
756 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700757 }
Yifan Hong2cbbdf92016-12-05 15:20:50 -0800758
759 out << "#include <hidl/ServiceManagement.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700760 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700761 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800762 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700763 }
764
765 out << "\n";
766
767 enterLeaveNamespace(out, true /* enter */);
768 out << "\n";
769
770 status_t err = generateTypeSource(out, ifaceName);
771
772 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700773 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700774 out << "constexpr ::android::hardware::hidl_version "
775 << ifaceName
776 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700777
778 // need to be put here, generateStubSource is using this.
Steven Morelandd39133b2016-11-11 12:30:08 -0800779 out << "const char* I"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700780 << iface->getBaseName()
781 << "::descriptor(\""
782 << iface->fqName().string()
783 << "\");\n\n";
784
Yifan Hong158655a2016-11-08 12:34:07 -0800785 out << "int I"
786 << iface->getBaseName()
787 << "::hidlStaticBlock = []() -> int {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800788 out.indent([&] {
Steven Morelandd39133b2016-11-11 12:30:08 -0800789 out << "::android::hardware::gBnConstructorMap[I"
Yifan Hong158655a2016-11-08 12:34:07 -0800790 << iface->getBaseName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800791 << "::descriptor]\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800792 out.indent(2, [&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800793 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800794 out.indent([&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800795 out << "return new Bn"
796 << iface->getBaseName()
797 << "(reinterpret_cast<I"
798 << iface->getBaseName()
799 << " *>(iIntf));\n";
800 });
801 out << "};\n";
802 });
803 out << "return 1;\n";
804 });
805 out << "}();\n\n";
806
Yifan Hongfe95aa22016-10-19 17:26:45 -0700807 err = generateInterfaceSource(out);
808 }
809
810 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -0700811 err = generateProxySource(out, baseName);
812 }
813
814 if (err == OK && isInterface) {
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100815 err = generateStubSource(out, iface, baseName);
Andreas Huber881227d2016-08-02 14:20:21 -0700816 }
817
Steven Moreland40786312016-08-16 10:29:40 -0700818 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700819 err = generatePassthroughSource(out);
820 }
821
822 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700823 const Interface *iface = mRootScope->getInterface();
824
Yifan Hongc8934042016-11-17 17:10:52 -0800825 if (isIBase()) {
826 out << "// skipped IMPLEMENT_SERVICE_MANAGER_INTERACTIONS\n";
827 } else {
828 out << "IMPLEMENT_SERVICE_MANAGER_INTERACTIONS("
829 << baseName << ", "
830 << "\"" << iface->fqName().package()
831 << iface->fqName().atVersion()
832 << "\")\n";
833 }
Steven Moreland40786312016-08-16 10:29:40 -0700834 }
835
Andreas Huber881227d2016-08-02 14:20:21 -0700836 enterLeaveNamespace(out, false /* enter */);
837
838 return err;
839}
840
Steven Moreland67f67b42016-09-29 08:59:02 -0700841// static
842void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
Yifan Honga018ed52016-12-13 16:35:08 -0800843 out.sIf(nonNull + " == nullptr", [&] {
844 out << "return ::android::hardware::Status::fromExceptionCode(\n";
845 out.indent(2, [&] {
846 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
847 });
848 }).endl().endl();
Steven Moreland67f67b42016-09-29 08:59:02 -0700849}
850
Andreas Huber881227d2016-08-02 14:20:21 -0700851status_t AST::generateTypeSource(
852 Formatter &out, const std::string &ifaceName) const {
853 return mRootScope->emitTypeDefinitions(out, ifaceName);
854}
855
Andreas Hubere7ff2282016-08-16 13:50:03 -0700856void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700857 Formatter &out,
858 const std::vector<TypedVar *> &args,
859 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700860 if (args.empty()) {
861 return;
862 }
863
864 for (const auto &arg : args) {
865 const Type &type = arg->type();
866
Yifan Hong3b320f82016-11-01 15:15:54 -0700867 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700868 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -0700869 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700870 << ";\n";
871 }
872
873 out << "\n";
874}
875
Andreas Huber881227d2016-08-02 14:20:21 -0700876void AST::emitCppReaderWriter(
877 Formatter &out,
878 const std::string &parcelObj,
879 bool parcelObjIsPointer,
880 const TypedVar *arg,
881 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700882 Type::ErrorMode mode,
883 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700884 const Type &type = arg->type();
885
Andreas Huber881227d2016-08-02 14:20:21 -0700886 type.emitReaderWriter(
887 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700888 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700889 parcelObj,
890 parcelObjIsPointer,
891 isReader,
892 mode);
893}
894
Yifan Hongbf459bc2016-08-23 16:50:37 -0700895void AST::emitCppResolveReferences(
896 Formatter &out,
897 const std::string &parcelObj,
898 bool parcelObjIsPointer,
899 const TypedVar *arg,
900 bool isReader,
901 Type::ErrorMode mode,
902 bool addPrefixToName) const {
903 const Type &type = arg->type();
904 if(type.needsResolveReferences()) {
905 type.emitResolveReferences(
906 out,
907 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
908 isReader, // nameIsPointer
909 parcelObj,
910 parcelObjIsPointer,
911 isReader,
912 mode);
913 }
914}
915
Yifan Hong068c5522016-10-31 14:07:25 -0700916status_t AST::generateProxyMethodSource(Formatter &out,
917 const std::string &klassName,
918 const Method *method,
919 const Interface *superInterface) const {
920
921 method->generateCppSignature(out,
922 klassName,
923 true /* specify namespaces */);
924
925 const bool returnsValue = !method->results().empty();
926 const TypedVar *elidedReturn = method->canElideCallback();
927
Steven Moreland41c6d2e2016-11-07 12:26:54 -0800928 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700929
930 out.indent();
931
932 if (returnsValue && elidedReturn == nullptr) {
933 generateCheckNonNull(out, "_hidl_cb");
934 }
935
936 status_t status = generateCppInstrumentationCall(
937 out,
938 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -0700939 method);
940 if (status != OK) {
941 return status;
942 }
943
944 out << "::android::hardware::Parcel _hidl_data;\n";
945 out << "::android::hardware::Parcel _hidl_reply;\n";
946 out << "::android::status_t _hidl_err;\n";
947 out << "::android::hardware::Status _hidl_status;\n\n";
948
949 declareCppReaderLocals(
950 out, method->results(), true /* forResults */);
951
952 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Yifan Hongc8934042016-11-17 17:10:52 -0800953 out << superInterface->fqName().cppNamespace()
954 << "::I"
955 << superInterface->getBaseName();
Yifan Hong068c5522016-10-31 14:07:25 -0700956 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700957 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
958
959 // First DFS: write all buffers and resolve pointers for parent
960 for (const auto &arg : method->args()) {
961 emitCppReaderWriter(
962 out,
963 "_hidl_data",
964 false /* parcelObjIsPointer */,
965 arg,
966 false /* reader */,
967 Type::ErrorMode_Goto,
968 false /* addPrefixToName */);
969 }
970
971 // Second DFS: resolve references.
972 for (const auto &arg : method->args()) {
973 emitCppResolveReferences(
974 out,
975 "_hidl_data",
976 false /* parcelObjIsPointer */,
977 arg,
978 false /* reader */,
979 Type::ErrorMode_Goto,
980 false /* addPrefixToName */);
981 }
982
983 out << "_hidl_err = remote()->transact("
984 << method->getSerialId()
985 << " /* "
986 << method->name()
987 << " */, _hidl_data, &_hidl_reply";
988
989 if (method->isOneway()) {
990 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
991 }
992 out << ");\n";
993
994 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
995
996 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -0800997 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700998 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
999 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1000
1001
1002 // First DFS: write all buffers and resolve pointers for parent
1003 for (const auto &arg : method->results()) {
1004 emitCppReaderWriter(
1005 out,
1006 "_hidl_reply",
1007 false /* parcelObjIsPointer */,
1008 arg,
1009 true /* reader */,
1010 Type::ErrorMode_Goto,
1011 true /* addPrefixToName */);
1012 }
1013
1014 // Second DFS: resolve references.
1015 for (const auto &arg : method->results()) {
1016 emitCppResolveReferences(
1017 out,
1018 "_hidl_reply",
1019 false /* parcelObjIsPointer */,
1020 arg,
1021 true /* reader */,
1022 Type::ErrorMode_Goto,
1023 true /* addPrefixToName */);
1024 }
1025
1026 if (returnsValue && elidedReturn == nullptr) {
1027 out << "_hidl_cb(";
1028
1029 bool first = true;
1030 for (const auto &arg : method->results()) {
1031 if (!first) {
1032 out << ", ";
1033 }
1034
1035 if (arg->type().resultNeedsDeref()) {
1036 out << "*";
1037 }
1038 out << "_hidl_out_" << arg->name();
1039
1040 first = false;
1041 }
1042
1043 out << ");\n\n";
1044 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001045 }
1046 status = generateCppInstrumentationCall(
1047 out,
1048 InstrumentationEvent::CLIENT_API_EXIT,
1049 method);
1050 if (status != OK) {
1051 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001052 }
1053
1054 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001055 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1056 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001057 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001058 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1059 } else {
1060 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1061 out << "return ::android::hardware::Return<void>();\n\n";
1062 }
1063
1064 out.unindent();
1065 out << "_hidl_error:\n";
1066 out.indent();
1067 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1068 out << "return ::android::hardware::Return<";
1069 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001070 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001071 } else {
1072 out << "void";
1073 }
1074 out << ">(_hidl_status);\n";
1075
1076 out.unindent();
1077 out << "}\n\n";
1078 return OK;
1079}
1080
Andreas Huber881227d2016-08-02 14:20:21 -07001081status_t AST::generateProxySource(
1082 Formatter &out, const std::string &baseName) const {
1083 const std::string klassName = "Bp" + baseName;
1084
1085 out << klassName
1086 << "::"
1087 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001088 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001089
1090 out.indent();
1091 out.indent();
1092
1093 out << ": BpInterface"
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001094 << "<I"
Andreas Huber881227d2016-08-02 14:20:21 -07001095 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001096 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001097 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001098 << mPackage.string()
1099 << "::I"
1100 << baseName
1101 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001102
Andreas Huber881227d2016-08-02 14:20:21 -07001103 out.unindent();
1104 out.unindent();
1105 out << "}\n\n";
1106
Yifan Hong068c5522016-10-31 14:07:25 -07001107 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1108 return generateProxyMethodSource(out, klassName, method, superInterface);
1109 });
Andreas Huber881227d2016-08-02 14:20:21 -07001110
Yifan Hong068c5522016-10-31 14:07:25 -07001111 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001112}
1113
1114status_t AST::generateStubSource(
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001115 Formatter &out,
1116 const Interface *iface,
1117 const std::string &baseName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001118 const std::string klassName = "Bn" + baseName;
1119
Steven Moreland40786312016-08-16 10:29:40 -07001120 out << klassName
1121 << "::"
1122 << klassName
1123 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1124
1125 out.indent();
1126 out.indent();
1127
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001128 if (iface->isIBase()) {
1129 out << ": ::android::hardware::HidlInstrumentor(\"";
1130 } else {
1131 out << ": ::android::hidl::base::V1_0::BnBase(_hidl_impl, \"";
1132 }
1133
1134 out << mPackage.string()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001135 << "::I"
1136 << baseName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001137 << "\") { \n";
1138 out.indent();
1139 out << "_hidl_mImpl = _hidl_impl;\n";
1140 out.unindent();
Steven Moreland40786312016-08-16 10:29:40 -07001141
1142 out.unindent();
1143 out.unindent();
1144 out << "}\n\n";
1145
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001146 if (iface->isIBase()) {
1147 // BnBase has a constructor to initialize the HidlInstrumentor
1148 // class properly.
1149 out << klassName
1150 << "::"
1151 << klassName
1152 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl,"
1153 << " const std::string &prefix)\n";
1154
1155 out.indent();
1156 out.indent();
1157
1158 out << ": ::android::hardware::HidlInstrumentor(prefix) { \n";
1159 out.indent();
1160 out << "_hidl_mImpl = _hidl_impl;\n";
1161 out.unindent();
1162
1163 out.unindent();
1164 out.unindent();
1165 out << "}\n\n";
1166 }
1167
1168
Andreas Huber881227d2016-08-02 14:20:21 -07001169 out << "::android::status_t " << klassName << "::onTransact(\n";
1170
1171 out.indent();
1172 out.indent();
1173
Iliyan Malchev549e2592016-08-10 08:59:12 -07001174 out << "uint32_t _hidl_code,\n"
1175 << "const ::android::hardware::Parcel &_hidl_data,\n"
1176 << "::android::hardware::Parcel *_hidl_reply,\n"
1177 << "uint32_t _hidl_flags,\n"
1178 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001179
1180 out.unindent();
1181
Iliyan Malchev549e2592016-08-10 08:59:12 -07001182 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001183 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001184 out.indent();
1185
Yifan Hong10fe0b52016-10-19 14:20:17 -07001186 for (const auto &tuple : iface->allMethodsFromRoot()) {
1187 const Method *method = tuple.method();
1188 const Interface *superInterface = tuple.interface();
1189 out << "case "
1190 << method->getSerialId()
1191 << " /* "
1192 << method->name()
1193 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001194
Yifan Hong10fe0b52016-10-19 14:20:17 -07001195 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001196
Yifan Hong10fe0b52016-10-19 14:20:17 -07001197 status_t err =
1198 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001199
Yifan Hong10fe0b52016-10-19 14:20:17 -07001200 if (err != OK) {
1201 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001202 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001203
1204 out.unindent();
1205 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001206 }
1207
1208 out << "default:\n{\n";
1209 out.indent();
1210
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001211 out << "return onTransact(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001212
1213 out.indent();
1214 out.indent();
1215
Iliyan Malchev549e2592016-08-10 08:59:12 -07001216 out << "_hidl_code, _hidl_data, _hidl_reply, "
1217 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001218
1219 out.unindent();
1220 out.unindent();
1221
1222 out.unindent();
1223 out << "}\n";
1224
1225 out.unindent();
1226 out << "}\n\n";
1227
Yifan Honga018ed52016-12-13 16:35:08 -08001228 out.sIf("_hidl_err == ::android::UNEXPECTED_NULL", [&] {
1229 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
1230 out.indent(2, [&] {
1231 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1232 out << "_hidl_reply);\n";
1233 });
1234 });
Andreas Huber881227d2016-08-02 14:20:21 -07001235
Iliyan Malchev549e2592016-08-10 08:59:12 -07001236 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001237
1238 out.unindent();
1239 out << "}\n\n";
1240
1241 return OK;
1242}
1243
1244status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001245 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001246 out << "if (!_hidl_data.enforceInterface(";
1247
Yifan Hongc8934042016-11-17 17:10:52 -08001248 out << iface->fqName().cppNamespace()
1249 << "::I"
1250 << iface->getBaseName();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001251
1252 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001253
Andreas Huber881227d2016-08-02 14:20:21 -07001254 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001255 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001256 out << "break;\n";
1257 out.unindent();
1258 out << "}\n\n";
1259
Andreas Huber5e44a292016-09-27 14:52:39 -07001260 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001261
Yifan Hongbf459bc2016-08-23 16:50:37 -07001262 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001263 for (const auto &arg : method->args()) {
1264 emitCppReaderWriter(
1265 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001266 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001267 false /* parcelObjIsPointer */,
1268 arg,
1269 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001270 Type::ErrorMode_Break,
1271 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001272 }
1273
Yifan Hongbf459bc2016-08-23 16:50:37 -07001274 // Second DFS: resolve references
1275 for (const auto &arg : method->args()) {
1276 emitCppResolveReferences(
1277 out,
1278 "_hidl_data",
1279 false /* parcelObjIsPointer */,
1280 arg,
1281 true /* reader */,
1282 Type::ErrorMode_Break,
1283 false /* addPrefixToName */);
1284 }
1285
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001286 status_t status = generateCppInstrumentationCall(
1287 out,
1288 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001289 method);
1290 if (status != OK) {
1291 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001292 }
1293
Andreas Huber881227d2016-08-02 14:20:21 -07001294 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001295 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001296
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001297 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001298 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -08001299 << " _hidl_out_"
Yifan Hong3b320f82016-11-01 15:15:54 -07001300 << elidedReturn->name()
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001301 << " = "
1302 << "_hidl_mImpl->" << method->name()
Yifan Hong3b320f82016-11-01 15:15:54 -07001303 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001304
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001305 bool first = true;
1306 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001307 if (!first) {
1308 out << ", ";
1309 }
1310
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001311 if (arg->type().resultNeedsDeref()) {
1312 out << "*";
1313 }
1314
1315 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001316
1317 first = false;
1318 }
1319
Steven Moreland2ae5bca2016-12-01 05:56:49 +00001320 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001321 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1322 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001323
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001324 elidedReturn->type().emitReaderWriter(
1325 out,
Yifan Honga47eef32016-12-12 10:38:54 -08001326 "_hidl_out_" + elidedReturn->name(),
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001327 "_hidl_reply",
1328 true, /* parcelObjIsPointer */
1329 false, /* isReader */
1330 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001331
Yifan Hongbf459bc2016-08-23 16:50:37 -07001332 emitCppResolveReferences(
1333 out,
1334 "_hidl_reply",
1335 true /* parcelObjIsPointer */,
1336 elidedReturn,
1337 false /* reader */,
1338 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001339 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001340
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001341 status_t status = generateCppInstrumentationCall(
1342 out,
1343 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001344 method);
1345 if (status != OK) {
1346 return status;
1347 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001348
Iliyan Malchev549e2592016-08-10 08:59:12 -07001349 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001350 } else {
1351 if (returnsValue) {
1352 out << "bool _hidl_callbackCalled = false;\n\n";
1353 }
Andreas Huber881227d2016-08-02 14:20:21 -07001354
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001355 out << "_hidl_mImpl->" << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001356
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001357 bool first = true;
1358 for (const auto &arg : method->args()) {
1359 if (!first) {
1360 out << ", ";
1361 }
Andreas Huber881227d2016-08-02 14:20:21 -07001362
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001363 if (arg->type().resultNeedsDeref()) {
1364 out << "*";
1365 }
1366
1367 out << arg->name();
1368
1369 first = false;
1370 }
1371
1372 if (returnsValue) {
1373 if (!first) {
1374 out << ", ";
1375 }
1376
1377 out << "[&](";
1378
1379 first = true;
1380 for (const auto &arg : method->results()) {
1381 if (!first) {
1382 out << ", ";
1383 }
1384
Yifan Honga47eef32016-12-12 10:38:54 -08001385 out << "const auto &_hidl_out_" << arg->name();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001386
1387 first = false;
1388 }
1389
1390 out << ") {\n";
1391 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001392 out << "if (_hidl_callbackCalled) {\n";
1393 out.indent();
1394 out << "LOG_ALWAYS_FATAL(\""
1395 << method->name()
1396 << ": _hidl_cb called a second time, but must be called once.\");\n";
1397 out.unindent();
1398 out << "}\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001399 out << "_hidl_callbackCalled = true;\n\n";
1400
Yifan Hong859e53f2016-11-14 19:08:24 -08001401 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1402 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001403
Yifan Hongbf459bc2016-08-23 16:50:37 -07001404 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001405 for (const auto &arg : method->results()) {
1406 emitCppReaderWriter(
1407 out,
1408 "_hidl_reply",
1409 true /* parcelObjIsPointer */,
1410 arg,
1411 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001412 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001413 true /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001414 }
1415
Yifan Hongbf459bc2016-08-23 16:50:37 -07001416 // Second DFS: resolve references
1417 for (const auto &arg : method->results()) {
1418 emitCppResolveReferences(
1419 out,
1420 "_hidl_reply",
1421 true /* parcelObjIsPointer */,
1422 arg,
1423 false /* reader */,
1424 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001425 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001426 }
1427
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001428 status_t status = generateCppInstrumentationCall(
1429 out,
1430 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001431 method);
1432 if (status != OK) {
1433 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001434 }
1435
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001436 out << "_hidl_cb(*_hidl_reply);\n";
1437
1438 out.unindent();
1439 out << "}\n";
1440 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001441 out << ");\n\n";
1442
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001443 if (returnsValue) {
1444 out << "if (!_hidl_callbackCalled) {\n";
1445 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001446 out << "LOG_ALWAYS_FATAL(\""
1447 << method->name()
1448 << ": _hidl_cb not called, but must be called once.\");\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001449 out.unindent();
1450 out << "}\n\n";
Steven Moreland05cd4232016-11-21 16:01:12 -08001451 } else {
1452 out << "::android::hardware::writeToParcel("
1453 << "::android::hardware::Status::ok(), "
1454 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001455 }
Andreas Huber881227d2016-08-02 14:20:21 -07001456 }
1457
1458 out << "break;\n";
1459
1460 return OK;
1461}
1462
Steven Moreland69e7c702016-09-09 11:16:32 -07001463status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1464 std::string ifaceName;
1465 if (!AST::isInterface(&ifaceName)) {
1466 // types.hal does not get a stub header.
1467 return OK;
1468 }
1469
1470 const Interface *iface = mRootScope->getInterface();
1471
1472 const std::string baseName = iface->getBaseName();
1473 const std::string klassName = "Bs" + baseName;
1474
1475 bool supportOneway = iface->hasOnewayMethods();
1476
1477 std::string path = outputPath;
1478 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1479 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1480 path.append(klassName);
1481 path.append(".h");
1482
1483 CHECK(Coordinator::MakeParentHierarchy(path));
1484 FILE *file = fopen(path.c_str(), "w");
1485
1486 if (file == NULL) {
1487 return -errno;
1488 }
1489
1490 Formatter out(file);
1491
1492 const std::string guard = makeHeaderGuard(klassName);
1493
1494 out << "#ifndef " << guard << "\n";
1495 out << "#define " << guard << "\n\n";
1496
1497 std::vector<std::string> packageComponents;
1498 getPackageAndVersionComponents(
1499 &packageComponents, false /* cpp_compatible */);
1500
Yifan Hongb0949432016-12-15 15:32:24 -08001501 out << "#include <cutils/trace.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001502 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001503
1504 generateCppPackageInclude(out, mPackage, ifaceName);
1505 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001506
1507 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001508 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001509 }
1510
1511 enterLeaveNamespace(out, true /* enter */);
1512 out << "\n";
1513
1514 out << "struct "
1515 << klassName
1516 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001517 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001518
1519 out.indent();
1520 out << "explicit "
1521 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001522 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001523 << ifaceName
1524 << "> impl);\n";
1525
Yifan Hong068c5522016-10-31 14:07:25 -07001526 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1527 return generatePassthroughMethod(out, method);
1528 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001529
1530 if (err != OK) {
1531 return err;
1532 }
1533
1534 out.unindent();
1535 out << "private:\n";
1536 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001537 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001538
1539 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001540 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001541
1542 out << "\n";
1543
1544 out << "::android::hardware::Return<void> addOnewayTask("
1545 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001546 }
1547
1548 out.unindent();
1549
1550 out << "};\n\n";
1551
1552 enterLeaveNamespace(out, false /* enter */);
1553
1554 out << "\n#endif // " << guard << "\n";
1555
1556 return OK;
1557}
1558
Yifan Hongfe95aa22016-10-19 17:26:45 -07001559status_t AST::generateInterfaceSource(Formatter &out) const {
1560 const Interface *iface = mRootScope->getInterface();
1561
Yifan Hong2d7126b2016-10-20 15:12:57 -07001562 // generate castFrom functions
Yifan Hong3d746092016-12-07 14:26:33 -08001563 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001564
Yifan Hong3d746092016-12-07 14:26:33 -08001565 for (const Interface *superType : iface->typeChain()) {
1566 out << "// static \n"
1567 << childTypeResult
1568 << " I"
1569 << iface->getBaseName()
1570 << "::castFrom("
1571 << superType->getCppArgumentType()
1572 << " parent) {\n";
1573 out.indent();
1574 if (iface == superType) {
1575 out << "return parent;\n";
1576 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001577 out << "return ::android::hardware::castInterface<";
1578 out << "I" << iface->getBaseName() << ", "
1579 << superType->fqName().cppName() << ", "
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001580 << iface->getProxyName().cppLocalName() << ", "
1581 << superType->getProxyName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001582 << ">(\n";
1583 out.indent();
1584 out.indent();
1585 out << "parent, \""
1586 << iface->fqName().string()
1587 << "\");\n";
1588 out.unindent();
1589 out.unindent();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001590 }
Yifan Hong3d746092016-12-07 14:26:33 -08001591 out.unindent();
1592 out << "}\n\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001593 }
1594
1595 return OK;
1596}
1597
Steven Moreland69e7c702016-09-09 11:16:32 -07001598status_t AST::generatePassthroughSource(Formatter &out) const {
1599 const Interface *iface = mRootScope->getInterface();
1600
1601 const std::string baseName = iface->getBaseName();
1602 const std::string klassName = "Bs" + baseName;
1603
1604 out << klassName
1605 << "::"
1606 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001607 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001608 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001609 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001610 << iface->fqName().string()
1611 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001612 if (iface->hasOnewayMethods()) {
1613 out << "\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001614 out.indent([&] {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001615 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1616 });
1617 }
1618 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001619
1620 if (iface->hasOnewayMethods()) {
1621 out << "::android::hardware::Return<void> "
1622 << klassName
1623 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1624 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001625 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001626 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001627 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1628 out.indent();
1629 out.indent();
1630 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1631 out.unindent();
1632 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001633 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001634 out << "}\n";
1635
Steven Morelandd366c262016-10-11 15:29:10 -07001636 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001637
1638 out.unindent();
1639 out << "}\n\n";
1640
1641
1642 }
1643
1644 return OK;
1645}
1646
Martijn Coenen7b295242016-11-04 16:52:56 +01001647status_t AST::generateCppAtraceCall(Formatter &out,
1648 InstrumentationEvent event,
1649 const Method *method) const {
1650 const Interface *iface = mRootScope->getInterface();
1651 std::string baseString = "HIDL::I" + iface->getBaseName() + "::" + method->name();
1652 switch (event) {
1653 case SERVER_API_ENTRY:
1654 {
1655 out << "atrace_begin(ATRACE_TAG_HAL, \""
1656 << baseString + "::server\");\n";
1657 break;
1658 }
1659 case CLIENT_API_ENTRY:
1660 {
1661 out << "atrace_begin(ATRACE_TAG_HAL, \""
1662 << baseString + "::client\");\n";
1663 break;
1664 }
1665 case PASSTHROUGH_ENTRY:
1666 {
1667 out << "atrace_begin(ATRACE_TAG_HAL, \""
1668 << baseString + "::passthrough\");\n";
1669 break;
1670 }
1671 case SERVER_API_EXIT:
1672 case CLIENT_API_EXIT:
1673 case PASSTHROUGH_EXIT:
1674 {
1675 out << "atrace_end(ATRACE_TAG_HAL);\n";
1676 break;
1677 }
1678 default:
1679 {
1680 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1681 return UNKNOWN_ERROR;
1682 }
1683 }
1684
1685 return OK;
1686}
1687
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001688status_t AST::generateCppInstrumentationCall(
1689 Formatter &out,
1690 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001691 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001692 status_t err = generateCppAtraceCall(out, event, method);
1693 if (err != OK) {
1694 return err;
1695 }
1696
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001697 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1698 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001699 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001700 std::string event_str = "";
1701 switch (event) {
1702 case SERVER_API_ENTRY:
1703 {
1704 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1705 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001706 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001707 << (arg->type().resultNeedsDeref() ? "" : "&")
1708 << arg->name()
1709 << ");\n";
1710 }
1711 break;
1712 }
1713 case SERVER_API_EXIT:
1714 {
1715 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001716 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001717 out << "_hidl_args.push_back((void *)&_hidl_out_"
Steven Moreland031ccf12016-10-31 15:54:38 -07001718 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001719 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001720 }
1721 break;
1722 }
1723 case CLIENT_API_ENTRY:
1724 {
1725 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1726 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001727 out << "_hidl_args.push_back((void *)&"
1728 << arg->name()
1729 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001730 }
1731 break;
1732 }
1733 case CLIENT_API_EXIT:
1734 {
1735 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1736 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001737 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001738 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001739 << "_hidl_out_"
1740 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001741 << ");\n";
1742 }
1743 break;
1744 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001745 case PASSTHROUGH_ENTRY:
1746 {
1747 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1748 for (const auto &arg : method->args()) {
1749 out << "_hidl_args.push_back((void *)&"
1750 << arg->name()
1751 << ");\n";
1752 }
1753 break;
1754 }
1755 case PASSTHROUGH_EXIT:
1756 {
1757 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001758 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001759 out << "_hidl_args.push_back((void *)&_hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001760 << arg->name()
1761 << ");\n";
1762 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001763 break;
1764 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001765 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001766 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001767 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001768 return UNKNOWN_ERROR;
1769 }
1770 }
1771
Steven Moreland031ccf12016-10-31 15:54:38 -07001772 const Interface *iface = mRootScope->getInterface();
1773
Steven Moreland1ab31442016-11-03 18:37:51 -07001774 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001775 out.indent();
1776 out << "callback("
1777 << event_str
1778 << ", \""
1779 << mPackage.package()
1780 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001781 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001782 << "\", \""
1783 << iface->localName()
1784 << "\", \""
1785 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001786 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001787 out.unindent();
1788 out << "}\n";
1789 out.unindent();
1790 out << "}\n\n";
1791
1792 return OK;
1793}
1794
Andreas Huber881227d2016-08-02 14:20:21 -07001795} // namespace android
1796