blob: 7b74cb6b2b2b261cee07a680476f1d5f182f78df [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huber881227d2016-08-02 14:20:21 -070017#include "AST.h"
18
19#include "Coordinator.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070020#include "EnumType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070021#include "Interface.h"
22#include "Method.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070023#include "ScalarType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070024#include "Scope.h"
25
Andreas Huberdca261f2016-08-04 13:47:51 -070026#include <algorithm>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070027#include <hidl-util/Formatter.h>
Steven Moreland5708edf2016-11-04 15:33:31 +000028#include <hidl-util/StringHelper.h>
Andreas Huber881227d2016-08-02 14:20:21 -070029#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070031#include <vector>
32
33namespace android {
34
Andreas Huberb82318c2016-08-02 14:45:54 -070035status_t AST::generateCpp(const std::string &outputPath) const {
36 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070037
38 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070039 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070040 }
41
42 if (err == OK) {
Steven Moreland40786312016-08-16 10:29:40 -070043 err = generateHwBinderHeader(outputPath);
44 }
45
46 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070047 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070048 }
49
50 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070051 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070052 }
53
Steven Moreland69e7c702016-09-09 11:16:32 -070054 if (err == OK) {
55 generatePassthroughHeader(outputPath);
56 }
57
Andreas Huber881227d2016-08-02 14:20:21 -070058 return err;
59}
60
Andreas Huber737080b2016-08-02 15:38:04 -070061void AST::getPackageComponents(
62 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070063 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070064}
65
66void AST::getPackageAndVersionComponents(
67 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070068 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070069}
70
Steven Moreland5708edf2016-11-04 15:33:31 +000071std::string AST::makeHeaderGuard(const std::string &baseName,
72 bool indicateGenerated) const {
73 std::string guard;
Andreas Huber881227d2016-08-02 14:20:21 -070074
Steven Moreland5708edf2016-11-04 15:33:31 +000075 if (indicateGenerated) {
76 guard += "HIDL_GENERATED_";
77 }
78
79 guard += StringHelper::Uppercase(mPackage.tokenName());
Andreas Huber881227d2016-08-02 14:20:21 -070080 guard += "_";
Steven Moreland5708edf2016-11-04 15:33:31 +000081 guard += StringHelper::Uppercase(baseName);
82 guard += "_H";
Andreas Huber881227d2016-08-02 14:20:21 -070083
84 return guard;
85}
86
Steven Morelandee88eed2016-10-31 17:49:00 -070087// static
88void AST::generateCppPackageInclude(
89 Formatter &out,
90 const FQName &package,
91 const std::string &klass) {
92
93 out << "#include <";
94
95 std::vector<std::string> components;
96 package.getPackageAndVersionComponents(&components, false /* cpp_compatible */);
97
98 for (const auto &component : components) {
99 out << component << "/";
100 }
101
102 out << klass
103 << ".h>\n";
104}
105
Andreas Huber881227d2016-08-02 14:20:21 -0700106void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
107 std::vector<std::string> packageComponents;
108 getPackageAndVersionComponents(
109 &packageComponents, true /* cpp_compatible */);
110
111 if (enter) {
112 for (const auto &component : packageComponents) {
113 out << "namespace " << component << " {\n";
114 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700115
Andreas Huber2831d512016-08-15 09:33:47 -0700116 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -0700117 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700118 out.setNamespace(std::string());
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120 for (auto it = packageComponents.rbegin();
121 it != packageComponents.rend();
122 ++it) {
123 out << "} // namespace " << *it << "\n";
124 }
125 }
126}
127
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
Steven Moreland69e7c702016-09-09 11:16:32 -0700522status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700523 const Method *method) const {
524 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700525
526 out << " {\n";
527 out.indent();
528
529 const bool returnsValue = !method->results().empty();
530 const TypedVar *elidedReturn = method->canElideCallback();
531
Steven Moreland67f67b42016-09-29 08:59:02 -0700532 if (returnsValue && elidedReturn == nullptr) {
533 generateCheckNonNull(out, "_hidl_cb");
534 }
535
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700536 generateCppInstrumentationCall(
537 out,
538 InstrumentationEvent::PASSTHROUGH_ENTRY,
539 method);
540
541 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700542
543 if (method->isOneway()) {
544 out << "addOnewayTask([this";
545 for (const auto &arg : method->args()) {
546 out << ", " << arg->name();
547 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700548 out << "] {\n";
549 out.indent();
550 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700551 }
552
553 out << "mImpl->"
554 << method->name()
555 << "(";
556
557 bool first = true;
558 for (const auto &arg : method->args()) {
559 if (!first) {
560 out << ", ";
561 }
562 first = false;
563 out << arg->name();
564 }
565 if (returnsValue && elidedReturn == nullptr) {
566 if (!method->args().empty()) {
567 out << ", ";
568 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800569 out << "[&](";
570 first = true;
571 for (const auto &arg : method->results()) {
572 if (!first) {
573 out << ", ";
574 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700575
Yifan Honga47eef32016-12-12 10:38:54 -0800576 out << "const auto &_hidl_out_" << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800577
578 first = false;
579 }
580
581 out << ") {\n";
582 out.indent();
583 status_t status = generateCppInstrumentationCall(
584 out,
585 InstrumentationEvent::PASSTHROUGH_EXIT,
586 method);
587 if (status != OK) {
588 return status;
589 }
590
591 out << "_hidl_cb(";
592 first = true;
593 for (const auto &arg : method->results()) {
594 if (!first) {
595 out << ", ";
596 }
597
Yifan Honga47eef32016-12-12 10:38:54 -0800598 out << "_hidl_out_" << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800599
600 first = false;
601 }
602 out << ");\n";
603 out.unindent();
604 out << "});\n\n";
605 } else {
606 out << ");\n\n";
607 if (elidedReturn != nullptr) {
608 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -0800609 << " _hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800610 << elidedReturn->name()
Steven Moreland2ae5bca2016-12-01 05:56:49 +0000611 << " = _hidl_return;\n";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800612 }
613 status_t status = generateCppInstrumentationCall(
614 out,
615 InstrumentationEvent::PASSTHROUGH_EXIT,
616 method);
617 if (status != OK) {
618 return status;
619 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700620 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700621
622 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700623 out.unindent();
624 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700625 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700626
627 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700628
629 out.unindent();
630 out << "}\n";
631
632 return OK;
633}
634
Yifan Hong068c5522016-10-31 14:07:25 -0700635status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700636
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700637 const Interface *iface = mRootScope->getInterface();
638
Yifan Hong10fe0b52016-10-19 14:20:17 -0700639 const Interface *prevIterface = nullptr;
640 for (const auto &tuple : iface->allMethodsFromRoot()) {
641 const Method *method = tuple.method();
642 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700643
Yifan Hong10fe0b52016-10-19 14:20:17 -0700644 if(prevIterface != superInterface) {
645 if (prevIterface != nullptr) {
646 out << "\n";
647 }
648 out << "// Methods from "
649 << superInterface->fullName()
650 << " follow.\n";
651 prevIterface = superInterface;
652 }
Yifan Hong068c5522016-10-31 14:07:25 -0700653 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700654
Yifan Hong10fe0b52016-10-19 14:20:17 -0700655 if (err != OK) {
656 return err;
657 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700658 }
659
Yifan Hong10fe0b52016-10-19 14:20:17 -0700660 out << "\n";
661
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700662 return OK;
663}
664
Andreas Huberb82318c2016-08-02 14:45:54 -0700665status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700666 std::string ifaceName;
667 if (!AST::isInterface(&ifaceName)) {
668 // types.hal does not get a stub header.
669 return OK;
670 }
671
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700672 const Interface *iface = mRootScope->getInterface();
673 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700674 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700675
Andreas Huberb82318c2016-08-02 14:45:54 -0700676 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700677 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700678 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700679 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700680 path.append(".h");
681
Andreas Huberd2943e12016-08-05 11:59:31 -0700682 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700683 FILE *file = fopen(path.c_str(), "w");
684
685 if (file == NULL) {
686 return -errno;
687 }
688
689 Formatter out(file);
690
Steven Moreland40786312016-08-16 10:29:40 -0700691 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700692
693 out << "#ifndef " << guard << "\n";
694 out << "#define " << guard << "\n\n";
695
Steven Morelandee88eed2016-10-31 17:49:00 -0700696 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
697 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700698
699 enterLeaveNamespace(out, true /* enter */);
700 out << "\n";
701
702 out << "struct "
703 << "Bn"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100704 << baseName;
705 if (iface->isIBase()) {
706 out << " : public ::android::hardware::BBinder";
707 out << ", public ::android::hardware::HidlInstrumentor {\n";
708 } else {
709 out << " : public ::android::hidl::base::V1_0::BnBase {\n";
710 }
Andreas Huber881227d2016-08-02 14:20:21 -0700711
712 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700713 out << "explicit Bn"
714 << baseName
715 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100716 << "\n";
717 out << "explicit Bn"
718 << baseName
719 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl,"
720 << " const std::string& prefix);"
Steven Moreland40786312016-08-16 10:29:40 -0700721 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700722 out << "::android::status_t onTransact(\n";
723 out.indent();
724 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700725 out << "uint32_t _hidl_code,\n";
726 out << "const ::android::hardware::Parcel &_hidl_data,\n";
727 out << "::android::hardware::Parcel *_hidl_reply,\n";
728 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700729 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700730 out.unindent();
731 out.unindent();
732
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100733 out << "::android::sp<" << ifaceName << "> getImpl() { return _hidl_mImpl; };\n";
734 out.unindent();
735 out << "private:\n";
736 out.indent();
737 out << "::android::sp<" << ifaceName << "> _hidl_mImpl;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700738 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700739 out << "};\n\n";
740
741 enterLeaveNamespace(out, false /* enter */);
742
743 out << "\n#endif // " << guard << "\n";
744
745 return OK;
746}
747
Andreas Huberb82318c2016-08-02 14:45:54 -0700748status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700749 std::string ifaceName;
750 if (!AST::isInterface(&ifaceName)) {
751 // types.hal does not get a proxy header.
752 return OK;
753 }
754
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700755 const Interface *iface = mRootScope->getInterface();
756 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700757
Andreas Huberb82318c2016-08-02 14:45:54 -0700758 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700759 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700760 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700761 path.append("Bp");
762 path.append(baseName);
763 path.append(".h");
764
Andreas Huberd2943e12016-08-05 11:59:31 -0700765 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700766 FILE *file = fopen(path.c_str(), "w");
767
768 if (file == NULL) {
769 return -errno;
770 }
771
772 Formatter out(file);
773
774 const std::string guard = makeHeaderGuard("Bp" + baseName);
775
776 out << "#ifndef " << guard << "\n";
777 out << "#define " << guard << "\n\n";
778
779 std::vector<std::string> packageComponents;
780 getPackageAndVersionComponents(
781 &packageComponents, false /* cpp_compatible */);
782
Steven Morelandee88eed2016-10-31 17:49:00 -0700783 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
784 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700785
786 enterLeaveNamespace(out, true /* enter */);
787 out << "\n";
788
789 out << "struct "
790 << "Bp"
791 << baseName
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100792 << " : public ::android::hardware::BpInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -0700793 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700794 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700795
796 out.indent();
797
798 out << "explicit Bp"
799 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700800 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700801 << "\n\n";
802
Yifan Hong10fe0b52016-10-19 14:20:17 -0700803 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700804
Yifan Hong068c5522016-10-31 14:07:25 -0700805 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
806 method->generateCppSignature(out);
807 out << " override;\n";
808 return OK;
809 });
Steven Moreland9c387612016-09-07 09:54:26 -0700810
811 if (err != OK) {
812 return err;
813 }
Andreas Huber881227d2016-08-02 14:20:21 -0700814
815 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700816 out << "};\n\n";
817
818 enterLeaveNamespace(out, false /* enter */);
819
820 out << "\n#endif // " << guard << "\n";
821
822 return OK;
823}
824
Andreas Huberb82318c2016-08-02 14:45:54 -0700825status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700826
Andreas Huberb82318c2016-08-02 14:45:54 -0700827 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700828 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700829 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700830
831 std::string ifaceName;
832 std::string baseName;
833
Yifan Hongfe95aa22016-10-19 17:26:45 -0700834 const Interface *iface = nullptr;
835 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700836 if (!AST::isInterface(&ifaceName)) {
837 baseName = "types";
838 isInterface = false;
839 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700840 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700841 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700842 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700843 }
844
845 path.append(baseName);
846
847 if (baseName != "types") {
848 path.append("All");
849 }
850
851 path.append(".cpp");
852
Andreas Huberd2943e12016-08-05 11:59:31 -0700853 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700854 FILE *file = fopen(path.c_str(), "w");
855
856 if (file == NULL) {
857 return -errno;
858 }
859
860 Formatter out(file);
861
Steven Moreland05cd4232016-11-21 16:01:12 -0800862 out << "#include <android/log.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100863 out << "#include <cutils/trace.h>\n";
864 out << "#include <hidl/HidlTransportSupport.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700865 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700866 // This is a no-op for IServiceManager itself.
867 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
868
Steven Morelandee88eed2016-10-31 17:49:00 -0700869 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
870 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
871 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700872
873 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700874 generateCppPackageInclude(out,
875 superType->fqName(),
876 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700877 }
Yifan Hong2cbbdf92016-12-05 15:20:50 -0800878
879 out << "#include <hidl/ServiceManagement.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700880 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700881 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800882 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700883 }
884
885 out << "\n";
886
887 enterLeaveNamespace(out, true /* enter */);
888 out << "\n";
889
890 status_t err = generateTypeSource(out, ifaceName);
891
892 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700893 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700894 out << "constexpr ::android::hardware::hidl_version "
895 << ifaceName
896 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700897
898 // need to be put here, generateStubSource is using this.
Steven Morelandd39133b2016-11-11 12:30:08 -0800899 out << "const char* I"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700900 << iface->getBaseName()
901 << "::descriptor(\""
902 << iface->fqName().string()
903 << "\");\n\n";
904
Yifan Hong158655a2016-11-08 12:34:07 -0800905 out << "int I"
906 << iface->getBaseName()
907 << "::hidlStaticBlock = []() -> int {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800908 out.indent([&] {
Steven Morelandd39133b2016-11-11 12:30:08 -0800909 out << "::android::hardware::gBnConstructorMap[I"
Yifan Hong158655a2016-11-08 12:34:07 -0800910 << iface->getBaseName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800911 << "::descriptor]\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800912 out.indent(2, [&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800913 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800914 out.indent([&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800915 out << "return new Bn"
916 << iface->getBaseName()
917 << "(reinterpret_cast<I"
918 << iface->getBaseName()
919 << " *>(iIntf));\n";
920 });
921 out << "};\n";
922 });
923 out << "return 1;\n";
924 });
925 out << "}();\n\n";
926
Yifan Hongfe95aa22016-10-19 17:26:45 -0700927 err = generateInterfaceSource(out);
928 }
929
930 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -0700931 err = generateProxySource(out, baseName);
932 }
933
934 if (err == OK && isInterface) {
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100935 err = generateStubSource(out, iface, baseName);
Andreas Huber881227d2016-08-02 14:20:21 -0700936 }
937
Steven Moreland40786312016-08-16 10:29:40 -0700938 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700939 err = generatePassthroughSource(out);
940 }
941
942 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700943 const Interface *iface = mRootScope->getInterface();
944
Yifan Hongc8934042016-11-17 17:10:52 -0800945 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800946 out << "// skipped getService, registerAsService, registerForNotifications\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800947 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800948 std::string package = iface->fqName().package()
949 + iface->fqName().atVersion();
950
951 implementServiceManagerInteractions(out, baseName, package);
Yifan Hongc8934042016-11-17 17:10:52 -0800952 }
Steven Moreland40786312016-08-16 10:29:40 -0700953 }
954
Andreas Huber881227d2016-08-02 14:20:21 -0700955 enterLeaveNamespace(out, false /* enter */);
956
957 return err;
958}
959
Steven Moreland67f67b42016-09-29 08:59:02 -0700960// static
961void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
Yifan Honga018ed52016-12-13 16:35:08 -0800962 out.sIf(nonNull + " == nullptr", [&] {
963 out << "return ::android::hardware::Status::fromExceptionCode(\n";
964 out.indent(2, [&] {
965 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
966 });
967 }).endl().endl();
Steven Moreland67f67b42016-09-29 08:59:02 -0700968}
969
Andreas Huber881227d2016-08-02 14:20:21 -0700970status_t AST::generateTypeSource(
971 Formatter &out, const std::string &ifaceName) const {
972 return mRootScope->emitTypeDefinitions(out, ifaceName);
973}
974
Andreas Hubere7ff2282016-08-16 13:50:03 -0700975void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700976 Formatter &out,
977 const std::vector<TypedVar *> &args,
978 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700979 if (args.empty()) {
980 return;
981 }
982
983 for (const auto &arg : args) {
984 const Type &type = arg->type();
985
Yifan Hong3b320f82016-11-01 15:15:54 -0700986 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700987 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -0700988 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700989 << ";\n";
990 }
991
992 out << "\n";
993}
994
Andreas Huber881227d2016-08-02 14:20:21 -0700995void AST::emitCppReaderWriter(
996 Formatter &out,
997 const std::string &parcelObj,
998 bool parcelObjIsPointer,
999 const TypedVar *arg,
1000 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -07001001 Type::ErrorMode mode,
1002 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001003 const Type &type = arg->type();
1004
Andreas Huber881227d2016-08-02 14:20:21 -07001005 type.emitReaderWriter(
1006 out,
Andreas Huber5e44a292016-09-27 14:52:39 -07001007 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -07001008 parcelObj,
1009 parcelObjIsPointer,
1010 isReader,
1011 mode);
1012}
1013
Yifan Hongbf459bc2016-08-23 16:50:37 -07001014void AST::emitCppResolveReferences(
1015 Formatter &out,
1016 const std::string &parcelObj,
1017 bool parcelObjIsPointer,
1018 const TypedVar *arg,
1019 bool isReader,
1020 Type::ErrorMode mode,
1021 bool addPrefixToName) const {
1022 const Type &type = arg->type();
1023 if(type.needsResolveReferences()) {
1024 type.emitResolveReferences(
1025 out,
1026 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
1027 isReader, // nameIsPointer
1028 parcelObj,
1029 parcelObjIsPointer,
1030 isReader,
1031 mode);
1032 }
1033}
1034
Yifan Hong068c5522016-10-31 14:07:25 -07001035status_t AST::generateProxyMethodSource(Formatter &out,
1036 const std::string &klassName,
1037 const Method *method,
1038 const Interface *superInterface) const {
1039
1040 method->generateCppSignature(out,
1041 klassName,
1042 true /* specify namespaces */);
1043
1044 const bool returnsValue = !method->results().empty();
1045 const TypedVar *elidedReturn = method->canElideCallback();
1046
Steven Moreland41c6d2e2016-11-07 12:26:54 -08001047 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001048
1049 out.indent();
1050
1051 if (returnsValue && elidedReturn == nullptr) {
1052 generateCheckNonNull(out, "_hidl_cb");
1053 }
1054
1055 status_t status = generateCppInstrumentationCall(
1056 out,
1057 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -07001058 method);
1059 if (status != OK) {
1060 return status;
1061 }
1062
1063 out << "::android::hardware::Parcel _hidl_data;\n";
1064 out << "::android::hardware::Parcel _hidl_reply;\n";
1065 out << "::android::status_t _hidl_err;\n";
1066 out << "::android::hardware::Status _hidl_status;\n\n";
1067
1068 declareCppReaderLocals(
1069 out, method->results(), true /* forResults */);
1070
1071 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Yifan Hongc8934042016-11-17 17:10:52 -08001072 out << superInterface->fqName().cppNamespace()
1073 << "::I"
1074 << superInterface->getBaseName();
Yifan Hong068c5522016-10-31 14:07:25 -07001075 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001076 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1077
1078 // First DFS: write all buffers and resolve pointers for parent
1079 for (const auto &arg : method->args()) {
1080 emitCppReaderWriter(
1081 out,
1082 "_hidl_data",
1083 false /* parcelObjIsPointer */,
1084 arg,
1085 false /* reader */,
1086 Type::ErrorMode_Goto,
1087 false /* addPrefixToName */);
1088 }
1089
1090 // Second DFS: resolve references.
1091 for (const auto &arg : method->args()) {
1092 emitCppResolveReferences(
1093 out,
1094 "_hidl_data",
1095 false /* parcelObjIsPointer */,
1096 arg,
1097 false /* reader */,
1098 Type::ErrorMode_Goto,
1099 false /* addPrefixToName */);
1100 }
1101
1102 out << "_hidl_err = remote()->transact("
1103 << method->getSerialId()
1104 << " /* "
1105 << method->name()
1106 << " */, _hidl_data, &_hidl_reply";
1107
1108 if (method->isOneway()) {
1109 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1110 }
1111 out << ");\n";
1112
1113 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1114
1115 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001116 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001117 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1118 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1119
1120
1121 // First DFS: write all buffers and resolve pointers for parent
1122 for (const auto &arg : method->results()) {
1123 emitCppReaderWriter(
1124 out,
1125 "_hidl_reply",
1126 false /* parcelObjIsPointer */,
1127 arg,
1128 true /* reader */,
1129 Type::ErrorMode_Goto,
1130 true /* addPrefixToName */);
1131 }
1132
1133 // Second DFS: resolve references.
1134 for (const auto &arg : method->results()) {
1135 emitCppResolveReferences(
1136 out,
1137 "_hidl_reply",
1138 false /* parcelObjIsPointer */,
1139 arg,
1140 true /* reader */,
1141 Type::ErrorMode_Goto,
1142 true /* addPrefixToName */);
1143 }
1144
1145 if (returnsValue && elidedReturn == nullptr) {
1146 out << "_hidl_cb(";
1147
1148 bool first = true;
1149 for (const auto &arg : method->results()) {
1150 if (!first) {
1151 out << ", ";
1152 }
1153
1154 if (arg->type().resultNeedsDeref()) {
1155 out << "*";
1156 }
1157 out << "_hidl_out_" << arg->name();
1158
1159 first = false;
1160 }
1161
1162 out << ");\n\n";
1163 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001164 }
1165 status = generateCppInstrumentationCall(
1166 out,
1167 InstrumentationEvent::CLIENT_API_EXIT,
1168 method);
1169 if (status != OK) {
1170 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001171 }
1172
1173 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001174 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1175 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001176 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001177 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1178 } else {
1179 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1180 out << "return ::android::hardware::Return<void>();\n\n";
1181 }
1182
1183 out.unindent();
1184 out << "_hidl_error:\n";
1185 out.indent();
1186 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1187 out << "return ::android::hardware::Return<";
1188 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001189 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001190 } else {
1191 out << "void";
1192 }
1193 out << ">(_hidl_status);\n";
1194
1195 out.unindent();
1196 out << "}\n\n";
1197 return OK;
1198}
1199
Andreas Huber881227d2016-08-02 14:20:21 -07001200status_t AST::generateProxySource(
1201 Formatter &out, const std::string &baseName) const {
1202 const std::string klassName = "Bp" + baseName;
1203
1204 out << klassName
1205 << "::"
1206 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001207 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001208
1209 out.indent();
1210 out.indent();
1211
1212 out << ": BpInterface"
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001213 << "<I"
Andreas Huber881227d2016-08-02 14:20:21 -07001214 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001215 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001216 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001217 << mPackage.string()
1218 << "::I"
1219 << baseName
1220 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001221
Andreas Huber881227d2016-08-02 14:20:21 -07001222 out.unindent();
1223 out.unindent();
1224 out << "}\n\n";
1225
Yifan Hong068c5522016-10-31 14:07:25 -07001226 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1227 return generateProxyMethodSource(out, klassName, method, superInterface);
1228 });
Andreas Huber881227d2016-08-02 14:20:21 -07001229
Yifan Hong068c5522016-10-31 14:07:25 -07001230 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001231}
1232
1233status_t AST::generateStubSource(
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001234 Formatter &out,
1235 const Interface *iface,
1236 const std::string &baseName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001237 const std::string klassName = "Bn" + baseName;
1238
Steven Moreland40786312016-08-16 10:29:40 -07001239 out << klassName
1240 << "::"
1241 << klassName
1242 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1243
1244 out.indent();
1245 out.indent();
1246
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001247 if (iface->isIBase()) {
1248 out << ": ::android::hardware::HidlInstrumentor(\"";
1249 } else {
1250 out << ": ::android::hidl::base::V1_0::BnBase(_hidl_impl, \"";
1251 }
1252
1253 out << mPackage.string()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001254 << "::I"
1255 << baseName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001256 << "\") { \n";
1257 out.indent();
1258 out << "_hidl_mImpl = _hidl_impl;\n";
1259 out.unindent();
Steven Moreland40786312016-08-16 10:29:40 -07001260
1261 out.unindent();
1262 out.unindent();
1263 out << "}\n\n";
1264
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001265 if (iface->isIBase()) {
1266 // BnBase has a constructor to initialize the HidlInstrumentor
1267 // class properly.
1268 out << klassName
1269 << "::"
1270 << klassName
1271 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl,"
1272 << " const std::string &prefix)\n";
1273
1274 out.indent();
1275 out.indent();
1276
1277 out << ": ::android::hardware::HidlInstrumentor(prefix) { \n";
1278 out.indent();
1279 out << "_hidl_mImpl = _hidl_impl;\n";
1280 out.unindent();
1281
1282 out.unindent();
1283 out.unindent();
1284 out << "}\n\n";
1285 }
1286
1287
Andreas Huber881227d2016-08-02 14:20:21 -07001288 out << "::android::status_t " << klassName << "::onTransact(\n";
1289
1290 out.indent();
1291 out.indent();
1292
Iliyan Malchev549e2592016-08-10 08:59:12 -07001293 out << "uint32_t _hidl_code,\n"
1294 << "const ::android::hardware::Parcel &_hidl_data,\n"
1295 << "::android::hardware::Parcel *_hidl_reply,\n"
1296 << "uint32_t _hidl_flags,\n"
1297 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001298
1299 out.unindent();
1300
Iliyan Malchev549e2592016-08-10 08:59:12 -07001301 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001302 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001303 out.indent();
1304
Yifan Hong10fe0b52016-10-19 14:20:17 -07001305 for (const auto &tuple : iface->allMethodsFromRoot()) {
1306 const Method *method = tuple.method();
1307 const Interface *superInterface = tuple.interface();
1308 out << "case "
1309 << method->getSerialId()
1310 << " /* "
1311 << method->name()
1312 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001313
Yifan Hong10fe0b52016-10-19 14:20:17 -07001314 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001315
Yifan Hong10fe0b52016-10-19 14:20:17 -07001316 status_t err =
1317 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001318
Yifan Hong10fe0b52016-10-19 14:20:17 -07001319 if (err != OK) {
1320 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001321 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001322
1323 out.unindent();
1324 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001325 }
1326
1327 out << "default:\n{\n";
1328 out.indent();
1329
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001330 out << "return onTransact(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001331
1332 out.indent();
1333 out.indent();
1334
Iliyan Malchev549e2592016-08-10 08:59:12 -07001335 out << "_hidl_code, _hidl_data, _hidl_reply, "
1336 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001337
1338 out.unindent();
1339 out.unindent();
1340
1341 out.unindent();
1342 out << "}\n";
1343
1344 out.unindent();
1345 out << "}\n\n";
1346
Yifan Honga018ed52016-12-13 16:35:08 -08001347 out.sIf("_hidl_err == ::android::UNEXPECTED_NULL", [&] {
1348 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
1349 out.indent(2, [&] {
1350 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1351 out << "_hidl_reply);\n";
1352 });
1353 });
Andreas Huber881227d2016-08-02 14:20:21 -07001354
Iliyan Malchev549e2592016-08-10 08:59:12 -07001355 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001356
1357 out.unindent();
1358 out << "}\n\n";
1359
1360 return OK;
1361}
1362
1363status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001364 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001365 out << "if (!_hidl_data.enforceInterface(";
1366
Yifan Hongc8934042016-11-17 17:10:52 -08001367 out << iface->fqName().cppNamespace()
1368 << "::I"
1369 << iface->getBaseName();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001370
1371 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001372
Andreas Huber881227d2016-08-02 14:20:21 -07001373 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001374 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001375 out << "break;\n";
1376 out.unindent();
1377 out << "}\n\n";
1378
Andreas Huber5e44a292016-09-27 14:52:39 -07001379 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001380
Yifan Hongbf459bc2016-08-23 16:50:37 -07001381 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001382 for (const auto &arg : method->args()) {
1383 emitCppReaderWriter(
1384 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001385 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001386 false /* parcelObjIsPointer */,
1387 arg,
1388 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001389 Type::ErrorMode_Break,
1390 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001391 }
1392
Yifan Hongbf459bc2016-08-23 16:50:37 -07001393 // Second DFS: resolve references
1394 for (const auto &arg : method->args()) {
1395 emitCppResolveReferences(
1396 out,
1397 "_hidl_data",
1398 false /* parcelObjIsPointer */,
1399 arg,
1400 true /* reader */,
1401 Type::ErrorMode_Break,
1402 false /* addPrefixToName */);
1403 }
1404
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001405 status_t status = generateCppInstrumentationCall(
1406 out,
1407 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001408 method);
1409 if (status != OK) {
1410 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001411 }
1412
Andreas Huber881227d2016-08-02 14:20:21 -07001413 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001414 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001415
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001416 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001417 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -08001418 << " _hidl_out_"
Yifan Hong3b320f82016-11-01 15:15:54 -07001419 << elidedReturn->name()
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001420 << " = "
1421 << "_hidl_mImpl->" << method->name()
Yifan Hong3b320f82016-11-01 15:15:54 -07001422 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001423
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001424 bool first = true;
1425 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001426 if (!first) {
1427 out << ", ";
1428 }
1429
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001430 if (arg->type().resultNeedsDeref()) {
1431 out << "*";
1432 }
1433
1434 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001435
1436 first = false;
1437 }
1438
Steven Moreland2ae5bca2016-12-01 05:56:49 +00001439 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001440 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1441 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001442
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001443 elidedReturn->type().emitReaderWriter(
1444 out,
Yifan Honga47eef32016-12-12 10:38:54 -08001445 "_hidl_out_" + elidedReturn->name(),
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001446 "_hidl_reply",
1447 true, /* parcelObjIsPointer */
1448 false, /* isReader */
1449 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001450
Yifan Hongbf459bc2016-08-23 16:50:37 -07001451 emitCppResolveReferences(
1452 out,
1453 "_hidl_reply",
1454 true /* parcelObjIsPointer */,
1455 elidedReturn,
1456 false /* reader */,
1457 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001458 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001459
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001460 status_t status = generateCppInstrumentationCall(
1461 out,
1462 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001463 method);
1464 if (status != OK) {
1465 return status;
1466 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001467
Iliyan Malchev549e2592016-08-10 08:59:12 -07001468 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001469 } else {
1470 if (returnsValue) {
1471 out << "bool _hidl_callbackCalled = false;\n\n";
1472 }
Andreas Huber881227d2016-08-02 14:20:21 -07001473
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001474 out << "_hidl_mImpl->" << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001475
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001476 bool first = true;
1477 for (const auto &arg : method->args()) {
1478 if (!first) {
1479 out << ", ";
1480 }
Andreas Huber881227d2016-08-02 14:20:21 -07001481
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001482 if (arg->type().resultNeedsDeref()) {
1483 out << "*";
1484 }
1485
1486 out << arg->name();
1487
1488 first = false;
1489 }
1490
1491 if (returnsValue) {
1492 if (!first) {
1493 out << ", ";
1494 }
1495
1496 out << "[&](";
1497
1498 first = true;
1499 for (const auto &arg : method->results()) {
1500 if (!first) {
1501 out << ", ";
1502 }
1503
Yifan Honga47eef32016-12-12 10:38:54 -08001504 out << "const auto &_hidl_out_" << arg->name();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001505
1506 first = false;
1507 }
1508
1509 out << ") {\n";
1510 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001511 out << "if (_hidl_callbackCalled) {\n";
1512 out.indent();
1513 out << "LOG_ALWAYS_FATAL(\""
1514 << method->name()
1515 << ": _hidl_cb called a second time, but must be called once.\");\n";
1516 out.unindent();
1517 out << "}\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001518 out << "_hidl_callbackCalled = true;\n\n";
1519
Yifan Hong859e53f2016-11-14 19:08:24 -08001520 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1521 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001522
Yifan Hongbf459bc2016-08-23 16:50:37 -07001523 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001524 for (const auto &arg : method->results()) {
1525 emitCppReaderWriter(
1526 out,
1527 "_hidl_reply",
1528 true /* parcelObjIsPointer */,
1529 arg,
1530 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001531 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001532 true /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001533 }
1534
Yifan Hongbf459bc2016-08-23 16:50:37 -07001535 // Second DFS: resolve references
1536 for (const auto &arg : method->results()) {
1537 emitCppResolveReferences(
1538 out,
1539 "_hidl_reply",
1540 true /* parcelObjIsPointer */,
1541 arg,
1542 false /* reader */,
1543 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001544 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001545 }
1546
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001547 status_t status = generateCppInstrumentationCall(
1548 out,
1549 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001550 method);
1551 if (status != OK) {
1552 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001553 }
1554
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001555 out << "_hidl_cb(*_hidl_reply);\n";
1556
1557 out.unindent();
1558 out << "}\n";
1559 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001560 out << ");\n\n";
1561
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001562 if (returnsValue) {
1563 out << "if (!_hidl_callbackCalled) {\n";
1564 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001565 out << "LOG_ALWAYS_FATAL(\""
1566 << method->name()
1567 << ": _hidl_cb not called, but must be called once.\");\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001568 out.unindent();
1569 out << "}\n\n";
Steven Moreland05cd4232016-11-21 16:01:12 -08001570 } else {
1571 out << "::android::hardware::writeToParcel("
1572 << "::android::hardware::Status::ok(), "
1573 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001574 }
Andreas Huber881227d2016-08-02 14:20:21 -07001575 }
1576
1577 out << "break;\n";
1578
1579 return OK;
1580}
1581
Steven Moreland69e7c702016-09-09 11:16:32 -07001582status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1583 std::string ifaceName;
1584 if (!AST::isInterface(&ifaceName)) {
1585 // types.hal does not get a stub header.
1586 return OK;
1587 }
1588
1589 const Interface *iface = mRootScope->getInterface();
1590
1591 const std::string baseName = iface->getBaseName();
1592 const std::string klassName = "Bs" + baseName;
1593
1594 bool supportOneway = iface->hasOnewayMethods();
1595
1596 std::string path = outputPath;
1597 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1598 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1599 path.append(klassName);
1600 path.append(".h");
1601
1602 CHECK(Coordinator::MakeParentHierarchy(path));
1603 FILE *file = fopen(path.c_str(), "w");
1604
1605 if (file == NULL) {
1606 return -errno;
1607 }
1608
1609 Formatter out(file);
1610
1611 const std::string guard = makeHeaderGuard(klassName);
1612
1613 out << "#ifndef " << guard << "\n";
1614 out << "#define " << guard << "\n\n";
1615
1616 std::vector<std::string> packageComponents;
1617 getPackageAndVersionComponents(
1618 &packageComponents, false /* cpp_compatible */);
1619
Yifan Hongb0949432016-12-15 15:32:24 -08001620 out << "#include <cutils/trace.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001621 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001622
1623 generateCppPackageInclude(out, mPackage, ifaceName);
1624 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001625
1626 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001627 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001628 }
1629
1630 enterLeaveNamespace(out, true /* enter */);
1631 out << "\n";
1632
1633 out << "struct "
1634 << klassName
1635 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001636 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001637
1638 out.indent();
1639 out << "explicit "
1640 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001641 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001642 << ifaceName
1643 << "> impl);\n";
1644
Yifan Hong068c5522016-10-31 14:07:25 -07001645 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1646 return generatePassthroughMethod(out, method);
1647 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001648
1649 if (err != OK) {
1650 return err;
1651 }
1652
1653 out.unindent();
1654 out << "private:\n";
1655 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001656 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001657
1658 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001659 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001660
1661 out << "\n";
1662
1663 out << "::android::hardware::Return<void> addOnewayTask("
1664 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001665 }
1666
1667 out.unindent();
1668
1669 out << "};\n\n";
1670
1671 enterLeaveNamespace(out, false /* enter */);
1672
1673 out << "\n#endif // " << guard << "\n";
1674
1675 return OK;
1676}
1677
Yifan Hongfe95aa22016-10-19 17:26:45 -07001678status_t AST::generateInterfaceSource(Formatter &out) const {
1679 const Interface *iface = mRootScope->getInterface();
1680
Yifan Hong2d7126b2016-10-20 15:12:57 -07001681 // generate castFrom functions
Yifan Hong3d746092016-12-07 14:26:33 -08001682 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001683
Yifan Hong3d746092016-12-07 14:26:33 -08001684 for (const Interface *superType : iface->typeChain()) {
1685 out << "// static \n"
1686 << childTypeResult
1687 << " I"
1688 << iface->getBaseName()
1689 << "::castFrom("
1690 << superType->getCppArgumentType()
1691 << " parent) {\n";
1692 out.indent();
1693 if (iface == superType) {
1694 out << "return parent;\n";
1695 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001696 out << "return ::android::hardware::castInterface<";
1697 out << "I" << iface->getBaseName() << ", "
1698 << superType->fqName().cppName() << ", "
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001699 << iface->getProxyName().cppLocalName() << ", "
1700 << superType->getProxyName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001701 << ">(\n";
1702 out.indent();
1703 out.indent();
1704 out << "parent, \""
1705 << iface->fqName().string()
1706 << "\");\n";
1707 out.unindent();
1708 out.unindent();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001709 }
Yifan Hong3d746092016-12-07 14:26:33 -08001710 out.unindent();
1711 out << "}\n\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001712 }
1713
1714 return OK;
1715}
1716
Steven Moreland69e7c702016-09-09 11:16:32 -07001717status_t AST::generatePassthroughSource(Formatter &out) const {
1718 const Interface *iface = mRootScope->getInterface();
1719
1720 const std::string baseName = iface->getBaseName();
1721 const std::string klassName = "Bs" + baseName;
1722
1723 out << klassName
1724 << "::"
1725 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001726 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001727 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001728 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001729 << iface->fqName().string()
1730 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001731 if (iface->hasOnewayMethods()) {
1732 out << "\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001733 out.indent([&] {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001734 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1735 });
1736 }
1737 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001738
1739 if (iface->hasOnewayMethods()) {
1740 out << "::android::hardware::Return<void> "
1741 << klassName
1742 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1743 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001744 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001745 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001746 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1747 out.indent();
1748 out.indent();
1749 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1750 out.unindent();
1751 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001752 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001753 out << "}\n";
1754
Steven Morelandd366c262016-10-11 15:29:10 -07001755 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001756
1757 out.unindent();
1758 out << "}\n\n";
1759
1760
1761 }
1762
1763 return OK;
1764}
1765
Martijn Coenen7b295242016-11-04 16:52:56 +01001766status_t AST::generateCppAtraceCall(Formatter &out,
1767 InstrumentationEvent event,
1768 const Method *method) const {
1769 const Interface *iface = mRootScope->getInterface();
1770 std::string baseString = "HIDL::I" + iface->getBaseName() + "::" + method->name();
1771 switch (event) {
1772 case SERVER_API_ENTRY:
1773 {
1774 out << "atrace_begin(ATRACE_TAG_HAL, \""
1775 << baseString + "::server\");\n";
1776 break;
1777 }
1778 case CLIENT_API_ENTRY:
1779 {
1780 out << "atrace_begin(ATRACE_TAG_HAL, \""
1781 << baseString + "::client\");\n";
1782 break;
1783 }
1784 case PASSTHROUGH_ENTRY:
1785 {
1786 out << "atrace_begin(ATRACE_TAG_HAL, \""
1787 << baseString + "::passthrough\");\n";
1788 break;
1789 }
1790 case SERVER_API_EXIT:
1791 case CLIENT_API_EXIT:
1792 case PASSTHROUGH_EXIT:
1793 {
1794 out << "atrace_end(ATRACE_TAG_HAL);\n";
1795 break;
1796 }
1797 default:
1798 {
1799 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1800 return UNKNOWN_ERROR;
1801 }
1802 }
1803
1804 return OK;
1805}
1806
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001807status_t AST::generateCppInstrumentationCall(
1808 Formatter &out,
1809 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001810 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001811 status_t err = generateCppAtraceCall(out, event, method);
1812 if (err != OK) {
1813 return err;
1814 }
1815
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001816 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1817 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001818 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001819 std::string event_str = "";
1820 switch (event) {
1821 case SERVER_API_ENTRY:
1822 {
1823 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1824 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001825 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001826 << (arg->type().resultNeedsDeref() ? "" : "&")
1827 << arg->name()
1828 << ");\n";
1829 }
1830 break;
1831 }
1832 case SERVER_API_EXIT:
1833 {
1834 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001835 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001836 out << "_hidl_args.push_back((void *)&_hidl_out_"
Steven Moreland031ccf12016-10-31 15:54:38 -07001837 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001838 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001839 }
1840 break;
1841 }
1842 case CLIENT_API_ENTRY:
1843 {
1844 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1845 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001846 out << "_hidl_args.push_back((void *)&"
1847 << arg->name()
1848 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001849 }
1850 break;
1851 }
1852 case CLIENT_API_EXIT:
1853 {
1854 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1855 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001856 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001857 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001858 << "_hidl_out_"
1859 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001860 << ");\n";
1861 }
1862 break;
1863 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001864 case PASSTHROUGH_ENTRY:
1865 {
1866 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1867 for (const auto &arg : method->args()) {
1868 out << "_hidl_args.push_back((void *)&"
1869 << arg->name()
1870 << ");\n";
1871 }
1872 break;
1873 }
1874 case PASSTHROUGH_EXIT:
1875 {
1876 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001877 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001878 out << "_hidl_args.push_back((void *)&_hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001879 << arg->name()
1880 << ");\n";
1881 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001882 break;
1883 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001884 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001885 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001886 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001887 return UNKNOWN_ERROR;
1888 }
1889 }
1890
Steven Moreland031ccf12016-10-31 15:54:38 -07001891 const Interface *iface = mRootScope->getInterface();
1892
Steven Moreland1ab31442016-11-03 18:37:51 -07001893 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001894 out.indent();
1895 out << "callback("
1896 << event_str
1897 << ", \""
1898 << mPackage.package()
1899 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001900 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001901 << "\", \""
1902 << iface->localName()
1903 << "\", \""
1904 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001905 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001906 out.unindent();
1907 out << "}\n";
1908 out.unindent();
1909 out << "}\n\n";
1910
1911 return OK;
1912}
1913
Andreas Huber881227d2016-08-02 14:20:21 -07001914} // namespace android
1915