blob: 51ebdc5d9362de57f83ced6b0893acd7c988c94c [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) {
Yifan Hong7a118f52016-12-07 11:21:15 -080055 err = generatePassthroughHeader(outputPath);
Steven Moreland69e7c702016-09-09 11:16:32 -070056 }
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
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700128static void declareGetService(Formatter &out, const std::string &interfaceName, bool isTry) {
129 const std::string functionName = isTry ? "tryGetService" : "getService";
130
131 out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
Chris Phoenixdb0d6342017-01-11 16:10:00 -0800132 << "const std::string &serviceName=\"default\", bool getStub=false);\n";
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700133 out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
Chris Phoenixdb0d6342017-01-11 16:10:00 -0800134 << "const char serviceName[], bool getStub=false)"
135 << " { std::string str(serviceName ? serviceName : \"\");"
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700136 << " return " << functionName << "(str, getStub); }\n";
137 out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
Chris Phoenixdb0d6342017-01-11 16:10:00 -0800138 << "const ::android::hardware::hidl_string& serviceName, bool getStub=false)"
139 // without c_str the std::string constructor is ambiguous
140 << " { std::string str(serviceName.c_str());"
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700141 << " return " << functionName << "(str, getStub); }\n";
142 out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
143 << "bool getStub) { return " << functionName << "(\"default\", getStub); }\n";
144}
145
146static void declareServiceManagerInteractions(Formatter &out, const std::string &interfaceName) {
147 declareGetService(out, interfaceName, true /* isTry */);
148 declareGetService(out, interfaceName, false /* isTry */);
149
Chris Phoenixdb0d6342017-01-11 16:10:00 -0800150 out << "::android::status_t registerAsService(const std::string &serviceName=\"default\");\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800151 out << "static bool registerForNotifications(\n";
152 out.indent(2, [&] {
153 out << "const std::string &serviceName,\n"
154 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
155 << "&notification);\n";
156 });
157
158}
159
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700160static void implementGetService(Formatter &out,
161 const FQName &fqName,
162 bool isTry) {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800163
164 const std::string interfaceName = fqName.getInterfaceName();
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700165 const std::string functionName = isTry ? "tryGetService" : "getService";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800166
167 out << "// static\n"
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700168 << "::android::sp<" << interfaceName << "> " << interfaceName << "::" << functionName << "("
Yifan Hong31f07ff2017-03-21 18:56:35 +0000169 << "const std::string &serviceName, const bool getStub) ";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800170 out.block([&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000171 out << "::android::sp<" << interfaceName << "> iface = nullptr;\n";
Yifan Hongd3b58ed2017-01-30 14:13:10 -0800172 out << "::android::vintf::Transport transport = ::android::hardware::getTransport("
Yifan Hong152866b2017-02-28 15:34:27 -0800173 << interfaceName << "::descriptor, serviceName);\n";
Steven Morelandf10af872017-01-25 16:01:56 +0000174
Yifan Hong31f07ff2017-03-21 18:56:35 +0000175 // TODO(b/34274385) remove sysprop check
176 out << "const bool vintfHwbinder = (transport == ::android::vintf::Transport::HWBINDER) ||\n"
177 << " (transport == ::android::vintf::Transport::TOGGLED &&\n"
178 << " ::android::hardware::details::blockingHalBinderizationEnabled());\n"
179 << "const bool vintfPassthru = (transport == ::android::vintf::Transport::PASSTHROUGH) ||\n"
180 << " (transport == ::android::vintf::Transport::TOGGLED &&\n"
181 << " !::android::hardware::details::blockingHalBinderizationEnabled());\n"
182 << "const bool vintfEmpty = (transport == ::android::vintf::Transport::EMPTY);\n\n";
183
184 // if (getStub) {
185 // getPassthroughServiceManager()->get only once.
186 // } else {
187 // if (vintfHwbinder) {
188 // while (no alive service) {
189 // waitForHwService
190 // defaultServiceManager()->get
191 // }
192 // } else if (vintfEmpty) {
193 // defaultServiceManager()->get only once.
194 // getPassthroughServiceManager()->get only once.
195 // } else if (vintfPassthru) {
196 // getPassthroughServiceManager()->get only once.
197 // }
198 // }
199
Yifan Hongf1ef44f2017-03-23 17:17:57 +0000200 out << "bool tried = false;\n";
201 out.sWhile("!getStub && (vintfHwbinder || (vintfEmpty && !tried))", [&] {
Yifan Hong31f07ff2017-03-21 18:56:35 +0000202
203 out.sIf("tried", [&] {
204 // sleep only after the first trial.
205 out << "ALOGI(\"getService: retrying in 1s...\");\n"
206 << "sleep(1);\n";
207 }).endl();
208
Yifan Hongf1ef44f2017-03-23 17:17:57 +0000209 out << "tried = true;\n";
210
Steven Morelandf10af872017-01-25 16:01:56 +0000211 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800212 out.indent(2, [&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000213 out << "= ::android::hardware::defaultServiceManager();\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800214 });
Yifan Hong31f07ff2017-03-21 18:56:35 +0000215 out.sIf("sm == nullptr", [&] {
216 // hwbinder is not available on this device, so future tries
217 // would also be null. I can only "break" here and
218 // (vintfEmpty) try passthrough or (vintfHwbinder) return nullptr.
219 out << "ALOGE(\"getService: defaultServiceManager() is null\");\n"
220 << "break;\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800221 }).endl();
Yifan Hong31f07ff2017-03-21 18:56:35 +0000222
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700223 if (!isTry) {
224 out.sIf("vintfHwbinder", [&] {
225 out << "::android::hardware::details::waitForHwService("
226 << interfaceName << "::descriptor" << ", serviceName);\n";
227 }).endl();
228 }
Yifan Hong31f07ff2017-03-21 18:56:35 +0000229
230 out << "::android::hardware::Return<::android::sp<"
231 << gIBaseFqName.cppName() << ">> ret = \n";
232 out.indent(2, [&] {
233 out << "sm->get(" << interfaceName << "::descriptor, serviceName);\n";
234 });
235
236 out.sIf("!ret.isOk()", [&] {
Steven Moreland42394ce2017-03-27 17:03:04 -0700237 // hwservicemanager fails, may be security issue
Yifan Hong31f07ff2017-03-21 18:56:35 +0000238 out << "ALOGE(\"getService: defaultServiceManager()->get returns %s\", "
239 << "ret.description().c_str());\n"
Steven Moreland42394ce2017-03-27 17:03:04 -0700240 << "break;\n";
Yifan Hong31f07ff2017-03-21 18:56:35 +0000241 }).endl();
242
243 out << "iface = " << interfaceName << "::castFrom(ret);\n";
244 out.sIf("iface == nullptr", [&] {
245 // 1. race condition. hwservicemanager drops the service
246 // from waitForHwService to here
247 // 2. service is dead (castFrom cannot call interfaceChain)
248 // 3. returned service isn't of correct type; this is a bug
249 // to hwservicemanager or to the service itself (interfaceChain
250 // is not consistent)
251 // In all cases, try again.
Steven Morelanddff644c2017-03-24 10:59:01 -0700252 out << "ALOGW(\"getService: found null hwbinder interface\");\n"
Steven Moreland9cca95b2017-03-29 00:55:32 -0700253 << "break;\n";
Yifan Hong31f07ff2017-03-21 18:56:35 +0000254 }).endl();
255
256 out << "return iface;\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800257 }).endl();
Steven Moreland2c2dea82017-01-18 17:24:17 -0800258
Yifan Hong31f07ff2017-03-21 18:56:35 +0000259 out.sIf("getStub || vintfPassthru || vintfEmpty", [&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000260 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> pm\n";
Steven Morelande3fa5da2017-01-25 07:07:53 +0000261 out.indent(2, [&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000262 out << "= ::android::hardware::getPassthroughServiceManager();\n";
Steven Morelande3fa5da2017-01-25 07:07:53 +0000263 });
Steven Morelandf10af872017-01-25 16:01:56 +0000264
265 out.sIf("pm != nullptr", [&] () {
266 out << "::android::hardware::Return<::android::sp<" << gIBaseFqName.cppName() << ">> ret = \n";
267 out.indent(2, [&] {
268 out << "pm->get(" << interfaceName << "::descriptor" << ", serviceName);\n";
Steven Moreland2c2dea82017-01-18 17:24:17 -0800269 });
Steven Morelandf10af872017-01-25 16:01:56 +0000270 out.sIf("ret.isOk()", [&] {
271 out << "::android::sp<" << gIBaseFqName.cppName()
272 << "> baseInterface = ret;\n";
273 out.sIf("baseInterface != nullptr", [&]() {
274 out << "iface = new " << fqName.getInterfacePassthroughName()
275 << "(" << interfaceName << "::castFrom(baseInterface));\n";
Yifan Hong31f07ff2017-03-21 18:56:35 +0000276 }).endl();
Steven Morelandf10af872017-01-25 16:01:56 +0000277 }).endl();
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800278 }).endl();
279 }).endl();
Steven Moreland2c2dea82017-01-18 17:24:17 -0800280
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800281 out << "return iface;\n";
282 }).endl().endl();
Steven Morelandeec5f7a2017-03-30 12:11:24 -0700283}
284
285static void implementServiceManagerInteractions(Formatter &out,
286 const FQName &fqName, const std::string &package) {
287
288 const std::string interfaceName = fqName.getInterfaceName();
289
290 implementGetService(out, fqName, true /* isTry */);
291 implementGetService(out, fqName, false /* isTry */);
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800292
Yifan Hongeefe4f22017-01-04 15:32:42 -0800293 out << "::android::status_t " << interfaceName << "::registerAsService("
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800294 << "const std::string &serviceName) ";
295 out.block([&] {
296 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
297 out.indent(2, [&] {
298 out << "= ::android::hardware::defaultServiceManager();\n";
299 });
300 out.sIf("sm == nullptr", [&] {
301 out << "return ::android::INVALID_OPERATION;\n";
302 }).endl();
Martijn Coenenbc9f5c92017-03-06 13:04:05 +0100303 out << "::android::hardware::Return<bool> ret = "
304 << "sm->add(serviceName.c_str(), this);\n"
305 << "return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800306 }).endl().endl();
307
Yifan Hongeefe4f22017-01-04 15:32:42 -0800308 out << "bool " << interfaceName << "::registerForNotifications(\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800309 out.indent(2, [&] {
310 out << "const std::string &serviceName,\n"
311 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
312 << "&notification) ";
313 });
314 out.block([&] {
315 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
316 out.indent(2, [&] {
317 out << "= ::android::hardware::defaultServiceManager();\n";
318 });
319 out.sIf("sm == nullptr", [&] {
320 out << "return false;\n";
321 }).endl();
322 out << "::android::hardware::Return<bool> success =\n";
323 out.indent(2, [&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800324 out << "sm->registerForNotifications(\"" << package << "::" << interfaceName << "\",\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800325 out.indent(2, [&] {
326 out << "serviceName, notification);\n";
327 });
328 });
329 out << "return success.isOk() && success;\n";
330 }).endl().endl();
331}
332
Andreas Huberb82318c2016-08-02 14:45:54 -0700333status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700334
Andreas Huberb82318c2016-08-02 14:45:54 -0700335 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700336 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700337 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700338
339 std::string ifaceName;
340 bool isInterface = true;
341 if (!AST::isInterface(&ifaceName)) {
342 ifaceName = "types";
343 isInterface = false;
344 }
345 path.append(ifaceName);
346 path.append(".h");
347
Andreas Huberd2943e12016-08-05 11:59:31 -0700348 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700349 FILE *file = fopen(path.c_str(), "w");
350
351 if (file == NULL) {
352 return -errno;
353 }
354
355 Formatter out(file);
356
357 const std::string guard = makeHeaderGuard(ifaceName);
358
359 out << "#ifndef " << guard << "\n";
360 out << "#define " << guard << "\n\n";
361
Andreas Huber737080b2016-08-02 15:38:04 -0700362 for (const auto &item : mImportedNames) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700363 generateCppPackageInclude(out, item, item.name());
Andreas Huber737080b2016-08-02 15:38:04 -0700364 }
365
366 if (!mImportedNames.empty()) {
367 out << "\n";
368 }
369
Steven Moreland0693f312016-11-09 15:06:14 -0800370 if (isInterface) {
Yifan Hongc8934042016-11-17 17:10:52 -0800371 if (isIBase()) {
372 out << "// skipped #include IServiceNotification.h\n\n";
373 } else {
374 out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
375 }
Steven Moreland0693f312016-11-09 15:06:14 -0800376 }
377
Yifan Hongc8934042016-11-17 17:10:52 -0800378 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700379 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700380
381 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200382 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700383 }
384
Martijn Coenenaf712c02016-11-16 15:26:27 +0100385 out << "#include <utils/NativeHandle.h>\n";
386 out << "#include <utils/misc.h>\n\n"; /* for report_sysprop_change() */
Andreas Huber881227d2016-08-02 14:20:21 -0700387
388 enterLeaveNamespace(out, true /* enter */);
389 out << "\n";
390
391 if (isInterface) {
392 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700393 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700394
395 const Interface *iface = mRootScope->getInterface();
396 const Interface *superType = iface->superType();
397
Steven Moreland40786312016-08-16 10:29:40 -0700398 if (superType == NULL) {
Yifan Hongc8934042016-11-17 17:10:52 -0800399 out << " : virtual public ::android::RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700400 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000401 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700402 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700403 }
404
405 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700406
407 out.indent();
408
Andreas Huber881227d2016-08-02 14:20:21 -0700409 }
410
411 status_t err = emitTypeDeclarations(out);
412
413 if (err != OK) {
414 return err;
415 }
416
417 if (isInterface) {
418 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800419
Yifan Hongc8934042016-11-17 17:10:52 -0800420 out << "virtual bool isRemote() const ";
421 if (!isIBase()) {
422 out << "override ";
423 }
424 out << "{ return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800425
Andreas Huber881227d2016-08-02 14:20:21 -0700426 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700427 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700428
Andreas Huber881227d2016-08-02 14:20:21 -0700429 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800430 const TypedVar *elidedReturn = method->canElideCallback();
431
432 if (elidedReturn == nullptr && returnsValue) {
433 out << "using "
434 << method->name()
Yifan Hong7d234ea2017-03-30 15:40:22 -0700435 << "_cb = std::function<void(";
436 method->emitCppResultSignature(out, true /* specify namespaces */);
437 out << ")>;\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800438 }
Andreas Huber881227d2016-08-02 14:20:21 -0700439
Andreas Huber3599d922016-08-09 10:42:57 -0700440 method->dumpAnnotations(out);
441
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700442 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700443 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700444 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700445 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700446 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700447 }
448
449 out << method->name()
Yifan Hong7d234ea2017-03-30 15:40:22 -0700450 << "(";
451 method->emitCppArgSignature(out, true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700452
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700453 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700454 if (!method->args().empty()) {
455 out << ", ";
456 }
457
Steven Moreland67f67b42016-09-29 08:59:02 -0700458 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700459 }
460
Yifan Hong10fe0b52016-10-19 14:20:17 -0700461 out << ")";
462 if (method->isHidlReserved()) {
Yifan Hongc8934042016-11-17 17:10:52 -0800463 if (!isIBase()) {
464 out << " override";
465 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700466 } else {
Steven Morelandd4b068a2017-03-20 06:30:51 -0700467 out << " = 0";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700468 }
Steven Morelandd4b068a2017-03-20 06:30:51 -0700469 out << ";\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700470 }
Steven Moreland40786312016-08-16 10:29:40 -0700471
Yifan Hong3d746092016-12-07 14:26:33 -0800472 out << "// cast static functions\n";
473 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700474
Yifan Hong3d746092016-12-07 14:26:33 -0800475 for (const Interface *superType : iface->typeChain()) {
476 out << "static "
477 << childTypeResult
478 << " castFrom("
479 << superType->getCppArgumentType()
480 << " parent"
481 << ");\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -0700482 }
483
Steven Morelandd39133b2016-11-11 12:30:08 -0800484 out << "\nstatic const char* descriptor;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700485
Yifan Hongc8934042016-11-17 17:10:52 -0800486 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800487 out << "// skipped getService, registerAsService, registerForNotifications\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800488 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800489 declareServiceManagerInteractions(out, iface->localName());
Yifan Hongc8934042016-11-17 17:10:52 -0800490 }
Andreas Huber881227d2016-08-02 14:20:21 -0700491 }
492
493 if (isInterface) {
494 out.unindent();
495
Andreas Hubere3f769a2016-10-10 10:54:44 -0700496 out << "};\n\n";
497 }
498
499 err = mRootScope->emitGlobalTypeDeclarations(out);
500
501 if (err != OK) {
502 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700503 }
504
505 out << "\n";
506 enterLeaveNamespace(out, false /* enter */);
507
508 out << "\n#endif // " << guard << "\n";
509
510 return OK;
511}
512
Steven Moreland40786312016-08-16 10:29:40 -0700513status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
514 std::string ifaceName;
Yifan Hong244e82d2016-11-11 11:13:57 -0800515 bool isInterface = AST::isInterface(&ifaceName);
516 const Interface *iface = nullptr;
Yifan Hong244e82d2016-11-11 11:13:57 -0800517 std::string klassName{};
518
519 if(isInterface) {
520 iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800521 klassName = iface->getHwName();
Yifan Hong244e82d2016-11-11 11:13:57 -0800522 } else {
523 klassName = "hwtypes";
Steven Moreland40786312016-08-16 10:29:40 -0700524 }
525
Steven Moreland40786312016-08-16 10:29:40 -0700526 std::string path = outputPath;
527 path.append(mCoordinator->convertPackageRootToPath(mPackage));
528 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
529 path.append(klassName + ".h");
530
Yifan Hong244e82d2016-11-11 11:13:57 -0800531 FILE *file = fopen(path.c_str(), "w");
Steven Moreland40786312016-08-16 10:29:40 -0700532
533 if (file == NULL) {
534 return -errno;
535 }
536
537 Formatter out(file);
538
539 const std::string guard = makeHeaderGuard(klassName);
540
541 out << "#ifndef " << guard << "\n";
542 out << "#define " << guard << "\n\n";
543
Yifan Hong244e82d2016-11-11 11:13:57 -0800544 if (isInterface) {
545 generateCppPackageInclude(out, mPackage, ifaceName);
546 } else {
547 generateCppPackageInclude(out, mPackage, "types");
548 }
Steven Moreland40786312016-08-16 10:29:40 -0700549
Steven Morelandee88eed2016-10-31 17:49:00 -0700550 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700551
552 for (const auto &item : mImportedNames) {
553 if (item.name() == "types") {
Yifan Hong244e82d2016-11-11 11:13:57 -0800554 generateCppPackageInclude(out, item, "hwtypes");
555 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800556 generateCppPackageInclude(out, item, item.getInterfaceStubName());
557 generateCppPackageInclude(out, item, item.getInterfaceProxyName());
Steven Moreland40786312016-08-16 10:29:40 -0700558 }
Steven Moreland40786312016-08-16 10:29:40 -0700559 }
560
561 out << "\n";
562
Martijn Coenen93915102016-09-01 01:35:52 +0200563 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700564 out << "#include <hwbinder/IBinder.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100565 out << "#include <hwbinder/Parcel.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700566
567 out << "\n";
568
569 enterLeaveNamespace(out, true /* enter */);
Steven Moreland40786312016-08-16 10:29:40 -0700570
Yifan Hong244e82d2016-11-11 11:13:57 -0800571 status_t err = mRootScope->emitGlobalHwDeclarations(out);
572 if (err != OK) {
573 return err;
574 }
Steven Moreland40786312016-08-16 10:29:40 -0700575
576 enterLeaveNamespace(out, false /* enter */);
577
578 out << "\n#endif // " << guard << "\n";
579
580 return OK;
581}
582
Andreas Huber881227d2016-08-02 14:20:21 -0700583status_t AST::emitTypeDeclarations(Formatter &out) const {
584 return mRootScope->emitTypeDeclarations(out);
585}
586
Yifan Hong7a118f52016-12-07 11:21:15 -0800587static void wrapPassthroughArg(Formatter &out,
588 const TypedVar *arg, bool addPrefixToName,
589 std::function<void(void)> handleError) {
590 if (!arg->type().isInterface()) {
591 return;
592 }
593 std::string name = (addPrefixToName ? "_hidl_out_" : "") + arg->name();
594 std::string wrappedName = (addPrefixToName ? "_hidl_out_wrapped_" : "_hidl_wrapped_")
595 + arg->name();
596 const Interface &iface = static_cast<const Interface &>(arg->type());
597 out << iface.getCppStackType() << " " << wrappedName << ";\n";
598 // TODO(elsk): b/33754152 Should not wrap this if object is Bs*
599 out.sIf(name + " != nullptr && !" + name + "->isRemote()", [&] {
600 out << wrappedName
601 << " = "
602 << iface.fqName().cppName()
Yifan Hong052425a2017-03-13 17:06:13 -0700603 << "::castFrom(::android::hardware::details::wrapPassthrough("
Yifan Hong7a118f52016-12-07 11:21:15 -0800604 << name << "));\n";
605 out.sIf(wrappedName + " == nullptr", [&] {
606 // Fatal error. Happens when the BsFoo class is not found in the binary
607 // or any dynamic libraries.
608 handleError();
609 }).endl();
610 }).sElse([&] {
611 out << wrappedName << " = " << name << ";\n";
612 }).endl().endl();
613}
614
Steven Moreland69e7c702016-09-09 11:16:32 -0700615status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700616 const Method *method) const {
617 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700618
619 out << " {\n";
620 out.indent();
621
Zhuoyao Zhangdd85c5c2017-01-03 17:30:24 -0800622 if (method->isHidlReserved()
623 && method->overridesCppImpl(IMPL_PASSTHROUGH)) {
624 method->cppImpl(IMPL_PASSTHROUGH, out);
625 out.unindent();
626 out << "}\n\n";
627 return OK;
628 }
629
Steven Moreland69e7c702016-09-09 11:16:32 -0700630 const bool returnsValue = !method->results().empty();
631 const TypedVar *elidedReturn = method->canElideCallback();
632
Steven Moreland67f67b42016-09-29 08:59:02 -0700633 if (returnsValue && elidedReturn == nullptr) {
634 generateCheckNonNull(out, "_hidl_cb");
635 }
636
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700637 generateCppInstrumentationCall(
638 out,
639 InstrumentationEvent::PASSTHROUGH_ENTRY,
640 method);
641
Yifan Hong7a118f52016-12-07 11:21:15 -0800642
643 for (const auto &arg : method->args()) {
644 wrapPassthroughArg(out, arg, false /* addPrefixToName */, [&] {
645 out << "return ::android::hardware::Status::fromExceptionCode(\n";
646 out.indent(2, [&] {
647 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
Yifan Hong0abd7392016-12-20 16:43:26 -0800648 << "\"Cannot wrap passthrough interface.\");\n";
Yifan Hong7a118f52016-12-07 11:21:15 -0800649 });
650 });
651 }
652
653 out << "auto _hidl_error = ::android::hardware::Void();\n";
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700654 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700655
656 if (method->isOneway()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800657 out << "addOnewayTask([this, &_hidl_error";
Steven Moreland69e7c702016-09-09 11:16:32 -0700658 for (const auto &arg : method->args()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800659 out << ", "
660 << (arg->type().isInterface() ? "_hidl_wrapped_" : "")
661 << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700662 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700663 out << "] {\n";
664 out.indent();
665 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700666 }
667
668 out << "mImpl->"
669 << method->name()
670 << "(";
671
Yifan Hong7d234ea2017-03-30 15:40:22 -0700672 out.join(method->args().begin(), method->args().end(), ", ", [&](const auto &arg) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800673 out << (arg->type().isInterface() ? "_hidl_wrapped_" : "") << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -0700674 });
Steven Moreland69e7c702016-09-09 11:16:32 -0700675 if (returnsValue && elidedReturn == nullptr) {
676 if (!method->args().empty()) {
677 out << ", ";
678 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800679 out << "[&](";
Yifan Hong7d234ea2017-03-30 15:40:22 -0700680 out.join(method->results().begin(), method->results().end(), ", ", [&](const auto &arg) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800681 out << "const auto &_hidl_out_"
682 << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -0700683 });
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800684
685 out << ") {\n";
686 out.indent();
687 status_t status = generateCppInstrumentationCall(
688 out,
689 InstrumentationEvent::PASSTHROUGH_EXIT,
690 method);
691 if (status != OK) {
692 return status;
693 }
694
Yifan Hong7a118f52016-12-07 11:21:15 -0800695 for (const auto &arg : method->results()) {
696 wrapPassthroughArg(out, arg, true /* addPrefixToName */, [&] {
697 out << "_hidl_error = ::android::hardware::Status::fromExceptionCode(\n";
698 out.indent(2, [&] {
699 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
Yifan Hong0abd7392016-12-20 16:43:26 -0800700 << "\"Cannot wrap passthrough interface.\");\n";
Yifan Hong7a118f52016-12-07 11:21:15 -0800701 });
702 out << "return;\n";
703 });
704 }
705
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800706 out << "_hidl_cb(";
Yifan Hong7d234ea2017-03-30 15:40:22 -0700707 out.join(method->results().begin(), method->results().end(), ", ", [&](const auto &arg) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800708 out << (arg->type().isInterface() ? "_hidl_out_wrapped_" : "_hidl_out_")
709 << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -0700710 });
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800711 out << ");\n";
712 out.unindent();
713 out << "});\n\n";
714 } else {
715 out << ");\n\n";
716 if (elidedReturn != nullptr) {
717 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -0800718 << " _hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800719 << elidedReturn->name()
Steven Moreland2ae5bca2016-12-01 05:56:49 +0000720 << " = _hidl_return;\n";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800721 }
722 status_t status = generateCppInstrumentationCall(
723 out,
724 InstrumentationEvent::PASSTHROUGH_EXIT,
725 method);
726 if (status != OK) {
727 return status;
728 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700729 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700730
731 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700732 out.unindent();
733 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700734 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700735
736 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700737
738 out.unindent();
739 out << "}\n";
740
741 return OK;
742}
743
Yifan Hong068c5522016-10-31 14:07:25 -0700744status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700745
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700746 const Interface *iface = mRootScope->getInterface();
747
Yifan Hong10fe0b52016-10-19 14:20:17 -0700748 const Interface *prevIterface = nullptr;
749 for (const auto &tuple : iface->allMethodsFromRoot()) {
750 const Method *method = tuple.method();
751 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700752
Yifan Hong10fe0b52016-10-19 14:20:17 -0700753 if(prevIterface != superInterface) {
754 if (prevIterface != nullptr) {
755 out << "\n";
756 }
757 out << "// Methods from "
758 << superInterface->fullName()
759 << " follow.\n";
760 prevIterface = superInterface;
761 }
Yifan Hong068c5522016-10-31 14:07:25 -0700762 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700763
Yifan Hong10fe0b52016-10-19 14:20:17 -0700764 if (err != OK) {
765 return err;
766 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700767 }
768
Yifan Hong10fe0b52016-10-19 14:20:17 -0700769 out << "\n";
770
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700771 return OK;
772}
773
Andreas Huberb82318c2016-08-02 14:45:54 -0700774status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700775 std::string ifaceName;
776 if (!AST::isInterface(&ifaceName)) {
777 // types.hal does not get a stub header.
778 return OK;
779 }
780
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700781 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800782 const std::string klassName = iface->getStubName();
Andreas Huber881227d2016-08-02 14:20:21 -0700783
Andreas Huberb82318c2016-08-02 14:45:54 -0700784 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700785 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700786 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700787 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700788 path.append(".h");
789
Andreas Huberd2943e12016-08-05 11:59:31 -0700790 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700791 FILE *file = fopen(path.c_str(), "w");
792
793 if (file == NULL) {
794 return -errno;
795 }
796
797 Formatter out(file);
798
Steven Moreland40786312016-08-16 10:29:40 -0700799 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700800
801 out << "#ifndef " << guard << "\n";
802 out << "#define " << guard << "\n\n";
803
Yifan Hongeefe4f22017-01-04 15:32:42 -0800804 generateCppPackageInclude(out, mPackage, iface->getHwName());
Steven Morelandee88eed2016-10-31 17:49:00 -0700805 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700806
807 enterLeaveNamespace(out, true /* enter */);
808 out << "\n";
809
810 out << "struct "
Yifan Hongeefe4f22017-01-04 15:32:42 -0800811 << klassName;
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100812 if (iface->isIBase()) {
Yifan Hong96a79e22017-01-12 14:22:05 -0800813 out << " : public ::android::hardware::BHwBinder";
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +0000814 out << ", public ::android::hardware::details::HidlInstrumentor {\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100815 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800816 out << " : public "
817 << gIBaseFqName.getInterfaceStubFqName().cppName()
818 << " {\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100819 }
Andreas Huber881227d2016-08-02 14:20:21 -0700820
821 out.indent();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800822 out << "explicit "
823 << klassName
Steven Moreland40786312016-08-16 10:29:40 -0700824 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100825 << "\n";
Yifan Hongeefe4f22017-01-04 15:32:42 -0800826 out << "explicit "
827 << klassName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100828 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl,"
Zhuoyao Zhangd10feea2017-01-23 17:29:58 -0800829 << " const std::string& HidlInstrumentor_package,"
830 << " const std::string& HidlInstrumentor_interface);"
Steven Moreland40786312016-08-16 10:29:40 -0700831 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700832 out << "::android::status_t onTransact(\n";
833 out.indent();
834 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700835 out << "uint32_t _hidl_code,\n";
836 out << "const ::android::hardware::Parcel &_hidl_data,\n";
837 out << "::android::hardware::Parcel *_hidl_reply,\n";
838 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700839 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700840 out.unindent();
841 out.unindent();
842
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100843 out << "::android::sp<" << ifaceName << "> getImpl() { return _hidl_mImpl; };\n";
844 out.unindent();
845 out << "private:\n";
846 out.indent();
Yifan Hongcd2ae452017-01-31 14:33:40 -0800847
848 status_t err = generateMethods(out, [&](const Method *method, const Interface *iface) {
849 if (!method->isHidlReserved() || !method->overridesCppImpl(IMPL_STUB_IMPL)) {
850 return OK;
851 }
852 const bool returnsValue = !method->results().empty();
853 const TypedVar *elidedReturn = method->canElideCallback();
854
855 if (elidedReturn == nullptr && returnsValue) {
856 out << "using " << method->name() << "_cb = "
857 << iface->fqName().cppName()
858 << "::" << method->name() << "_cb;\n";
859 }
860 method->generateCppSignature(out);
Yifan Hongbcffce22017-02-01 15:52:06 -0800861 out << ";\n";
Yifan Hongcd2ae452017-01-31 14:33:40 -0800862 return OK;
863 });
864 if (err != OK) {
865 return err;
866 }
867
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100868 out << "::android::sp<" << ifaceName << "> _hidl_mImpl;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700869 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700870 out << "};\n\n";
871
872 enterLeaveNamespace(out, false /* enter */);
873
874 out << "\n#endif // " << guard << "\n";
875
876 return OK;
877}
878
Andreas Huberb82318c2016-08-02 14:45:54 -0700879status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700880 std::string ifaceName;
881 if (!AST::isInterface(&ifaceName)) {
882 // types.hal does not get a proxy header.
883 return OK;
884 }
885
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700886 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800887 const std::string proxyName = iface->getProxyName();
Andreas Huber881227d2016-08-02 14:20:21 -0700888
Andreas Huberb82318c2016-08-02 14:45:54 -0700889 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700890 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700891 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Yifan Hongeefe4f22017-01-04 15:32:42 -0800892 path.append(proxyName);
Andreas Huber881227d2016-08-02 14:20:21 -0700893 path.append(".h");
894
Andreas Huberd2943e12016-08-05 11:59:31 -0700895 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700896 FILE *file = fopen(path.c_str(), "w");
897
898 if (file == NULL) {
899 return -errno;
900 }
901
902 Formatter out(file);
903
Yifan Hongeefe4f22017-01-04 15:32:42 -0800904 const std::string guard = makeHeaderGuard(proxyName);
Andreas Huber881227d2016-08-02 14:20:21 -0700905
906 out << "#ifndef " << guard << "\n";
907 out << "#define " << guard << "\n\n";
908
Martijn Coenen115d4282016-12-19 05:14:04 +0100909 out << "#include <hidl/HidlTransportSupport.h>\n\n";
910
Andreas Huber881227d2016-08-02 14:20:21 -0700911 std::vector<std::string> packageComponents;
912 getPackageAndVersionComponents(
913 &packageComponents, false /* cpp_compatible */);
914
Yifan Hongeefe4f22017-01-04 15:32:42 -0800915 generateCppPackageInclude(out, mPackage, iface->getHwName());
Steven Morelandee88eed2016-10-31 17:49:00 -0700916 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700917
918 enterLeaveNamespace(out, true /* enter */);
919 out << "\n";
920
921 out << "struct "
Yifan Hongeefe4f22017-01-04 15:32:42 -0800922 << proxyName
923 << " : public ::android::hardware::BpInterface<"
924 << iface->localName()
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +0000925 << ">, public ::android::hardware::details::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700926
927 out.indent();
928
Yifan Hongeefe4f22017-01-04 15:32:42 -0800929 out << "explicit "
930 << proxyName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700931 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700932 << "\n\n";
933
Yifan Hong10fe0b52016-10-19 14:20:17 -0700934 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700935
Yifan Hong068c5522016-10-31 14:07:25 -0700936 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
937 method->generateCppSignature(out);
938 out << " override;\n";
939 return OK;
940 });
Steven Moreland9c387612016-09-07 09:54:26 -0700941
942 if (err != OK) {
943 return err;
944 }
Andreas Huber881227d2016-08-02 14:20:21 -0700945
946 out.unindent();
Martijn Coenen115d4282016-12-19 05:14:04 +0100947 out << "private:\n";
948 out.indent();
949 out << "std::mutex _hidl_mMutex;\n"
950 << "std::vector<::android::sp<::android::hardware::hidl_binder_death_recipient>>"
951 << " _hidl_mDeathRecipients;\n";
952 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700953 out << "};\n\n";
954
955 enterLeaveNamespace(out, false /* enter */);
956
957 out << "\n#endif // " << guard << "\n";
958
959 return OK;
960}
961
Andreas Huberb82318c2016-08-02 14:45:54 -0700962status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700963
Andreas Huberb82318c2016-08-02 14:45:54 -0700964 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700965 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700966 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700967
968 std::string ifaceName;
969 std::string baseName;
970
Yifan Hongfe95aa22016-10-19 17:26:45 -0700971 const Interface *iface = nullptr;
972 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700973 if (!AST::isInterface(&ifaceName)) {
974 baseName = "types";
975 isInterface = false;
976 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700977 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700978 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700979 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700980 }
981
982 path.append(baseName);
983
984 if (baseName != "types") {
985 path.append("All");
986 }
987
988 path.append(".cpp");
989
Andreas Huberd2943e12016-08-05 11:59:31 -0700990 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700991 FILE *file = fopen(path.c_str(), "w");
992
993 if (file == NULL) {
994 return -errno;
995 }
996
997 Formatter out(file);
998
Steven Moreland623c0042017-01-13 14:42:29 -0800999 out << "#define LOG_TAG \""
1000 << mPackage.string() << "::" << baseName
1001 << "\"\n\n";
1002
Steven Moreland05cd4232016-11-21 16:01:12 -08001003 out << "#include <android/log.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001004 out << "#include <cutils/trace.h>\n";
1005 out << "#include <hidl/HidlTransportSupport.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001006 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -07001007 // This is a no-op for IServiceManager itself.
1008 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
1009
Steven Morelandbec74ed2017-01-25 17:42:35 -08001010 // TODO(b/34274385) remove this
1011 out << "#include <hidl/LegacySupport.h>\n";
1012
Yifan Hongeefe4f22017-01-04 15:32:42 -08001013 generateCppPackageInclude(out, mPackage, iface->getProxyName());
1014 generateCppPackageInclude(out, mPackage, iface->getStubName());
1015 generateCppPackageInclude(out, mPackage, iface->getPassthroughName());
Yifan Hongfe95aa22016-10-19 17:26:45 -07001016
1017 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -07001018 generateCppPackageInclude(out,
1019 superType->fqName(),
Yifan Hongeefe4f22017-01-04 15:32:42 -08001020 superType->fqName().getInterfaceProxyName());
Yifan Hongfe95aa22016-10-19 17:26:45 -07001021 }
Yifan Hong2cbbdf92016-12-05 15:20:50 -08001022
1023 out << "#include <hidl/ServiceManagement.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001024 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -07001025 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -08001026 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -07001027 }
1028
1029 out << "\n";
1030
1031 enterLeaveNamespace(out, true /* enter */);
1032 out << "\n";
1033
1034 status_t err = generateTypeSource(out, ifaceName);
1035
1036 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001037 const Interface *iface = mRootScope->getInterface();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001038
1039 // need to be put here, generateStubSource is using this.
Yifan Hongeefe4f22017-01-04 15:32:42 -08001040 out << "const char* "
1041 << iface->localName()
Yifan Hong10fe0b52016-10-19 14:20:17 -07001042 << "::descriptor(\""
1043 << iface->fqName().string()
1044 << "\");\n\n";
Martijn Coenen8adcb652017-02-03 17:37:36 +01001045 out << "__attribute__((constructor))";
1046 out << "static void static_constructor() {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001047 out.indent([&] {
Yifan Honga159f3b2017-03-16 14:53:51 -07001048 out << "::android::hardware::details::gBnConstructorMap.set("
Yifan Hongeefe4f22017-01-04 15:32:42 -08001049 << iface->localName()
Yifan Hongb04de382017-02-06 15:31:52 -08001050 << "::descriptor,\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001051 out.indent(2, [&] {
Yifan Hongb04de382017-02-06 15:31:52 -08001052 out << "[](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001053 out.indent([&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001054 out << "return new "
1055 << iface->getStubName()
1056 << "(reinterpret_cast<"
1057 << iface->localName()
Yifan Hong158655a2016-11-08 12:34:07 -08001058 << " *>(iIntf));\n";
1059 });
Yifan Hongb04de382017-02-06 15:31:52 -08001060 out << "});\n";
Yifan Hong158655a2016-11-08 12:34:07 -08001061 });
Yifan Honga159f3b2017-03-16 14:53:51 -07001062 out << "::android::hardware::details::gBsConstructorMap.set("
Yifan Hongeefe4f22017-01-04 15:32:42 -08001063 << iface->localName()
Yifan Hongb04de382017-02-06 15:31:52 -08001064 << "::descriptor,\n";
Yifan Hong7a118f52016-12-07 11:21:15 -08001065 out.indent(2, [&] {
Yifan Hongb04de382017-02-06 15:31:52 -08001066 out << "[](void *iIntf) -> ::android::sp<"
Yifan Hong7a118f52016-12-07 11:21:15 -08001067 << gIBaseFqName.cppName()
1068 << "> {\n";
1069 out.indent([&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001070 out << "return new "
1071 << iface->getPassthroughName()
1072 << "(reinterpret_cast<"
1073 << iface->localName()
Yifan Hong7a118f52016-12-07 11:21:15 -08001074 << " *>(iIntf));\n";
1075 });
Yifan Hongb04de382017-02-06 15:31:52 -08001076 out << "});\n";
Yifan Hong7a118f52016-12-07 11:21:15 -08001077 });
Yifan Hong158655a2016-11-08 12:34:07 -08001078 });
Martijn Coenen8adcb652017-02-03 17:37:36 +01001079 out << "};\n\n";
1080 out << "__attribute__((destructor))";
1081 out << "static void static_destructor() {\n";
1082 out.indent([&] {
Yifan Honga159f3b2017-03-16 14:53:51 -07001083 out << "::android::hardware::details::gBnConstructorMap.erase("
Martijn Coenen8adcb652017-02-03 17:37:36 +01001084 << iface->localName()
1085 << "::descriptor);\n";
Yifan Honga159f3b2017-03-16 14:53:51 -07001086 out << "::android::hardware::details::gBsConstructorMap.erase("
Martijn Coenen8adcb652017-02-03 17:37:36 +01001087 << iface->localName()
1088 << "::descriptor);\n";
1089 });
1090 out << "};\n\n";
Yifan Hong158655a2016-11-08 12:34:07 -08001091
Yifan Hongfe95aa22016-10-19 17:26:45 -07001092 err = generateInterfaceSource(out);
1093 }
1094
1095 if (err == OK && isInterface) {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001096 err = generateProxySource(out, iface->fqName());
Andreas Huber881227d2016-08-02 14:20:21 -07001097 }
1098
1099 if (err == OK && isInterface) {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001100 err = generateStubSource(out, iface);
Andreas Huber881227d2016-08-02 14:20:21 -07001101 }
1102
Steven Moreland40786312016-08-16 10:29:40 -07001103 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -07001104 err = generatePassthroughSource(out);
1105 }
1106
1107 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -07001108 const Interface *iface = mRootScope->getInterface();
1109
Yifan Hongc8934042016-11-17 17:10:52 -08001110 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001111 out << "// skipped getService, registerAsService, registerForNotifications\n";
Yifan Hongc8934042016-11-17 17:10:52 -08001112 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001113 std::string package = iface->fqName().package()
1114 + iface->fqName().atVersion();
1115
Yifan Hongeefe4f22017-01-04 15:32:42 -08001116 implementServiceManagerInteractions(out, iface->fqName(), package);
Yifan Hongc8934042016-11-17 17:10:52 -08001117 }
Steven Moreland40786312016-08-16 10:29:40 -07001118 }
1119
Andreas Huber881227d2016-08-02 14:20:21 -07001120 enterLeaveNamespace(out, false /* enter */);
1121
1122 return err;
1123}
1124
Steven Moreland67f67b42016-09-29 08:59:02 -07001125// static
1126void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
Yifan Honga018ed52016-12-13 16:35:08 -08001127 out.sIf(nonNull + " == nullptr", [&] {
1128 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1129 out.indent(2, [&] {
1130 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
1131 });
1132 }).endl().endl();
Steven Moreland67f67b42016-09-29 08:59:02 -07001133}
1134
Andreas Huber881227d2016-08-02 14:20:21 -07001135status_t AST::generateTypeSource(
1136 Formatter &out, const std::string &ifaceName) const {
1137 return mRootScope->emitTypeDefinitions(out, ifaceName);
1138}
1139
Andreas Hubere7ff2282016-08-16 13:50:03 -07001140void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -07001141 Formatter &out,
1142 const std::vector<TypedVar *> &args,
1143 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -07001144 if (args.empty()) {
1145 return;
1146 }
1147
1148 for (const auto &arg : args) {
1149 const Type &type = arg->type();
1150
Yifan Hong3b320f82016-11-01 15:15:54 -07001151 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001152 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -07001153 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001154 << ";\n";
1155 }
1156
1157 out << "\n";
1158}
1159
Andreas Huber881227d2016-08-02 14:20:21 -07001160void AST::emitCppReaderWriter(
1161 Formatter &out,
1162 const std::string &parcelObj,
1163 bool parcelObjIsPointer,
1164 const TypedVar *arg,
1165 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -07001166 Type::ErrorMode mode,
1167 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001168 const Type &type = arg->type();
1169
Andreas Huber881227d2016-08-02 14:20:21 -07001170 type.emitReaderWriter(
1171 out,
Andreas Huber5e44a292016-09-27 14:52:39 -07001172 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -07001173 parcelObj,
1174 parcelObjIsPointer,
1175 isReader,
1176 mode);
1177}
1178
Yifan Hongbf459bc2016-08-23 16:50:37 -07001179void AST::emitCppResolveReferences(
1180 Formatter &out,
1181 const std::string &parcelObj,
1182 bool parcelObjIsPointer,
1183 const TypedVar *arg,
1184 bool isReader,
1185 Type::ErrorMode mode,
1186 bool addPrefixToName) const {
1187 const Type &type = arg->type();
1188 if(type.needsResolveReferences()) {
1189 type.emitResolveReferences(
1190 out,
1191 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
1192 isReader, // nameIsPointer
1193 parcelObj,
1194 parcelObjIsPointer,
1195 isReader,
1196 mode);
1197 }
1198}
1199
Yifan Hong068c5522016-10-31 14:07:25 -07001200status_t AST::generateProxyMethodSource(Formatter &out,
1201 const std::string &klassName,
1202 const Method *method,
1203 const Interface *superInterface) const {
1204
1205 method->generateCppSignature(out,
1206 klassName,
1207 true /* specify namespaces */);
1208
1209 const bool returnsValue = !method->results().empty();
1210 const TypedVar *elidedReturn = method->canElideCallback();
1211
Steven Moreland41c6d2e2016-11-07 12:26:54 -08001212 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001213
1214 out.indent();
1215
Martijn Coenen115d4282016-12-19 05:14:04 +01001216 if (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
1217 method->cppImpl(IMPL_PROXY, out);
1218 out.unindent();
1219 out << "}\n\n";
1220 return OK;
1221 }
1222
Yifan Hong068c5522016-10-31 14:07:25 -07001223 if (returnsValue && elidedReturn == nullptr) {
1224 generateCheckNonNull(out, "_hidl_cb");
1225 }
1226
1227 status_t status = generateCppInstrumentationCall(
1228 out,
1229 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -07001230 method);
1231 if (status != OK) {
1232 return status;
1233 }
1234
1235 out << "::android::hardware::Parcel _hidl_data;\n";
1236 out << "::android::hardware::Parcel _hidl_reply;\n";
1237 out << "::android::status_t _hidl_err;\n";
1238 out << "::android::hardware::Status _hidl_status;\n\n";
1239
1240 declareCppReaderLocals(
1241 out, method->results(), true /* forResults */);
1242
1243 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Yifan Hongeefe4f22017-01-04 15:32:42 -08001244 out << superInterface->fqName().cppName();
Yifan Hong068c5522016-10-31 14:07:25 -07001245 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001246 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1247
Martijn Coenenfff73352017-01-04 16:36:31 +01001248 bool hasInterfaceArgument = false;
Yifan Hong068c5522016-10-31 14:07:25 -07001249 // First DFS: write all buffers and resolve pointers for parent
1250 for (const auto &arg : method->args()) {
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001251 if (arg->type().isInterface()) {
1252 hasInterfaceArgument = true;
1253 }
Yifan Hong068c5522016-10-31 14:07:25 -07001254 emitCppReaderWriter(
1255 out,
1256 "_hidl_data",
1257 false /* parcelObjIsPointer */,
1258 arg,
1259 false /* reader */,
1260 Type::ErrorMode_Goto,
1261 false /* addPrefixToName */);
1262 }
1263
1264 // Second DFS: resolve references.
1265 for (const auto &arg : method->args()) {
1266 emitCppResolveReferences(
1267 out,
1268 "_hidl_data",
1269 false /* parcelObjIsPointer */,
1270 arg,
1271 false /* reader */,
1272 Type::ErrorMode_Goto,
1273 false /* addPrefixToName */);
1274 }
1275
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001276 if (hasInterfaceArgument) {
1277 // Start binder threadpool to handle incoming transactions
1278 out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
1279 }
Yifan Hong068c5522016-10-31 14:07:25 -07001280 out << "_hidl_err = remote()->transact("
1281 << method->getSerialId()
1282 << " /* "
1283 << method->name()
1284 << " */, _hidl_data, &_hidl_reply";
1285
1286 if (method->isOneway()) {
1287 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1288 }
1289 out << ");\n";
1290
1291 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1292
1293 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001294 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001295 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1296 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1297
1298
1299 // First DFS: write all buffers and resolve pointers for parent
1300 for (const auto &arg : method->results()) {
1301 emitCppReaderWriter(
1302 out,
1303 "_hidl_reply",
1304 false /* parcelObjIsPointer */,
1305 arg,
1306 true /* reader */,
1307 Type::ErrorMode_Goto,
1308 true /* addPrefixToName */);
1309 }
1310
1311 // Second DFS: resolve references.
1312 for (const auto &arg : method->results()) {
1313 emitCppResolveReferences(
1314 out,
1315 "_hidl_reply",
1316 false /* parcelObjIsPointer */,
1317 arg,
1318 true /* reader */,
1319 Type::ErrorMode_Goto,
1320 true /* addPrefixToName */);
1321 }
1322
1323 if (returnsValue && elidedReturn == nullptr) {
1324 out << "_hidl_cb(";
1325
Yifan Hong7d234ea2017-03-30 15:40:22 -07001326 out.join(method->results().begin(), method->results().end(), ", ", [&] (const auto &arg) {
Yifan Hong068c5522016-10-31 14:07:25 -07001327 if (arg->type().resultNeedsDeref()) {
1328 out << "*";
1329 }
1330 out << "_hidl_out_" << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -07001331 });
Yifan Hong068c5522016-10-31 14:07:25 -07001332
1333 out << ");\n\n";
1334 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001335 }
1336 status = generateCppInstrumentationCall(
1337 out,
1338 InstrumentationEvent::CLIENT_API_EXIT,
1339 method);
1340 if (status != OK) {
1341 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001342 }
1343
1344 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001345 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1346 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001347 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001348 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1349 } else {
1350 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1351 out << "return ::android::hardware::Return<void>();\n\n";
1352 }
1353
1354 out.unindent();
1355 out << "_hidl_error:\n";
1356 out.indent();
1357 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1358 out << "return ::android::hardware::Return<";
1359 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001360 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001361 } else {
1362 out << "void";
1363 }
1364 out << ">(_hidl_status);\n";
1365
1366 out.unindent();
1367 out << "}\n\n";
1368 return OK;
1369}
1370
Andreas Huber881227d2016-08-02 14:20:21 -07001371status_t AST::generateProxySource(
Yifan Hongeefe4f22017-01-04 15:32:42 -08001372 Formatter &out, const FQName &fqName) const {
1373 const std::string klassName = fqName.getInterfaceProxyName();
Andreas Huber881227d2016-08-02 14:20:21 -07001374
1375 out << klassName
1376 << "::"
1377 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001378 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001379
1380 out.indent();
1381 out.indent();
1382
1383 out << ": BpInterface"
Yifan Hongeefe4f22017-01-04 15:32:42 -08001384 << "<"
1385 << fqName.getInterfaceName()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001386 << ">(_hidl_impl),\n"
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +00001387 << " ::android::hardware::details::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001388 << mPackage.string()
Zhuoyao Zhangd10feea2017-01-23 17:29:58 -08001389 << "\", \""
Yifan Hongeefe4f22017-01-04 15:32:42 -08001390 << fqName.getInterfaceName()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001391 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001392
Andreas Huber881227d2016-08-02 14:20:21 -07001393 out.unindent();
1394 out.unindent();
1395 out << "}\n\n";
1396
Yifan Hong068c5522016-10-31 14:07:25 -07001397 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1398 return generateProxyMethodSource(out, klassName, method, superInterface);
1399 });
Andreas Huber881227d2016-08-02 14:20:21 -07001400
Yifan Hong068c5522016-10-31 14:07:25 -07001401 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001402}
1403
1404status_t AST::generateStubSource(
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001405 Formatter &out,
Yifan Hongeefe4f22017-01-04 15:32:42 -08001406 const Interface *iface) const {
1407 const std::string interfaceName = iface->localName();
1408 const std::string klassName = iface->getStubName();
Andreas Huber881227d2016-08-02 14:20:21 -07001409
Steven Moreland40786312016-08-16 10:29:40 -07001410 out << klassName
1411 << "::"
1412 << klassName
Yifan Hongeefe4f22017-01-04 15:32:42 -08001413 << "(const ::android::sp<" << interfaceName <<"> &_hidl_impl)\n";
Steven Moreland40786312016-08-16 10:29:40 -07001414
1415 out.indent();
1416 out.indent();
1417
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001418 if (iface->isIBase()) {
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +00001419 out << ": ::android::hardware::details::HidlInstrumentor(\"";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001420 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001421 out << ": "
1422 << gIBaseFqName.getInterfaceStubFqName().cppName()
1423 << "(_hidl_impl, \"";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001424 }
1425
1426 out << mPackage.string()
Zhuoyao Zhangd10feea2017-01-23 17:29:58 -08001427 << "\", \""
Yifan Hongeefe4f22017-01-04 15:32:42 -08001428 << interfaceName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001429 << "\") { \n";
1430 out.indent();
1431 out << "_hidl_mImpl = _hidl_impl;\n";
1432 out.unindent();
Steven Moreland40786312016-08-16 10:29:40 -07001433
1434 out.unindent();
1435 out.unindent();
1436 out << "}\n\n";
1437
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001438 if (iface->isIBase()) {
Yifan Hong01e7cde2017-01-09 17:45:45 -08001439 // BnHwBase has a constructor to initialize the HidlInstrumentor
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001440 // class properly.
1441 out << klassName
1442 << "::"
1443 << klassName
Zhuoyao Zhangd10feea2017-01-23 17:29:58 -08001444 << "(const ::android::sp<" << interfaceName << "> &_hidl_impl,"
1445 << " const std::string &HidlInstrumentor_package,"
1446 << " const std::string &HidlInstrumentor_interface)\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001447
1448 out.indent();
1449 out.indent();
1450
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +00001451 out << ": ::android::hardware::details::HidlInstrumentor("
Zhuoyao Zhangd10feea2017-01-23 17:29:58 -08001452 << "HidlInstrumentor_package, HidlInstrumentor_interface) {\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001453 out.indent();
1454 out << "_hidl_mImpl = _hidl_impl;\n";
1455 out.unindent();
1456
1457 out.unindent();
1458 out.unindent();
1459 out << "}\n\n";
1460 }
1461
Yifan Hongbcffce22017-02-01 15:52:06 -08001462 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1463 if (!method->isHidlReserved() || !method->overridesCppImpl(IMPL_STUB_IMPL)) {
1464 return OK;
1465 }
1466 method->generateCppSignature(out, iface->getStubName());
1467 out << " ";
1468 out.block([&] {
1469 method->cppImpl(IMPL_STUB_IMPL, out);
1470 }).endl();
1471 return OK;
1472 });
Steven Moreland60818632017-02-04 00:33:42 -08001473 if (err != OK) {
1474 return err;
1475 }
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001476
Andreas Huber881227d2016-08-02 14:20:21 -07001477 out << "::android::status_t " << klassName << "::onTransact(\n";
1478
1479 out.indent();
1480 out.indent();
1481
Iliyan Malchev549e2592016-08-10 08:59:12 -07001482 out << "uint32_t _hidl_code,\n"
1483 << "const ::android::hardware::Parcel &_hidl_data,\n"
1484 << "::android::hardware::Parcel *_hidl_reply,\n"
1485 << "uint32_t _hidl_flags,\n"
1486 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001487
1488 out.unindent();
1489
Iliyan Malchev549e2592016-08-10 08:59:12 -07001490 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001491 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001492 out.indent();
1493
Yifan Hong10fe0b52016-10-19 14:20:17 -07001494 for (const auto &tuple : iface->allMethodsFromRoot()) {
1495 const Method *method = tuple.method();
1496 const Interface *superInterface = tuple.interface();
1497 out << "case "
1498 << method->getSerialId()
1499 << " /* "
1500 << method->name()
1501 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001502
Yifan Hong10fe0b52016-10-19 14:20:17 -07001503 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001504
Yifan Hong10fe0b52016-10-19 14:20:17 -07001505 status_t err =
1506 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001507
Yifan Hong10fe0b52016-10-19 14:20:17 -07001508 if (err != OK) {
1509 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001510 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001511
1512 out.unindent();
1513 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001514 }
1515
1516 out << "default:\n{\n";
1517 out.indent();
1518
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001519 out << "return onTransact(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001520
1521 out.indent();
1522 out.indent();
1523
Iliyan Malchev549e2592016-08-10 08:59:12 -07001524 out << "_hidl_code, _hidl_data, _hidl_reply, "
1525 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001526
1527 out.unindent();
1528 out.unindent();
1529
1530 out.unindent();
1531 out << "}\n";
1532
1533 out.unindent();
1534 out << "}\n\n";
1535
Yifan Honga018ed52016-12-13 16:35:08 -08001536 out.sIf("_hidl_err == ::android::UNEXPECTED_NULL", [&] {
1537 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
1538 out.indent(2, [&] {
1539 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1540 out << "_hidl_reply);\n";
1541 });
1542 });
Andreas Huber881227d2016-08-02 14:20:21 -07001543
Iliyan Malchev549e2592016-08-10 08:59:12 -07001544 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001545
1546 out.unindent();
1547 out << "}\n\n";
1548
1549 return OK;
1550}
1551
1552status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001553 Formatter &out, const Interface *iface, const Method *method) const {
Martijn Coenen115d4282016-12-19 05:14:04 +01001554 if (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB)) {
1555 method->cppImpl(IMPL_STUB, out);
1556 out << "break;\n";
1557 return OK;
1558 }
1559
Yifan Hongeefe4f22017-01-04 15:32:42 -08001560 out << "if (!_hidl_data.enforceInterface("
1561 << iface->fullName()
1562 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001563
Andreas Huber881227d2016-08-02 14:20:21 -07001564 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001565 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001566 out << "break;\n";
1567 out.unindent();
1568 out << "}\n\n";
1569
Andreas Huber5e44a292016-09-27 14:52:39 -07001570 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001571
Yifan Hongbf459bc2016-08-23 16:50:37 -07001572 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001573 for (const auto &arg : method->args()) {
1574 emitCppReaderWriter(
1575 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001576 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001577 false /* parcelObjIsPointer */,
1578 arg,
1579 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001580 Type::ErrorMode_Break,
1581 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001582 }
1583
Yifan Hongbf459bc2016-08-23 16:50:37 -07001584 // Second DFS: resolve references
1585 for (const auto &arg : method->args()) {
1586 emitCppResolveReferences(
1587 out,
1588 "_hidl_data",
1589 false /* parcelObjIsPointer */,
1590 arg,
1591 true /* reader */,
1592 Type::ErrorMode_Break,
1593 false /* addPrefixToName */);
1594 }
1595
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001596 status_t status = generateCppInstrumentationCall(
1597 out,
1598 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001599 method);
1600 if (status != OK) {
1601 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001602 }
1603
Andreas Huber881227d2016-08-02 14:20:21 -07001604 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001605 const TypedVar *elidedReturn = method->canElideCallback();
Yifan Hongcd2ae452017-01-31 14:33:40 -08001606 const std::string callee =
1607 (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB_IMPL))
1608 ? "this" : "_hidl_mImpl";
Andreas Huber881227d2016-08-02 14:20:21 -07001609
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001610 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001611 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -08001612 << " _hidl_out_"
Yifan Hong3b320f82016-11-01 15:15:54 -07001613 << elidedReturn->name()
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001614 << " = "
Yifan Hongcd2ae452017-01-31 14:33:40 -08001615 << callee << "->" << method->name()
Yifan Hong3b320f82016-11-01 15:15:54 -07001616 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001617
Yifan Hong7d234ea2017-03-30 15:40:22 -07001618 out.join(method->args().begin(), method->args().end(), ", ", [&] (const auto &arg) {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001619 if (arg->type().resultNeedsDeref()) {
1620 out << "*";
1621 }
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001622 out << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -07001623 });
Andreas Huber881227d2016-08-02 14:20:21 -07001624
Steven Moreland2ae5bca2016-12-01 05:56:49 +00001625 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001626 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1627 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001628
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001629 elidedReturn->type().emitReaderWriter(
1630 out,
Yifan Honga47eef32016-12-12 10:38:54 -08001631 "_hidl_out_" + elidedReturn->name(),
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001632 "_hidl_reply",
1633 true, /* parcelObjIsPointer */
1634 false, /* isReader */
1635 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001636
Yifan Hongbf459bc2016-08-23 16:50:37 -07001637 emitCppResolveReferences(
1638 out,
1639 "_hidl_reply",
1640 true /* parcelObjIsPointer */,
1641 elidedReturn,
1642 false /* reader */,
1643 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001644 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001645
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001646 status_t status = generateCppInstrumentationCall(
1647 out,
1648 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001649 method);
1650 if (status != OK) {
1651 return status;
1652 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001653
Iliyan Malchev549e2592016-08-10 08:59:12 -07001654 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001655 } else {
1656 if (returnsValue) {
1657 out << "bool _hidl_callbackCalled = false;\n\n";
1658 }
Andreas Huber881227d2016-08-02 14:20:21 -07001659
Yifan Hongcd2ae452017-01-31 14:33:40 -08001660 out << callee << "->" << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001661
Yifan Hong7d234ea2017-03-30 15:40:22 -07001662 out.join(method->args().begin(), method->args().end(), ", ", [&] (const auto &arg) {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001663 if (arg->type().resultNeedsDeref()) {
1664 out << "*";
1665 }
1666
1667 out << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -07001668 });
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001669
1670 if (returnsValue) {
Yifan Hong7d234ea2017-03-30 15:40:22 -07001671 if (!method->args().empty()) {
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001672 out << ", ";
1673 }
1674
1675 out << "[&](";
1676
Yifan Hong7d234ea2017-03-30 15:40:22 -07001677 out.join(method->results().begin(), method->results().end(), ", ", [&](const auto &arg) {
Yifan Honga47eef32016-12-12 10:38:54 -08001678 out << "const auto &_hidl_out_" << arg->name();
Yifan Hong7d234ea2017-03-30 15:40:22 -07001679 });
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001680
1681 out << ") {\n";
1682 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001683 out << "if (_hidl_callbackCalled) {\n";
1684 out.indent();
1685 out << "LOG_ALWAYS_FATAL(\""
1686 << method->name()
1687 << ": _hidl_cb called a second time, but must be called once.\");\n";
1688 out.unindent();
1689 out << "}\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001690 out << "_hidl_callbackCalled = true;\n\n";
1691
Yifan Hong859e53f2016-11-14 19:08:24 -08001692 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1693 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001694
Yifan Hongbf459bc2016-08-23 16:50:37 -07001695 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001696 for (const auto &arg : method->results()) {
1697 emitCppReaderWriter(
1698 out,
1699 "_hidl_reply",
1700 true /* parcelObjIsPointer */,
1701 arg,
1702 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001703 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001704 true /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001705 }
1706
Yifan Hongbf459bc2016-08-23 16:50:37 -07001707 // Second DFS: resolve references
1708 for (const auto &arg : method->results()) {
1709 emitCppResolveReferences(
1710 out,
1711 "_hidl_reply",
1712 true /* parcelObjIsPointer */,
1713 arg,
1714 false /* reader */,
1715 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001716 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001717 }
1718
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001719 status_t status = generateCppInstrumentationCall(
1720 out,
1721 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001722 method);
1723 if (status != OK) {
1724 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001725 }
1726
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001727 out << "_hidl_cb(*_hidl_reply);\n";
1728
1729 out.unindent();
Martijn Coenen8e4fc842017-01-09 16:28:59 +01001730 out << "});\n\n";
1731 } else {
1732 out << ");\n\n";
1733 status_t status = generateCppInstrumentationCall(
1734 out,
1735 InstrumentationEvent::SERVER_API_EXIT,
1736 method);
1737 if (status != OK) {
1738 return status;
1739 }
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001740 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001741
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001742 if (returnsValue) {
1743 out << "if (!_hidl_callbackCalled) {\n";
1744 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001745 out << "LOG_ALWAYS_FATAL(\""
1746 << method->name()
1747 << ": _hidl_cb not called, but must be called once.\");\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001748 out.unindent();
1749 out << "}\n\n";
Steven Moreland05cd4232016-11-21 16:01:12 -08001750 } else {
1751 out << "::android::hardware::writeToParcel("
1752 << "::android::hardware::Status::ok(), "
1753 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001754 }
Andreas Huber881227d2016-08-02 14:20:21 -07001755 }
1756
1757 out << "break;\n";
1758
1759 return OK;
1760}
1761
Steven Moreland69e7c702016-09-09 11:16:32 -07001762status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1763 std::string ifaceName;
1764 if (!AST::isInterface(&ifaceName)) {
1765 // types.hal does not get a stub header.
1766 return OK;
1767 }
1768
1769 const Interface *iface = mRootScope->getInterface();
1770
Yifan Hongeefe4f22017-01-04 15:32:42 -08001771 const std::string klassName = iface->getPassthroughName();
Steven Moreland69e7c702016-09-09 11:16:32 -07001772
1773 bool supportOneway = iface->hasOnewayMethods();
1774
1775 std::string path = outputPath;
1776 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1777 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1778 path.append(klassName);
1779 path.append(".h");
1780
1781 CHECK(Coordinator::MakeParentHierarchy(path));
1782 FILE *file = fopen(path.c_str(), "w");
1783
1784 if (file == NULL) {
1785 return -errno;
1786 }
1787
1788 Formatter out(file);
1789
1790 const std::string guard = makeHeaderGuard(klassName);
1791
1792 out << "#ifndef " << guard << "\n";
1793 out << "#define " << guard << "\n\n";
1794
1795 std::vector<std::string> packageComponents;
1796 getPackageAndVersionComponents(
1797 &packageComponents, false /* cpp_compatible */);
1798
Yifan Hongb0949432016-12-15 15:32:24 -08001799 out << "#include <cutils/trace.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001800 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001801
1802 generateCppPackageInclude(out, mPackage, ifaceName);
1803 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001804
Yifan Hong7a118f52016-12-07 11:21:15 -08001805 out << "#include <hidl/HidlPassthroughSupport.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001806 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001807 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001808 }
1809
1810 enterLeaveNamespace(out, true /* enter */);
1811 out << "\n";
1812
1813 out << "struct "
1814 << klassName
1815 << " : " << ifaceName
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +00001816 << ", ::android::hardware::details::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001817
1818 out.indent();
1819 out << "explicit "
1820 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001821 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001822 << ifaceName
1823 << "> impl);\n";
1824
Yifan Hong068c5522016-10-31 14:07:25 -07001825 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1826 return generatePassthroughMethod(out, method);
1827 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001828
1829 if (err != OK) {
1830 return err;
1831 }
1832
1833 out.unindent();
1834 out << "private:\n";
1835 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001836 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001837
1838 if (supportOneway) {
Yifan Hongef91d362017-03-20 17:18:13 -07001839 out << "::android::hardware::details::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001840
1841 out << "\n";
1842
1843 out << "::android::hardware::Return<void> addOnewayTask("
1844 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001845 }
1846
1847 out.unindent();
1848
1849 out << "};\n\n";
1850
1851 enterLeaveNamespace(out, false /* enter */);
1852
1853 out << "\n#endif // " << guard << "\n";
1854
1855 return OK;
1856}
1857
Yifan Hongfe95aa22016-10-19 17:26:45 -07001858status_t AST::generateInterfaceSource(Formatter &out) const {
1859 const Interface *iface = mRootScope->getInterface();
1860
Yifan Hong2d7126b2016-10-20 15:12:57 -07001861 // generate castFrom functions
Yifan Hong3d746092016-12-07 14:26:33 -08001862 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001863
Steven Morelandd4b068a2017-03-20 06:30:51 -07001864 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1865 bool reserved = method->isHidlReserved();
1866
1867 if (!reserved) {
1868 out << "// no default implementation for: ";
1869 }
1870 method->generateCppSignature(out, iface->localName());
1871 if (reserved) {
1872 out.block([&]() {
Steven Moreland937408a2017-03-20 09:54:18 -07001873 method->cppImpl(IMPL_INTERFACE, out);
Steven Morelandd4b068a2017-03-20 06:30:51 -07001874 }).endl();
1875 }
1876
1877 out << "\n";
1878
1879 return OK;
1880 });
1881 if (err != OK) {
1882 return err;
1883 }
1884
Yifan Hong3d746092016-12-07 14:26:33 -08001885 for (const Interface *superType : iface->typeChain()) {
1886 out << "// static \n"
1887 << childTypeResult
Yifan Hongeefe4f22017-01-04 15:32:42 -08001888 << " "
1889 << iface->localName()
Yifan Hong3d746092016-12-07 14:26:33 -08001890 << "::castFrom("
1891 << superType->getCppArgumentType()
1892 << " parent) {\n";
1893 out.indent();
1894 if (iface == superType) {
1895 out << "return parent;\n";
1896 } else {
Yifan Hong33e78012017-03-13 17:46:33 -07001897 out << "return ::android::hardware::details::castInterface<";
Yifan Hongeefe4f22017-01-04 15:32:42 -08001898 out << iface->localName() << ", "
Yifan Hongfe95aa22016-10-19 17:26:45 -07001899 << superType->fqName().cppName() << ", "
Yifan Hongeefe4f22017-01-04 15:32:42 -08001900 << iface->getProxyName() << ", "
Yifan Hong51a65092017-01-04 15:41:44 -08001901 << superType->getProxyFqName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001902 << ">(\n";
1903 out.indent();
1904 out.indent();
1905 out << "parent, \""
1906 << iface->fqName().string()
1907 << "\");\n";
1908 out.unindent();
1909 out.unindent();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001910 }
Yifan Hong3d746092016-12-07 14:26:33 -08001911 out.unindent();
1912 out << "}\n\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001913 }
1914
1915 return OK;
1916}
1917
Steven Moreland69e7c702016-09-09 11:16:32 -07001918status_t AST::generatePassthroughSource(Formatter &out) const {
1919 const Interface *iface = mRootScope->getInterface();
1920
Yifan Hongeefe4f22017-01-04 15:32:42 -08001921 const std::string klassName = iface->getPassthroughName();
Steven Moreland69e7c702016-09-09 11:16:32 -07001922
1923 out << klassName
1924 << "::"
1925 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001926 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001927 << iface->fullName()
Zhuoyao Zhang7d3ac802017-02-15 21:05:49 +00001928 << "> impl) : ::android::hardware::details::HidlInstrumentor(\""
Zhuoyao Zhangd10feea2017-01-23 17:29:58 -08001929 << mPackage.string()
1930 << "\", \""
1931 << iface->localName()
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001932 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001933 if (iface->hasOnewayMethods()) {
1934 out << "\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001935 out.indent([&] {
Yifan Hongf01dad42017-03-20 19:03:11 -07001936 out << "mOnewayQueue.start(3000 /* similar limit to binderized */);\n";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001937 });
1938 }
1939 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001940
1941 if (iface->hasOnewayMethods()) {
1942 out << "::android::hardware::Return<void> "
1943 << klassName
1944 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1945 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001946 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001947 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001948 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1949 out.indent();
1950 out.indent();
1951 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1952 out.unindent();
1953 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001954 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001955 out << "}\n";
1956
Steven Morelandd366c262016-10-11 15:29:10 -07001957 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001958
1959 out.unindent();
1960 out << "}\n\n";
1961
1962
1963 }
1964
1965 return OK;
1966}
1967
Martijn Coenen7b295242016-11-04 16:52:56 +01001968status_t AST::generateCppAtraceCall(Formatter &out,
1969 InstrumentationEvent event,
1970 const Method *method) const {
1971 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -08001972 std::string baseString = "HIDL::" + iface->localName() + "::" + method->name();
Martijn Coenen7b295242016-11-04 16:52:56 +01001973 switch (event) {
1974 case SERVER_API_ENTRY:
1975 {
1976 out << "atrace_begin(ATRACE_TAG_HAL, \""
1977 << baseString + "::server\");\n";
1978 break;
1979 }
1980 case CLIENT_API_ENTRY:
1981 {
1982 out << "atrace_begin(ATRACE_TAG_HAL, \""
1983 << baseString + "::client\");\n";
1984 break;
1985 }
1986 case PASSTHROUGH_ENTRY:
1987 {
1988 out << "atrace_begin(ATRACE_TAG_HAL, \""
1989 << baseString + "::passthrough\");\n";
1990 break;
1991 }
1992 case SERVER_API_EXIT:
1993 case CLIENT_API_EXIT:
1994 case PASSTHROUGH_EXIT:
1995 {
1996 out << "atrace_end(ATRACE_TAG_HAL);\n";
1997 break;
1998 }
1999 default:
2000 {
2001 LOG(ERROR) << "Unsupported instrumentation event: " << event;
2002 return UNKNOWN_ERROR;
2003 }
2004 }
2005
2006 return OK;
2007}
2008
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002009status_t AST::generateCppInstrumentationCall(
2010 Formatter &out,
2011 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07002012 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01002013 status_t err = generateCppAtraceCall(out, event, method);
2014 if (err != OK) {
2015 return err;
2016 }
2017
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002018 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
2019 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002020 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002021 std::string event_str = "";
2022 switch (event) {
2023 case SERVER_API_ENTRY:
2024 {
2025 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
2026 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002027 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002028 << (arg->type().resultNeedsDeref() ? "" : "&")
2029 << arg->name()
2030 << ");\n";
2031 }
2032 break;
2033 }
2034 case SERVER_API_EXIT:
2035 {
2036 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07002037 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08002038 out << "_hidl_args.push_back((void *)&_hidl_out_"
Steven Moreland031ccf12016-10-31 15:54:38 -07002039 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002040 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002041 }
2042 break;
2043 }
2044 case CLIENT_API_ENTRY:
2045 {
2046 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
2047 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002048 out << "_hidl_args.push_back((void *)&"
2049 << arg->name()
2050 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002051 }
2052 break;
2053 }
2054 case CLIENT_API_EXIT:
2055 {
2056 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
2057 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002058 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002059 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002060 << "_hidl_out_"
2061 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002062 << ");\n";
2063 }
2064 break;
2065 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07002066 case PASSTHROUGH_ENTRY:
2067 {
2068 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
2069 for (const auto &arg : method->args()) {
2070 out << "_hidl_args.push_back((void *)&"
2071 << arg->name()
2072 << ");\n";
2073 }
2074 break;
2075 }
2076 case PASSTHROUGH_EXIT:
2077 {
2078 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08002079 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08002080 out << "_hidl_args.push_back((void *)&_hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08002081 << arg->name()
2082 << ");\n";
2083 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07002084 break;
2085 }
Steven Moreland031ccf12016-10-31 15:54:38 -07002086 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002087 {
Steven Moreland031ccf12016-10-31 15:54:38 -07002088 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002089 return UNKNOWN_ERROR;
2090 }
2091 }
2092
Steven Moreland031ccf12016-10-31 15:54:38 -07002093 const Interface *iface = mRootScope->getInterface();
2094
Steven Moreland1ab31442016-11-03 18:37:51 -07002095 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002096 out.indent();
2097 out << "callback("
2098 << event_str
2099 << ", \""
2100 << mPackage.package()
2101 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07002102 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002103 << "\", \""
2104 << iface->localName()
2105 << "\", \""
2106 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002107 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002108 out.unindent();
2109 out << "}\n";
2110 out.unindent();
2111 out << "}\n\n";
2112
2113 return OK;
2114}
2115
Andreas Huber881227d2016-08-02 14:20:21 -07002116} // namespace android