blob: d81d241712c4bec1fd9a0beca04f1f11c84df5b6 [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 Hongeefe4f22017-01-04 15:32:42 -0800128static void declareServiceManagerInteractions(Formatter &out, const std::string &interfaceName) {
129 out << "static ::android::sp<" << interfaceName << "> getService("
Chris Phoenixdb0d6342017-01-11 16:10:00 -0800130 << "const std::string &serviceName=\"default\", bool getStub=false);\n";
131 out << "static ::android::sp<" << interfaceName << "> getService("
132 << "const char serviceName[], bool getStub=false)"
133 << " { std::string str(serviceName ? serviceName : \"\");"
134 << " return getService(str, getStub); }\n";
135 out << "static ::android::sp<" << interfaceName << "> getService("
136 << "const ::android::hardware::hidl_string& serviceName, bool getStub=false)"
137 // without c_str the std::string constructor is ambiguous
138 << " { std::string str(serviceName.c_str());"
139 << " return getService(str, getStub); }\n";
140 out << "static ::android::sp<" << interfaceName << "> getService("
141 << "bool getStub) { return getService(\"default\", getStub); }\n";
142 out << "::android::status_t registerAsService(const std::string &serviceName=\"default\");\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800143 out << "static bool registerForNotifications(\n";
144 out.indent(2, [&] {
145 out << "const std::string &serviceName,\n"
146 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
147 << "&notification);\n";
148 });
149
150}
151
152static void implementServiceManagerInteractions(Formatter &out,
Yifan Hongeefe4f22017-01-04 15:32:42 -0800153 const FQName &fqName, const std::string &package) {
154
155 const std::string interfaceName = fqName.getInterfaceName();
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800156
157 out << "// static\n"
Yifan Hongeefe4f22017-01-04 15:32:42 -0800158 << "::android::sp<" << interfaceName << "> " << interfaceName << "::getService("
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800159 << "const std::string &serviceName, bool getStub) ";
160 out.block([&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000161 out << "::android::sp<" << interfaceName << "> iface = nullptr;\n";
162 out << "::android::vintf::Transport transport = ::android::hardware::getTransportFromManifest(\""
163 << fqName.package() << "\");\n";
164
165 out.sIf("!getStub && "
166 "(transport == ::android::vintf::Transport::HWBINDER || "
167 // TODO(b/34625838): Don't load in passthrough mode
168 "transport == ::android::vintf::Transport::PASSTHROUGH || "
169 "transport == ::android::vintf::Transport::EMPTY)", [&] {
170 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800171 out.indent(2, [&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000172 out << "= ::android::hardware::defaultServiceManager();\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800173 });
Steven Morelandf10af872017-01-25 16:01:56 +0000174 out.sIf("sm != nullptr", [&] {
175 out << "::android::hardware::Return<::android::sp<" << gIBaseFqName.cppName() << ">> ret = \n";
176 out.indent(2, [&] {
177 out << "sm->get(" << interfaceName << "::descriptor" << ", serviceName);\n";
178 });
179 out.sIf("ret.isOk()", [&] {
180 out << "iface = " << interfaceName << "::castFrom(ret);\n";
181 out.sIf("iface != nullptr", [&] {
182 out << "return iface;\n";
183 }).endl();
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800184 }).endl();
185 }).endl();
186 }).endl();
Steven Moreland2c2dea82017-01-18 17:24:17 -0800187
Steven Morelandf10af872017-01-25 16:01:56 +0000188 out.sIf("getStub || "
189 "transport == ::android::vintf::Transport::PASSTHROUGH || "
190 "transport == ::android::vintf::Transport::EMPTY", [&] {
191 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> pm\n";
Steven Morelande3fa5da2017-01-25 07:07:53 +0000192 out.indent(2, [&] {
Steven Morelandf10af872017-01-25 16:01:56 +0000193 out << "= ::android::hardware::getPassthroughServiceManager();\n";
Steven Morelande3fa5da2017-01-25 07:07:53 +0000194 });
Steven Morelandf10af872017-01-25 16:01:56 +0000195
196 out.sIf("pm != nullptr", [&] () {
197 out << "::android::hardware::Return<::android::sp<" << gIBaseFqName.cppName() << ">> ret = \n";
198 out.indent(2, [&] {
199 out << "pm->get(" << interfaceName << "::descriptor" << ", serviceName);\n";
Steven Moreland2c2dea82017-01-18 17:24:17 -0800200 });
Steven Morelandf10af872017-01-25 16:01:56 +0000201 out.sIf("ret.isOk()", [&] {
202 out << "::android::sp<" << gIBaseFqName.cppName()
203 << "> baseInterface = ret;\n";
204 out.sIf("baseInterface != nullptr", [&]() {
205 out << "iface = new " << fqName.getInterfacePassthroughName()
206 << "(" << interfaceName << "::castFrom(baseInterface));\n";
207 });
208 }).endl();
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800209 }).endl();
210 }).endl();
Steven Moreland2c2dea82017-01-18 17:24:17 -0800211
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800212 out << "return iface;\n";
213 }).endl().endl();
214
Yifan Hongeefe4f22017-01-04 15:32:42 -0800215 out << "::android::status_t " << interfaceName << "::registerAsService("
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800216 << "const std::string &serviceName) ";
217 out.block([&] {
218 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
219 out.indent(2, [&] {
220 out << "= ::android::hardware::defaultServiceManager();\n";
221 });
222 out.sIf("sm == nullptr", [&] {
223 out << "return ::android::INVALID_OPERATION;\n";
224 }).endl();
225 out << "bool success = false;\n"
226 << "::android::hardware::Return<void> ret =\n";
227 out.indent(2, [&] {
228 out << "this->interfaceChain("
229 << "[&success, &sm, &serviceName, this](const auto &chain) ";
230 out.block([&] {
231 out << "::android::hardware::Return<bool> addRet = "
232 << "sm->add(chain, serviceName.c_str(), this);\n";
233 out << "success = addRet.isOk() && addRet;\n";
234 });
235 out << ");\n";
Steven Morelandcd00b9b2016-12-29 10:34:03 -0800236 out << "success = success && ret.isOk();\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800237 });
238 out << "return success ? ::android::OK : ::android::UNKNOWN_ERROR;\n";
239 }).endl().endl();
240
Yifan Hongeefe4f22017-01-04 15:32:42 -0800241 out << "bool " << interfaceName << "::registerForNotifications(\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800242 out.indent(2, [&] {
243 out << "const std::string &serviceName,\n"
244 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
245 << "&notification) ";
246 });
247 out.block([&] {
248 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
249 out.indent(2, [&] {
250 out << "= ::android::hardware::defaultServiceManager();\n";
251 });
252 out.sIf("sm == nullptr", [&] {
253 out << "return false;\n";
254 }).endl();
255 out << "::android::hardware::Return<bool> success =\n";
256 out.indent(2, [&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800257 out << "sm->registerForNotifications(\"" << package << "::" << interfaceName << "\",\n";
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800258 out.indent(2, [&] {
259 out << "serviceName, notification);\n";
260 });
261 });
262 out << "return success.isOk() && success;\n";
263 }).endl().endl();
264}
265
Andreas Huberb82318c2016-08-02 14:45:54 -0700266status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700267
Andreas Huberb82318c2016-08-02 14:45:54 -0700268 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700269 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700270 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700271
272 std::string ifaceName;
273 bool isInterface = true;
274 if (!AST::isInterface(&ifaceName)) {
275 ifaceName = "types";
276 isInterface = false;
277 }
278 path.append(ifaceName);
279 path.append(".h");
280
Andreas Huberd2943e12016-08-05 11:59:31 -0700281 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700282 FILE *file = fopen(path.c_str(), "w");
283
284 if (file == NULL) {
285 return -errno;
286 }
287
288 Formatter out(file);
289
290 const std::string guard = makeHeaderGuard(ifaceName);
291
292 out << "#ifndef " << guard << "\n";
293 out << "#define " << guard << "\n\n";
294
Andreas Huber737080b2016-08-02 15:38:04 -0700295 for (const auto &item : mImportedNames) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700296 generateCppPackageInclude(out, item, item.name());
Andreas Huber737080b2016-08-02 15:38:04 -0700297 }
298
299 if (!mImportedNames.empty()) {
300 out << "\n";
301 }
302
Steven Moreland0693f312016-11-09 15:06:14 -0800303 if (isInterface) {
Yifan Hongc8934042016-11-17 17:10:52 -0800304 if (isIBase()) {
305 out << "// skipped #include IServiceNotification.h\n\n";
306 } else {
307 out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
308 }
Steven Moreland0693f312016-11-09 15:06:14 -0800309 }
310
Yifan Hongc8934042016-11-17 17:10:52 -0800311 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700312 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700313
314 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200315 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700316 }
317
Martijn Coenenaf712c02016-11-16 15:26:27 +0100318 out << "#include <utils/NativeHandle.h>\n";
319 out << "#include <utils/misc.h>\n\n"; /* for report_sysprop_change() */
Andreas Huber881227d2016-08-02 14:20:21 -0700320
321 enterLeaveNamespace(out, true /* enter */);
322 out << "\n";
323
324 if (isInterface) {
325 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700326 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700327
328 const Interface *iface = mRootScope->getInterface();
329 const Interface *superType = iface->superType();
330
Steven Moreland40786312016-08-16 10:29:40 -0700331 if (superType == NULL) {
Yifan Hongc8934042016-11-17 17:10:52 -0800332 out << " : virtual public ::android::RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700333 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000334 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700335 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700336 }
337
338 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700339
340 out.indent();
341
Andreas Huber881227d2016-08-02 14:20:21 -0700342 }
343
344 status_t err = emitTypeDeclarations(out);
345
346 if (err != OK) {
347 return err;
348 }
349
350 if (isInterface) {
351 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700352 const Interface *superType = iface->superType();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800353
Yifan Hongc8934042016-11-17 17:10:52 -0800354 out << "virtual bool isRemote() const ";
355 if (!isIBase()) {
356 out << "override ";
357 }
358 out << "{ return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800359
Andreas Huber881227d2016-08-02 14:20:21 -0700360 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700361 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700362
Andreas Huber881227d2016-08-02 14:20:21 -0700363 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800364 const TypedVar *elidedReturn = method->canElideCallback();
365
366 if (elidedReturn == nullptr && returnsValue) {
367 out << "using "
368 << method->name()
369 << "_cb = std::function<void("
370 << Method::GetArgSignature(method->results(),
371 true /* specify namespaces */)
372 << ")>;\n";
373 }
Andreas Huber881227d2016-08-02 14:20:21 -0700374
Andreas Huber3599d922016-08-09 10:42:57 -0700375 method->dumpAnnotations(out);
376
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700377 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700378 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700379 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700380 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700381 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700382 }
383
384 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700385 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700386 << Method::GetArgSignature(method->args(),
387 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700388
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700389 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700390 if (!method->args().empty()) {
391 out << ", ";
392 }
393
Steven Moreland67f67b42016-09-29 08:59:02 -0700394 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700395 }
396
Yifan Hong10fe0b52016-10-19 14:20:17 -0700397 out << ")";
398 if (method->isHidlReserved()) {
Yifan Hongc8934042016-11-17 17:10:52 -0800399 if (!isIBase()) {
400 out << " override";
401 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700402 out << " {\n";
403 out.indent();
Martijn Coenen115d4282016-12-19 05:14:04 +0100404 method->cppImpl(IMPL_HEADER, out);
Yifan Hong10fe0b52016-10-19 14:20:17 -0700405 out.unindent();
406 out << "\n}\n";
407 } else {
408 out << " = 0;\n";
409 }
Andreas Huber881227d2016-08-02 14:20:21 -0700410 }
Steven Moreland40786312016-08-16 10:29:40 -0700411
Yifan Hong3d746092016-12-07 14:26:33 -0800412 out << "// cast static functions\n";
413 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700414
Yifan Hong3d746092016-12-07 14:26:33 -0800415 for (const Interface *superType : iface->typeChain()) {
416 out << "static "
417 << childTypeResult
418 << " castFrom("
419 << superType->getCppArgumentType()
420 << " parent"
421 << ");\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -0700422 }
423
Steven Morelandd39133b2016-11-11 12:30:08 -0800424 out << "\nstatic const char* descriptor;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700425
Yifan Hongc8934042016-11-17 17:10:52 -0800426 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800427 out << "// skipped getService, registerAsService, registerForNotifications\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800428 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800429 declareServiceManagerInteractions(out, iface->localName());
Yifan Hongc8934042016-11-17 17:10:52 -0800430 }
Yifan Hong158655a2016-11-08 12:34:07 -0800431
432 out << "private: static int hidlStaticBlock;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700433 }
434
435 if (isInterface) {
436 out.unindent();
437
Andreas Hubere3f769a2016-10-10 10:54:44 -0700438 out << "};\n\n";
439 }
440
441 err = mRootScope->emitGlobalTypeDeclarations(out);
442
443 if (err != OK) {
444 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700445 }
446
447 out << "\n";
448 enterLeaveNamespace(out, false /* enter */);
449
450 out << "\n#endif // " << guard << "\n";
451
452 return OK;
453}
454
Steven Moreland40786312016-08-16 10:29:40 -0700455status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
456 std::string ifaceName;
Yifan Hong244e82d2016-11-11 11:13:57 -0800457 bool isInterface = AST::isInterface(&ifaceName);
458 const Interface *iface = nullptr;
Yifan Hong244e82d2016-11-11 11:13:57 -0800459 std::string klassName{};
460
461 if(isInterface) {
462 iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800463 klassName = iface->getHwName();
Yifan Hong244e82d2016-11-11 11:13:57 -0800464 } else {
465 klassName = "hwtypes";
Steven Moreland40786312016-08-16 10:29:40 -0700466 }
467
Steven Moreland40786312016-08-16 10:29:40 -0700468 std::string path = outputPath;
469 path.append(mCoordinator->convertPackageRootToPath(mPackage));
470 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
471 path.append(klassName + ".h");
472
Yifan Hong244e82d2016-11-11 11:13:57 -0800473 FILE *file = fopen(path.c_str(), "w");
Steven Moreland40786312016-08-16 10:29:40 -0700474
475 if (file == NULL) {
476 return -errno;
477 }
478
479 Formatter out(file);
480
481 const std::string guard = makeHeaderGuard(klassName);
482
483 out << "#ifndef " << guard << "\n";
484 out << "#define " << guard << "\n\n";
485
Yifan Hong244e82d2016-11-11 11:13:57 -0800486 if (isInterface) {
487 generateCppPackageInclude(out, mPackage, ifaceName);
488 } else {
489 generateCppPackageInclude(out, mPackage, "types");
490 }
Steven Moreland40786312016-08-16 10:29:40 -0700491
Steven Morelandee88eed2016-10-31 17:49:00 -0700492 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700493
494 for (const auto &item : mImportedNames) {
495 if (item.name() == "types") {
Yifan Hong244e82d2016-11-11 11:13:57 -0800496 generateCppPackageInclude(out, item, "hwtypes");
497 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800498 generateCppPackageInclude(out, item, item.getInterfaceStubName());
499 generateCppPackageInclude(out, item, item.getInterfaceProxyName());
Steven Moreland40786312016-08-16 10:29:40 -0700500 }
Steven Moreland40786312016-08-16 10:29:40 -0700501 }
502
503 out << "\n";
504
Martijn Coenen93915102016-09-01 01:35:52 +0200505 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700506 out << "#include <hwbinder/IBinder.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100507 out << "#include <hwbinder/Parcel.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700508
509 out << "\n";
510
511 enterLeaveNamespace(out, true /* enter */);
Steven Moreland40786312016-08-16 10:29:40 -0700512
Yifan Hong244e82d2016-11-11 11:13:57 -0800513 status_t err = mRootScope->emitGlobalHwDeclarations(out);
514 if (err != OK) {
515 return err;
516 }
Steven Moreland40786312016-08-16 10:29:40 -0700517
518 enterLeaveNamespace(out, false /* enter */);
519
520 out << "\n#endif // " << guard << "\n";
521
522 return OK;
523}
524
Andreas Huber881227d2016-08-02 14:20:21 -0700525status_t AST::emitTypeDeclarations(Formatter &out) const {
526 return mRootScope->emitTypeDeclarations(out);
527}
528
Yifan Hong7a118f52016-12-07 11:21:15 -0800529static void wrapPassthroughArg(Formatter &out,
530 const TypedVar *arg, bool addPrefixToName,
531 std::function<void(void)> handleError) {
532 if (!arg->type().isInterface()) {
533 return;
534 }
535 std::string name = (addPrefixToName ? "_hidl_out_" : "") + arg->name();
536 std::string wrappedName = (addPrefixToName ? "_hidl_out_wrapped_" : "_hidl_wrapped_")
537 + arg->name();
538 const Interface &iface = static_cast<const Interface &>(arg->type());
539 out << iface.getCppStackType() << " " << wrappedName << ";\n";
540 // TODO(elsk): b/33754152 Should not wrap this if object is Bs*
541 out.sIf(name + " != nullptr && !" + name + "->isRemote()", [&] {
542 out << wrappedName
543 << " = "
544 << iface.fqName().cppName()
545 << "::castFrom(::android::hardware::wrapPassthrough("
546 << name << "));\n";
547 out.sIf(wrappedName + " == nullptr", [&] {
548 // Fatal error. Happens when the BsFoo class is not found in the binary
549 // or any dynamic libraries.
550 handleError();
551 }).endl();
552 }).sElse([&] {
553 out << wrappedName << " = " << name << ";\n";
554 }).endl().endl();
555}
556
Steven Moreland69e7c702016-09-09 11:16:32 -0700557status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700558 const Method *method) const {
559 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700560
561 out << " {\n";
562 out.indent();
563
Zhuoyao Zhangdd85c5c2017-01-03 17:30:24 -0800564 if (method->isHidlReserved()
565 && method->overridesCppImpl(IMPL_PASSTHROUGH)) {
566 method->cppImpl(IMPL_PASSTHROUGH, out);
567 out.unindent();
568 out << "}\n\n";
569 return OK;
570 }
571
Steven Moreland69e7c702016-09-09 11:16:32 -0700572 const bool returnsValue = !method->results().empty();
573 const TypedVar *elidedReturn = method->canElideCallback();
574
Steven Moreland67f67b42016-09-29 08:59:02 -0700575 if (returnsValue && elidedReturn == nullptr) {
576 generateCheckNonNull(out, "_hidl_cb");
577 }
578
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700579 generateCppInstrumentationCall(
580 out,
581 InstrumentationEvent::PASSTHROUGH_ENTRY,
582 method);
583
Yifan Hong7a118f52016-12-07 11:21:15 -0800584
585 for (const auto &arg : method->args()) {
586 wrapPassthroughArg(out, arg, false /* addPrefixToName */, [&] {
587 out << "return ::android::hardware::Status::fromExceptionCode(\n";
588 out.indent(2, [&] {
589 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
Yifan Hong0abd7392016-12-20 16:43:26 -0800590 << "\"Cannot wrap passthrough interface.\");\n";
Yifan Hong7a118f52016-12-07 11:21:15 -0800591 });
592 });
593 }
594
595 out << "auto _hidl_error = ::android::hardware::Void();\n";
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700596 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700597
598 if (method->isOneway()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800599 out << "addOnewayTask([this, &_hidl_error";
Steven Moreland69e7c702016-09-09 11:16:32 -0700600 for (const auto &arg : method->args()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800601 out << ", "
602 << (arg->type().isInterface() ? "_hidl_wrapped_" : "")
603 << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700604 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700605 out << "] {\n";
606 out.indent();
607 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700608 }
609
610 out << "mImpl->"
611 << method->name()
612 << "(";
613
614 bool first = true;
615 for (const auto &arg : method->args()) {
616 if (!first) {
617 out << ", ";
618 }
619 first = false;
Yifan Hong7a118f52016-12-07 11:21:15 -0800620 out << (arg->type().isInterface() ? "_hidl_wrapped_" : "") << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700621 }
622 if (returnsValue && elidedReturn == nullptr) {
623 if (!method->args().empty()) {
624 out << ", ";
625 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800626 out << "[&](";
627 first = true;
628 for (const auto &arg : method->results()) {
629 if (!first) {
630 out << ", ";
631 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700632
Yifan Hong7a118f52016-12-07 11:21:15 -0800633 out << "const auto &_hidl_out_"
634 << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800635
636 first = false;
637 }
638
639 out << ") {\n";
640 out.indent();
641 status_t status = generateCppInstrumentationCall(
642 out,
643 InstrumentationEvent::PASSTHROUGH_EXIT,
644 method);
645 if (status != OK) {
646 return status;
647 }
648
Yifan Hong7a118f52016-12-07 11:21:15 -0800649 for (const auto &arg : method->results()) {
650 wrapPassthroughArg(out, arg, true /* addPrefixToName */, [&] {
651 out << "_hidl_error = ::android::hardware::Status::fromExceptionCode(\n";
652 out.indent(2, [&] {
653 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
Yifan Hong0abd7392016-12-20 16:43:26 -0800654 << "\"Cannot wrap passthrough interface.\");\n";
Yifan Hong7a118f52016-12-07 11:21:15 -0800655 });
656 out << "return;\n";
657 });
658 }
659
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800660 out << "_hidl_cb(";
661 first = true;
662 for (const auto &arg : method->results()) {
663 if (!first) {
664 out << ", ";
665 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800666 first = false;
Yifan Hong7a118f52016-12-07 11:21:15 -0800667 out << (arg->type().isInterface() ? "_hidl_out_wrapped_" : "_hidl_out_")
668 << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800669 }
670 out << ");\n";
671 out.unindent();
672 out << "});\n\n";
673 } else {
674 out << ");\n\n";
675 if (elidedReturn != nullptr) {
676 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -0800677 << " _hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800678 << elidedReturn->name()
Steven Moreland2ae5bca2016-12-01 05:56:49 +0000679 << " = _hidl_return;\n";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800680 }
681 status_t status = generateCppInstrumentationCall(
682 out,
683 InstrumentationEvent::PASSTHROUGH_EXIT,
684 method);
685 if (status != OK) {
686 return status;
687 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700688 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700689
690 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700691 out.unindent();
692 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700693 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700694
695 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700696
697 out.unindent();
698 out << "}\n";
699
700 return OK;
701}
702
Yifan Hong068c5522016-10-31 14:07:25 -0700703status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700704
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700705 const Interface *iface = mRootScope->getInterface();
706
Yifan Hong10fe0b52016-10-19 14:20:17 -0700707 const Interface *prevIterface = nullptr;
708 for (const auto &tuple : iface->allMethodsFromRoot()) {
709 const Method *method = tuple.method();
710 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700711
Yifan Hong10fe0b52016-10-19 14:20:17 -0700712 if(prevIterface != superInterface) {
713 if (prevIterface != nullptr) {
714 out << "\n";
715 }
716 out << "// Methods from "
717 << superInterface->fullName()
718 << " follow.\n";
719 prevIterface = superInterface;
720 }
Yifan Hong068c5522016-10-31 14:07:25 -0700721 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700722
Yifan Hong10fe0b52016-10-19 14:20:17 -0700723 if (err != OK) {
724 return err;
725 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700726 }
727
Yifan Hong10fe0b52016-10-19 14:20:17 -0700728 out << "\n";
729
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700730 return OK;
731}
732
Andreas Huberb82318c2016-08-02 14:45:54 -0700733status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700734 std::string ifaceName;
735 if (!AST::isInterface(&ifaceName)) {
736 // types.hal does not get a stub header.
737 return OK;
738 }
739
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700740 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800741 const std::string klassName = iface->getStubName();
Andreas Huber881227d2016-08-02 14:20:21 -0700742
Andreas Huberb82318c2016-08-02 14:45:54 -0700743 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700744 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700745 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700746 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700747 path.append(".h");
748
Andreas Huberd2943e12016-08-05 11:59:31 -0700749 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700750 FILE *file = fopen(path.c_str(), "w");
751
752 if (file == NULL) {
753 return -errno;
754 }
755
756 Formatter out(file);
757
Steven Moreland40786312016-08-16 10:29:40 -0700758 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700759
760 out << "#ifndef " << guard << "\n";
761 out << "#define " << guard << "\n\n";
762
Yifan Hongeefe4f22017-01-04 15:32:42 -0800763 generateCppPackageInclude(out, mPackage, iface->getHwName());
Steven Morelandee88eed2016-10-31 17:49:00 -0700764 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700765
766 enterLeaveNamespace(out, true /* enter */);
767 out << "\n";
768
769 out << "struct "
Yifan Hongeefe4f22017-01-04 15:32:42 -0800770 << klassName;
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100771 if (iface->isIBase()) {
Yifan Hong96a79e22017-01-12 14:22:05 -0800772 out << " : public ::android::hardware::BHwBinder";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100773 out << ", public ::android::hardware::HidlInstrumentor {\n";
774 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800775 out << " : public "
776 << gIBaseFqName.getInterfaceStubFqName().cppName()
777 << " {\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100778 }
Andreas Huber881227d2016-08-02 14:20:21 -0700779
780 out.indent();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800781 out << "explicit "
782 << klassName
Steven Moreland40786312016-08-16 10:29:40 -0700783 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100784 << "\n";
Yifan Hongeefe4f22017-01-04 15:32:42 -0800785 out << "explicit "
786 << klassName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100787 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl,"
788 << " const std::string& prefix);"
Steven Moreland40786312016-08-16 10:29:40 -0700789 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700790 out << "::android::status_t onTransact(\n";
791 out.indent();
792 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700793 out << "uint32_t _hidl_code,\n";
794 out << "const ::android::hardware::Parcel &_hidl_data,\n";
795 out << "::android::hardware::Parcel *_hidl_reply,\n";
796 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700797 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700798 out.unindent();
799 out.unindent();
800
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100801 out << "::android::sp<" << ifaceName << "> getImpl() { return _hidl_mImpl; };\n";
802 out.unindent();
803 out << "private:\n";
804 out.indent();
805 out << "::android::sp<" << ifaceName << "> _hidl_mImpl;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700806 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700807 out << "};\n\n";
808
809 enterLeaveNamespace(out, false /* enter */);
810
811 out << "\n#endif // " << guard << "\n";
812
813 return OK;
814}
815
Andreas Huberb82318c2016-08-02 14:45:54 -0700816status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700817 std::string ifaceName;
818 if (!AST::isInterface(&ifaceName)) {
819 // types.hal does not get a proxy header.
820 return OK;
821 }
822
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700823 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -0800824 const std::string proxyName = iface->getProxyName();
Andreas Huber881227d2016-08-02 14:20:21 -0700825
Andreas Huberb82318c2016-08-02 14:45:54 -0700826 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700827 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700828 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Yifan Hongeefe4f22017-01-04 15:32:42 -0800829 path.append(proxyName);
Andreas Huber881227d2016-08-02 14:20:21 -0700830 path.append(".h");
831
Andreas Huberd2943e12016-08-05 11:59:31 -0700832 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700833 FILE *file = fopen(path.c_str(), "w");
834
835 if (file == NULL) {
836 return -errno;
837 }
838
839 Formatter out(file);
840
Yifan Hongeefe4f22017-01-04 15:32:42 -0800841 const std::string guard = makeHeaderGuard(proxyName);
Andreas Huber881227d2016-08-02 14:20:21 -0700842
843 out << "#ifndef " << guard << "\n";
844 out << "#define " << guard << "\n\n";
845
Martijn Coenen115d4282016-12-19 05:14:04 +0100846 out << "#include <hidl/HidlTransportSupport.h>\n\n";
847
Andreas Huber881227d2016-08-02 14:20:21 -0700848 std::vector<std::string> packageComponents;
849 getPackageAndVersionComponents(
850 &packageComponents, false /* cpp_compatible */);
851
Yifan Hongeefe4f22017-01-04 15:32:42 -0800852 generateCppPackageInclude(out, mPackage, iface->getHwName());
Steven Morelandee88eed2016-10-31 17:49:00 -0700853 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700854
855 enterLeaveNamespace(out, true /* enter */);
856 out << "\n";
857
858 out << "struct "
Yifan Hongeefe4f22017-01-04 15:32:42 -0800859 << proxyName
860 << " : public ::android::hardware::BpInterface<"
861 << iface->localName()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700862 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700863
864 out.indent();
865
Yifan Hongeefe4f22017-01-04 15:32:42 -0800866 out << "explicit "
867 << proxyName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700868 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700869 << "\n\n";
870
Yifan Hong10fe0b52016-10-19 14:20:17 -0700871 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700872
Yifan Hong068c5522016-10-31 14:07:25 -0700873 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
874 method->generateCppSignature(out);
875 out << " override;\n";
876 return OK;
877 });
Steven Moreland9c387612016-09-07 09:54:26 -0700878
879 if (err != OK) {
880 return err;
881 }
Andreas Huber881227d2016-08-02 14:20:21 -0700882
883 out.unindent();
Martijn Coenen115d4282016-12-19 05:14:04 +0100884 out << "private:\n";
885 out.indent();
886 out << "std::mutex _hidl_mMutex;\n"
887 << "std::vector<::android::sp<::android::hardware::hidl_binder_death_recipient>>"
888 << " _hidl_mDeathRecipients;\n";
889 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700890 out << "};\n\n";
891
892 enterLeaveNamespace(out, false /* enter */);
893
894 out << "\n#endif // " << guard << "\n";
895
896 return OK;
897}
898
Andreas Huberb82318c2016-08-02 14:45:54 -0700899status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700900
Andreas Huberb82318c2016-08-02 14:45:54 -0700901 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700902 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700903 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700904
905 std::string ifaceName;
906 std::string baseName;
907
Yifan Hongfe95aa22016-10-19 17:26:45 -0700908 const Interface *iface = nullptr;
909 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700910 if (!AST::isInterface(&ifaceName)) {
911 baseName = "types";
912 isInterface = false;
913 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700914 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700915 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700916 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700917 }
918
919 path.append(baseName);
920
921 if (baseName != "types") {
922 path.append("All");
923 }
924
925 path.append(".cpp");
926
Andreas Huberd2943e12016-08-05 11:59:31 -0700927 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700928 FILE *file = fopen(path.c_str(), "w");
929
930 if (file == NULL) {
931 return -errno;
932 }
933
934 Formatter out(file);
935
Steven Moreland623c0042017-01-13 14:42:29 -0800936 out << "#define LOG_TAG \""
937 << mPackage.string() << "::" << baseName
938 << "\"\n\n";
939
Steven Moreland05cd4232016-11-21 16:01:12 -0800940 out << "#include <android/log.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100941 out << "#include <cutils/trace.h>\n";
942 out << "#include <hidl/HidlTransportSupport.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700943 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700944 // This is a no-op for IServiceManager itself.
945 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
946
Yifan Hongeefe4f22017-01-04 15:32:42 -0800947 generateCppPackageInclude(out, mPackage, iface->getProxyName());
948 generateCppPackageInclude(out, mPackage, iface->getStubName());
949 generateCppPackageInclude(out, mPackage, iface->getPassthroughName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700950
951 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700952 generateCppPackageInclude(out,
953 superType->fqName(),
Yifan Hongeefe4f22017-01-04 15:32:42 -0800954 superType->fqName().getInterfaceProxyName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700955 }
Yifan Hong2cbbdf92016-12-05 15:20:50 -0800956
957 out << "#include <hidl/ServiceManagement.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700958 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700959 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800960 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700961 }
962
963 out << "\n";
964
965 enterLeaveNamespace(out, true /* enter */);
966 out << "\n";
967
968 status_t err = generateTypeSource(out, ifaceName);
969
970 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700971 const Interface *iface = mRootScope->getInterface();
Yifan Hong10fe0b52016-10-19 14:20:17 -0700972
973 // need to be put here, generateStubSource is using this.
Yifan Hongeefe4f22017-01-04 15:32:42 -0800974 out << "const char* "
975 << iface->localName()
Yifan Hong10fe0b52016-10-19 14:20:17 -0700976 << "::descriptor(\""
977 << iface->fqName().string()
978 << "\");\n\n";
979
Yifan Hongeefe4f22017-01-04 15:32:42 -0800980 out << "int "
981 << iface->localName()
Yifan Hong158655a2016-11-08 12:34:07 -0800982 << "::hidlStaticBlock = []() -> int {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800983 out.indent([&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800984 out << "::android::hardware::gBnConstructorMap["
985 << iface->localName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800986 << "::descriptor]\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800987 out.indent(2, [&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800988 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800989 out.indent([&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800990 out << "return new "
991 << iface->getStubName()
992 << "(reinterpret_cast<"
993 << iface->localName()
Yifan Hong158655a2016-11-08 12:34:07 -0800994 << " *>(iIntf));\n";
995 });
996 out << "};\n";
997 });
Yifan Hongeefe4f22017-01-04 15:32:42 -0800998 out << "::android::hardware::gBsConstructorMap["
999 << iface->localName()
Yifan Hong7a118f52016-12-07 11:21:15 -08001000 << "::descriptor]\n";
1001 out.indent(2, [&] {
1002 out << "= [](void *iIntf) -> ::android::sp<"
1003 << gIBaseFqName.cppName()
1004 << "> {\n";
1005 out.indent([&] {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001006 out << "return new "
1007 << iface->getPassthroughName()
1008 << "(reinterpret_cast<"
1009 << iface->localName()
Yifan Hong7a118f52016-12-07 11:21:15 -08001010 << " *>(iIntf));\n";
1011 });
1012 out << "};\n";
1013 });
Yifan Hong158655a2016-11-08 12:34:07 -08001014 out << "return 1;\n";
1015 });
1016 out << "}();\n\n";
1017
Yifan Hongfe95aa22016-10-19 17:26:45 -07001018 err = generateInterfaceSource(out);
1019 }
1020
1021 if (err == OK && isInterface) {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001022 err = generateProxySource(out, iface->fqName());
Andreas Huber881227d2016-08-02 14:20:21 -07001023 }
1024
1025 if (err == OK && isInterface) {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001026 err = generateStubSource(out, iface);
Andreas Huber881227d2016-08-02 14:20:21 -07001027 }
1028
Steven Moreland40786312016-08-16 10:29:40 -07001029 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -07001030 err = generatePassthroughSource(out);
1031 }
1032
1033 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -07001034 const Interface *iface = mRootScope->getInterface();
1035
Yifan Hongc8934042016-11-17 17:10:52 -08001036 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001037 out << "// skipped getService, registerAsService, registerForNotifications\n";
Yifan Hongc8934042016-11-17 17:10:52 -08001038 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001039 std::string package = iface->fqName().package()
1040 + iface->fqName().atVersion();
1041
Yifan Hongeefe4f22017-01-04 15:32:42 -08001042 implementServiceManagerInteractions(out, iface->fqName(), package);
Yifan Hongc8934042016-11-17 17:10:52 -08001043 }
Steven Moreland40786312016-08-16 10:29:40 -07001044 }
1045
Andreas Huber881227d2016-08-02 14:20:21 -07001046 enterLeaveNamespace(out, false /* enter */);
1047
1048 return err;
1049}
1050
Steven Moreland67f67b42016-09-29 08:59:02 -07001051// static
1052void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
Yifan Honga018ed52016-12-13 16:35:08 -08001053 out.sIf(nonNull + " == nullptr", [&] {
1054 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1055 out.indent(2, [&] {
1056 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
1057 });
1058 }).endl().endl();
Steven Moreland67f67b42016-09-29 08:59:02 -07001059}
1060
Andreas Huber881227d2016-08-02 14:20:21 -07001061status_t AST::generateTypeSource(
1062 Formatter &out, const std::string &ifaceName) const {
1063 return mRootScope->emitTypeDefinitions(out, ifaceName);
1064}
1065
Andreas Hubere7ff2282016-08-16 13:50:03 -07001066void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -07001067 Formatter &out,
1068 const std::vector<TypedVar *> &args,
1069 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -07001070 if (args.empty()) {
1071 return;
1072 }
1073
1074 for (const auto &arg : args) {
1075 const Type &type = arg->type();
1076
Yifan Hong3b320f82016-11-01 15:15:54 -07001077 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001078 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -07001079 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001080 << ";\n";
1081 }
1082
1083 out << "\n";
1084}
1085
Andreas Huber881227d2016-08-02 14:20:21 -07001086void AST::emitCppReaderWriter(
1087 Formatter &out,
1088 const std::string &parcelObj,
1089 bool parcelObjIsPointer,
1090 const TypedVar *arg,
1091 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -07001092 Type::ErrorMode mode,
1093 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001094 const Type &type = arg->type();
1095
Andreas Huber881227d2016-08-02 14:20:21 -07001096 type.emitReaderWriter(
1097 out,
Andreas Huber5e44a292016-09-27 14:52:39 -07001098 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -07001099 parcelObj,
1100 parcelObjIsPointer,
1101 isReader,
1102 mode);
1103}
1104
Yifan Hongbf459bc2016-08-23 16:50:37 -07001105void AST::emitCppResolveReferences(
1106 Formatter &out,
1107 const std::string &parcelObj,
1108 bool parcelObjIsPointer,
1109 const TypedVar *arg,
1110 bool isReader,
1111 Type::ErrorMode mode,
1112 bool addPrefixToName) const {
1113 const Type &type = arg->type();
1114 if(type.needsResolveReferences()) {
1115 type.emitResolveReferences(
1116 out,
1117 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
1118 isReader, // nameIsPointer
1119 parcelObj,
1120 parcelObjIsPointer,
1121 isReader,
1122 mode);
1123 }
1124}
1125
Yifan Hong068c5522016-10-31 14:07:25 -07001126status_t AST::generateProxyMethodSource(Formatter &out,
1127 const std::string &klassName,
1128 const Method *method,
1129 const Interface *superInterface) const {
1130
1131 method->generateCppSignature(out,
1132 klassName,
1133 true /* specify namespaces */);
1134
1135 const bool returnsValue = !method->results().empty();
1136 const TypedVar *elidedReturn = method->canElideCallback();
1137
Steven Moreland41c6d2e2016-11-07 12:26:54 -08001138 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001139
1140 out.indent();
1141
Martijn Coenen115d4282016-12-19 05:14:04 +01001142 if (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
1143 method->cppImpl(IMPL_PROXY, out);
1144 out.unindent();
1145 out << "}\n\n";
1146 return OK;
1147 }
1148
Yifan Hong068c5522016-10-31 14:07:25 -07001149 if (returnsValue && elidedReturn == nullptr) {
1150 generateCheckNonNull(out, "_hidl_cb");
1151 }
1152
1153 status_t status = generateCppInstrumentationCall(
1154 out,
1155 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -07001156 method);
1157 if (status != OK) {
1158 return status;
1159 }
1160
1161 out << "::android::hardware::Parcel _hidl_data;\n";
1162 out << "::android::hardware::Parcel _hidl_reply;\n";
1163 out << "::android::status_t _hidl_err;\n";
1164 out << "::android::hardware::Status _hidl_status;\n\n";
1165
1166 declareCppReaderLocals(
1167 out, method->results(), true /* forResults */);
1168
1169 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Yifan Hongeefe4f22017-01-04 15:32:42 -08001170 out << superInterface->fqName().cppName();
Yifan Hong068c5522016-10-31 14:07:25 -07001171 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001172 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1173
Martijn Coenenfff73352017-01-04 16:36:31 +01001174 bool hasInterfaceArgument = false;
Yifan Hong068c5522016-10-31 14:07:25 -07001175 // First DFS: write all buffers and resolve pointers for parent
1176 for (const auto &arg : method->args()) {
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001177 if (arg->type().isInterface()) {
1178 hasInterfaceArgument = true;
1179 }
Yifan Hong068c5522016-10-31 14:07:25 -07001180 emitCppReaderWriter(
1181 out,
1182 "_hidl_data",
1183 false /* parcelObjIsPointer */,
1184 arg,
1185 false /* reader */,
1186 Type::ErrorMode_Goto,
1187 false /* addPrefixToName */);
1188 }
1189
1190 // Second DFS: resolve references.
1191 for (const auto &arg : method->args()) {
1192 emitCppResolveReferences(
1193 out,
1194 "_hidl_data",
1195 false /* parcelObjIsPointer */,
1196 arg,
1197 false /* reader */,
1198 Type::ErrorMode_Goto,
1199 false /* addPrefixToName */);
1200 }
1201
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001202 if (hasInterfaceArgument) {
1203 // Start binder threadpool to handle incoming transactions
1204 out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
1205 }
Yifan Hong068c5522016-10-31 14:07:25 -07001206 out << "_hidl_err = remote()->transact("
1207 << method->getSerialId()
1208 << " /* "
1209 << method->name()
1210 << " */, _hidl_data, &_hidl_reply";
1211
1212 if (method->isOneway()) {
1213 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1214 }
1215 out << ");\n";
1216
1217 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1218
1219 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001220 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001221 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1222 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1223
1224
1225 // First DFS: write all buffers and resolve pointers for parent
1226 for (const auto &arg : method->results()) {
1227 emitCppReaderWriter(
1228 out,
1229 "_hidl_reply",
1230 false /* parcelObjIsPointer */,
1231 arg,
1232 true /* reader */,
1233 Type::ErrorMode_Goto,
1234 true /* addPrefixToName */);
1235 }
1236
1237 // Second DFS: resolve references.
1238 for (const auto &arg : method->results()) {
1239 emitCppResolveReferences(
1240 out,
1241 "_hidl_reply",
1242 false /* parcelObjIsPointer */,
1243 arg,
1244 true /* reader */,
1245 Type::ErrorMode_Goto,
1246 true /* addPrefixToName */);
1247 }
1248
1249 if (returnsValue && elidedReturn == nullptr) {
1250 out << "_hidl_cb(";
1251
1252 bool first = true;
1253 for (const auto &arg : method->results()) {
1254 if (!first) {
1255 out << ", ";
1256 }
1257
1258 if (arg->type().resultNeedsDeref()) {
1259 out << "*";
1260 }
1261 out << "_hidl_out_" << arg->name();
1262
1263 first = false;
1264 }
1265
1266 out << ");\n\n";
1267 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001268 }
1269 status = generateCppInstrumentationCall(
1270 out,
1271 InstrumentationEvent::CLIENT_API_EXIT,
1272 method);
1273 if (status != OK) {
1274 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001275 }
1276
1277 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001278 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1279 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001280 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001281 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1282 } else {
1283 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1284 out << "return ::android::hardware::Return<void>();\n\n";
1285 }
1286
1287 out.unindent();
1288 out << "_hidl_error:\n";
1289 out.indent();
1290 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1291 out << "return ::android::hardware::Return<";
1292 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001293 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001294 } else {
1295 out << "void";
1296 }
1297 out << ">(_hidl_status);\n";
1298
1299 out.unindent();
1300 out << "}\n\n";
1301 return OK;
1302}
1303
Andreas Huber881227d2016-08-02 14:20:21 -07001304status_t AST::generateProxySource(
Yifan Hongeefe4f22017-01-04 15:32:42 -08001305 Formatter &out, const FQName &fqName) const {
1306 const std::string klassName = fqName.getInterfaceProxyName();
Andreas Huber881227d2016-08-02 14:20:21 -07001307
1308 out << klassName
1309 << "::"
1310 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001311 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001312
1313 out.indent();
1314 out.indent();
1315
1316 out << ": BpInterface"
Yifan Hongeefe4f22017-01-04 15:32:42 -08001317 << "<"
1318 << fqName.getInterfaceName()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001319 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001320 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001321 << mPackage.string()
Yifan Hongeefe4f22017-01-04 15:32:42 -08001322 << "::"
1323 << fqName.getInterfaceName()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001324 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001325
Andreas Huber881227d2016-08-02 14:20:21 -07001326 out.unindent();
1327 out.unindent();
1328 out << "}\n\n";
1329
Yifan Hong068c5522016-10-31 14:07:25 -07001330 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1331 return generateProxyMethodSource(out, klassName, method, superInterface);
1332 });
Andreas Huber881227d2016-08-02 14:20:21 -07001333
Yifan Hong068c5522016-10-31 14:07:25 -07001334 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001335}
1336
1337status_t AST::generateStubSource(
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001338 Formatter &out,
Yifan Hongeefe4f22017-01-04 15:32:42 -08001339 const Interface *iface) const {
1340 const std::string interfaceName = iface->localName();
1341 const std::string klassName = iface->getStubName();
Andreas Huber881227d2016-08-02 14:20:21 -07001342
Steven Moreland40786312016-08-16 10:29:40 -07001343 out << klassName
1344 << "::"
1345 << klassName
Yifan Hongeefe4f22017-01-04 15:32:42 -08001346 << "(const ::android::sp<" << interfaceName <<"> &_hidl_impl)\n";
Steven Moreland40786312016-08-16 10:29:40 -07001347
1348 out.indent();
1349 out.indent();
1350
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001351 if (iface->isIBase()) {
1352 out << ": ::android::hardware::HidlInstrumentor(\"";
1353 } else {
Yifan Hongeefe4f22017-01-04 15:32:42 -08001354 out << ": "
1355 << gIBaseFqName.getInterfaceStubFqName().cppName()
1356 << "(_hidl_impl, \"";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001357 }
1358
1359 out << mPackage.string()
Yifan Hongeefe4f22017-01-04 15:32:42 -08001360 << "::"
1361 << interfaceName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001362 << "\") { \n";
1363 out.indent();
1364 out << "_hidl_mImpl = _hidl_impl;\n";
1365 out.unindent();
Steven Moreland40786312016-08-16 10:29:40 -07001366
1367 out.unindent();
1368 out.unindent();
1369 out << "}\n\n";
1370
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001371 if (iface->isIBase()) {
Yifan Hong01e7cde2017-01-09 17:45:45 -08001372 // BnHwBase has a constructor to initialize the HidlInstrumentor
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001373 // class properly.
1374 out << klassName
1375 << "::"
1376 << klassName
Yifan Hongeefe4f22017-01-04 15:32:42 -08001377 << "(const ::android::sp<" << interfaceName <<"> &_hidl_impl,"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001378 << " const std::string &prefix)\n";
1379
1380 out.indent();
1381 out.indent();
1382
1383 out << ": ::android::hardware::HidlInstrumentor(prefix) { \n";
1384 out.indent();
1385 out << "_hidl_mImpl = _hidl_impl;\n";
1386 out.unindent();
1387
1388 out.unindent();
1389 out.unindent();
1390 out << "}\n\n";
1391 }
1392
1393
Andreas Huber881227d2016-08-02 14:20:21 -07001394 out << "::android::status_t " << klassName << "::onTransact(\n";
1395
1396 out.indent();
1397 out.indent();
1398
Iliyan Malchev549e2592016-08-10 08:59:12 -07001399 out << "uint32_t _hidl_code,\n"
1400 << "const ::android::hardware::Parcel &_hidl_data,\n"
1401 << "::android::hardware::Parcel *_hidl_reply,\n"
1402 << "uint32_t _hidl_flags,\n"
1403 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001404
1405 out.unindent();
1406
Iliyan Malchev549e2592016-08-10 08:59:12 -07001407 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001408 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001409 out.indent();
1410
Yifan Hong10fe0b52016-10-19 14:20:17 -07001411 for (const auto &tuple : iface->allMethodsFromRoot()) {
1412 const Method *method = tuple.method();
1413 const Interface *superInterface = tuple.interface();
1414 out << "case "
1415 << method->getSerialId()
1416 << " /* "
1417 << method->name()
1418 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001419
Yifan Hong10fe0b52016-10-19 14:20:17 -07001420 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001421
Yifan Hong10fe0b52016-10-19 14:20:17 -07001422 status_t err =
1423 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001424
Yifan Hong10fe0b52016-10-19 14:20:17 -07001425 if (err != OK) {
1426 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001427 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001428
1429 out.unindent();
1430 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001431 }
1432
1433 out << "default:\n{\n";
1434 out.indent();
1435
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001436 out << "return onTransact(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001437
1438 out.indent();
1439 out.indent();
1440
Iliyan Malchev549e2592016-08-10 08:59:12 -07001441 out << "_hidl_code, _hidl_data, _hidl_reply, "
1442 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001443
1444 out.unindent();
1445 out.unindent();
1446
1447 out.unindent();
1448 out << "}\n";
1449
1450 out.unindent();
1451 out << "}\n\n";
1452
Yifan Honga018ed52016-12-13 16:35:08 -08001453 out.sIf("_hidl_err == ::android::UNEXPECTED_NULL", [&] {
1454 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
1455 out.indent(2, [&] {
1456 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1457 out << "_hidl_reply);\n";
1458 });
1459 });
Andreas Huber881227d2016-08-02 14:20:21 -07001460
Iliyan Malchev549e2592016-08-10 08:59:12 -07001461 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001462
1463 out.unindent();
1464 out << "}\n\n";
1465
1466 return OK;
1467}
1468
1469status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001470 Formatter &out, const Interface *iface, const Method *method) const {
Martijn Coenen115d4282016-12-19 05:14:04 +01001471 if (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB)) {
1472 method->cppImpl(IMPL_STUB, out);
1473 out << "break;\n";
1474 return OK;
1475 }
1476
Yifan Hongeefe4f22017-01-04 15:32:42 -08001477 out << "if (!_hidl_data.enforceInterface("
1478 << iface->fullName()
1479 << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001480
Andreas Huber881227d2016-08-02 14:20:21 -07001481 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001482 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001483 out << "break;\n";
1484 out.unindent();
1485 out << "}\n\n";
1486
Andreas Huber5e44a292016-09-27 14:52:39 -07001487 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001488
Yifan Hongbf459bc2016-08-23 16:50:37 -07001489 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001490 for (const auto &arg : method->args()) {
1491 emitCppReaderWriter(
1492 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001493 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001494 false /* parcelObjIsPointer */,
1495 arg,
1496 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001497 Type::ErrorMode_Break,
1498 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001499 }
1500
Yifan Hongbf459bc2016-08-23 16:50:37 -07001501 // Second DFS: resolve references
1502 for (const auto &arg : method->args()) {
1503 emitCppResolveReferences(
1504 out,
1505 "_hidl_data",
1506 false /* parcelObjIsPointer */,
1507 arg,
1508 true /* reader */,
1509 Type::ErrorMode_Break,
1510 false /* addPrefixToName */);
1511 }
1512
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001513 status_t status = generateCppInstrumentationCall(
1514 out,
1515 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001516 method);
1517 if (status != OK) {
1518 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001519 }
1520
Andreas Huber881227d2016-08-02 14:20:21 -07001521 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001522 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001523
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001524 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001525 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -08001526 << " _hidl_out_"
Yifan Hong3b320f82016-11-01 15:15:54 -07001527 << elidedReturn->name()
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001528 << " = "
1529 << "_hidl_mImpl->" << method->name()
Yifan Hong3b320f82016-11-01 15:15:54 -07001530 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001531
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001532 bool first = true;
1533 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001534 if (!first) {
1535 out << ", ";
1536 }
1537
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001538 if (arg->type().resultNeedsDeref()) {
1539 out << "*";
1540 }
1541
1542 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001543
1544 first = false;
1545 }
1546
Steven Moreland2ae5bca2016-12-01 05:56:49 +00001547 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001548 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1549 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001550
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001551 elidedReturn->type().emitReaderWriter(
1552 out,
Yifan Honga47eef32016-12-12 10:38:54 -08001553 "_hidl_out_" + elidedReturn->name(),
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001554 "_hidl_reply",
1555 true, /* parcelObjIsPointer */
1556 false, /* isReader */
1557 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001558
Yifan Hongbf459bc2016-08-23 16:50:37 -07001559 emitCppResolveReferences(
1560 out,
1561 "_hidl_reply",
1562 true /* parcelObjIsPointer */,
1563 elidedReturn,
1564 false /* reader */,
1565 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001566 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001567
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001568 status_t status = generateCppInstrumentationCall(
1569 out,
1570 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001571 method);
1572 if (status != OK) {
1573 return status;
1574 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001575
Iliyan Malchev549e2592016-08-10 08:59:12 -07001576 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001577 } else {
1578 if (returnsValue) {
1579 out << "bool _hidl_callbackCalled = false;\n\n";
1580 }
Andreas Huber881227d2016-08-02 14:20:21 -07001581
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001582 out << "_hidl_mImpl->" << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001583
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001584 bool first = true;
1585 for (const auto &arg : method->args()) {
1586 if (!first) {
1587 out << ", ";
1588 }
Andreas Huber881227d2016-08-02 14:20:21 -07001589
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001590 if (arg->type().resultNeedsDeref()) {
1591 out << "*";
1592 }
1593
1594 out << arg->name();
1595
1596 first = false;
1597 }
1598
1599 if (returnsValue) {
1600 if (!first) {
1601 out << ", ";
1602 }
1603
1604 out << "[&](";
1605
1606 first = true;
1607 for (const auto &arg : method->results()) {
1608 if (!first) {
1609 out << ", ";
1610 }
1611
Yifan Honga47eef32016-12-12 10:38:54 -08001612 out << "const auto &_hidl_out_" << arg->name();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001613
1614 first = false;
1615 }
1616
1617 out << ") {\n";
1618 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001619 out << "if (_hidl_callbackCalled) {\n";
1620 out.indent();
1621 out << "LOG_ALWAYS_FATAL(\""
1622 << method->name()
1623 << ": _hidl_cb called a second time, but must be called once.\");\n";
1624 out.unindent();
1625 out << "}\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001626 out << "_hidl_callbackCalled = true;\n\n";
1627
Yifan Hong859e53f2016-11-14 19:08:24 -08001628 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1629 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001630
Yifan Hongbf459bc2016-08-23 16:50:37 -07001631 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001632 for (const auto &arg : method->results()) {
1633 emitCppReaderWriter(
1634 out,
1635 "_hidl_reply",
1636 true /* parcelObjIsPointer */,
1637 arg,
1638 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001639 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001640 true /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001641 }
1642
Yifan Hongbf459bc2016-08-23 16:50:37 -07001643 // Second DFS: resolve references
1644 for (const auto &arg : method->results()) {
1645 emitCppResolveReferences(
1646 out,
1647 "_hidl_reply",
1648 true /* parcelObjIsPointer */,
1649 arg,
1650 false /* reader */,
1651 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001652 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001653 }
1654
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001655 status_t status = generateCppInstrumentationCall(
1656 out,
1657 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001658 method);
1659 if (status != OK) {
1660 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001661 }
1662
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001663 out << "_hidl_cb(*_hidl_reply);\n";
1664
1665 out.unindent();
Martijn Coenen8e4fc842017-01-09 16:28:59 +01001666 out << "});\n\n";
1667 } else {
1668 out << ");\n\n";
1669 status_t status = generateCppInstrumentationCall(
1670 out,
1671 InstrumentationEvent::SERVER_API_EXIT,
1672 method);
1673 if (status != OK) {
1674 return status;
1675 }
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001676 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001677
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001678 if (returnsValue) {
1679 out << "if (!_hidl_callbackCalled) {\n";
1680 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001681 out << "LOG_ALWAYS_FATAL(\""
1682 << method->name()
1683 << ": _hidl_cb not called, but must be called once.\");\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001684 out.unindent();
1685 out << "}\n\n";
Steven Moreland05cd4232016-11-21 16:01:12 -08001686 } else {
1687 out << "::android::hardware::writeToParcel("
1688 << "::android::hardware::Status::ok(), "
1689 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001690 }
Andreas Huber881227d2016-08-02 14:20:21 -07001691 }
1692
1693 out << "break;\n";
1694
1695 return OK;
1696}
1697
Steven Moreland69e7c702016-09-09 11:16:32 -07001698status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1699 std::string ifaceName;
1700 if (!AST::isInterface(&ifaceName)) {
1701 // types.hal does not get a stub header.
1702 return OK;
1703 }
1704
1705 const Interface *iface = mRootScope->getInterface();
1706
Yifan Hongeefe4f22017-01-04 15:32:42 -08001707 const std::string klassName = iface->getPassthroughName();
Steven Moreland69e7c702016-09-09 11:16:32 -07001708
1709 bool supportOneway = iface->hasOnewayMethods();
1710
1711 std::string path = outputPath;
1712 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1713 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1714 path.append(klassName);
1715 path.append(".h");
1716
1717 CHECK(Coordinator::MakeParentHierarchy(path));
1718 FILE *file = fopen(path.c_str(), "w");
1719
1720 if (file == NULL) {
1721 return -errno;
1722 }
1723
1724 Formatter out(file);
1725
1726 const std::string guard = makeHeaderGuard(klassName);
1727
1728 out << "#ifndef " << guard << "\n";
1729 out << "#define " << guard << "\n\n";
1730
1731 std::vector<std::string> packageComponents;
1732 getPackageAndVersionComponents(
1733 &packageComponents, false /* cpp_compatible */);
1734
Yifan Hongb0949432016-12-15 15:32:24 -08001735 out << "#include <cutils/trace.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001736 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001737
1738 generateCppPackageInclude(out, mPackage, ifaceName);
1739 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001740
Yifan Hong7a118f52016-12-07 11:21:15 -08001741 out << "#include <hidl/HidlPassthroughSupport.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001742 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001743 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001744 }
1745
1746 enterLeaveNamespace(out, true /* enter */);
1747 out << "\n";
1748
1749 out << "struct "
1750 << klassName
1751 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001752 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001753
1754 out.indent();
1755 out << "explicit "
1756 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001757 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001758 << ifaceName
1759 << "> impl);\n";
1760
Yifan Hong068c5522016-10-31 14:07:25 -07001761 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1762 return generatePassthroughMethod(out, method);
1763 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001764
1765 if (err != OK) {
1766 return err;
1767 }
1768
1769 out.unindent();
1770 out << "private:\n";
1771 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001772 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001773
1774 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001775 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001776
1777 out << "\n";
1778
1779 out << "::android::hardware::Return<void> addOnewayTask("
1780 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001781 }
1782
1783 out.unindent();
1784
1785 out << "};\n\n";
1786
1787 enterLeaveNamespace(out, false /* enter */);
1788
1789 out << "\n#endif // " << guard << "\n";
1790
1791 return OK;
1792}
1793
Yifan Hongfe95aa22016-10-19 17:26:45 -07001794status_t AST::generateInterfaceSource(Formatter &out) const {
1795 const Interface *iface = mRootScope->getInterface();
1796
Yifan Hong2d7126b2016-10-20 15:12:57 -07001797 // generate castFrom functions
Yifan Hong3d746092016-12-07 14:26:33 -08001798 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001799
Yifan Hong3d746092016-12-07 14:26:33 -08001800 for (const Interface *superType : iface->typeChain()) {
1801 out << "// static \n"
1802 << childTypeResult
Yifan Hongeefe4f22017-01-04 15:32:42 -08001803 << " "
1804 << iface->localName()
Yifan Hong3d746092016-12-07 14:26:33 -08001805 << "::castFrom("
1806 << superType->getCppArgumentType()
1807 << " parent) {\n";
1808 out.indent();
1809 if (iface == superType) {
1810 out << "return parent;\n";
1811 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001812 out << "return ::android::hardware::castInterface<";
Yifan Hongeefe4f22017-01-04 15:32:42 -08001813 out << iface->localName() << ", "
Yifan Hongfe95aa22016-10-19 17:26:45 -07001814 << superType->fqName().cppName() << ", "
Yifan Hongeefe4f22017-01-04 15:32:42 -08001815 << iface->getProxyName() << ", "
Yifan Hong51a65092017-01-04 15:41:44 -08001816 << superType->getProxyFqName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001817 << ">(\n";
1818 out.indent();
1819 out.indent();
1820 out << "parent, \""
1821 << iface->fqName().string()
1822 << "\");\n";
1823 out.unindent();
1824 out.unindent();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001825 }
Yifan Hong3d746092016-12-07 14:26:33 -08001826 out.unindent();
1827 out << "}\n\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001828 }
1829
1830 return OK;
1831}
1832
Steven Moreland69e7c702016-09-09 11:16:32 -07001833status_t AST::generatePassthroughSource(Formatter &out) const {
1834 const Interface *iface = mRootScope->getInterface();
1835
Yifan Hongeefe4f22017-01-04 15:32:42 -08001836 const std::string klassName = iface->getPassthroughName();
Steven Moreland69e7c702016-09-09 11:16:32 -07001837
1838 out << klassName
1839 << "::"
1840 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001841 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001842 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001843 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001844 << iface->fqName().string()
1845 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001846 if (iface->hasOnewayMethods()) {
1847 out << "\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001848 out.indent([&] {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001849 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1850 });
1851 }
1852 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001853
1854 if (iface->hasOnewayMethods()) {
1855 out << "::android::hardware::Return<void> "
1856 << klassName
1857 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1858 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001859 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001860 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001861 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1862 out.indent();
1863 out.indent();
1864 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1865 out.unindent();
1866 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001867 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001868 out << "}\n";
1869
Steven Morelandd366c262016-10-11 15:29:10 -07001870 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001871
1872 out.unindent();
1873 out << "}\n\n";
1874
1875
1876 }
1877
1878 return OK;
1879}
1880
Martijn Coenen7b295242016-11-04 16:52:56 +01001881status_t AST::generateCppAtraceCall(Formatter &out,
1882 InstrumentationEvent event,
1883 const Method *method) const {
1884 const Interface *iface = mRootScope->getInterface();
Yifan Hongeefe4f22017-01-04 15:32:42 -08001885 std::string baseString = "HIDL::" + iface->localName() + "::" + method->name();
Martijn Coenen7b295242016-11-04 16:52:56 +01001886 switch (event) {
1887 case SERVER_API_ENTRY:
1888 {
1889 out << "atrace_begin(ATRACE_TAG_HAL, \""
1890 << baseString + "::server\");\n";
1891 break;
1892 }
1893 case CLIENT_API_ENTRY:
1894 {
1895 out << "atrace_begin(ATRACE_TAG_HAL, \""
1896 << baseString + "::client\");\n";
1897 break;
1898 }
1899 case PASSTHROUGH_ENTRY:
1900 {
1901 out << "atrace_begin(ATRACE_TAG_HAL, \""
1902 << baseString + "::passthrough\");\n";
1903 break;
1904 }
1905 case SERVER_API_EXIT:
1906 case CLIENT_API_EXIT:
1907 case PASSTHROUGH_EXIT:
1908 {
1909 out << "atrace_end(ATRACE_TAG_HAL);\n";
1910 break;
1911 }
1912 default:
1913 {
1914 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1915 return UNKNOWN_ERROR;
1916 }
1917 }
1918
1919 return OK;
1920}
1921
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001922status_t AST::generateCppInstrumentationCall(
1923 Formatter &out,
1924 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001925 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001926 status_t err = generateCppAtraceCall(out, event, method);
1927 if (err != OK) {
1928 return err;
1929 }
1930
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001931 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1932 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001933 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001934 std::string event_str = "";
1935 switch (event) {
1936 case SERVER_API_ENTRY:
1937 {
1938 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1939 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001940 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001941 << (arg->type().resultNeedsDeref() ? "" : "&")
1942 << arg->name()
1943 << ");\n";
1944 }
1945 break;
1946 }
1947 case SERVER_API_EXIT:
1948 {
1949 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001950 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001951 out << "_hidl_args.push_back((void *)&_hidl_out_"
Steven Moreland031ccf12016-10-31 15:54:38 -07001952 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001953 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001954 }
1955 break;
1956 }
1957 case CLIENT_API_ENTRY:
1958 {
1959 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1960 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001961 out << "_hidl_args.push_back((void *)&"
1962 << arg->name()
1963 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001964 }
1965 break;
1966 }
1967 case CLIENT_API_EXIT:
1968 {
1969 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1970 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001971 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001972 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001973 << "_hidl_out_"
1974 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001975 << ");\n";
1976 }
1977 break;
1978 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001979 case PASSTHROUGH_ENTRY:
1980 {
1981 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1982 for (const auto &arg : method->args()) {
1983 out << "_hidl_args.push_back((void *)&"
1984 << arg->name()
1985 << ");\n";
1986 }
1987 break;
1988 }
1989 case PASSTHROUGH_EXIT:
1990 {
1991 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001992 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001993 out << "_hidl_args.push_back((void *)&_hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001994 << arg->name()
1995 << ");\n";
1996 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001997 break;
1998 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001999 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002000 {
Steven Moreland031ccf12016-10-31 15:54:38 -07002001 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002002 return UNKNOWN_ERROR;
2003 }
2004 }
2005
Steven Moreland031ccf12016-10-31 15:54:38 -07002006 const Interface *iface = mRootScope->getInterface();
2007
Steven Moreland1ab31442016-11-03 18:37:51 -07002008 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002009 out.indent();
2010 out << "callback("
2011 << event_str
2012 << ", \""
2013 << mPackage.package()
2014 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07002015 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002016 << "\", \""
2017 << iface->localName()
2018 << "\", \""
2019 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002020 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002021 out.unindent();
2022 out << "}\n";
2023 out.unindent();
2024 out << "}\n\n";
2025
2026 return OK;
2027}
2028
Andreas Huber881227d2016-08-02 14:20:21 -07002029} // namespace android