blob: b96a9a0dd3c9254d58a1ffa4acc82d30d56568fd [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
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800128static void declareServiceManagerInteractions(Formatter &out, const std::string &baseName) {
129 out << "static ::android::sp<I" << baseName << "> getService("
130 << "const std::string &serviceName, bool getStub=false);\n";
131 out << "::android::status_t registerAsService(const std::string &serviceName);\n";
132 out << "static bool registerForNotifications(\n";
133 out.indent(2, [&] {
134 out << "const std::string &serviceName,\n"
135 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
136 << "&notification);\n";
137 });
138
139}
140
141static void implementServiceManagerInteractions(Formatter &out,
142 const std::string &baseName, const std::string &package) {
143
144 out << "// static\n"
145 << "::android::sp<I" << baseName << "> I" << baseName << "::getService("
146 << "const std::string &serviceName, bool getStub) ";
147 out.block([&] {
148 out << "::android::sp<I" << baseName << "> iface;\n"
149 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
150 out.indent(2, [&] {
151 out << "= ::android::hardware::defaultServiceManager();\n";
152 });
153 out.sIf("sm != nullptr && !getStub", [&] {
154 out << "::android::sp<::android::hidl::base::V1_0::IBase> base;\n"
155 << "::android::hardware::Return<void> ret =\n";
156 out.indent(2, [&] {
157 out << "sm->get(\"" << package << "::I" << baseName << "\", serviceName.c_str(),\n";
158 out.indent(2, [&] {
159 out << "[&base](::android::sp<::android::hidl::base::V1_0::IBase> found) ";
160 out.block([&] {
161 out << "base = found;\n";
162 });
163 out << ");\n";
164 });
165 });
166 out.sIf("ret.getStatus().isOk()", [&] {
167 out << "iface = I" << baseName << "::castFrom(base);\n";
168 out.sIf("iface != nullptr", [&] {
169 out << "return iface;\n";
170 }).endl();
171 }).endl();
172 }).endl();
173 out << "const int dlMode = RTLD_LAZY;\n";
174 out << "void *handle = nullptr;\n";
175 for (const auto &path : std::vector<std::string>({
176 "HAL_LIBRARY_PATH_ODM", "HAL_LIBRARY_PATH_VENDOR", "HAL_LIBRARY_PATH_SYSTEM"
177 })) {
178 out.sIf("handle == nullptr", [&] {
179 out << "handle = dlopen("
180 << path << " \"" << package << "-impl.so\", dlMode);\n";
181 }).endl();
182 }
183 out.sIf("handle == nullptr", [&] {
184 out << "return iface;\n";
185 }).endl();
186 out << "I" << baseName << "* (*generator)(const char* name);\n"
187 << "*(void **)(&generator) = dlsym(handle, \"HIDL_FETCH_I" << baseName << "\");\n";
188 out.sIf("generator", [&] {
189 out << "iface = (*generator)(serviceName.c_str());\n";
190 out.sIf("iface != nullptr", [&] {
191 out << "iface = new Bs" << baseName << "(iface);\n";
192 }).endl();
193 }).endl();
194 out << "return iface;\n";
195 }).endl().endl();
196
197 out << "::android::status_t I" << baseName << "::registerAsService("
198 << "const std::string &serviceName) ";
199 out.block([&] {
200 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
201 out.indent(2, [&] {
202 out << "= ::android::hardware::defaultServiceManager();\n";
203 });
204 out.sIf("sm == nullptr", [&] {
205 out << "return ::android::INVALID_OPERATION;\n";
206 }).endl();
207 out << "bool success = false;\n"
208 << "::android::hardware::Return<void> ret =\n";
209 out.indent(2, [&] {
210 out << "this->interfaceChain("
211 << "[&success, &sm, &serviceName, this](const auto &chain) ";
212 out.block([&] {
213 out << "::android::hardware::Return<bool> addRet = "
214 << "sm->add(chain, serviceName.c_str(), this);\n";
215 out << "success = addRet.isOk() && addRet;\n";
216 });
217 out << ");\n";
218 out << "success = success && ret.getStatus().isOk();\n";
219 });
220 out << "return success ? ::android::OK : ::android::UNKNOWN_ERROR;\n";
221 }).endl().endl();
222
223 out << "bool I" << baseName << "::registerForNotifications(\n";
224 out.indent(2, [&] {
225 out << "const std::string &serviceName,\n"
226 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
227 << "&notification) ";
228 });
229 out.block([&] {
230 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
231 out.indent(2, [&] {
232 out << "= ::android::hardware::defaultServiceManager();\n";
233 });
234 out.sIf("sm == nullptr", [&] {
235 out << "return false;\n";
236 }).endl();
237 out << "::android::hardware::Return<bool> success =\n";
238 out.indent(2, [&] {
239 out << "sm->registerForNotifications(\"" << package << "::I" << baseName << "\",\n";
240 out.indent(2, [&] {
241 out << "serviceName, notification);\n";
242 });
243 });
244 out << "return success.isOk() && success;\n";
245 }).endl().endl();
246}
247
Andreas Huberb82318c2016-08-02 14:45:54 -0700248status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700249
Andreas Huberb82318c2016-08-02 14:45:54 -0700250 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700251 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700252 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700253
254 std::string ifaceName;
255 bool isInterface = true;
256 if (!AST::isInterface(&ifaceName)) {
257 ifaceName = "types";
258 isInterface = false;
259 }
260 path.append(ifaceName);
261 path.append(".h");
262
Andreas Huberd2943e12016-08-05 11:59:31 -0700263 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700264 FILE *file = fopen(path.c_str(), "w");
265
266 if (file == NULL) {
267 return -errno;
268 }
269
270 Formatter out(file);
271
272 const std::string guard = makeHeaderGuard(ifaceName);
273
274 out << "#ifndef " << guard << "\n";
275 out << "#define " << guard << "\n\n";
276
Andreas Huber737080b2016-08-02 15:38:04 -0700277 for (const auto &item : mImportedNames) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700278 generateCppPackageInclude(out, item, item.name());
Andreas Huber737080b2016-08-02 15:38:04 -0700279 }
280
281 if (!mImportedNames.empty()) {
282 out << "\n";
283 }
284
Steven Moreland0693f312016-11-09 15:06:14 -0800285 if (isInterface) {
Yifan Hongc8934042016-11-17 17:10:52 -0800286 if (isIBase()) {
287 out << "// skipped #include IServiceNotification.h\n\n";
288 } else {
289 out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
290 }
Steven Moreland0693f312016-11-09 15:06:14 -0800291 }
292
Yifan Hongc8934042016-11-17 17:10:52 -0800293 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700294 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700295
296 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200297 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700298 }
299
Martijn Coenenaf712c02016-11-16 15:26:27 +0100300 out << "#include <utils/NativeHandle.h>\n";
301 out << "#include <utils/misc.h>\n\n"; /* for report_sysprop_change() */
Andreas Huber881227d2016-08-02 14:20:21 -0700302
303 enterLeaveNamespace(out, true /* enter */);
304 out << "\n";
305
306 if (isInterface) {
307 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700308 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700309
310 const Interface *iface = mRootScope->getInterface();
311 const Interface *superType = iface->superType();
312
Steven Moreland40786312016-08-16 10:29:40 -0700313 if (superType == NULL) {
Yifan Hongc8934042016-11-17 17:10:52 -0800314 out << " : virtual public ::android::RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700315 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000316 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700317 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700318 }
319
320 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700321
322 out.indent();
323
Andreas Huber881227d2016-08-02 14:20:21 -0700324 }
325
326 status_t err = emitTypeDeclarations(out);
327
328 if (err != OK) {
329 return err;
330 }
331
332 if (isInterface) {
333 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700334 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700335 const std::string baseName = iface->getBaseName();
Steven Moreland19d5c172016-10-20 19:20:25 -0700336 out << "constexpr static ::android::hardware::hidl_version version = {"
Martijn Coenena21f1492016-09-08 15:55:14 +0200337 << mPackage.getPackageMajorVersion() << ","
338 << mPackage.getPackageMinorVersion() << "};\n";
Steven Moreland19d5c172016-10-20 19:20:25 -0700339 out << "virtual const ::android::hardware::hidl_version&"
340 << "getInterfaceVersion() const {\n";
Martijn Coenena21f1492016-09-08 15:55:14 +0200341 out.indent();
342 out << "return version;\n";
343 out.unindent();
344 out << "}\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800345 out << "virtual bool isRemote() const ";
346 if (!isIBase()) {
347 out << "override ";
348 }
349 out << "{ return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800350
Andreas Huber881227d2016-08-02 14:20:21 -0700351 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700352 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700353
Andreas Huber881227d2016-08-02 14:20:21 -0700354 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800355 const TypedVar *elidedReturn = method->canElideCallback();
356
357 if (elidedReturn == nullptr && returnsValue) {
358 out << "using "
359 << method->name()
360 << "_cb = std::function<void("
361 << Method::GetArgSignature(method->results(),
362 true /* specify namespaces */)
363 << ")>;\n";
364 }
Andreas Huber881227d2016-08-02 14:20:21 -0700365
Andreas Huber3599d922016-08-09 10:42:57 -0700366 method->dumpAnnotations(out);
367
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700368 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700369 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700370 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700371 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700372 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700373 }
374
375 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700376 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700377 << Method::GetArgSignature(method->args(),
378 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700379
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700380 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700381 if (!method->args().empty()) {
382 out << ", ";
383 }
384
Steven Moreland67f67b42016-09-29 08:59:02 -0700385 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700386 }
387
Yifan Hong10fe0b52016-10-19 14:20:17 -0700388 out << ")";
389 if (method->isHidlReserved()) {
Yifan Hongc8934042016-11-17 17:10:52 -0800390 if (!isIBase()) {
391 out << " override";
392 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700393 out << " {\n";
394 out.indent();
395 method->cppImpl(out);
396 out.unindent();
397 out << "\n}\n";
398 } else {
399 out << " = 0;\n";
400 }
Andreas Huber881227d2016-08-02 14:20:21 -0700401 }
Steven Moreland40786312016-08-16 10:29:40 -0700402
Yifan Hong3d746092016-12-07 14:26:33 -0800403 out << "// cast static functions\n";
404 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700405
Yifan Hong3d746092016-12-07 14:26:33 -0800406 for (const Interface *superType : iface->typeChain()) {
407 out << "static "
408 << childTypeResult
409 << " castFrom("
410 << superType->getCppArgumentType()
411 << " parent"
412 << ");\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -0700413 }
414
Steven Morelandd39133b2016-11-11 12:30:08 -0800415 out << "\nstatic const char* descriptor;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700416
Yifan Hongc8934042016-11-17 17:10:52 -0800417 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800418 out << "// skipped getService, registerAsService, registerForNotifications\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800419 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800420 declareServiceManagerInteractions(out, baseName);
Yifan Hongc8934042016-11-17 17:10:52 -0800421 }
Yifan Hong158655a2016-11-08 12:34:07 -0800422
423 out << "private: static int hidlStaticBlock;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700424 }
425
426 if (isInterface) {
427 out.unindent();
428
Andreas Hubere3f769a2016-10-10 10:54:44 -0700429 out << "};\n\n";
430 }
431
432 err = mRootScope->emitGlobalTypeDeclarations(out);
433
434 if (err != OK) {
435 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700436 }
437
438 out << "\n";
439 enterLeaveNamespace(out, false /* enter */);
440
441 out << "\n#endif // " << guard << "\n";
442
443 return OK;
444}
445
Steven Moreland40786312016-08-16 10:29:40 -0700446status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
447 std::string ifaceName;
Yifan Hong244e82d2016-11-11 11:13:57 -0800448 bool isInterface = AST::isInterface(&ifaceName);
449 const Interface *iface = nullptr;
450 std::string baseName{};
451 std::string klassName{};
452
453 if(isInterface) {
454 iface = mRootScope->getInterface();
455 baseName = iface->getBaseName();
456 klassName = "IHw" + baseName;
457 } else {
458 klassName = "hwtypes";
Steven Moreland40786312016-08-16 10:29:40 -0700459 }
460
Steven Moreland40786312016-08-16 10:29:40 -0700461 std::string path = outputPath;
462 path.append(mCoordinator->convertPackageRootToPath(mPackage));
463 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
464 path.append(klassName + ".h");
465
Yifan Hong244e82d2016-11-11 11:13:57 -0800466 FILE *file = fopen(path.c_str(), "w");
Steven Moreland40786312016-08-16 10:29:40 -0700467
468 if (file == NULL) {
469 return -errno;
470 }
471
472 Formatter out(file);
473
474 const std::string guard = makeHeaderGuard(klassName);
475
476 out << "#ifndef " << guard << "\n";
477 out << "#define " << guard << "\n\n";
478
Yifan Hong244e82d2016-11-11 11:13:57 -0800479 if (isInterface) {
480 generateCppPackageInclude(out, mPackage, ifaceName);
481 } else {
482 generateCppPackageInclude(out, mPackage, "types");
483 }
Steven Moreland40786312016-08-16 10:29:40 -0700484
Steven Morelandee88eed2016-10-31 17:49:00 -0700485 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700486
487 for (const auto &item : mImportedNames) {
488 if (item.name() == "types") {
Yifan Hong244e82d2016-11-11 11:13:57 -0800489 generateCppPackageInclude(out, item, "hwtypes");
490 } else {
491 generateCppPackageInclude(out, item, "Bn" + item.getInterfaceBaseName());
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100492 generateCppPackageInclude(out, item, "Bp" + item.getInterfaceBaseName());
Steven Moreland40786312016-08-16 10:29:40 -0700493 }
Steven Moreland40786312016-08-16 10:29:40 -0700494 }
495
496 out << "\n";
497
Martijn Coenen93915102016-09-01 01:35:52 +0200498 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700499 out << "#include <hwbinder/IBinder.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100500 out << "#include <hwbinder/Parcel.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700501
502 out << "\n";
503
504 enterLeaveNamespace(out, true /* enter */);
Steven Moreland40786312016-08-16 10:29:40 -0700505
Yifan Hong244e82d2016-11-11 11:13:57 -0800506 status_t err = mRootScope->emitGlobalHwDeclarations(out);
507 if (err != OK) {
508 return err;
509 }
Steven Moreland40786312016-08-16 10:29:40 -0700510
511 enterLeaveNamespace(out, false /* enter */);
512
513 out << "\n#endif // " << guard << "\n";
514
515 return OK;
516}
517
Andreas Huber881227d2016-08-02 14:20:21 -0700518status_t AST::emitTypeDeclarations(Formatter &out) const {
519 return mRootScope->emitTypeDeclarations(out);
520}
521
Yifan Hong7a118f52016-12-07 11:21:15 -0800522static void wrapPassthroughArg(Formatter &out,
523 const TypedVar *arg, bool addPrefixToName,
524 std::function<void(void)> handleError) {
525 if (!arg->type().isInterface()) {
526 return;
527 }
528 std::string name = (addPrefixToName ? "_hidl_out_" : "") + arg->name();
529 std::string wrappedName = (addPrefixToName ? "_hidl_out_wrapped_" : "_hidl_wrapped_")
530 + arg->name();
531 const Interface &iface = static_cast<const Interface &>(arg->type());
532 out << iface.getCppStackType() << " " << wrappedName << ";\n";
533 // TODO(elsk): b/33754152 Should not wrap this if object is Bs*
534 out.sIf(name + " != nullptr && !" + name + "->isRemote()", [&] {
535 out << wrappedName
536 << " = "
537 << iface.fqName().cppName()
538 << "::castFrom(::android::hardware::wrapPassthrough("
539 << name << "));\n";
540 out.sIf(wrappedName + " == nullptr", [&] {
541 // Fatal error. Happens when the BsFoo class is not found in the binary
542 // or any dynamic libraries.
543 handleError();
544 }).endl();
545 }).sElse([&] {
546 out << wrappedName << " = " << name << ";\n";
547 }).endl().endl();
548}
549
Steven Moreland69e7c702016-09-09 11:16:32 -0700550status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700551 const Method *method) const {
552 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700553
554 out << " {\n";
555 out.indent();
556
557 const bool returnsValue = !method->results().empty();
558 const TypedVar *elidedReturn = method->canElideCallback();
559
Steven Moreland67f67b42016-09-29 08:59:02 -0700560 if (returnsValue && elidedReturn == nullptr) {
561 generateCheckNonNull(out, "_hidl_cb");
562 }
563
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700564 generateCppInstrumentationCall(
565 out,
566 InstrumentationEvent::PASSTHROUGH_ENTRY,
567 method);
568
Yifan Hong7a118f52016-12-07 11:21:15 -0800569
570 for (const auto &arg : method->args()) {
571 wrapPassthroughArg(out, arg, false /* addPrefixToName */, [&] {
572 out << "return ::android::hardware::Status::fromExceptionCode(\n";
573 out.indent(2, [&] {
574 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
575 << "::android::String8(\"Cannot wrap passthrough interface.\"));\n";
576 });
577 });
578 }
579
580 out << "auto _hidl_error = ::android::hardware::Void();\n";
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700581 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700582
583 if (method->isOneway()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800584 out << "addOnewayTask([this, &_hidl_error";
Steven Moreland69e7c702016-09-09 11:16:32 -0700585 for (const auto &arg : method->args()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800586 out << ", "
587 << (arg->type().isInterface() ? "_hidl_wrapped_" : "")
588 << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700589 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700590 out << "] {\n";
591 out.indent();
592 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700593 }
594
595 out << "mImpl->"
596 << method->name()
597 << "(";
598
599 bool first = true;
600 for (const auto &arg : method->args()) {
601 if (!first) {
602 out << ", ";
603 }
604 first = false;
Yifan Hong7a118f52016-12-07 11:21:15 -0800605 out << (arg->type().isInterface() ? "_hidl_wrapped_" : "") << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700606 }
607 if (returnsValue && elidedReturn == nullptr) {
608 if (!method->args().empty()) {
609 out << ", ";
610 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800611 out << "[&](";
612 first = true;
613 for (const auto &arg : method->results()) {
614 if (!first) {
615 out << ", ";
616 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700617
Yifan Hong7a118f52016-12-07 11:21:15 -0800618 out << "const auto &_hidl_out_"
619 << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800620
621 first = false;
622 }
623
624 out << ") {\n";
625 out.indent();
626 status_t status = generateCppInstrumentationCall(
627 out,
628 InstrumentationEvent::PASSTHROUGH_EXIT,
629 method);
630 if (status != OK) {
631 return status;
632 }
633
Yifan Hong7a118f52016-12-07 11:21:15 -0800634 for (const auto &arg : method->results()) {
635 wrapPassthroughArg(out, arg, true /* addPrefixToName */, [&] {
636 out << "_hidl_error = ::android::hardware::Status::fromExceptionCode(\n";
637 out.indent(2, [&] {
638 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
639 << "::android::String8(\"Cannot wrap passthrough interface.\"));\n";
640 });
641 out << "return;\n";
642 });
643 }
644
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800645 out << "_hidl_cb(";
646 first = true;
647 for (const auto &arg : method->results()) {
648 if (!first) {
649 out << ", ";
650 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800651 first = false;
Yifan Hong7a118f52016-12-07 11:21:15 -0800652 out << (arg->type().isInterface() ? "_hidl_out_wrapped_" : "_hidl_out_")
653 << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800654 }
655 out << ");\n";
656 out.unindent();
657 out << "});\n\n";
658 } else {
659 out << ");\n\n";
660 if (elidedReturn != nullptr) {
661 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -0800662 << " _hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800663 << elidedReturn->name()
Steven Moreland2ae5bca2016-12-01 05:56:49 +0000664 << " = _hidl_return;\n";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800665 }
666 status_t status = generateCppInstrumentationCall(
667 out,
668 InstrumentationEvent::PASSTHROUGH_EXIT,
669 method);
670 if (status != OK) {
671 return status;
672 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700673 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700674
675 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700676 out.unindent();
677 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700678 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700679
680 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700681
682 out.unindent();
683 out << "}\n";
684
685 return OK;
686}
687
Yifan Hong068c5522016-10-31 14:07:25 -0700688status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700689
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700690 const Interface *iface = mRootScope->getInterface();
691
Yifan Hong10fe0b52016-10-19 14:20:17 -0700692 const Interface *prevIterface = nullptr;
693 for (const auto &tuple : iface->allMethodsFromRoot()) {
694 const Method *method = tuple.method();
695 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700696
Yifan Hong10fe0b52016-10-19 14:20:17 -0700697 if(prevIterface != superInterface) {
698 if (prevIterface != nullptr) {
699 out << "\n";
700 }
701 out << "// Methods from "
702 << superInterface->fullName()
703 << " follow.\n";
704 prevIterface = superInterface;
705 }
Yifan Hong068c5522016-10-31 14:07:25 -0700706 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700707
Yifan Hong10fe0b52016-10-19 14:20:17 -0700708 if (err != OK) {
709 return err;
710 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700711 }
712
Yifan Hong10fe0b52016-10-19 14:20:17 -0700713 out << "\n";
714
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700715 return OK;
716}
717
Andreas Huberb82318c2016-08-02 14:45:54 -0700718status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700719 std::string ifaceName;
720 if (!AST::isInterface(&ifaceName)) {
721 // types.hal does not get a stub header.
722 return OK;
723 }
724
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700725 const Interface *iface = mRootScope->getInterface();
726 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700727 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700728
Andreas Huberb82318c2016-08-02 14:45:54 -0700729 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700730 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700731 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700732 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700733 path.append(".h");
734
Andreas Huberd2943e12016-08-05 11:59:31 -0700735 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700736 FILE *file = fopen(path.c_str(), "w");
737
738 if (file == NULL) {
739 return -errno;
740 }
741
742 Formatter out(file);
743
Steven Moreland40786312016-08-16 10:29:40 -0700744 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700745
746 out << "#ifndef " << guard << "\n";
747 out << "#define " << guard << "\n\n";
748
Steven Morelandee88eed2016-10-31 17:49:00 -0700749 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
750 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700751
752 enterLeaveNamespace(out, true /* enter */);
753 out << "\n";
754
755 out << "struct "
756 << "Bn"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100757 << baseName;
758 if (iface->isIBase()) {
759 out << " : public ::android::hardware::BBinder";
760 out << ", public ::android::hardware::HidlInstrumentor {\n";
761 } else {
762 out << " : public ::android::hidl::base::V1_0::BnBase {\n";
763 }
Andreas Huber881227d2016-08-02 14:20:21 -0700764
765 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700766 out << "explicit Bn"
767 << baseName
768 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100769 << "\n";
770 out << "explicit Bn"
771 << baseName
772 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl,"
773 << " const std::string& prefix);"
Steven Moreland40786312016-08-16 10:29:40 -0700774 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700775 out << "::android::status_t onTransact(\n";
776 out.indent();
777 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700778 out << "uint32_t _hidl_code,\n";
779 out << "const ::android::hardware::Parcel &_hidl_data,\n";
780 out << "::android::hardware::Parcel *_hidl_reply,\n";
781 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700782 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700783 out.unindent();
784 out.unindent();
785
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100786 out << "::android::sp<" << ifaceName << "> getImpl() { return _hidl_mImpl; };\n";
787 out.unindent();
788 out << "private:\n";
789 out.indent();
790 out << "::android::sp<" << ifaceName << "> _hidl_mImpl;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700791 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700792 out << "};\n\n";
793
794 enterLeaveNamespace(out, false /* enter */);
795
796 out << "\n#endif // " << guard << "\n";
797
798 return OK;
799}
800
Andreas Huberb82318c2016-08-02 14:45:54 -0700801status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700802 std::string ifaceName;
803 if (!AST::isInterface(&ifaceName)) {
804 // types.hal does not get a proxy header.
805 return OK;
806 }
807
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700808 const Interface *iface = mRootScope->getInterface();
809 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700810
Andreas Huberb82318c2016-08-02 14:45:54 -0700811 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700812 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700813 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700814 path.append("Bp");
815 path.append(baseName);
816 path.append(".h");
817
Andreas Huberd2943e12016-08-05 11:59:31 -0700818 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700819 FILE *file = fopen(path.c_str(), "w");
820
821 if (file == NULL) {
822 return -errno;
823 }
824
825 Formatter out(file);
826
827 const std::string guard = makeHeaderGuard("Bp" + baseName);
828
829 out << "#ifndef " << guard << "\n";
830 out << "#define " << guard << "\n\n";
831
832 std::vector<std::string> packageComponents;
833 getPackageAndVersionComponents(
834 &packageComponents, false /* cpp_compatible */);
835
Steven Morelandee88eed2016-10-31 17:49:00 -0700836 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
837 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700838
839 enterLeaveNamespace(out, true /* enter */);
840 out << "\n";
841
842 out << "struct "
843 << "Bp"
844 << baseName
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100845 << " : public ::android::hardware::BpInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -0700846 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700847 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700848
849 out.indent();
850
851 out << "explicit Bp"
852 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700853 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700854 << "\n\n";
855
Yifan Hong10fe0b52016-10-19 14:20:17 -0700856 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700857
Yifan Hong068c5522016-10-31 14:07:25 -0700858 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
859 method->generateCppSignature(out);
860 out << " override;\n";
861 return OK;
862 });
Steven Moreland9c387612016-09-07 09:54:26 -0700863
864 if (err != OK) {
865 return err;
866 }
Andreas Huber881227d2016-08-02 14:20:21 -0700867
868 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700869 out << "};\n\n";
870
871 enterLeaveNamespace(out, false /* enter */);
872
873 out << "\n#endif // " << guard << "\n";
874
875 return OK;
876}
877
Andreas Huberb82318c2016-08-02 14:45:54 -0700878status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700879
Andreas Huberb82318c2016-08-02 14:45:54 -0700880 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700881 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700882 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700883
884 std::string ifaceName;
885 std::string baseName;
886
Yifan Hongfe95aa22016-10-19 17:26:45 -0700887 const Interface *iface = nullptr;
888 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700889 if (!AST::isInterface(&ifaceName)) {
890 baseName = "types";
891 isInterface = false;
892 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700893 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700894 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700895 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700896 }
897
898 path.append(baseName);
899
900 if (baseName != "types") {
901 path.append("All");
902 }
903
904 path.append(".cpp");
905
Andreas Huberd2943e12016-08-05 11:59:31 -0700906 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700907 FILE *file = fopen(path.c_str(), "w");
908
909 if (file == NULL) {
910 return -errno;
911 }
912
913 Formatter out(file);
914
Steven Moreland05cd4232016-11-21 16:01:12 -0800915 out << "#include <android/log.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100916 out << "#include <cutils/trace.h>\n";
917 out << "#include <hidl/HidlTransportSupport.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700918 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700919 // This is a no-op for IServiceManager itself.
920 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
921
Steven Morelandee88eed2016-10-31 17:49:00 -0700922 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
923 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
924 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700925
926 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700927 generateCppPackageInclude(out,
928 superType->fqName(),
929 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700930 }
Yifan Hong2cbbdf92016-12-05 15:20:50 -0800931
932 out << "#include <hidl/ServiceManagement.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700933 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700934 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800935 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700936 }
937
938 out << "\n";
939
940 enterLeaveNamespace(out, true /* enter */);
941 out << "\n";
942
943 status_t err = generateTypeSource(out, ifaceName);
944
945 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700946 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700947 out << "constexpr ::android::hardware::hidl_version "
948 << ifaceName
949 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700950
951 // need to be put here, generateStubSource is using this.
Steven Morelandd39133b2016-11-11 12:30:08 -0800952 out << "const char* I"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700953 << iface->getBaseName()
954 << "::descriptor(\""
955 << iface->fqName().string()
956 << "\");\n\n";
957
Yifan Hong158655a2016-11-08 12:34:07 -0800958 out << "int I"
959 << iface->getBaseName()
960 << "::hidlStaticBlock = []() -> int {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800961 out.indent([&] {
Steven Morelandd39133b2016-11-11 12:30:08 -0800962 out << "::android::hardware::gBnConstructorMap[I"
Yifan Hong158655a2016-11-08 12:34:07 -0800963 << iface->getBaseName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800964 << "::descriptor]\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800965 out.indent(2, [&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800966 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800967 out.indent([&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800968 out << "return new Bn"
969 << iface->getBaseName()
970 << "(reinterpret_cast<I"
971 << iface->getBaseName()
972 << " *>(iIntf));\n";
973 });
974 out << "};\n";
975 });
Yifan Hong7a118f52016-12-07 11:21:15 -0800976 out << "::android::hardware::gBsConstructorMap[I"
977 << iface->getBaseName()
978 << "::descriptor]\n";
979 out.indent(2, [&] {
980 out << "= [](void *iIntf) -> ::android::sp<"
981 << gIBaseFqName.cppName()
982 << "> {\n";
983 out.indent([&] {
984 out << "return new Bs"
985 << iface->getBaseName()
986 << "(reinterpret_cast<I"
987 << iface->getBaseName()
988 << " *>(iIntf));\n";
989 });
990 out << "};\n";
991 });
Yifan Hong158655a2016-11-08 12:34:07 -0800992 out << "return 1;\n";
993 });
994 out << "}();\n\n";
995
Yifan Hongfe95aa22016-10-19 17:26:45 -0700996 err = generateInterfaceSource(out);
997 }
998
999 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -07001000 err = generateProxySource(out, baseName);
1001 }
1002
1003 if (err == OK && isInterface) {
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001004 err = generateStubSource(out, iface, baseName);
Andreas Huber881227d2016-08-02 14:20:21 -07001005 }
1006
Steven Moreland40786312016-08-16 10:29:40 -07001007 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -07001008 err = generatePassthroughSource(out);
1009 }
1010
1011 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -07001012 const Interface *iface = mRootScope->getInterface();
1013
Yifan Hongc8934042016-11-17 17:10:52 -08001014 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001015 out << "// skipped getService, registerAsService, registerForNotifications\n";
Yifan Hongc8934042016-11-17 17:10:52 -08001016 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001017 std::string package = iface->fqName().package()
1018 + iface->fqName().atVersion();
1019
1020 implementServiceManagerInteractions(out, baseName, package);
Yifan Hongc8934042016-11-17 17:10:52 -08001021 }
Steven Moreland40786312016-08-16 10:29:40 -07001022 }
1023
Andreas Huber881227d2016-08-02 14:20:21 -07001024 enterLeaveNamespace(out, false /* enter */);
1025
1026 return err;
1027}
1028
Steven Moreland67f67b42016-09-29 08:59:02 -07001029// static
1030void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
Yifan Honga018ed52016-12-13 16:35:08 -08001031 out.sIf(nonNull + " == nullptr", [&] {
1032 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1033 out.indent(2, [&] {
1034 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
1035 });
1036 }).endl().endl();
Steven Moreland67f67b42016-09-29 08:59:02 -07001037}
1038
Andreas Huber881227d2016-08-02 14:20:21 -07001039status_t AST::generateTypeSource(
1040 Formatter &out, const std::string &ifaceName) const {
1041 return mRootScope->emitTypeDefinitions(out, ifaceName);
1042}
1043
Andreas Hubere7ff2282016-08-16 13:50:03 -07001044void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -07001045 Formatter &out,
1046 const std::vector<TypedVar *> &args,
1047 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -07001048 if (args.empty()) {
1049 return;
1050 }
1051
1052 for (const auto &arg : args) {
1053 const Type &type = arg->type();
1054
Yifan Hong3b320f82016-11-01 15:15:54 -07001055 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001056 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -07001057 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001058 << ";\n";
1059 }
1060
1061 out << "\n";
1062}
1063
Andreas Huber881227d2016-08-02 14:20:21 -07001064void AST::emitCppReaderWriter(
1065 Formatter &out,
1066 const std::string &parcelObj,
1067 bool parcelObjIsPointer,
1068 const TypedVar *arg,
1069 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -07001070 Type::ErrorMode mode,
1071 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001072 const Type &type = arg->type();
1073
Andreas Huber881227d2016-08-02 14:20:21 -07001074 type.emitReaderWriter(
1075 out,
Andreas Huber5e44a292016-09-27 14:52:39 -07001076 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -07001077 parcelObj,
1078 parcelObjIsPointer,
1079 isReader,
1080 mode);
1081}
1082
Yifan Hongbf459bc2016-08-23 16:50:37 -07001083void AST::emitCppResolveReferences(
1084 Formatter &out,
1085 const std::string &parcelObj,
1086 bool parcelObjIsPointer,
1087 const TypedVar *arg,
1088 bool isReader,
1089 Type::ErrorMode mode,
1090 bool addPrefixToName) const {
1091 const Type &type = arg->type();
1092 if(type.needsResolveReferences()) {
1093 type.emitResolveReferences(
1094 out,
1095 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
1096 isReader, // nameIsPointer
1097 parcelObj,
1098 parcelObjIsPointer,
1099 isReader,
1100 mode);
1101 }
1102}
1103
Yifan Hong068c5522016-10-31 14:07:25 -07001104status_t AST::generateProxyMethodSource(Formatter &out,
1105 const std::string &klassName,
1106 const Method *method,
1107 const Interface *superInterface) const {
1108
1109 method->generateCppSignature(out,
1110 klassName,
1111 true /* specify namespaces */);
1112
1113 const bool returnsValue = !method->results().empty();
1114 const TypedVar *elidedReturn = method->canElideCallback();
1115
Steven Moreland41c6d2e2016-11-07 12:26:54 -08001116 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001117
1118 out.indent();
1119
1120 if (returnsValue && elidedReturn == nullptr) {
1121 generateCheckNonNull(out, "_hidl_cb");
1122 }
1123
1124 status_t status = generateCppInstrumentationCall(
1125 out,
1126 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -07001127 method);
1128 if (status != OK) {
1129 return status;
1130 }
1131
1132 out << "::android::hardware::Parcel _hidl_data;\n";
1133 out << "::android::hardware::Parcel _hidl_reply;\n";
1134 out << "::android::status_t _hidl_err;\n";
1135 out << "::android::hardware::Status _hidl_status;\n\n";
1136
1137 declareCppReaderLocals(
1138 out, method->results(), true /* forResults */);
1139
1140 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Yifan Hongc8934042016-11-17 17:10:52 -08001141 out << superInterface->fqName().cppNamespace()
1142 << "::I"
1143 << superInterface->getBaseName();
Yifan Hong068c5522016-10-31 14:07:25 -07001144 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001145 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1146
1147 // First DFS: write all buffers and resolve pointers for parent
1148 for (const auto &arg : method->args()) {
1149 emitCppReaderWriter(
1150 out,
1151 "_hidl_data",
1152 false /* parcelObjIsPointer */,
1153 arg,
1154 false /* reader */,
1155 Type::ErrorMode_Goto,
1156 false /* addPrefixToName */);
1157 }
1158
1159 // Second DFS: resolve references.
1160 for (const auto &arg : method->args()) {
1161 emitCppResolveReferences(
1162 out,
1163 "_hidl_data",
1164 false /* parcelObjIsPointer */,
1165 arg,
1166 false /* reader */,
1167 Type::ErrorMode_Goto,
1168 false /* addPrefixToName */);
1169 }
1170
1171 out << "_hidl_err = remote()->transact("
1172 << method->getSerialId()
1173 << " /* "
1174 << method->name()
1175 << " */, _hidl_data, &_hidl_reply";
1176
1177 if (method->isOneway()) {
1178 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1179 }
1180 out << ");\n";
1181
1182 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1183
1184 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001185 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001186 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1187 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1188
1189
1190 // First DFS: write all buffers and resolve pointers for parent
1191 for (const auto &arg : method->results()) {
1192 emitCppReaderWriter(
1193 out,
1194 "_hidl_reply",
1195 false /* parcelObjIsPointer */,
1196 arg,
1197 true /* reader */,
1198 Type::ErrorMode_Goto,
1199 true /* addPrefixToName */);
1200 }
1201
1202 // Second DFS: resolve references.
1203 for (const auto &arg : method->results()) {
1204 emitCppResolveReferences(
1205 out,
1206 "_hidl_reply",
1207 false /* parcelObjIsPointer */,
1208 arg,
1209 true /* reader */,
1210 Type::ErrorMode_Goto,
1211 true /* addPrefixToName */);
1212 }
1213
1214 if (returnsValue && elidedReturn == nullptr) {
1215 out << "_hidl_cb(";
1216
1217 bool first = true;
1218 for (const auto &arg : method->results()) {
1219 if (!first) {
1220 out << ", ";
1221 }
1222
1223 if (arg->type().resultNeedsDeref()) {
1224 out << "*";
1225 }
1226 out << "_hidl_out_" << arg->name();
1227
1228 first = false;
1229 }
1230
1231 out << ");\n\n";
1232 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001233 }
1234 status = generateCppInstrumentationCall(
1235 out,
1236 InstrumentationEvent::CLIENT_API_EXIT,
1237 method);
1238 if (status != OK) {
1239 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001240 }
1241
1242 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001243 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1244 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001245 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001246 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1247 } else {
1248 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1249 out << "return ::android::hardware::Return<void>();\n\n";
1250 }
1251
1252 out.unindent();
1253 out << "_hidl_error:\n";
1254 out.indent();
1255 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1256 out << "return ::android::hardware::Return<";
1257 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001258 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001259 } else {
1260 out << "void";
1261 }
1262 out << ">(_hidl_status);\n";
1263
1264 out.unindent();
1265 out << "}\n\n";
1266 return OK;
1267}
1268
Andreas Huber881227d2016-08-02 14:20:21 -07001269status_t AST::generateProxySource(
1270 Formatter &out, const std::string &baseName) const {
1271 const std::string klassName = "Bp" + baseName;
1272
1273 out << klassName
1274 << "::"
1275 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001276 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001277
1278 out.indent();
1279 out.indent();
1280
1281 out << ": BpInterface"
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001282 << "<I"
Andreas Huber881227d2016-08-02 14:20:21 -07001283 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001284 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001285 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001286 << mPackage.string()
1287 << "::I"
1288 << baseName
1289 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001290
Andreas Huber881227d2016-08-02 14:20:21 -07001291 out.unindent();
1292 out.unindent();
1293 out << "}\n\n";
1294
Yifan Hong068c5522016-10-31 14:07:25 -07001295 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1296 return generateProxyMethodSource(out, klassName, method, superInterface);
1297 });
Andreas Huber881227d2016-08-02 14:20:21 -07001298
Yifan Hong068c5522016-10-31 14:07:25 -07001299 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001300}
1301
1302status_t AST::generateStubSource(
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001303 Formatter &out,
1304 const Interface *iface,
1305 const std::string &baseName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001306 const std::string klassName = "Bn" + baseName;
1307
Steven Moreland40786312016-08-16 10:29:40 -07001308 out << klassName
1309 << "::"
1310 << klassName
1311 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1312
1313 out.indent();
1314 out.indent();
1315
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001316 if (iface->isIBase()) {
1317 out << ": ::android::hardware::HidlInstrumentor(\"";
1318 } else {
1319 out << ": ::android::hidl::base::V1_0::BnBase(_hidl_impl, \"";
1320 }
1321
1322 out << mPackage.string()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001323 << "::I"
1324 << baseName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001325 << "\") { \n";
1326 out.indent();
1327 out << "_hidl_mImpl = _hidl_impl;\n";
1328 out.unindent();
Steven Moreland40786312016-08-16 10:29:40 -07001329
1330 out.unindent();
1331 out.unindent();
1332 out << "}\n\n";
1333
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001334 if (iface->isIBase()) {
1335 // BnBase has a constructor to initialize the HidlInstrumentor
1336 // class properly.
1337 out << klassName
1338 << "::"
1339 << klassName
1340 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl,"
1341 << " const std::string &prefix)\n";
1342
1343 out.indent();
1344 out.indent();
1345
1346 out << ": ::android::hardware::HidlInstrumentor(prefix) { \n";
1347 out.indent();
1348 out << "_hidl_mImpl = _hidl_impl;\n";
1349 out.unindent();
1350
1351 out.unindent();
1352 out.unindent();
1353 out << "}\n\n";
1354 }
1355
1356
Andreas Huber881227d2016-08-02 14:20:21 -07001357 out << "::android::status_t " << klassName << "::onTransact(\n";
1358
1359 out.indent();
1360 out.indent();
1361
Iliyan Malchev549e2592016-08-10 08:59:12 -07001362 out << "uint32_t _hidl_code,\n"
1363 << "const ::android::hardware::Parcel &_hidl_data,\n"
1364 << "::android::hardware::Parcel *_hidl_reply,\n"
1365 << "uint32_t _hidl_flags,\n"
1366 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001367
1368 out.unindent();
1369
Iliyan Malchev549e2592016-08-10 08:59:12 -07001370 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001371 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001372 out.indent();
1373
Yifan Hong10fe0b52016-10-19 14:20:17 -07001374 for (const auto &tuple : iface->allMethodsFromRoot()) {
1375 const Method *method = tuple.method();
1376 const Interface *superInterface = tuple.interface();
1377 out << "case "
1378 << method->getSerialId()
1379 << " /* "
1380 << method->name()
1381 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001382
Yifan Hong10fe0b52016-10-19 14:20:17 -07001383 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001384
Yifan Hong10fe0b52016-10-19 14:20:17 -07001385 status_t err =
1386 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001387
Yifan Hong10fe0b52016-10-19 14:20:17 -07001388 if (err != OK) {
1389 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001390 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001391
1392 out.unindent();
1393 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001394 }
1395
1396 out << "default:\n{\n";
1397 out.indent();
1398
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001399 out << "return onTransact(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001400
1401 out.indent();
1402 out.indent();
1403
Iliyan Malchev549e2592016-08-10 08:59:12 -07001404 out << "_hidl_code, _hidl_data, _hidl_reply, "
1405 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001406
1407 out.unindent();
1408 out.unindent();
1409
1410 out.unindent();
1411 out << "}\n";
1412
1413 out.unindent();
1414 out << "}\n\n";
1415
Yifan Honga018ed52016-12-13 16:35:08 -08001416 out.sIf("_hidl_err == ::android::UNEXPECTED_NULL", [&] {
1417 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
1418 out.indent(2, [&] {
1419 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1420 out << "_hidl_reply);\n";
1421 });
1422 });
Andreas Huber881227d2016-08-02 14:20:21 -07001423
Iliyan Malchev549e2592016-08-10 08:59:12 -07001424 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001425
1426 out.unindent();
1427 out << "}\n\n";
1428
1429 return OK;
1430}
1431
1432status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001433 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001434 out << "if (!_hidl_data.enforceInterface(";
1435
Yifan Hongc8934042016-11-17 17:10:52 -08001436 out << iface->fqName().cppNamespace()
1437 << "::I"
1438 << iface->getBaseName();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001439
1440 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001441
Andreas Huber881227d2016-08-02 14:20:21 -07001442 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001443 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001444 out << "break;\n";
1445 out.unindent();
1446 out << "}\n\n";
1447
Andreas Huber5e44a292016-09-27 14:52:39 -07001448 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001449
Yifan Hongbf459bc2016-08-23 16:50:37 -07001450 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001451 for (const auto &arg : method->args()) {
1452 emitCppReaderWriter(
1453 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001454 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001455 false /* parcelObjIsPointer */,
1456 arg,
1457 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001458 Type::ErrorMode_Break,
1459 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001460 }
1461
Yifan Hongbf459bc2016-08-23 16:50:37 -07001462 // Second DFS: resolve references
1463 for (const auto &arg : method->args()) {
1464 emitCppResolveReferences(
1465 out,
1466 "_hidl_data",
1467 false /* parcelObjIsPointer */,
1468 arg,
1469 true /* reader */,
1470 Type::ErrorMode_Break,
1471 false /* addPrefixToName */);
1472 }
1473
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001474 status_t status = generateCppInstrumentationCall(
1475 out,
1476 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001477 method);
1478 if (status != OK) {
1479 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001480 }
1481
Andreas Huber881227d2016-08-02 14:20:21 -07001482 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001483 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001484
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001485 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001486 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -08001487 << " _hidl_out_"
Yifan Hong3b320f82016-11-01 15:15:54 -07001488 << elidedReturn->name()
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001489 << " = "
1490 << "_hidl_mImpl->" << method->name()
Yifan Hong3b320f82016-11-01 15:15:54 -07001491 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001492
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001493 bool first = true;
1494 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001495 if (!first) {
1496 out << ", ";
1497 }
1498
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001499 if (arg->type().resultNeedsDeref()) {
1500 out << "*";
1501 }
1502
1503 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001504
1505 first = false;
1506 }
1507
Steven Moreland2ae5bca2016-12-01 05:56:49 +00001508 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001509 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1510 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001511
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001512 elidedReturn->type().emitReaderWriter(
1513 out,
Yifan Honga47eef32016-12-12 10:38:54 -08001514 "_hidl_out_" + elidedReturn->name(),
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001515 "_hidl_reply",
1516 true, /* parcelObjIsPointer */
1517 false, /* isReader */
1518 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001519
Yifan Hongbf459bc2016-08-23 16:50:37 -07001520 emitCppResolveReferences(
1521 out,
1522 "_hidl_reply",
1523 true /* parcelObjIsPointer */,
1524 elidedReturn,
1525 false /* reader */,
1526 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001527 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001528
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001529 status_t status = generateCppInstrumentationCall(
1530 out,
1531 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001532 method);
1533 if (status != OK) {
1534 return status;
1535 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001536
Iliyan Malchev549e2592016-08-10 08:59:12 -07001537 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001538 } else {
1539 if (returnsValue) {
1540 out << "bool _hidl_callbackCalled = false;\n\n";
1541 }
Andreas Huber881227d2016-08-02 14:20:21 -07001542
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001543 out << "_hidl_mImpl->" << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001544
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001545 bool first = true;
1546 for (const auto &arg : method->args()) {
1547 if (!first) {
1548 out << ", ";
1549 }
Andreas Huber881227d2016-08-02 14:20:21 -07001550
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001551 if (arg->type().resultNeedsDeref()) {
1552 out << "*";
1553 }
1554
1555 out << arg->name();
1556
1557 first = false;
1558 }
1559
1560 if (returnsValue) {
1561 if (!first) {
1562 out << ", ";
1563 }
1564
1565 out << "[&](";
1566
1567 first = true;
1568 for (const auto &arg : method->results()) {
1569 if (!first) {
1570 out << ", ";
1571 }
1572
Yifan Honga47eef32016-12-12 10:38:54 -08001573 out << "const auto &_hidl_out_" << arg->name();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001574
1575 first = false;
1576 }
1577
1578 out << ") {\n";
1579 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001580 out << "if (_hidl_callbackCalled) {\n";
1581 out.indent();
1582 out << "LOG_ALWAYS_FATAL(\""
1583 << method->name()
1584 << ": _hidl_cb called a second time, but must be called once.\");\n";
1585 out.unindent();
1586 out << "}\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001587 out << "_hidl_callbackCalled = true;\n\n";
1588
Yifan Hong859e53f2016-11-14 19:08:24 -08001589 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1590 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001591
Yifan Hongbf459bc2016-08-23 16:50:37 -07001592 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001593 for (const auto &arg : method->results()) {
1594 emitCppReaderWriter(
1595 out,
1596 "_hidl_reply",
1597 true /* parcelObjIsPointer */,
1598 arg,
1599 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001600 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001601 true /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001602 }
1603
Yifan Hongbf459bc2016-08-23 16:50:37 -07001604 // Second DFS: resolve references
1605 for (const auto &arg : method->results()) {
1606 emitCppResolveReferences(
1607 out,
1608 "_hidl_reply",
1609 true /* parcelObjIsPointer */,
1610 arg,
1611 false /* reader */,
1612 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001613 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001614 }
1615
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001616 status_t status = generateCppInstrumentationCall(
1617 out,
1618 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001619 method);
1620 if (status != OK) {
1621 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001622 }
1623
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001624 out << "_hidl_cb(*_hidl_reply);\n";
1625
1626 out.unindent();
1627 out << "}\n";
1628 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001629 out << ");\n\n";
1630
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001631 if (returnsValue) {
1632 out << "if (!_hidl_callbackCalled) {\n";
1633 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001634 out << "LOG_ALWAYS_FATAL(\""
1635 << method->name()
1636 << ": _hidl_cb not called, but must be called once.\");\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001637 out.unindent();
1638 out << "}\n\n";
Steven Moreland05cd4232016-11-21 16:01:12 -08001639 } else {
1640 out << "::android::hardware::writeToParcel("
1641 << "::android::hardware::Status::ok(), "
1642 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001643 }
Andreas Huber881227d2016-08-02 14:20:21 -07001644 }
1645
1646 out << "break;\n";
1647
1648 return OK;
1649}
1650
Steven Moreland69e7c702016-09-09 11:16:32 -07001651status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1652 std::string ifaceName;
1653 if (!AST::isInterface(&ifaceName)) {
1654 // types.hal does not get a stub header.
1655 return OK;
1656 }
1657
1658 const Interface *iface = mRootScope->getInterface();
1659
1660 const std::string baseName = iface->getBaseName();
1661 const std::string klassName = "Bs" + baseName;
1662
1663 bool supportOneway = iface->hasOnewayMethods();
1664
1665 std::string path = outputPath;
1666 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1667 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1668 path.append(klassName);
1669 path.append(".h");
1670
1671 CHECK(Coordinator::MakeParentHierarchy(path));
1672 FILE *file = fopen(path.c_str(), "w");
1673
1674 if (file == NULL) {
1675 return -errno;
1676 }
1677
1678 Formatter out(file);
1679
1680 const std::string guard = makeHeaderGuard(klassName);
1681
1682 out << "#ifndef " << guard << "\n";
1683 out << "#define " << guard << "\n\n";
1684
1685 std::vector<std::string> packageComponents;
1686 getPackageAndVersionComponents(
1687 &packageComponents, false /* cpp_compatible */);
1688
Yifan Hongb0949432016-12-15 15:32:24 -08001689 out << "#include <cutils/trace.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001690 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001691
1692 generateCppPackageInclude(out, mPackage, ifaceName);
1693 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001694
Yifan Hong7a118f52016-12-07 11:21:15 -08001695 out << "#include <hidl/HidlPassthroughSupport.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001696 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001697 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001698 }
1699
1700 enterLeaveNamespace(out, true /* enter */);
1701 out << "\n";
1702
1703 out << "struct "
1704 << klassName
1705 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001706 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001707
1708 out.indent();
1709 out << "explicit "
1710 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001711 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001712 << ifaceName
1713 << "> impl);\n";
1714
Yifan Hong068c5522016-10-31 14:07:25 -07001715 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1716 return generatePassthroughMethod(out, method);
1717 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001718
1719 if (err != OK) {
1720 return err;
1721 }
1722
1723 out.unindent();
1724 out << "private:\n";
1725 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001726 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001727
1728 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001729 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001730
1731 out << "\n";
1732
1733 out << "::android::hardware::Return<void> addOnewayTask("
1734 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001735 }
1736
1737 out.unindent();
1738
1739 out << "};\n\n";
1740
1741 enterLeaveNamespace(out, false /* enter */);
1742
1743 out << "\n#endif // " << guard << "\n";
1744
1745 return OK;
1746}
1747
Yifan Hongfe95aa22016-10-19 17:26:45 -07001748status_t AST::generateInterfaceSource(Formatter &out) const {
1749 const Interface *iface = mRootScope->getInterface();
1750
Yifan Hong2d7126b2016-10-20 15:12:57 -07001751 // generate castFrom functions
Yifan Hong3d746092016-12-07 14:26:33 -08001752 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001753
Yifan Hong3d746092016-12-07 14:26:33 -08001754 for (const Interface *superType : iface->typeChain()) {
1755 out << "// static \n"
1756 << childTypeResult
1757 << " I"
1758 << iface->getBaseName()
1759 << "::castFrom("
1760 << superType->getCppArgumentType()
1761 << " parent) {\n";
1762 out.indent();
1763 if (iface == superType) {
1764 out << "return parent;\n";
1765 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001766 out << "return ::android::hardware::castInterface<";
1767 out << "I" << iface->getBaseName() << ", "
1768 << superType->fqName().cppName() << ", "
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001769 << iface->getProxyName().cppLocalName() << ", "
1770 << superType->getProxyName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001771 << ">(\n";
1772 out.indent();
1773 out.indent();
1774 out << "parent, \""
1775 << iface->fqName().string()
1776 << "\");\n";
1777 out.unindent();
1778 out.unindent();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001779 }
Yifan Hong3d746092016-12-07 14:26:33 -08001780 out.unindent();
1781 out << "}\n\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001782 }
1783
1784 return OK;
1785}
1786
Steven Moreland69e7c702016-09-09 11:16:32 -07001787status_t AST::generatePassthroughSource(Formatter &out) const {
1788 const Interface *iface = mRootScope->getInterface();
1789
1790 const std::string baseName = iface->getBaseName();
1791 const std::string klassName = "Bs" + baseName;
1792
1793 out << klassName
1794 << "::"
1795 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001796 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001797 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001798 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001799 << iface->fqName().string()
1800 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001801 if (iface->hasOnewayMethods()) {
1802 out << "\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001803 out.indent([&] {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001804 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1805 });
1806 }
1807 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001808
1809 if (iface->hasOnewayMethods()) {
1810 out << "::android::hardware::Return<void> "
1811 << klassName
1812 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1813 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001814 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001815 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001816 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1817 out.indent();
1818 out.indent();
1819 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1820 out.unindent();
1821 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001822 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001823 out << "}\n";
1824
Steven Morelandd366c262016-10-11 15:29:10 -07001825 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001826
1827 out.unindent();
1828 out << "}\n\n";
1829
1830
1831 }
1832
1833 return OK;
1834}
1835
Martijn Coenen7b295242016-11-04 16:52:56 +01001836status_t AST::generateCppAtraceCall(Formatter &out,
1837 InstrumentationEvent event,
1838 const Method *method) const {
1839 const Interface *iface = mRootScope->getInterface();
1840 std::string baseString = "HIDL::I" + iface->getBaseName() + "::" + method->name();
1841 switch (event) {
1842 case SERVER_API_ENTRY:
1843 {
1844 out << "atrace_begin(ATRACE_TAG_HAL, \""
1845 << baseString + "::server\");\n";
1846 break;
1847 }
1848 case CLIENT_API_ENTRY:
1849 {
1850 out << "atrace_begin(ATRACE_TAG_HAL, \""
1851 << baseString + "::client\");\n";
1852 break;
1853 }
1854 case PASSTHROUGH_ENTRY:
1855 {
1856 out << "atrace_begin(ATRACE_TAG_HAL, \""
1857 << baseString + "::passthrough\");\n";
1858 break;
1859 }
1860 case SERVER_API_EXIT:
1861 case CLIENT_API_EXIT:
1862 case PASSTHROUGH_EXIT:
1863 {
1864 out << "atrace_end(ATRACE_TAG_HAL);\n";
1865 break;
1866 }
1867 default:
1868 {
1869 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1870 return UNKNOWN_ERROR;
1871 }
1872 }
1873
1874 return OK;
1875}
1876
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001877status_t AST::generateCppInstrumentationCall(
1878 Formatter &out,
1879 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001880 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001881 status_t err = generateCppAtraceCall(out, event, method);
1882 if (err != OK) {
1883 return err;
1884 }
1885
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001886 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1887 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001888 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001889 std::string event_str = "";
1890 switch (event) {
1891 case SERVER_API_ENTRY:
1892 {
1893 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1894 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001895 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001896 << (arg->type().resultNeedsDeref() ? "" : "&")
1897 << arg->name()
1898 << ");\n";
1899 }
1900 break;
1901 }
1902 case SERVER_API_EXIT:
1903 {
1904 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001905 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001906 out << "_hidl_args.push_back((void *)&_hidl_out_"
Steven Moreland031ccf12016-10-31 15:54:38 -07001907 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001908 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001909 }
1910 break;
1911 }
1912 case CLIENT_API_ENTRY:
1913 {
1914 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1915 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001916 out << "_hidl_args.push_back((void *)&"
1917 << arg->name()
1918 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001919 }
1920 break;
1921 }
1922 case CLIENT_API_EXIT:
1923 {
1924 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1925 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001926 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001927 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001928 << "_hidl_out_"
1929 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001930 << ");\n";
1931 }
1932 break;
1933 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001934 case PASSTHROUGH_ENTRY:
1935 {
1936 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1937 for (const auto &arg : method->args()) {
1938 out << "_hidl_args.push_back((void *)&"
1939 << arg->name()
1940 << ");\n";
1941 }
1942 break;
1943 }
1944 case PASSTHROUGH_EXIT:
1945 {
1946 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001947 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001948 out << "_hidl_args.push_back((void *)&_hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001949 << arg->name()
1950 << ");\n";
1951 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001952 break;
1953 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001954 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001955 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001956 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001957 return UNKNOWN_ERROR;
1958 }
1959 }
1960
Steven Moreland031ccf12016-10-31 15:54:38 -07001961 const Interface *iface = mRootScope->getInterface();
1962
Steven Moreland1ab31442016-11-03 18:37:51 -07001963 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001964 out.indent();
1965 out << "callback("
1966 << event_str
1967 << ", \""
1968 << mPackage.package()
1969 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001970 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001971 << "\", \""
1972 << iface->localName()
1973 << "\", \""
1974 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001975 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001976 out.unindent();
1977 out << "}\n";
1978 out.unindent();
1979 out << "}\n\n";
1980
1981 return OK;
1982}
1983
Andreas Huber881227d2016-08-02 14:20:21 -07001984} // namespace android
1985