blob: f40a9d15f088c620da7d32b0a4f00deb1e1ba6ec [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 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800498 out << "[&](";
499 first = true;
500 for (const auto &arg : method->results()) {
501 if (!first) {
502 out << ", ";
503 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700504
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800505 out << "const auto &" << arg->name();
506
507 first = false;
508 }
509
510 out << ") {\n";
511 out.indent();
512 status_t status = generateCppInstrumentationCall(
513 out,
514 InstrumentationEvent::PASSTHROUGH_EXIT,
515 method);
516 if (status != OK) {
517 return status;
518 }
519
520 out << "_hidl_cb(";
521 first = true;
522 for (const auto &arg : method->results()) {
523 if (!first) {
524 out << ", ";
525 }
526
527 out << arg->name();
528
529 first = false;
530 }
531 out << ");\n";
532 out.unindent();
533 out << "});\n\n";
534 } else {
535 out << ");\n\n";
536 if (elidedReturn != nullptr) {
537 out << elidedReturn->type().getCppResultType()
538 << " "
539 << elidedReturn->name()
540 << " = _hidl_return;\n";
541 }
542 status_t status = generateCppInstrumentationCall(
543 out,
544 InstrumentationEvent::PASSTHROUGH_EXIT,
545 method);
546 if (status != OK) {
547 return status;
548 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700549 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700550
551 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700552 out.unindent();
553 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700554 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700555
556 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700557
558 out.unindent();
559 out << "}\n";
560
561 return OK;
562}
563
Yifan Hong068c5522016-10-31 14:07:25 -0700564status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700565
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700566 const Interface *iface = mRootScope->getInterface();
567
Yifan Hong10fe0b52016-10-19 14:20:17 -0700568 const Interface *prevIterface = nullptr;
569 for (const auto &tuple : iface->allMethodsFromRoot()) {
570 const Method *method = tuple.method();
571 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700572
Yifan Hong10fe0b52016-10-19 14:20:17 -0700573 if(prevIterface != superInterface) {
574 if (prevIterface != nullptr) {
575 out << "\n";
576 }
577 out << "// Methods from "
578 << superInterface->fullName()
579 << " follow.\n";
580 prevIterface = superInterface;
581 }
Yifan Hong068c5522016-10-31 14:07:25 -0700582 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700583
Yifan Hong10fe0b52016-10-19 14:20:17 -0700584 if (err != OK) {
585 return err;
586 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700587 }
588
Yifan Hong10fe0b52016-10-19 14:20:17 -0700589 out << "\n";
590
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700591 return OK;
592}
593
Andreas Huberb82318c2016-08-02 14:45:54 -0700594status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700595 std::string ifaceName;
596 if (!AST::isInterface(&ifaceName)) {
597 // types.hal does not get a stub header.
598 return OK;
599 }
600
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700601 const Interface *iface = mRootScope->getInterface();
602 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700603 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700604
Andreas Huberb82318c2016-08-02 14:45:54 -0700605 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700606 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700607 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700608 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700609 path.append(".h");
610
Andreas Huberd2943e12016-08-05 11:59:31 -0700611 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700612 FILE *file = fopen(path.c_str(), "w");
613
614 if (file == NULL) {
615 return -errno;
616 }
617
618 Formatter out(file);
619
Steven Moreland40786312016-08-16 10:29:40 -0700620 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700621
622 out << "#ifndef " << guard << "\n";
623 out << "#define " << guard << "\n\n";
624
Steven Morelandee88eed2016-10-31 17:49:00 -0700625 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
626 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700627
628 enterLeaveNamespace(out, true /* enter */);
629 out << "\n";
630
631 out << "struct "
632 << "Bn"
633 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700634 << " : public ::android::hardware::BnInterface<I"
635 << baseName << ", IHw" << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700636 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700637
638 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700639 out << "explicit Bn"
640 << baseName
641 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
642 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700643 out << "::android::status_t onTransact(\n";
644 out.indent();
645 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700646 out << "uint32_t _hidl_code,\n";
647 out << "const ::android::hardware::Parcel &_hidl_data,\n";
648 out << "::android::hardware::Parcel *_hidl_reply,\n";
649 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700650 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700651 out.unindent();
652 out.unindent();
653
Yifan Hong068c5522016-10-31 14:07:25 -0700654 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
655 return generateStubMethod(out, method);
656 });
Steven Moreland9c387612016-09-07 09:54:26 -0700657
658 if (err != OK) {
659 return err;
660 }
661
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700662
Andreas Huber881227d2016-08-02 14:20:21 -0700663 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700664 out << "};\n\n";
665
666 enterLeaveNamespace(out, false /* enter */);
667
668 out << "\n#endif // " << guard << "\n";
669
670 return OK;
671}
672
Andreas Huberb82318c2016-08-02 14:45:54 -0700673status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700674 std::string ifaceName;
675 if (!AST::isInterface(&ifaceName)) {
676 // types.hal does not get a proxy header.
677 return OK;
678 }
679
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700680 const Interface *iface = mRootScope->getInterface();
681 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700682
Andreas Huberb82318c2016-08-02 14:45:54 -0700683 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700684 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700685 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700686 path.append("Bp");
687 path.append(baseName);
688 path.append(".h");
689
Andreas Huberd2943e12016-08-05 11:59:31 -0700690 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700691 FILE *file = fopen(path.c_str(), "w");
692
693 if (file == NULL) {
694 return -errno;
695 }
696
697 Formatter out(file);
698
699 const std::string guard = makeHeaderGuard("Bp" + baseName);
700
701 out << "#ifndef " << guard << "\n";
702 out << "#define " << guard << "\n\n";
703
704 std::vector<std::string> packageComponents;
705 getPackageAndVersionComponents(
706 &packageComponents, false /* cpp_compatible */);
707
Steven Morelandee88eed2016-10-31 17:49:00 -0700708 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
709 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700710
711 enterLeaveNamespace(out, true /* enter */);
712 out << "\n";
713
714 out << "struct "
715 << "Bp"
716 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700717 << " : public ::android::hardware::BpInterface<IHw"
718 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700719 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700720
721 out.indent();
722
723 out << "explicit Bp"
724 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700725 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700726 << "\n\n";
727
Yifan Hong10fe0b52016-10-19 14:20:17 -0700728 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700729
Yifan Hong068c5522016-10-31 14:07:25 -0700730 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
731 method->generateCppSignature(out);
732 out << " override;\n";
733 return OK;
734 });
Steven Moreland9c387612016-09-07 09:54:26 -0700735
736 if (err != OK) {
737 return err;
738 }
Andreas Huber881227d2016-08-02 14:20:21 -0700739
740 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700741 out << "};\n\n";
742
743 enterLeaveNamespace(out, false /* enter */);
744
745 out << "\n#endif // " << guard << "\n";
746
747 return OK;
748}
749
Andreas Huberb82318c2016-08-02 14:45:54 -0700750status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700751
Andreas Huberb82318c2016-08-02 14:45:54 -0700752 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700753 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700754 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700755
756 std::string ifaceName;
757 std::string baseName;
758
Yifan Hongfe95aa22016-10-19 17:26:45 -0700759 const Interface *iface = nullptr;
760 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700761 if (!AST::isInterface(&ifaceName)) {
762 baseName = "types";
763 isInterface = false;
764 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700765 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700766 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700767 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700768 }
769
770 path.append(baseName);
771
772 if (baseName != "types") {
773 path.append("All");
774 }
775
776 path.append(".cpp");
777
Andreas Huberd2943e12016-08-05 11:59:31 -0700778 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700779 FILE *file = fopen(path.c_str(), "w");
780
781 if (file == NULL) {
782 return -errno;
783 }
784
785 Formatter out(file);
786
Martijn Coenen7b295242016-11-04 16:52:56 +0100787
788 out << "#include <cutils/trace.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700789 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700790 // This is a no-op for IServiceManager itself.
791 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
792
Steven Morelandee88eed2016-10-31 17:49:00 -0700793 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
794 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
795 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700796
797 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700798 generateCppPackageInclude(out,
799 superType->fqName(),
800 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700801 }
Andreas Huber881227d2016-08-02 14:20:21 -0700802 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700803 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800804 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700805 }
806
807 out << "\n";
808
809 enterLeaveNamespace(out, true /* enter */);
810 out << "\n";
811
812 status_t err = generateTypeSource(out, ifaceName);
813
814 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700815 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700816 out << "constexpr ::android::hardware::hidl_version "
817 << ifaceName
818 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700819
820 // need to be put here, generateStubSource is using this.
Steven Morelandd39133b2016-11-11 12:30:08 -0800821 out << "const char* I"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700822 << iface->getBaseName()
823 << "::descriptor(\""
824 << iface->fqName().string()
825 << "\");\n\n";
826
Yifan Hong158655a2016-11-08 12:34:07 -0800827 out << "int I"
828 << iface->getBaseName()
829 << "::hidlStaticBlock = []() -> int {\n";
830 out.indentBlock([&] {
Steven Morelandd39133b2016-11-11 12:30:08 -0800831 out << "::android::hardware::gBnConstructorMap[I"
Yifan Hong158655a2016-11-08 12:34:07 -0800832 << iface->getBaseName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800833 << "::descriptor]\n";
Yifan Hong158655a2016-11-08 12:34:07 -0800834 out.indentBlock(2, [&] {
835 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
836 out.indentBlock([&] {
837 out << "return new Bn"
838 << iface->getBaseName()
839 << "(reinterpret_cast<I"
840 << iface->getBaseName()
841 << " *>(iIntf));\n";
842 });
843 out << "};\n";
844 });
845 out << "return 1;\n";
846 });
847 out << "}();\n\n";
848
Yifan Hongfe95aa22016-10-19 17:26:45 -0700849 err = generateInterfaceSource(out);
850 }
851
852 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -0700853 err = generateProxySource(out, baseName);
854 }
855
856 if (err == OK && isInterface) {
857 err = generateStubSource(out, baseName);
858 }
859
Steven Moreland40786312016-08-16 10:29:40 -0700860 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700861 err = generatePassthroughSource(out);
862 }
863
864 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700865 const Interface *iface = mRootScope->getInterface();
866
Steven Moreland0693f312016-11-09 15:06:14 -0800867 out << "IMPLEMENT_SERVICE_MANAGER_INTERACTIONS("
Steven Moreland9c387612016-09-07 09:54:26 -0700868 << baseName << ", "
869 << "\"" << iface->fqName().package()
Steven Moreland7e367bf2016-11-04 11:31:41 -0700870 << iface->fqName().atVersion()
871 << "\")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700872 }
873
Andreas Huber881227d2016-08-02 14:20:21 -0700874 enterLeaveNamespace(out, false /* enter */);
875
876 return err;
877}
878
Steven Moreland67f67b42016-09-29 08:59:02 -0700879// static
880void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
881 out << "if (" << nonNull << " == nullptr) {\n";
882 out.indent();
883 out << "return ::android::hardware::Status::fromExceptionCode(\n";
884 out.indent();
885 out.indent();
886 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
887 out.unindent();
888 out.unindent();
889 out.unindent();
890 out << "}\n\n";
891}
892
Andreas Huber881227d2016-08-02 14:20:21 -0700893status_t AST::generateTypeSource(
894 Formatter &out, const std::string &ifaceName) const {
895 return mRootScope->emitTypeDefinitions(out, ifaceName);
896}
897
Andreas Hubere7ff2282016-08-16 13:50:03 -0700898void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700899 Formatter &out,
900 const std::vector<TypedVar *> &args,
901 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700902 if (args.empty()) {
903 return;
904 }
905
906 for (const auto &arg : args) {
907 const Type &type = arg->type();
908
Yifan Hong3b320f82016-11-01 15:15:54 -0700909 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700910 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -0700911 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700912 << ";\n";
913 }
914
915 out << "\n";
916}
917
Andreas Huber881227d2016-08-02 14:20:21 -0700918void AST::emitCppReaderWriter(
919 Formatter &out,
920 const std::string &parcelObj,
921 bool parcelObjIsPointer,
922 const TypedVar *arg,
923 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700924 Type::ErrorMode mode,
925 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700926 const Type &type = arg->type();
927
Andreas Huber881227d2016-08-02 14:20:21 -0700928 type.emitReaderWriter(
929 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700930 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700931 parcelObj,
932 parcelObjIsPointer,
933 isReader,
934 mode);
935}
936
Yifan Hongbf459bc2016-08-23 16:50:37 -0700937void AST::emitCppResolveReferences(
938 Formatter &out,
939 const std::string &parcelObj,
940 bool parcelObjIsPointer,
941 const TypedVar *arg,
942 bool isReader,
943 Type::ErrorMode mode,
944 bool addPrefixToName) const {
945 const Type &type = arg->type();
946 if(type.needsResolveReferences()) {
947 type.emitResolveReferences(
948 out,
949 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
950 isReader, // nameIsPointer
951 parcelObj,
952 parcelObjIsPointer,
953 isReader,
954 mode);
955 }
956}
957
Yifan Hong068c5522016-10-31 14:07:25 -0700958status_t AST::generateProxyMethodSource(Formatter &out,
959 const std::string &klassName,
960 const Method *method,
961 const Interface *superInterface) const {
962
963 method->generateCppSignature(out,
964 klassName,
965 true /* specify namespaces */);
966
967 const bool returnsValue = !method->results().empty();
968 const TypedVar *elidedReturn = method->canElideCallback();
969
Steven Moreland41c6d2e2016-11-07 12:26:54 -0800970 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700971
972 out.indent();
973
974 if (returnsValue && elidedReturn == nullptr) {
975 generateCheckNonNull(out, "_hidl_cb");
976 }
977
978 status_t status = generateCppInstrumentationCall(
979 out,
980 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -0700981 method);
982 if (status != OK) {
983 return status;
984 }
985
986 out << "::android::hardware::Parcel _hidl_data;\n";
987 out << "::android::hardware::Parcel _hidl_reply;\n";
988 out << "::android::status_t _hidl_err;\n";
989 out << "::android::hardware::Status _hidl_status;\n\n";
990
991 declareCppReaderLocals(
992 out, method->results(), true /* forResults */);
993
994 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Steven Morelandd39133b2016-11-11 12:30:08 -0800995 if (method->isHidlReserved()) {
Yifan Hong5bd9aff2016-11-08 18:52:55 -0800996 out << "::android::hardware::IBase";
Steven Morelandd39133b2016-11-11 12:30:08 -0800997 } else {
998 out << superInterface->fqName().cppNamespace()
999 << "::I"
1000 << superInterface->getBaseName();
Yifan Hong068c5522016-10-31 14:07:25 -07001001 }
1002 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001003 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1004
1005 // First DFS: write all buffers and resolve pointers for parent
1006 for (const auto &arg : method->args()) {
1007 emitCppReaderWriter(
1008 out,
1009 "_hidl_data",
1010 false /* parcelObjIsPointer */,
1011 arg,
1012 false /* reader */,
1013 Type::ErrorMode_Goto,
1014 false /* addPrefixToName */);
1015 }
1016
1017 // Second DFS: resolve references.
1018 for (const auto &arg : method->args()) {
1019 emitCppResolveReferences(
1020 out,
1021 "_hidl_data",
1022 false /* parcelObjIsPointer */,
1023 arg,
1024 false /* reader */,
1025 Type::ErrorMode_Goto,
1026 false /* addPrefixToName */);
1027 }
1028
1029 out << "_hidl_err = remote()->transact("
1030 << method->getSerialId()
1031 << " /* "
1032 << method->name()
1033 << " */, _hidl_data, &_hidl_reply";
1034
1035 if (method->isOneway()) {
1036 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1037 }
1038 out << ");\n";
1039
1040 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1041
1042 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001043 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001044 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1045 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1046
1047
1048 // First DFS: write all buffers and resolve pointers for parent
1049 for (const auto &arg : method->results()) {
1050 emitCppReaderWriter(
1051 out,
1052 "_hidl_reply",
1053 false /* parcelObjIsPointer */,
1054 arg,
1055 true /* reader */,
1056 Type::ErrorMode_Goto,
1057 true /* addPrefixToName */);
1058 }
1059
1060 // Second DFS: resolve references.
1061 for (const auto &arg : method->results()) {
1062 emitCppResolveReferences(
1063 out,
1064 "_hidl_reply",
1065 false /* parcelObjIsPointer */,
1066 arg,
1067 true /* reader */,
1068 Type::ErrorMode_Goto,
1069 true /* addPrefixToName */);
1070 }
1071
1072 if (returnsValue && elidedReturn == nullptr) {
1073 out << "_hidl_cb(";
1074
1075 bool first = true;
1076 for (const auto &arg : method->results()) {
1077 if (!first) {
1078 out << ", ";
1079 }
1080
1081 if (arg->type().resultNeedsDeref()) {
1082 out << "*";
1083 }
1084 out << "_hidl_out_" << arg->name();
1085
1086 first = false;
1087 }
1088
1089 out << ");\n\n";
1090 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001091 }
1092 status = generateCppInstrumentationCall(
1093 out,
1094 InstrumentationEvent::CLIENT_API_EXIT,
1095 method);
1096 if (status != OK) {
1097 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001098 }
1099
1100 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001101 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1102 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001103 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001104 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1105 } else {
1106 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1107 out << "return ::android::hardware::Return<void>();\n\n";
1108 }
1109
1110 out.unindent();
1111 out << "_hidl_error:\n";
1112 out.indent();
1113 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1114 out << "return ::android::hardware::Return<";
1115 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001116 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001117 } else {
1118 out << "void";
1119 }
1120 out << ">(_hidl_status);\n";
1121
1122 out.unindent();
1123 out << "}\n\n";
1124 return OK;
1125}
1126
Andreas Huber881227d2016-08-02 14:20:21 -07001127status_t AST::generateProxySource(
1128 Formatter &out, const std::string &baseName) const {
1129 const std::string klassName = "Bp" + baseName;
1130
1131 out << klassName
1132 << "::"
1133 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001134 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001135
1136 out.indent();
1137 out.indent();
1138
1139 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -07001140 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -07001141 << 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";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001148
Andreas Huber881227d2016-08-02 14:20:21 -07001149 out.unindent();
1150 out.unindent();
1151 out << "}\n\n";
1152
Yifan Hong068c5522016-10-31 14:07:25 -07001153 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1154 return generateProxyMethodSource(out, klassName, method, superInterface);
1155 });
Andreas Huber881227d2016-08-02 14:20:21 -07001156
Yifan Hong068c5522016-10-31 14:07:25 -07001157 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001158}
1159
1160status_t AST::generateStubSource(
1161 Formatter &out, const std::string &baseName) const {
1162 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1163 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001164 << ", "
1165 << mPackage.cppNamespace()
Andreas Huber881227d2016-08-02 14:20:21 -07001166 << "::I"
1167 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001168 << "::descriptor);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001169
1170 const std::string klassName = "Bn" + baseName;
1171
Steven Moreland40786312016-08-16 10:29:40 -07001172 out << klassName
1173 << "::"
1174 << klassName
1175 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1176
1177 out.indent();
1178 out.indent();
1179
1180 out << ": BnInterface"
1181 << "<I"
1182 << baseName
1183 << ", IHw"
1184 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001185 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001186 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001187 << mPackage.string()
1188 << "::I"
1189 << baseName
1190 << "\") {\n";
Steven Moreland40786312016-08-16 10:29:40 -07001191
1192 out.unindent();
1193 out.unindent();
1194 out << "}\n\n";
1195
Andreas Huber881227d2016-08-02 14:20:21 -07001196 out << "::android::status_t " << klassName << "::onTransact(\n";
1197
1198 out.indent();
1199 out.indent();
1200
Iliyan Malchev549e2592016-08-10 08:59:12 -07001201 out << "uint32_t _hidl_code,\n"
1202 << "const ::android::hardware::Parcel &_hidl_data,\n"
1203 << "::android::hardware::Parcel *_hidl_reply,\n"
1204 << "uint32_t _hidl_flags,\n"
1205 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001206
1207 out.unindent();
1208
Iliyan Malchev549e2592016-08-10 08:59:12 -07001209 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001210 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001211 out.indent();
1212
1213 const Interface *iface = mRootScope->getInterface();
1214
Yifan Hong10fe0b52016-10-19 14:20:17 -07001215 for (const auto &tuple : iface->allMethodsFromRoot()) {
1216 const Method *method = tuple.method();
1217 const Interface *superInterface = tuple.interface();
1218 out << "case "
1219 << method->getSerialId()
1220 << " /* "
1221 << method->name()
1222 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001223
Yifan Hong10fe0b52016-10-19 14:20:17 -07001224 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001225
Yifan Hong10fe0b52016-10-19 14:20:17 -07001226 status_t err =
1227 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001228
Yifan Hong10fe0b52016-10-19 14:20:17 -07001229 if (err != OK) {
1230 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001231 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001232
1233 out.unindent();
1234 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001235 }
1236
1237 out << "default:\n{\n";
1238 out.indent();
1239
Andreas Huber8a82ff72016-08-04 10:29:39 -07001240 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001241 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001242 << ">::onTransact(\n";
1243
1244 out.indent();
1245 out.indent();
1246
Iliyan Malchev549e2592016-08-10 08:59:12 -07001247 out << "_hidl_code, _hidl_data, _hidl_reply, "
1248 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001249
1250 out.unindent();
1251 out.unindent();
1252
1253 out.unindent();
1254 out << "}\n";
1255
1256 out.unindent();
1257 out << "}\n\n";
1258
Iliyan Malchev549e2592016-08-10 08:59:12 -07001259 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001260 out.indent();
Yifan Hong859e53f2016-11-14 19:08:24 -08001261 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001262 out.indent();
1263 out.indent();
Yifan Hong859e53f2016-11-14 19:08:24 -08001264 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1265 out << "_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001266 out.unindent();
1267 out.unindent();
1268
1269 out.unindent();
1270 out << "}\n\n";
1271
Iliyan Malchev549e2592016-08-10 08:59:12 -07001272 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001273
1274 out.unindent();
1275 out << "}\n\n";
1276
1277 return OK;
1278}
1279
1280status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001281 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001282 out << "if (!_hidl_data.enforceInterface(";
1283
Steven Morelandd39133b2016-11-11 12:30:08 -08001284 if (method->isHidlReserved()) {
Yifan Hong5bd9aff2016-11-08 18:52:55 -08001285 out << "::android::hardware::IBase";
Steven Morelandd39133b2016-11-11 12:30:08 -08001286 } else {
1287 out << iface->fqName().cppNamespace()
1288 << "::I"
1289 << iface->getBaseName();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001290 }
1291
1292 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001293
Andreas Huber881227d2016-08-02 14:20:21 -07001294 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001295 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001296 out << "break;\n";
1297 out.unindent();
1298 out << "}\n\n";
1299
Andreas Huber5e44a292016-09-27 14:52:39 -07001300 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001301
Yifan Hongbf459bc2016-08-23 16:50:37 -07001302 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001303 for (const auto &arg : method->args()) {
1304 emitCppReaderWriter(
1305 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001306 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001307 false /* parcelObjIsPointer */,
1308 arg,
1309 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001310 Type::ErrorMode_Break,
1311 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001312 }
1313
Yifan Hongbf459bc2016-08-23 16:50:37 -07001314 // Second DFS: resolve references
1315 for (const auto &arg : method->args()) {
1316 emitCppResolveReferences(
1317 out,
1318 "_hidl_data",
1319 false /* parcelObjIsPointer */,
1320 arg,
1321 true /* reader */,
1322 Type::ErrorMode_Break,
1323 false /* addPrefixToName */);
1324 }
1325
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001326 status_t status = generateCppInstrumentationCall(
1327 out,
1328 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001329 method);
1330 if (status != OK) {
1331 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001332 }
1333
Andreas Huber881227d2016-08-02 14:20:21 -07001334 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001335 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001336
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001337 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001338 out << elidedReturn->type().getCppResultType()
1339 << " "
1340 << elidedReturn->name()
1341 << " = "
1342 << method->name()
1343 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001344
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001345 bool first = true;
1346 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001347 if (!first) {
1348 out << ", ";
1349 }
1350
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001351 if (arg->type().resultNeedsDeref()) {
1352 out << "*";
1353 }
1354
1355 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001356
1357 first = false;
1358 }
1359
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001360 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001361 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1362 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001363
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001364 elidedReturn->type().emitReaderWriter(
1365 out,
1366 elidedReturn->name(),
1367 "_hidl_reply",
1368 true, /* parcelObjIsPointer */
1369 false, /* isReader */
1370 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001371
Yifan Hongbf459bc2016-08-23 16:50:37 -07001372 emitCppResolveReferences(
1373 out,
1374 "_hidl_reply",
1375 true /* parcelObjIsPointer */,
1376 elidedReturn,
1377 false /* reader */,
1378 Type::ErrorMode_Ignore,
1379 false /* addPrefixToName */);
1380
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001381 status_t status = generateCppInstrumentationCall(
1382 out,
1383 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001384 method);
1385 if (status != OK) {
1386 return status;
1387 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001388
Iliyan Malchev549e2592016-08-10 08:59:12 -07001389 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001390 } else {
1391 if (returnsValue) {
1392 out << "bool _hidl_callbackCalled = false;\n\n";
1393 }
Andreas Huber881227d2016-08-02 14:20:21 -07001394
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001395 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001396
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001397 bool first = true;
1398 for (const auto &arg : method->args()) {
1399 if (!first) {
1400 out << ", ";
1401 }
Andreas Huber881227d2016-08-02 14:20:21 -07001402
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001403 if (arg->type().resultNeedsDeref()) {
1404 out << "*";
1405 }
1406
1407 out << arg->name();
1408
1409 first = false;
1410 }
1411
1412 if (returnsValue) {
1413 if (!first) {
1414 out << ", ";
1415 }
1416
1417 out << "[&](";
1418
1419 first = true;
1420 for (const auto &arg : method->results()) {
1421 if (!first) {
1422 out << ", ";
1423 }
1424
1425 out << "const auto &" << arg->name();
1426
1427 first = false;
1428 }
1429
1430 out << ") {\n";
1431 out.indent();
1432 out << "_hidl_callbackCalled = true;\n\n";
1433
Yifan Hong859e53f2016-11-14 19:08:24 -08001434 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1435 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001436
Yifan Hongbf459bc2016-08-23 16:50:37 -07001437 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001438 for (const auto &arg : method->results()) {
1439 emitCppReaderWriter(
1440 out,
1441 "_hidl_reply",
1442 true /* parcelObjIsPointer */,
1443 arg,
1444 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001445 Type::ErrorMode_Ignore,
1446 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001447 }
1448
Yifan Hongbf459bc2016-08-23 16:50:37 -07001449 // Second DFS: resolve references
1450 for (const auto &arg : method->results()) {
1451 emitCppResolveReferences(
1452 out,
1453 "_hidl_reply",
1454 true /* parcelObjIsPointer */,
1455 arg,
1456 false /* reader */,
1457 Type::ErrorMode_Ignore,
1458 false /* addPrefixToName */);
1459 }
1460
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001461 status_t status = generateCppInstrumentationCall(
1462 out,
1463 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001464 method);
1465 if (status != OK) {
1466 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001467 }
1468
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001469 out << "_hidl_cb(*_hidl_reply);\n";
1470
1471 out.unindent();
1472 out << "}\n";
1473 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001474 out << ");\n\n";
1475
1476 // What to do if the stub implementation has a synchronous callback
1477 // which does not get invoked? This is not a transport error but a
1478 // service error of sorts. For now, return OK to the caller, as this is
1479 // not a transport error.
1480 //
1481 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001482
1483 if (returnsValue) {
1484 out << "if (!_hidl_callbackCalled) {\n";
1485 out.indent();
1486 }
1487
Yifan Hong859e53f2016-11-14 19:08:24 -08001488 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1489 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001490
1491 if (returnsValue) {
1492 out.unindent();
1493 out << "}\n\n";
1494 }
Andreas Huber881227d2016-08-02 14:20:21 -07001495 }
1496
1497 out << "break;\n";
1498
1499 return OK;
1500}
1501
Steven Moreland69e7c702016-09-09 11:16:32 -07001502status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1503 std::string ifaceName;
1504 if (!AST::isInterface(&ifaceName)) {
1505 // types.hal does not get a stub header.
1506 return OK;
1507 }
1508
1509 const Interface *iface = mRootScope->getInterface();
1510
1511 const std::string baseName = iface->getBaseName();
1512 const std::string klassName = "Bs" + baseName;
1513
1514 bool supportOneway = iface->hasOnewayMethods();
1515
1516 std::string path = outputPath;
1517 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1518 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1519 path.append(klassName);
1520 path.append(".h");
1521
1522 CHECK(Coordinator::MakeParentHierarchy(path));
1523 FILE *file = fopen(path.c_str(), "w");
1524
1525 if (file == NULL) {
1526 return -errno;
1527 }
1528
1529 Formatter out(file);
1530
1531 const std::string guard = makeHeaderGuard(klassName);
1532
1533 out << "#ifndef " << guard << "\n";
1534 out << "#define " << guard << "\n\n";
1535
1536 std::vector<std::string> packageComponents;
1537 getPackageAndVersionComponents(
1538 &packageComponents, false /* cpp_compatible */);
1539
1540 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001541
1542 generateCppPackageInclude(out, mPackage, ifaceName);
1543 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001544
1545 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001546 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001547 }
1548
1549 enterLeaveNamespace(out, true /* enter */);
1550 out << "\n";
1551
1552 out << "struct "
1553 << klassName
1554 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001555 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001556
1557 out.indent();
1558 out << "explicit "
1559 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001560 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001561 << ifaceName
1562 << "> impl);\n";
1563
Yifan Hong068c5522016-10-31 14:07:25 -07001564 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1565 return generatePassthroughMethod(out, method);
1566 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001567
1568 if (err != OK) {
1569 return err;
1570 }
1571
1572 out.unindent();
1573 out << "private:\n";
1574 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001575 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001576
1577 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001578 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001579
1580 out << "\n";
1581
1582 out << "::android::hardware::Return<void> addOnewayTask("
1583 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001584 }
1585
1586 out.unindent();
1587
1588 out << "};\n\n";
1589
1590 enterLeaveNamespace(out, false /* enter */);
1591
1592 out << "\n#endif // " << guard << "\n";
1593
1594 return OK;
1595}
1596
Yifan Hongfe95aa22016-10-19 17:26:45 -07001597status_t AST::generateInterfaceSource(Formatter &out) const {
1598 const Interface *iface = mRootScope->getInterface();
1599
Yifan Hong2d7126b2016-10-20 15:12:57 -07001600 // generate castFrom functions
Yifan Hongfe95aa22016-10-19 17:26:45 -07001601 if (!iface->isRootType()) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001602 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001603
1604 for (const Interface *superType : iface->superTypeChain()) {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001605 out << "// static \n"
1606 << childTypeResult
1607 << " I"
1608 << iface->getBaseName()
1609 << "::castFrom("
Yifan Hong3b320f82016-11-01 15:15:54 -07001610 << superType->getCppArgumentType()
1611 << " parent) {\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001612 out.indent();
1613 out << "return ::android::hardware::castInterface<";
1614 out << "I" << iface->getBaseName() << ", "
1615 << superType->fqName().cppName() << ", "
Yifan Hong158655a2016-11-08 12:34:07 -08001616 << "Bp" << iface->getBaseName() << ", "
1617 << superType->getHwName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001618 << ">(\n";
1619 out.indent();
1620 out.indent();
1621 out << "parent, \""
1622 << iface->fqName().string()
1623 << "\");\n";
1624 out.unindent();
1625 out.unindent();
1626 out.unindent();
1627 out << "}\n\n";
1628 }
1629 }
1630
1631 return OK;
1632}
1633
Steven Moreland69e7c702016-09-09 11:16:32 -07001634status_t AST::generatePassthroughSource(Formatter &out) const {
1635 const Interface *iface = mRootScope->getInterface();
1636
1637 const std::string baseName = iface->getBaseName();
1638 const std::string klassName = "Bs" + baseName;
1639
1640 out << klassName
1641 << "::"
1642 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001643 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001644 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001645 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001646 << iface->fqName().string()
1647 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001648 if (iface->hasOnewayMethods()) {
1649 out << "\n";
1650 out.indentBlock([&] {
1651 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1652 });
1653 }
1654 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001655
1656 if (iface->hasOnewayMethods()) {
1657 out << "::android::hardware::Return<void> "
1658 << klassName
1659 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1660 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001661 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001662 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001663 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1664 out.indent();
1665 out.indent();
1666 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1667 out.unindent();
1668 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001669 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001670 out << "}\n";
1671
Steven Morelandd366c262016-10-11 15:29:10 -07001672 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001673
1674 out.unindent();
1675 out << "}\n\n";
1676
1677
1678 }
1679
1680 return OK;
1681}
1682
Martijn Coenen7b295242016-11-04 16:52:56 +01001683status_t AST::generateCppAtraceCall(Formatter &out,
1684 InstrumentationEvent event,
1685 const Method *method) const {
1686 const Interface *iface = mRootScope->getInterface();
1687 std::string baseString = "HIDL::I" + iface->getBaseName() + "::" + method->name();
1688 switch (event) {
1689 case SERVER_API_ENTRY:
1690 {
1691 out << "atrace_begin(ATRACE_TAG_HAL, \""
1692 << baseString + "::server\");\n";
1693 break;
1694 }
1695 case CLIENT_API_ENTRY:
1696 {
1697 out << "atrace_begin(ATRACE_TAG_HAL, \""
1698 << baseString + "::client\");\n";
1699 break;
1700 }
1701 case PASSTHROUGH_ENTRY:
1702 {
1703 out << "atrace_begin(ATRACE_TAG_HAL, \""
1704 << baseString + "::passthrough\");\n";
1705 break;
1706 }
1707 case SERVER_API_EXIT:
1708 case CLIENT_API_EXIT:
1709 case PASSTHROUGH_EXIT:
1710 {
1711 out << "atrace_end(ATRACE_TAG_HAL);\n";
1712 break;
1713 }
1714 default:
1715 {
1716 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1717 return UNKNOWN_ERROR;
1718 }
1719 }
1720
1721 return OK;
1722}
1723
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001724status_t AST::generateCppInstrumentationCall(
1725 Formatter &out,
1726 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001727 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001728 status_t err = generateCppAtraceCall(out, event, method);
1729 if (err != OK) {
1730 return err;
1731 }
1732
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001733 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1734 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001735 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001736 std::string event_str = "";
1737 switch (event) {
1738 case SERVER_API_ENTRY:
1739 {
1740 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1741 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001742 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001743 << (arg->type().resultNeedsDeref() ? "" : "&")
1744 << arg->name()
1745 << ");\n";
1746 }
1747 break;
1748 }
1749 case SERVER_API_EXIT:
1750 {
1751 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001752 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001753 out << "_hidl_args.push_back((void *)&"
Steven Moreland031ccf12016-10-31 15:54:38 -07001754 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001755 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001756 }
1757 break;
1758 }
1759 case CLIENT_API_ENTRY:
1760 {
1761 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1762 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001763 out << "_hidl_args.push_back((void *)&"
1764 << arg->name()
1765 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001766 }
1767 break;
1768 }
1769 case CLIENT_API_EXIT:
1770 {
1771 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1772 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001773 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001774 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001775 << "_hidl_out_"
1776 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001777 << ");\n";
1778 }
1779 break;
1780 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001781 case PASSTHROUGH_ENTRY:
1782 {
1783 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1784 for (const auto &arg : method->args()) {
1785 out << "_hidl_args.push_back((void *)&"
1786 << arg->name()
1787 << ");\n";
1788 }
1789 break;
1790 }
1791 case PASSTHROUGH_EXIT:
1792 {
1793 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001794 for (const auto &arg : method->results()) {
1795 out << "_hidl_args.push_back((void *)&"
1796 << arg->name()
1797 << ");\n";
1798 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001799 break;
1800 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001801 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001802 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001803 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001804 return UNKNOWN_ERROR;
1805 }
1806 }
1807
Steven Moreland031ccf12016-10-31 15:54:38 -07001808 const Interface *iface = mRootScope->getInterface();
1809
Steven Moreland1ab31442016-11-03 18:37:51 -07001810 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001811 out.indent();
1812 out << "callback("
1813 << event_str
1814 << ", \""
1815 << mPackage.package()
1816 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001817 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001818 << "\", \""
1819 << iface->localName()
1820 << "\", \""
1821 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001822 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001823 out.unindent();
1824 out << "}\n";
1825 out.unindent();
1826 out << "}\n\n";
1827
1828 return OK;
1829}
1830
Andreas Huber881227d2016-08-02 14:20:21 -07001831} // namespace android
1832