blob: 1fa12870daaceb8e2a7bf71e46a87b41a172bbf2 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huber881227d2016-08-02 14:20:21 -070017#include "AST.h"
18
19#include "Coordinator.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070020#include "EnumType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070021#include "Interface.h"
22#include "Method.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070023#include "ScalarType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070024#include "Scope.h"
25
Andreas Huberdca261f2016-08-04 13:47:51 -070026#include <algorithm>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070027#include <hidl-util/Formatter.h>
Steven Moreland5708edf2016-11-04 15:33:31 +000028#include <hidl-util/StringHelper.h>
Andreas Huber881227d2016-08-02 14:20:21 -070029#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070031#include <vector>
32
33namespace android {
34
Andreas Huberb82318c2016-08-02 14:45:54 -070035status_t AST::generateCpp(const std::string &outputPath) const {
36 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070037
38 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070039 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070040 }
41
42 if (err == OK) {
Steven Moreland40786312016-08-16 10:29:40 -070043 err = generateHwBinderHeader(outputPath);
44 }
45
46 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070047 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070048 }
49
50 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070051 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070052 }
53
Steven Moreland69e7c702016-09-09 11:16:32 -070054 if (err == OK) {
55 generatePassthroughHeader(outputPath);
56 }
57
Andreas Huber881227d2016-08-02 14:20:21 -070058 return err;
59}
60
Andreas Huber737080b2016-08-02 15:38:04 -070061void AST::getPackageComponents(
62 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070063 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070064}
65
66void AST::getPackageAndVersionComponents(
67 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070068 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070069}
70
Steven Moreland5708edf2016-11-04 15:33:31 +000071std::string AST::makeHeaderGuard(const std::string &baseName,
72 bool indicateGenerated) const {
73 std::string guard;
Andreas Huber881227d2016-08-02 14:20:21 -070074
Steven Moreland5708edf2016-11-04 15:33:31 +000075 if (indicateGenerated) {
76 guard += "HIDL_GENERATED_";
77 }
78
79 guard += StringHelper::Uppercase(mPackage.tokenName());
Andreas Huber881227d2016-08-02 14:20:21 -070080 guard += "_";
Steven Moreland5708edf2016-11-04 15:33:31 +000081 guard += StringHelper::Uppercase(baseName);
82 guard += "_H";
Andreas Huber881227d2016-08-02 14:20:21 -070083
84 return guard;
85}
86
Steven Morelandee88eed2016-10-31 17:49:00 -070087// static
88void AST::generateCppPackageInclude(
89 Formatter &out,
90 const FQName &package,
91 const std::string &klass) {
92
93 out << "#include <";
94
95 std::vector<std::string> components;
96 package.getPackageAndVersionComponents(&components, false /* cpp_compatible */);
97
98 for (const auto &component : components) {
99 out << component << "/";
100 }
101
102 out << klass
103 << ".h>\n";
104}
105
Andreas Huber881227d2016-08-02 14:20:21 -0700106void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
107 std::vector<std::string> packageComponents;
108 getPackageAndVersionComponents(
109 &packageComponents, true /* cpp_compatible */);
110
111 if (enter) {
112 for (const auto &component : packageComponents) {
113 out << "namespace " << component << " {\n";
114 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700115
Andreas Huber2831d512016-08-15 09:33:47 -0700116 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -0700117 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700118 out.setNamespace(std::string());
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120 for (auto it = packageComponents.rbegin();
121 it != packageComponents.rend();
122 ++it) {
123 out << "} // namespace " << *it << "\n";
124 }
125 }
126}
127
Andreas Huberb82318c2016-08-02 14:45:54 -0700128status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700129
Andreas Huberb82318c2016-08-02 14:45:54 -0700130 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700131 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700132 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700133
134 std::string ifaceName;
135 bool isInterface = true;
136 if (!AST::isInterface(&ifaceName)) {
137 ifaceName = "types";
138 isInterface = false;
139 }
140 path.append(ifaceName);
141 path.append(".h");
142
Andreas Huberd2943e12016-08-05 11:59:31 -0700143 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700144 FILE *file = fopen(path.c_str(), "w");
145
146 if (file == NULL) {
147 return -errno;
148 }
149
150 Formatter out(file);
151
152 const std::string guard = makeHeaderGuard(ifaceName);
153
154 out << "#ifndef " << guard << "\n";
155 out << "#define " << guard << "\n\n";
156
Andreas Huber737080b2016-08-02 15:38:04 -0700157 for (const auto &item : mImportedNames) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700158 generateCppPackageInclude(out, item, item.name());
Andreas Huber737080b2016-08-02 15:38:04 -0700159 }
160
161 if (!mImportedNames.empty()) {
162 out << "\n";
163 }
164
Steven Moreland0693f312016-11-09 15:06:14 -0800165 if (isInterface) {
166 out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
167 }
168
Yifan Hong859e53f2016-11-14 19:08:24 -0800169 // TODO b/32756130 change back to HidlSupport.h
170 out << "#include <hidl/HidlTransportSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700171 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700172
173 if (isInterface) {
Steven Moreland0693f312016-11-09 15:06:14 -0800174 out << "#include <hidl/ServiceManagement.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200175 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700176 }
177
178 out << "#include <utils/NativeHandle.h>\n\n";
179
180 enterLeaveNamespace(out, true /* enter */);
181 out << "\n";
182
183 if (isInterface) {
184 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700185 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700186
187 const Interface *iface = mRootScope->getInterface();
188 const Interface *superType = iface->superType();
189
Steven Moreland40786312016-08-16 10:29:40 -0700190 if (superType == NULL) {
Yifan Hong5bd9aff2016-11-08 18:52:55 -0800191 out << " : virtual public ::android::hardware::IBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700192 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000193 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700194 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700195 }
196
197 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700198
199 out.indent();
200
Andreas Huber881227d2016-08-02 14:20:21 -0700201 }
202
203 status_t err = emitTypeDeclarations(out);
204
205 if (err != OK) {
206 return err;
207 }
208
209 if (isInterface) {
210 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700211 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700212 const std::string baseName = iface->getBaseName();
Steven Moreland19d5c172016-10-20 19:20:25 -0700213 out << "constexpr static ::android::hardware::hidl_version version = {"
Martijn Coenena21f1492016-09-08 15:55:14 +0200214 << mPackage.getPackageMajorVersion() << ","
215 << mPackage.getPackageMinorVersion() << "};\n";
Steven Moreland19d5c172016-10-20 19:20:25 -0700216 out << "virtual const ::android::hardware::hidl_version&"
217 << "getInterfaceVersion() const {\n";
Martijn Coenena21f1492016-09-08 15:55:14 +0200218 out.indent();
219 out << "return version;\n";
220 out.unindent();
221 out << "}\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700222 out << "virtual bool isRemote() const override { return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800223
Andreas Huber881227d2016-08-02 14:20:21 -0700224 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700225 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700226
Andreas Huber881227d2016-08-02 14:20:21 -0700227 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800228 const TypedVar *elidedReturn = method->canElideCallback();
229
230 if (elidedReturn == nullptr && returnsValue) {
231 out << "using "
232 << method->name()
233 << "_cb = std::function<void("
234 << Method::GetArgSignature(method->results(),
235 true /* specify namespaces */)
236 << ")>;\n";
237 }
Andreas Huber881227d2016-08-02 14:20:21 -0700238
Andreas Huber3599d922016-08-09 10:42:57 -0700239 method->dumpAnnotations(out);
240
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700241 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700242 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700243 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700244 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700245 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700246 }
247
248 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700249 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700250 << Method::GetArgSignature(method->args(),
251 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700252
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700253 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700254 if (!method->args().empty()) {
255 out << ", ";
256 }
257
Steven Moreland67f67b42016-09-29 08:59:02 -0700258 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700259 }
260
Yifan Hong10fe0b52016-10-19 14:20:17 -0700261 out << ")";
262 if (method->isHidlReserved()) {
263 out << " override";
264 out << " {\n";
265 out.indent();
266 method->cppImpl(out);
267 out.unindent();
268 out << "\n}\n";
269 } else {
270 out << " = 0;\n";
271 }
Andreas Huber881227d2016-08-02 14:20:21 -0700272 }
Steven Moreland40786312016-08-16 10:29:40 -0700273
Yifan Hongfe95aa22016-10-19 17:26:45 -0700274 if (!iface->isRootType()) {
275 out << "// cast static functions\n";
Yifan Hong3b320f82016-11-01 15:15:54 -0700276 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700277
278 for (const Interface *superType : iface->superTypeChain()) {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700279 out << "static "
280 << childTypeResult
281 << " castFrom("
Yifan Hong3b320f82016-11-01 15:15:54 -0700282 << superType->getCppArgumentType()
Yifan Hongfe95aa22016-10-19 17:26:45 -0700283 << " parent"
Yifan Hongfe95aa22016-10-19 17:26:45 -0700284 << ");\n";
285 }
286 }
287
Steven Morelandd39133b2016-11-11 12:30:08 -0800288 out << "\nstatic const char* descriptor;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700289
Steven Moreland0693f312016-11-09 15:06:14 -0800290 out << "DECLARE_SERVICE_MANAGER_INTERACTIONS(" << baseName << ")\n\n";
Yifan Hong158655a2016-11-08 12:34:07 -0800291
292 out << "private: static int hidlStaticBlock;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700293 }
294
295 if (isInterface) {
296 out.unindent();
297
Andreas Hubere3f769a2016-10-10 10:54:44 -0700298 out << "};\n\n";
299 }
300
301 err = mRootScope->emitGlobalTypeDeclarations(out);
302
303 if (err != OK) {
304 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700305 }
306
307 out << "\n";
308 enterLeaveNamespace(out, false /* enter */);
309
310 out << "\n#endif // " << guard << "\n";
311
312 return OK;
313}
314
Steven Moreland40786312016-08-16 10:29:40 -0700315status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
316 std::string ifaceName;
Yifan Hong244e82d2016-11-11 11:13:57 -0800317 bool isInterface = AST::isInterface(&ifaceName);
318 const Interface *iface = nullptr;
319 std::string baseName{};
320 std::string klassName{};
321
322 if(isInterface) {
323 iface = mRootScope->getInterface();
324 baseName = iface->getBaseName();
325 klassName = "IHw" + baseName;
326 } else {
327 klassName = "hwtypes";
Steven Moreland40786312016-08-16 10:29:40 -0700328 }
329
Steven Moreland40786312016-08-16 10:29:40 -0700330 std::string path = outputPath;
331 path.append(mCoordinator->convertPackageRootToPath(mPackage));
332 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
333 path.append(klassName + ".h");
334
Yifan Hong244e82d2016-11-11 11:13:57 -0800335 FILE *file = fopen(path.c_str(), "w");
Steven Moreland40786312016-08-16 10:29:40 -0700336
337 if (file == NULL) {
338 return -errno;
339 }
340
341 Formatter out(file);
342
343 const std::string guard = makeHeaderGuard(klassName);
344
345 out << "#ifndef " << guard << "\n";
346 out << "#define " << guard << "\n\n";
347
Yifan Hong244e82d2016-11-11 11:13:57 -0800348 if (isInterface) {
349 generateCppPackageInclude(out, mPackage, ifaceName);
350 } else {
351 generateCppPackageInclude(out, mPackage, "types");
352 }
Steven Moreland40786312016-08-16 10:29:40 -0700353
Steven Morelandee88eed2016-10-31 17:49:00 -0700354 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700355
356 for (const auto &item : mImportedNames) {
357 if (item.name() == "types") {
Yifan Hong244e82d2016-11-11 11:13:57 -0800358 generateCppPackageInclude(out, item, "hwtypes");
359 } else {
360 generateCppPackageInclude(out, item, "Bn" + item.getInterfaceBaseName());
Steven Moreland40786312016-08-16 10:29:40 -0700361 }
Steven Moreland40786312016-08-16 10:29:40 -0700362 }
363
364 out << "\n";
365
Yifan Hong859e53f2016-11-14 19:08:24 -0800366 out << "#include <hidl/HidlTransportSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200367 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700368 out << "#include <hwbinder/IBinder.h>\n";
369 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700370
371 out << "\n";
372
373 enterLeaveNamespace(out, true /* enter */);
Steven Moreland40786312016-08-16 10:29:40 -0700374
Yifan Hong244e82d2016-11-11 11:13:57 -0800375 if (isInterface) {
376 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700377
Yifan Hong244e82d2016-11-11 11:13:57 -0800378 out << "struct "
379 << klassName
380 << " : public "
381 << ifaceName;
Steven Moreland40786312016-08-16 10:29:40 -0700382
Yifan Hong244e82d2016-11-11 11:13:57 -0800383 const Interface *superType = iface->superType();
Steven Moreland40786312016-08-16 10:29:40 -0700384
Yifan Hong244e82d2016-11-11 11:13:57 -0800385 out << ", public ::android::hardware::IInterface";
Steven Moreland40786312016-08-16 10:29:40 -0700386
Yifan Hong244e82d2016-11-11 11:13:57 -0800387 out << " {\n";
Steven Moreland40786312016-08-16 10:29:40 -0700388
Yifan Hong244e82d2016-11-11 11:13:57 -0800389 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700390
Yifan Hong244e82d2016-11-11 11:13:57 -0800391 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700392
Yifan Hong244e82d2016-11-11 11:13:57 -0800393 out.unindent();
394
395 out << "};\n\n";
396 }
397
398 status_t err = mRootScope->emitGlobalHwDeclarations(out);
399 if (err != OK) {
400 return err;
401 }
Steven Moreland40786312016-08-16 10:29:40 -0700402
403 enterLeaveNamespace(out, false /* enter */);
404
405 out << "\n#endif // " << guard << "\n";
406
407 return OK;
408}
409
Andreas Huber881227d2016-08-02 14:20:21 -0700410status_t AST::emitTypeDeclarations(Formatter &out) const {
411 return mRootScope->emitTypeDeclarations(out);
412}
413
Steven Morelanda7a421a2016-09-07 08:35:18 -0700414status_t AST::generateStubMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700415 const Method *method) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700416 out << "inline ";
417
Yifan Hong068c5522016-10-31 14:07:25 -0700418 method->generateCppSignature(out);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700419
420 const bool returnsValue = !method->results().empty();
421 const TypedVar *elidedReturn = method->canElideCallback();
422 out << " {\n";
423 out.indent();
424 out << "return mImpl->"
425 << method->name()
426 << "(";
427 bool first = true;
428 for (const auto &arg : method->args()) {
429 if (!first) {
430 out << ", ";
431 }
432 first = false;
433 out << arg->name();
434 }
435 if (returnsValue && elidedReturn == nullptr) {
436 if (!method->args().empty()) {
437 out << ", ";
438 }
439
440 out << "_hidl_cb";
441 }
442 out << ");\n";
443 out.unindent();
444 out << "}";
445
446 out << ";\n";
447
448 return OK;
449}
450
Steven Moreland69e7c702016-09-09 11:16:32 -0700451status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700452 const Method *method) const {
453 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700454
455 out << " {\n";
456 out.indent();
457
458 const bool returnsValue = !method->results().empty();
459 const TypedVar *elidedReturn = method->canElideCallback();
460
Steven Moreland67f67b42016-09-29 08:59:02 -0700461 if (returnsValue && elidedReturn == nullptr) {
462 generateCheckNonNull(out, "_hidl_cb");
463 }
464
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700465 generateCppInstrumentationCall(
466 out,
467 InstrumentationEvent::PASSTHROUGH_ENTRY,
468 method);
469
470 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700471
472 if (method->isOneway()) {
473 out << "addOnewayTask([this";
474 for (const auto &arg : method->args()) {
475 out << ", " << arg->name();
476 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700477 out << "] {\n";
478 out.indent();
479 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700480 }
481
482 out << "mImpl->"
483 << method->name()
484 << "(";
485
486 bool first = true;
487 for (const auto &arg : method->args()) {
488 if (!first) {
489 out << ", ";
490 }
491 first = false;
492 out << arg->name();
493 }
494 if (returnsValue && elidedReturn == nullptr) {
495 if (!method->args().empty()) {
496 out << ", ";
497 }
498
499 out << "_hidl_cb";
500 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700501 out << ");\n\n";
502
503 generateCppInstrumentationCall(
504 out,
505 InstrumentationEvent::PASSTHROUGH_EXIT,
506 method);
Steven Moreland69e7c702016-09-09 11:16:32 -0700507
508 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700509 out.unindent();
510 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700511 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700512
513 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700514
515 out.unindent();
516 out << "}\n";
517
518 return OK;
519}
520
Yifan Hong068c5522016-10-31 14:07:25 -0700521status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700522
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700523 const Interface *iface = mRootScope->getInterface();
524
Yifan Hong10fe0b52016-10-19 14:20:17 -0700525 const Interface *prevIterface = nullptr;
526 for (const auto &tuple : iface->allMethodsFromRoot()) {
527 const Method *method = tuple.method();
528 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700529
Yifan Hong10fe0b52016-10-19 14:20:17 -0700530 if(prevIterface != superInterface) {
531 if (prevIterface != nullptr) {
532 out << "\n";
533 }
534 out << "// Methods from "
535 << superInterface->fullName()
536 << " follow.\n";
537 prevIterface = superInterface;
538 }
Yifan Hong068c5522016-10-31 14:07:25 -0700539 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700540
Yifan Hong10fe0b52016-10-19 14:20:17 -0700541 if (err != OK) {
542 return err;
543 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700544 }
545
Yifan Hong10fe0b52016-10-19 14:20:17 -0700546 out << "\n";
547
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700548 return OK;
549}
550
Andreas Huberb82318c2016-08-02 14:45:54 -0700551status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700552 std::string ifaceName;
553 if (!AST::isInterface(&ifaceName)) {
554 // types.hal does not get a stub header.
555 return OK;
556 }
557
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700558 const Interface *iface = mRootScope->getInterface();
559 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700560 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700561
Andreas Huberb82318c2016-08-02 14:45:54 -0700562 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700563 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700564 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700565 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700566 path.append(".h");
567
Andreas Huberd2943e12016-08-05 11:59:31 -0700568 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700569 FILE *file = fopen(path.c_str(), "w");
570
571 if (file == NULL) {
572 return -errno;
573 }
574
575 Formatter out(file);
576
Steven Moreland40786312016-08-16 10:29:40 -0700577 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700578
579 out << "#ifndef " << guard << "\n";
580 out << "#define " << guard << "\n\n";
581
Steven Morelandee88eed2016-10-31 17:49:00 -0700582 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
583 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700584
585 enterLeaveNamespace(out, true /* enter */);
586 out << "\n";
587
588 out << "struct "
589 << "Bn"
590 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700591 << " : public ::android::hardware::BnInterface<I"
592 << baseName << ", IHw" << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700593 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700594
595 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700596 out << "explicit Bn"
597 << baseName
598 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
599 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700600 out << "::android::status_t onTransact(\n";
601 out.indent();
602 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700603 out << "uint32_t _hidl_code,\n";
604 out << "const ::android::hardware::Parcel &_hidl_data,\n";
605 out << "::android::hardware::Parcel *_hidl_reply,\n";
606 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700607 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700608 out.unindent();
609 out.unindent();
610
Yifan Hong068c5522016-10-31 14:07:25 -0700611 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
612 return generateStubMethod(out, method);
613 });
Steven Moreland9c387612016-09-07 09:54:26 -0700614
615 if (err != OK) {
616 return err;
617 }
618
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700619
Andreas Huber881227d2016-08-02 14:20:21 -0700620 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700621 out << "};\n\n";
622
623 enterLeaveNamespace(out, false /* enter */);
624
625 out << "\n#endif // " << guard << "\n";
626
627 return OK;
628}
629
Andreas Huberb82318c2016-08-02 14:45:54 -0700630status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700631 std::string ifaceName;
632 if (!AST::isInterface(&ifaceName)) {
633 // types.hal does not get a proxy header.
634 return OK;
635 }
636
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700637 const Interface *iface = mRootScope->getInterface();
638 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700639
Andreas Huberb82318c2016-08-02 14:45:54 -0700640 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700641 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700642 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700643 path.append("Bp");
644 path.append(baseName);
645 path.append(".h");
646
Andreas Huberd2943e12016-08-05 11:59:31 -0700647 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700648 FILE *file = fopen(path.c_str(), "w");
649
650 if (file == NULL) {
651 return -errno;
652 }
653
654 Formatter out(file);
655
656 const std::string guard = makeHeaderGuard("Bp" + baseName);
657
658 out << "#ifndef " << guard << "\n";
659 out << "#define " << guard << "\n\n";
660
661 std::vector<std::string> packageComponents;
662 getPackageAndVersionComponents(
663 &packageComponents, false /* cpp_compatible */);
664
Steven Morelandee88eed2016-10-31 17:49:00 -0700665 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
666 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700667
668 enterLeaveNamespace(out, true /* enter */);
669 out << "\n";
670
671 out << "struct "
672 << "Bp"
673 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700674 << " : public ::android::hardware::BpInterface<IHw"
675 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700676 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700677
678 out.indent();
679
680 out << "explicit Bp"
681 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700682 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700683 << "\n\n";
684
Yifan Hong10fe0b52016-10-19 14:20:17 -0700685 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700686
Yifan Hong068c5522016-10-31 14:07:25 -0700687 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
688 method->generateCppSignature(out);
689 out << " override;\n";
690 return OK;
691 });
Steven Moreland9c387612016-09-07 09:54:26 -0700692
693 if (err != OK) {
694 return err;
695 }
Andreas Huber881227d2016-08-02 14:20:21 -0700696
697 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700698 out << "};\n\n";
699
700 enterLeaveNamespace(out, false /* enter */);
701
702 out << "\n#endif // " << guard << "\n";
703
704 return OK;
705}
706
Andreas Huberb82318c2016-08-02 14:45:54 -0700707status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700708
Andreas Huberb82318c2016-08-02 14:45:54 -0700709 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700710 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700711 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700712
713 std::string ifaceName;
714 std::string baseName;
715
Yifan Hongfe95aa22016-10-19 17:26:45 -0700716 const Interface *iface = nullptr;
717 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700718 if (!AST::isInterface(&ifaceName)) {
719 baseName = "types";
720 isInterface = false;
721 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700722 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700723 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700724 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700725 }
726
727 path.append(baseName);
728
729 if (baseName != "types") {
730 path.append("All");
731 }
732
733 path.append(".cpp");
734
Andreas Huberd2943e12016-08-05 11:59:31 -0700735 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700736 FILE *file = fopen(path.c_str(), "w");
737
738 if (file == NULL) {
739 return -errno;
740 }
741
742 Formatter out(file);
743
Martijn Coenen7b295242016-11-04 16:52:56 +0100744
745 out << "#include <cutils/trace.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700746 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700747 // This is a no-op for IServiceManager itself.
748 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
749
Steven Morelandee88eed2016-10-31 17:49:00 -0700750 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
751 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
752 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700753
754 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700755 generateCppPackageInclude(out,
756 superType->fqName(),
757 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700758 }
Andreas Huber881227d2016-08-02 14:20:21 -0700759 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700760 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800761 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700762 }
763
764 out << "\n";
765
766 enterLeaveNamespace(out, true /* enter */);
767 out << "\n";
768
769 status_t err = generateTypeSource(out, ifaceName);
770
771 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700772 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700773 out << "constexpr ::android::hardware::hidl_version "
774 << ifaceName
775 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700776
777 // need to be put here, generateStubSource is using this.
Steven Morelandd39133b2016-11-11 12:30:08 -0800778 out << "const char* I"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700779 << iface->getBaseName()
780 << "::descriptor(\""
781 << iface->fqName().string()
782 << "\");\n\n";
783
Yifan Hong158655a2016-11-08 12:34:07 -0800784 out << "int I"
785 << iface->getBaseName()
786 << "::hidlStaticBlock = []() -> int {\n";
787 out.indentBlock([&] {
Steven Morelandd39133b2016-11-11 12:30:08 -0800788 out << "::android::hardware::gBnConstructorMap[I"
Yifan Hong158655a2016-11-08 12:34:07 -0800789 << iface->getBaseName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800790 << "::descriptor]\n";
Yifan Hong158655a2016-11-08 12:34:07 -0800791 out.indentBlock(2, [&] {
792 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
793 out.indentBlock([&] {
794 out << "return new Bn"
795 << iface->getBaseName()
796 << "(reinterpret_cast<I"
797 << iface->getBaseName()
798 << " *>(iIntf));\n";
799 });
800 out << "};\n";
801 });
802 out << "return 1;\n";
803 });
804 out << "}();\n\n";
805
Yifan Hongfe95aa22016-10-19 17:26:45 -0700806 err = generateInterfaceSource(out);
807 }
808
809 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -0700810 err = generateProxySource(out, baseName);
811 }
812
813 if (err == OK && isInterface) {
814 err = generateStubSource(out, baseName);
815 }
816
Steven Moreland40786312016-08-16 10:29:40 -0700817 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700818 err = generatePassthroughSource(out);
819 }
820
821 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700822 const Interface *iface = mRootScope->getInterface();
823
Steven Moreland0693f312016-11-09 15:06:14 -0800824 out << "IMPLEMENT_SERVICE_MANAGER_INTERACTIONS("
Steven Moreland9c387612016-09-07 09:54:26 -0700825 << baseName << ", "
826 << "\"" << iface->fqName().package()
Steven Moreland7e367bf2016-11-04 11:31:41 -0700827 << iface->fqName().atVersion()
828 << "\")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700829 }
830
Andreas Huber881227d2016-08-02 14:20:21 -0700831 enterLeaveNamespace(out, false /* enter */);
832
833 return err;
834}
835
Steven Moreland67f67b42016-09-29 08:59:02 -0700836// static
837void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
838 out << "if (" << nonNull << " == nullptr) {\n";
839 out.indent();
840 out << "return ::android::hardware::Status::fromExceptionCode(\n";
841 out.indent();
842 out.indent();
843 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
844 out.unindent();
845 out.unindent();
846 out.unindent();
847 out << "}\n\n";
848}
849
Andreas Huber881227d2016-08-02 14:20:21 -0700850status_t AST::generateTypeSource(
851 Formatter &out, const std::string &ifaceName) const {
852 return mRootScope->emitTypeDefinitions(out, ifaceName);
853}
854
Andreas Hubere7ff2282016-08-16 13:50:03 -0700855void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700856 Formatter &out,
857 const std::vector<TypedVar *> &args,
858 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700859 if (args.empty()) {
860 return;
861 }
862
863 for (const auto &arg : args) {
864 const Type &type = arg->type();
865
Yifan Hong3b320f82016-11-01 15:15:54 -0700866 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700867 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -0700868 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700869 << ";\n";
870 }
871
872 out << "\n";
873}
874
Andreas Huber881227d2016-08-02 14:20:21 -0700875void AST::emitCppReaderWriter(
876 Formatter &out,
877 const std::string &parcelObj,
878 bool parcelObjIsPointer,
879 const TypedVar *arg,
880 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700881 Type::ErrorMode mode,
882 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700883 const Type &type = arg->type();
884
Andreas Huber881227d2016-08-02 14:20:21 -0700885 type.emitReaderWriter(
886 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700887 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700888 parcelObj,
889 parcelObjIsPointer,
890 isReader,
891 mode);
892}
893
Yifan Hongbf459bc2016-08-23 16:50:37 -0700894void AST::emitCppResolveReferences(
895 Formatter &out,
896 const std::string &parcelObj,
897 bool parcelObjIsPointer,
898 const TypedVar *arg,
899 bool isReader,
900 Type::ErrorMode mode,
901 bool addPrefixToName) const {
902 const Type &type = arg->type();
903 if(type.needsResolveReferences()) {
904 type.emitResolveReferences(
905 out,
906 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
907 isReader, // nameIsPointer
908 parcelObj,
909 parcelObjIsPointer,
910 isReader,
911 mode);
912 }
913}
914
Yifan Hong068c5522016-10-31 14:07:25 -0700915status_t AST::generateProxyMethodSource(Formatter &out,
916 const std::string &klassName,
917 const Method *method,
918 const Interface *superInterface) const {
919
920 method->generateCppSignature(out,
921 klassName,
922 true /* specify namespaces */);
923
924 const bool returnsValue = !method->results().empty();
925 const TypedVar *elidedReturn = method->canElideCallback();
926
Steven Moreland41c6d2e2016-11-07 12:26:54 -0800927 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700928
929 out.indent();
930
931 if (returnsValue && elidedReturn == nullptr) {
932 generateCheckNonNull(out, "_hidl_cb");
933 }
934
935 status_t status = generateCppInstrumentationCall(
936 out,
937 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -0700938 method);
939 if (status != OK) {
940 return status;
941 }
942
943 out << "::android::hardware::Parcel _hidl_data;\n";
944 out << "::android::hardware::Parcel _hidl_reply;\n";
945 out << "::android::status_t _hidl_err;\n";
946 out << "::android::hardware::Status _hidl_status;\n\n";
947
948 declareCppReaderLocals(
949 out, method->results(), true /* forResults */);
950
951 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Steven Morelandd39133b2016-11-11 12:30:08 -0800952 if (method->isHidlReserved()) {
Yifan Hong5bd9aff2016-11-08 18:52:55 -0800953 out << "::android::hardware::IBase";
Steven Morelandd39133b2016-11-11 12:30:08 -0800954 } else {
955 out << superInterface->fqName().cppNamespace()
956 << "::I"
957 << superInterface->getBaseName();
Yifan Hong068c5522016-10-31 14:07:25 -0700958 }
959 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700960 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
961
962 // First DFS: write all buffers and resolve pointers for parent
963 for (const auto &arg : method->args()) {
964 emitCppReaderWriter(
965 out,
966 "_hidl_data",
967 false /* parcelObjIsPointer */,
968 arg,
969 false /* reader */,
970 Type::ErrorMode_Goto,
971 false /* addPrefixToName */);
972 }
973
974 // Second DFS: resolve references.
975 for (const auto &arg : method->args()) {
976 emitCppResolveReferences(
977 out,
978 "_hidl_data",
979 false /* parcelObjIsPointer */,
980 arg,
981 false /* reader */,
982 Type::ErrorMode_Goto,
983 false /* addPrefixToName */);
984 }
985
986 out << "_hidl_err = remote()->transact("
987 << method->getSerialId()
988 << " /* "
989 << method->name()
990 << " */, _hidl_data, &_hidl_reply";
991
992 if (method->isOneway()) {
993 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
994 }
995 out << ");\n";
996
997 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
998
999 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001000 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001001 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1002 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1003
1004
1005 // First DFS: write all buffers and resolve pointers for parent
1006 for (const auto &arg : method->results()) {
1007 emitCppReaderWriter(
1008 out,
1009 "_hidl_reply",
1010 false /* parcelObjIsPointer */,
1011 arg,
1012 true /* reader */,
1013 Type::ErrorMode_Goto,
1014 true /* addPrefixToName */);
1015 }
1016
1017 // Second DFS: resolve references.
1018 for (const auto &arg : method->results()) {
1019 emitCppResolveReferences(
1020 out,
1021 "_hidl_reply",
1022 false /* parcelObjIsPointer */,
1023 arg,
1024 true /* reader */,
1025 Type::ErrorMode_Goto,
1026 true /* addPrefixToName */);
1027 }
1028
1029 if (returnsValue && elidedReturn == nullptr) {
1030 out << "_hidl_cb(";
1031
1032 bool first = true;
1033 for (const auto &arg : method->results()) {
1034 if (!first) {
1035 out << ", ";
1036 }
1037
1038 if (arg->type().resultNeedsDeref()) {
1039 out << "*";
1040 }
1041 out << "_hidl_out_" << arg->name();
1042
1043 first = false;
1044 }
1045
1046 out << ");\n\n";
1047 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001048 }
1049 status = generateCppInstrumentationCall(
1050 out,
1051 InstrumentationEvent::CLIENT_API_EXIT,
1052 method);
1053 if (status != OK) {
1054 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001055 }
1056
1057 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001058 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1059 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001060 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001061 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1062 } else {
1063 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1064 out << "return ::android::hardware::Return<void>();\n\n";
1065 }
1066
1067 out.unindent();
1068 out << "_hidl_error:\n";
1069 out.indent();
1070 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1071 out << "return ::android::hardware::Return<";
1072 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001073 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001074 } else {
1075 out << "void";
1076 }
1077 out << ">(_hidl_status);\n";
1078
1079 out.unindent();
1080 out << "}\n\n";
1081 return OK;
1082}
1083
Andreas Huber881227d2016-08-02 14:20:21 -07001084status_t AST::generateProxySource(
1085 Formatter &out, const std::string &baseName) const {
1086 const std::string klassName = "Bp" + baseName;
1087
1088 out << klassName
1089 << "::"
1090 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001091 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001092
1093 out.indent();
1094 out.indent();
1095
1096 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -07001097 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -07001098 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001099 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001100 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001101 << mPackage.string()
1102 << "::I"
1103 << baseName
1104 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001105
Andreas Huber881227d2016-08-02 14:20:21 -07001106 out.unindent();
1107 out.unindent();
1108 out << "}\n\n";
1109
Yifan Hong068c5522016-10-31 14:07:25 -07001110 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1111 return generateProxyMethodSource(out, klassName, method, superInterface);
1112 });
Andreas Huber881227d2016-08-02 14:20:21 -07001113
Yifan Hong068c5522016-10-31 14:07:25 -07001114 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001115}
1116
1117status_t AST::generateStubSource(
1118 Formatter &out, const std::string &baseName) const {
1119 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1120 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001121 << ", "
1122 << mPackage.cppNamespace()
Andreas Huber881227d2016-08-02 14:20:21 -07001123 << "::I"
1124 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001125 << "::descriptor);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001126
1127 const std::string klassName = "Bn" + baseName;
1128
Steven Moreland40786312016-08-16 10:29:40 -07001129 out << klassName
1130 << "::"
1131 << klassName
1132 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1133
1134 out.indent();
1135 out.indent();
1136
1137 out << ": BnInterface"
1138 << "<I"
1139 << baseName
1140 << ", IHw"
1141 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001142 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001143 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001144 << mPackage.string()
1145 << "::I"
1146 << baseName
1147 << "\") {\n";
Steven Moreland40786312016-08-16 10:29:40 -07001148
1149 out.unindent();
1150 out.unindent();
1151 out << "}\n\n";
1152
Andreas Huber881227d2016-08-02 14:20:21 -07001153 out << "::android::status_t " << klassName << "::onTransact(\n";
1154
1155 out.indent();
1156 out.indent();
1157
Iliyan Malchev549e2592016-08-10 08:59:12 -07001158 out << "uint32_t _hidl_code,\n"
1159 << "const ::android::hardware::Parcel &_hidl_data,\n"
1160 << "::android::hardware::Parcel *_hidl_reply,\n"
1161 << "uint32_t _hidl_flags,\n"
1162 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001163
1164 out.unindent();
1165
Iliyan Malchev549e2592016-08-10 08:59:12 -07001166 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001167 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001168 out.indent();
1169
1170 const Interface *iface = mRootScope->getInterface();
1171
Yifan Hong10fe0b52016-10-19 14:20:17 -07001172 for (const auto &tuple : iface->allMethodsFromRoot()) {
1173 const Method *method = tuple.method();
1174 const Interface *superInterface = tuple.interface();
1175 out << "case "
1176 << method->getSerialId()
1177 << " /* "
1178 << method->name()
1179 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001180
Yifan Hong10fe0b52016-10-19 14:20:17 -07001181 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001182
Yifan Hong10fe0b52016-10-19 14:20:17 -07001183 status_t err =
1184 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001185
Yifan Hong10fe0b52016-10-19 14:20:17 -07001186 if (err != OK) {
1187 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001188 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001189
1190 out.unindent();
1191 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001192 }
1193
1194 out << "default:\n{\n";
1195 out.indent();
1196
Andreas Huber8a82ff72016-08-04 10:29:39 -07001197 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001198 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001199 << ">::onTransact(\n";
1200
1201 out.indent();
1202 out.indent();
1203
Iliyan Malchev549e2592016-08-10 08:59:12 -07001204 out << "_hidl_code, _hidl_data, _hidl_reply, "
1205 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001206
1207 out.unindent();
1208 out.unindent();
1209
1210 out.unindent();
1211 out << "}\n";
1212
1213 out.unindent();
1214 out << "}\n\n";
1215
Iliyan Malchev549e2592016-08-10 08:59:12 -07001216 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001217 out.indent();
Yifan Hong859e53f2016-11-14 19:08:24 -08001218 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001219 out.indent();
1220 out.indent();
Yifan Hong859e53f2016-11-14 19:08:24 -08001221 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1222 out << "_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001223 out.unindent();
1224 out.unindent();
1225
1226 out.unindent();
1227 out << "}\n\n";
1228
Iliyan Malchev549e2592016-08-10 08:59:12 -07001229 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001230
1231 out.unindent();
1232 out << "}\n\n";
1233
1234 return OK;
1235}
1236
1237status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001238 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001239 out << "if (!_hidl_data.enforceInterface(";
1240
Steven Morelandd39133b2016-11-11 12:30:08 -08001241 if (method->isHidlReserved()) {
Yifan Hong5bd9aff2016-11-08 18:52:55 -08001242 out << "::android::hardware::IBase";
Steven Morelandd39133b2016-11-11 12:30:08 -08001243 } else {
1244 out << iface->fqName().cppNamespace()
1245 << "::I"
1246 << iface->getBaseName();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001247 }
1248
1249 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001250
Andreas Huber881227d2016-08-02 14:20:21 -07001251 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001252 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001253 out << "break;\n";
1254 out.unindent();
1255 out << "}\n\n";
1256
Andreas Huber5e44a292016-09-27 14:52:39 -07001257 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001258
Yifan Hongbf459bc2016-08-23 16:50:37 -07001259 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001260 for (const auto &arg : method->args()) {
1261 emitCppReaderWriter(
1262 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001263 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001264 false /* parcelObjIsPointer */,
1265 arg,
1266 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001267 Type::ErrorMode_Break,
1268 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001269 }
1270
Yifan Hongbf459bc2016-08-23 16:50:37 -07001271 // Second DFS: resolve references
1272 for (const auto &arg : method->args()) {
1273 emitCppResolveReferences(
1274 out,
1275 "_hidl_data",
1276 false /* parcelObjIsPointer */,
1277 arg,
1278 true /* reader */,
1279 Type::ErrorMode_Break,
1280 false /* addPrefixToName */);
1281 }
1282
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001283 status_t status = generateCppInstrumentationCall(
1284 out,
1285 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001286 method);
1287 if (status != OK) {
1288 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001289 }
1290
Andreas Huber881227d2016-08-02 14:20:21 -07001291 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001292 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001293
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001294 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001295 out << elidedReturn->type().getCppResultType()
1296 << " "
1297 << elidedReturn->name()
1298 << " = "
1299 << method->name()
1300 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001301
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001302 bool first = true;
1303 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001304 if (!first) {
1305 out << ", ";
1306 }
1307
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001308 if (arg->type().resultNeedsDeref()) {
1309 out << "*";
1310 }
1311
1312 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001313
1314 first = false;
1315 }
1316
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001317 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001318 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1319 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001320
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001321 elidedReturn->type().emitReaderWriter(
1322 out,
1323 elidedReturn->name(),
1324 "_hidl_reply",
1325 true, /* parcelObjIsPointer */
1326 false, /* isReader */
1327 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001328
Yifan Hongbf459bc2016-08-23 16:50:37 -07001329 emitCppResolveReferences(
1330 out,
1331 "_hidl_reply",
1332 true /* parcelObjIsPointer */,
1333 elidedReturn,
1334 false /* reader */,
1335 Type::ErrorMode_Ignore,
1336 false /* addPrefixToName */);
1337
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001338 status_t status = generateCppInstrumentationCall(
1339 out,
1340 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001341 method);
1342 if (status != OK) {
1343 return status;
1344 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001345
Iliyan Malchev549e2592016-08-10 08:59:12 -07001346 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001347 } else {
1348 if (returnsValue) {
1349 out << "bool _hidl_callbackCalled = false;\n\n";
1350 }
Andreas Huber881227d2016-08-02 14:20:21 -07001351
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001352 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001353
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001354 bool first = true;
1355 for (const auto &arg : method->args()) {
1356 if (!first) {
1357 out << ", ";
1358 }
Andreas Huber881227d2016-08-02 14:20:21 -07001359
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001360 if (arg->type().resultNeedsDeref()) {
1361 out << "*";
1362 }
1363
1364 out << arg->name();
1365
1366 first = false;
1367 }
1368
1369 if (returnsValue) {
1370 if (!first) {
1371 out << ", ";
1372 }
1373
1374 out << "[&](";
1375
1376 first = true;
1377 for (const auto &arg : method->results()) {
1378 if (!first) {
1379 out << ", ";
1380 }
1381
1382 out << "const auto &" << arg->name();
1383
1384 first = false;
1385 }
1386
1387 out << ") {\n";
1388 out.indent();
1389 out << "_hidl_callbackCalled = true;\n\n";
1390
Yifan Hong859e53f2016-11-14 19:08:24 -08001391 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1392 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001393
Yifan Hongbf459bc2016-08-23 16:50:37 -07001394 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001395 for (const auto &arg : method->results()) {
1396 emitCppReaderWriter(
1397 out,
1398 "_hidl_reply",
1399 true /* parcelObjIsPointer */,
1400 arg,
1401 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001402 Type::ErrorMode_Ignore,
1403 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001404 }
1405
Yifan Hongbf459bc2016-08-23 16:50:37 -07001406 // Second DFS: resolve references
1407 for (const auto &arg : method->results()) {
1408 emitCppResolveReferences(
1409 out,
1410 "_hidl_reply",
1411 true /* parcelObjIsPointer */,
1412 arg,
1413 false /* reader */,
1414 Type::ErrorMode_Ignore,
1415 false /* addPrefixToName */);
1416 }
1417
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001418 status_t status = generateCppInstrumentationCall(
1419 out,
1420 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001421 method);
1422 if (status != OK) {
1423 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001424 }
1425
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001426 out << "_hidl_cb(*_hidl_reply);\n";
1427
1428 out.unindent();
1429 out << "}\n";
1430 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001431 out << ");\n\n";
1432
1433 // What to do if the stub implementation has a synchronous callback
1434 // which does not get invoked? This is not a transport error but a
1435 // service error of sorts. For now, return OK to the caller, as this is
1436 // not a transport error.
1437 //
1438 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001439
1440 if (returnsValue) {
1441 out << "if (!_hidl_callbackCalled) {\n";
1442 out.indent();
1443 }
1444
Yifan Hong859e53f2016-11-14 19:08:24 -08001445 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1446 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001447
1448 if (returnsValue) {
1449 out.unindent();
1450 out << "}\n\n";
1451 }
Andreas Huber881227d2016-08-02 14:20:21 -07001452 }
1453
1454 out << "break;\n";
1455
1456 return OK;
1457}
1458
Steven Moreland69e7c702016-09-09 11:16:32 -07001459status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1460 std::string ifaceName;
1461 if (!AST::isInterface(&ifaceName)) {
1462 // types.hal does not get a stub header.
1463 return OK;
1464 }
1465
1466 const Interface *iface = mRootScope->getInterface();
1467
1468 const std::string baseName = iface->getBaseName();
1469 const std::string klassName = "Bs" + baseName;
1470
1471 bool supportOneway = iface->hasOnewayMethods();
1472
1473 std::string path = outputPath;
1474 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1475 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1476 path.append(klassName);
1477 path.append(".h");
1478
1479 CHECK(Coordinator::MakeParentHierarchy(path));
1480 FILE *file = fopen(path.c_str(), "w");
1481
1482 if (file == NULL) {
1483 return -errno;
1484 }
1485
1486 Formatter out(file);
1487
1488 const std::string guard = makeHeaderGuard(klassName);
1489
1490 out << "#ifndef " << guard << "\n";
1491 out << "#define " << guard << "\n\n";
1492
1493 std::vector<std::string> packageComponents;
1494 getPackageAndVersionComponents(
1495 &packageComponents, false /* cpp_compatible */);
1496
1497 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001498
1499 generateCppPackageInclude(out, mPackage, ifaceName);
1500 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001501
1502 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001503 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001504 }
1505
1506 enterLeaveNamespace(out, true /* enter */);
1507 out << "\n";
1508
1509 out << "struct "
1510 << klassName
1511 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001512 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001513
1514 out.indent();
1515 out << "explicit "
1516 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001517 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001518 << ifaceName
1519 << "> impl);\n";
1520
Yifan Hong068c5522016-10-31 14:07:25 -07001521 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1522 return generatePassthroughMethod(out, method);
1523 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001524
1525 if (err != OK) {
1526 return err;
1527 }
1528
1529 out.unindent();
1530 out << "private:\n";
1531 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001532 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001533
1534 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001535 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001536
1537 out << "\n";
1538
1539 out << "::android::hardware::Return<void> addOnewayTask("
1540 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001541 }
1542
1543 out.unindent();
1544
1545 out << "};\n\n";
1546
1547 enterLeaveNamespace(out, false /* enter */);
1548
1549 out << "\n#endif // " << guard << "\n";
1550
1551 return OK;
1552}
1553
Yifan Hongfe95aa22016-10-19 17:26:45 -07001554status_t AST::generateInterfaceSource(Formatter &out) const {
1555 const Interface *iface = mRootScope->getInterface();
1556
Yifan Hong2d7126b2016-10-20 15:12:57 -07001557 // generate castFrom functions
Yifan Hongfe95aa22016-10-19 17:26:45 -07001558 if (!iface->isRootType()) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001559 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001560
1561 for (const Interface *superType : iface->superTypeChain()) {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001562 out << "// static \n"
1563 << childTypeResult
1564 << " I"
1565 << iface->getBaseName()
1566 << "::castFrom("
Yifan Hong3b320f82016-11-01 15:15:54 -07001567 << superType->getCppArgumentType()
1568 << " parent) {\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001569 out.indent();
1570 out << "return ::android::hardware::castInterface<";
1571 out << "I" << iface->getBaseName() << ", "
1572 << superType->fqName().cppName() << ", "
Yifan Hong158655a2016-11-08 12:34:07 -08001573 << "Bp" << iface->getBaseName() << ", "
1574 << superType->getHwName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001575 << ">(\n";
1576 out.indent();
1577 out.indent();
1578 out << "parent, \""
1579 << iface->fqName().string()
1580 << "\");\n";
1581 out.unindent();
1582 out.unindent();
1583 out.unindent();
1584 out << "}\n\n";
1585 }
1586 }
1587
1588 return OK;
1589}
1590
Steven Moreland69e7c702016-09-09 11:16:32 -07001591status_t AST::generatePassthroughSource(Formatter &out) const {
1592 const Interface *iface = mRootScope->getInterface();
1593
1594 const std::string baseName = iface->getBaseName();
1595 const std::string klassName = "Bs" + baseName;
1596
1597 out << klassName
1598 << "::"
1599 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001600 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001601 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001602 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001603 << iface->fqName().string()
1604 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001605 if (iface->hasOnewayMethods()) {
1606 out << "\n";
1607 out.indentBlock([&] {
1608 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1609 });
1610 }
1611 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001612
1613 if (iface->hasOnewayMethods()) {
1614 out << "::android::hardware::Return<void> "
1615 << klassName
1616 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1617 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001618 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001619 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001620 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1621 out.indent();
1622 out.indent();
1623 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1624 out.unindent();
1625 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001626 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001627 out << "}\n";
1628
Steven Morelandd366c262016-10-11 15:29:10 -07001629 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001630
1631 out.unindent();
1632 out << "}\n\n";
1633
1634
1635 }
1636
1637 return OK;
1638}
1639
Martijn Coenen7b295242016-11-04 16:52:56 +01001640status_t AST::generateCppAtraceCall(Formatter &out,
1641 InstrumentationEvent event,
1642 const Method *method) const {
1643 const Interface *iface = mRootScope->getInterface();
1644 std::string baseString = "HIDL::I" + iface->getBaseName() + "::" + method->name();
1645 switch (event) {
1646 case SERVER_API_ENTRY:
1647 {
1648 out << "atrace_begin(ATRACE_TAG_HAL, \""
1649 << baseString + "::server\");\n";
1650 break;
1651 }
1652 case CLIENT_API_ENTRY:
1653 {
1654 out << "atrace_begin(ATRACE_TAG_HAL, \""
1655 << baseString + "::client\");\n";
1656 break;
1657 }
1658 case PASSTHROUGH_ENTRY:
1659 {
1660 out << "atrace_begin(ATRACE_TAG_HAL, \""
1661 << baseString + "::passthrough\");\n";
1662 break;
1663 }
1664 case SERVER_API_EXIT:
1665 case CLIENT_API_EXIT:
1666 case PASSTHROUGH_EXIT:
1667 {
1668 out << "atrace_end(ATRACE_TAG_HAL);\n";
1669 break;
1670 }
1671 default:
1672 {
1673 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1674 return UNKNOWN_ERROR;
1675 }
1676 }
1677
1678 return OK;
1679}
1680
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001681status_t AST::generateCppInstrumentationCall(
1682 Formatter &out,
1683 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001684 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001685 status_t err = generateCppAtraceCall(out, event, method);
1686 if (err != OK) {
1687 return err;
1688 }
1689
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001690 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1691 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001692 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001693 std::string event_str = "";
1694 switch (event) {
1695 case SERVER_API_ENTRY:
1696 {
1697 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1698 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001699 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001700 << (arg->type().resultNeedsDeref() ? "" : "&")
1701 << arg->name()
1702 << ");\n";
1703 }
1704 break;
1705 }
1706 case SERVER_API_EXIT:
1707 {
1708 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001709 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001710 out << "_hidl_args.push_back((void *)&"
Steven Moreland031ccf12016-10-31 15:54:38 -07001711 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001712 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001713 }
1714 break;
1715 }
1716 case CLIENT_API_ENTRY:
1717 {
1718 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1719 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001720 out << "_hidl_args.push_back((void *)&"
1721 << arg->name()
1722 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001723 }
1724 break;
1725 }
1726 case CLIENT_API_EXIT:
1727 {
1728 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1729 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001730 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001731 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001732 << "_hidl_out_"
1733 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001734 << ");\n";
1735 }
1736 break;
1737 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001738 case PASSTHROUGH_ENTRY:
1739 {
1740 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1741 for (const auto &arg : method->args()) {
1742 out << "_hidl_args.push_back((void *)&"
1743 << arg->name()
1744 << ");\n";
1745 }
1746 break;
1747 }
1748 case PASSTHROUGH_EXIT:
1749 {
1750 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
1751 // TODO(b/32576620): passthrough return values
1752 break;
1753 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001754 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001755 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001756 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001757 return UNKNOWN_ERROR;
1758 }
1759 }
1760
Steven Moreland031ccf12016-10-31 15:54:38 -07001761 const Interface *iface = mRootScope->getInterface();
1762
Steven Moreland1ab31442016-11-03 18:37:51 -07001763 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001764 out.indent();
1765 out << "callback("
1766 << event_str
1767 << ", \""
1768 << mPackage.package()
1769 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001770 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001771 << "\", \""
1772 << iface->localName()
1773 << "\", \""
1774 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001775 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001776 out.unindent();
1777 out << "}\n";
1778 out.unindent();
1779 out << "}\n\n";
1780
1781 return OK;
1782}
1783
Andreas Huber881227d2016-08-02 14:20:21 -07001784} // namespace android
1785