blob: ba1d2718290dd8b021e6cb8021505541b197c7c2 [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
Martijn Coenen7473fab2016-08-19 14:05:40 +0200169 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700170 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700171
172 if (isInterface) {
Steven Moreland0693f312016-11-09 15:06:14 -0800173 out << "#include <hidl/ServiceManagement.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200174 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700175 }
176
177 out << "#include <utils/NativeHandle.h>\n\n";
178
179 enterLeaveNamespace(out, true /* enter */);
180 out << "\n";
181
182 if (isInterface) {
183 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700184 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700185
186 const Interface *iface = mRootScope->getInterface();
187 const Interface *superType = iface->superType();
188
Steven Moreland40786312016-08-16 10:29:40 -0700189 if (superType == NULL) {
Yifan Hong5bd9aff2016-11-08 18:52:55 -0800190 out << " : virtual public ::android::hardware::IBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700191 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000192 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700193 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700194 }
195
196 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700197
198 out.indent();
199
Andreas Huber881227d2016-08-02 14:20:21 -0700200 }
201
202 status_t err = emitTypeDeclarations(out);
203
204 if (err != OK) {
205 return err;
206 }
207
208 if (isInterface) {
209 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700210 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700211 const std::string baseName = iface->getBaseName();
Steven Moreland19d5c172016-10-20 19:20:25 -0700212 out << "constexpr static ::android::hardware::hidl_version version = {"
Martijn Coenena21f1492016-09-08 15:55:14 +0200213 << mPackage.getPackageMajorVersion() << ","
214 << mPackage.getPackageMinorVersion() << "};\n";
Steven Moreland19d5c172016-10-20 19:20:25 -0700215 out << "virtual const ::android::hardware::hidl_version&"
216 << "getInterfaceVersion() const {\n";
Martijn Coenena21f1492016-09-08 15:55:14 +0200217 out.indent();
218 out << "return version;\n";
219 out.unindent();
220 out << "}\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700221 out << "virtual bool isRemote() const override { return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800222
Andreas Huber881227d2016-08-02 14:20:21 -0700223 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700224 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700225
Andreas Huber881227d2016-08-02 14:20:21 -0700226 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800227 const TypedVar *elidedReturn = method->canElideCallback();
228
229 if (elidedReturn == nullptr && returnsValue) {
230 out << "using "
231 << method->name()
232 << "_cb = std::function<void("
233 << Method::GetArgSignature(method->results(),
234 true /* specify namespaces */)
235 << ")>;\n";
236 }
Andreas Huber881227d2016-08-02 14:20:21 -0700237
Andreas Huber3599d922016-08-09 10:42:57 -0700238 method->dumpAnnotations(out);
239
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700240 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700241 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700242 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700243 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700244 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700245 }
246
247 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700248 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700249 << Method::GetArgSignature(method->args(),
250 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700251
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700252 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700253 if (!method->args().empty()) {
254 out << ", ";
255 }
256
Steven Moreland67f67b42016-09-29 08:59:02 -0700257 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700258 }
259
Yifan Hong10fe0b52016-10-19 14:20:17 -0700260 out << ")";
261 if (method->isHidlReserved()) {
262 out << " override";
263 out << " {\n";
264 out.indent();
265 method->cppImpl(out);
266 out.unindent();
267 out << "\n}\n";
268 } else {
269 out << " = 0;\n";
270 }
Andreas Huber881227d2016-08-02 14:20:21 -0700271 }
Steven Moreland40786312016-08-16 10:29:40 -0700272
Yifan Hongfe95aa22016-10-19 17:26:45 -0700273 if (!iface->isRootType()) {
274 out << "// cast static functions\n";
Yifan Hong3b320f82016-11-01 15:15:54 -0700275 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700276
277 for (const Interface *superType : iface->superTypeChain()) {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700278 out << "static "
279 << childTypeResult
280 << " castFrom("
Yifan Hong3b320f82016-11-01 15:15:54 -0700281 << superType->getCppArgumentType()
Yifan Hongfe95aa22016-10-19 17:26:45 -0700282 << " parent"
Yifan Hongfe95aa22016-10-19 17:26:45 -0700283 << ");\n";
284 }
285 }
286
Yifan Hong10fe0b52016-10-19 14:20:17 -0700287 out << "\nstatic const ::android::String16 descriptor;\n\n";
288
Steven Moreland0693f312016-11-09 15:06:14 -0800289 out << "DECLARE_SERVICE_MANAGER_INTERACTIONS(" << baseName << ")\n\n";
Yifan Hong158655a2016-11-08 12:34:07 -0800290
291 out << "private: static int hidlStaticBlock;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700292 }
293
294 if (isInterface) {
295 out.unindent();
296
Andreas Hubere3f769a2016-10-10 10:54:44 -0700297 out << "};\n\n";
298 }
299
300 err = mRootScope->emitGlobalTypeDeclarations(out);
301
302 if (err != OK) {
303 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700304 }
305
306 out << "\n";
307 enterLeaveNamespace(out, false /* enter */);
308
309 out << "\n#endif // " << guard << "\n";
310
311 return OK;
312}
313
Steven Moreland40786312016-08-16 10:29:40 -0700314status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
315 std::string ifaceName;
316 if(!AST::isInterface(&ifaceName)) {
317 // types.hal does not get an HwBinder header.
318 return OK;
319 }
320
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700321 const Interface *iface = mRootScope->getInterface();
322 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700323
324 const std::string klassName = "IHw" + baseName;
325
326 std::string path = outputPath;
327 path.append(mCoordinator->convertPackageRootToPath(mPackage));
328 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
329 path.append(klassName + ".h");
330
331 FILE* file = fopen(path.c_str(), "w");
332
333 if (file == NULL) {
334 return -errno;
335 }
336
337 Formatter out(file);
338
339 const std::string guard = makeHeaderGuard(klassName);
340
341 out << "#ifndef " << guard << "\n";
342 out << "#define " << guard << "\n\n";
343
Steven Morelandee88eed2016-10-31 17:49:00 -0700344 generateCppPackageInclude(out, mPackage, ifaceName);
Steven Moreland40786312016-08-16 10:29:40 -0700345
Steven Morelandee88eed2016-10-31 17:49:00 -0700346 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700347
348 for (const auto &item : mImportedNames) {
349 if (item.name() == "types") {
350 continue;
351 }
352
Steven Morelandee88eed2016-10-31 17:49:00 -0700353 generateCppPackageInclude(out, item, "Bn" + item.getInterfaceBaseName());
Steven Moreland40786312016-08-16 10:29:40 -0700354 }
355
356 out << "\n";
357
358 out << "#include <hidl/HidlSupport.h>\n";
Martijn Coenen93915102016-09-01 01:35:52 +0200359 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700360 out << "#include <hwbinder/IBinder.h>\n";
361 out << "#include <hwbinder/IInterface.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700362
363 out << "\n";
364
365 enterLeaveNamespace(out, true /* enter */);
366 out << "\n";
367
368 out << "struct "
369 << klassName
370 << " : public "
371 << ifaceName;
372
Steven Moreland40786312016-08-16 10:29:40 -0700373 const Interface *superType = iface->superType();
374
375 out << ", public ::android::hardware::IInterface";
376
377 out << " {\n";
378
379 out.indent();
380
381 out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
382
Steven Moreland40786312016-08-16 10:29:40 -0700383 out.unindent();
384
385 out << "};\n\n";
386
387 enterLeaveNamespace(out, false /* enter */);
388
389 out << "\n#endif // " << guard << "\n";
390
391 return OK;
392}
393
Andreas Huber881227d2016-08-02 14:20:21 -0700394status_t AST::emitTypeDeclarations(Formatter &out) const {
395 return mRootScope->emitTypeDeclarations(out);
396}
397
Steven Morelanda7a421a2016-09-07 08:35:18 -0700398status_t AST::generateStubMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700399 const Method *method) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700400 out << "inline ";
401
Yifan Hong068c5522016-10-31 14:07:25 -0700402 method->generateCppSignature(out);
Steven Morelanda7a421a2016-09-07 08:35:18 -0700403
404 const bool returnsValue = !method->results().empty();
405 const TypedVar *elidedReturn = method->canElideCallback();
406 out << " {\n";
407 out.indent();
408 out << "return mImpl->"
409 << method->name()
410 << "(";
411 bool first = true;
412 for (const auto &arg : method->args()) {
413 if (!first) {
414 out << ", ";
415 }
416 first = false;
417 out << arg->name();
418 }
419 if (returnsValue && elidedReturn == nullptr) {
420 if (!method->args().empty()) {
421 out << ", ";
422 }
423
424 out << "_hidl_cb";
425 }
426 out << ");\n";
427 out.unindent();
428 out << "}";
429
430 out << ";\n";
431
432 return OK;
433}
434
Steven Moreland69e7c702016-09-09 11:16:32 -0700435status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700436 const Method *method) const {
437 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700438
439 out << " {\n";
440 out.indent();
441
442 const bool returnsValue = !method->results().empty();
443 const TypedVar *elidedReturn = method->canElideCallback();
444
Steven Moreland67f67b42016-09-29 08:59:02 -0700445 if (returnsValue && elidedReturn == nullptr) {
446 generateCheckNonNull(out, "_hidl_cb");
447 }
448
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700449 generateCppInstrumentationCall(
450 out,
451 InstrumentationEvent::PASSTHROUGH_ENTRY,
452 method);
453
454 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700455
456 if (method->isOneway()) {
457 out << "addOnewayTask([this";
458 for (const auto &arg : method->args()) {
459 out << ", " << arg->name();
460 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700461 out << "] {\n";
462 out.indent();
463 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700464 }
465
466 out << "mImpl->"
467 << method->name()
468 << "(";
469
470 bool first = true;
471 for (const auto &arg : method->args()) {
472 if (!first) {
473 out << ", ";
474 }
475 first = false;
476 out << arg->name();
477 }
478 if (returnsValue && elidedReturn == nullptr) {
479 if (!method->args().empty()) {
480 out << ", ";
481 }
482
483 out << "_hidl_cb";
484 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700485 out << ");\n\n";
486
487 generateCppInstrumentationCall(
488 out,
489 InstrumentationEvent::PASSTHROUGH_EXIT,
490 method);
Steven Moreland69e7c702016-09-09 11:16:32 -0700491
492 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700493 out.unindent();
494 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700495 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700496
497 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700498
499 out.unindent();
500 out << "}\n";
501
502 return OK;
503}
504
Yifan Hong068c5522016-10-31 14:07:25 -0700505status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700506
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700507 const Interface *iface = mRootScope->getInterface();
508
Yifan Hong10fe0b52016-10-19 14:20:17 -0700509 const Interface *prevIterface = nullptr;
510 for (const auto &tuple : iface->allMethodsFromRoot()) {
511 const Method *method = tuple.method();
512 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700513
Yifan Hong10fe0b52016-10-19 14:20:17 -0700514 if(prevIterface != superInterface) {
515 if (prevIterface != nullptr) {
516 out << "\n";
517 }
518 out << "// Methods from "
519 << superInterface->fullName()
520 << " follow.\n";
521 prevIterface = superInterface;
522 }
Yifan Hong068c5522016-10-31 14:07:25 -0700523 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700524
Yifan Hong10fe0b52016-10-19 14:20:17 -0700525 if (err != OK) {
526 return err;
527 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700528 }
529
Yifan Hong10fe0b52016-10-19 14:20:17 -0700530 out << "\n";
531
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700532 return OK;
533}
534
Andreas Huberb82318c2016-08-02 14:45:54 -0700535status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700536 std::string ifaceName;
537 if (!AST::isInterface(&ifaceName)) {
538 // types.hal does not get a stub header.
539 return OK;
540 }
541
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700542 const Interface *iface = mRootScope->getInterface();
543 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700544 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700545
Andreas Huberb82318c2016-08-02 14:45:54 -0700546 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700547 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700548 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700549 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700550 path.append(".h");
551
Andreas Huberd2943e12016-08-05 11:59:31 -0700552 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700553 FILE *file = fopen(path.c_str(), "w");
554
555 if (file == NULL) {
556 return -errno;
557 }
558
559 Formatter out(file);
560
Steven Moreland40786312016-08-16 10:29:40 -0700561 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700562
563 out << "#ifndef " << guard << "\n";
564 out << "#define " << guard << "\n\n";
565
Steven Morelandee88eed2016-10-31 17:49:00 -0700566 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
567 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700568
569 enterLeaveNamespace(out, true /* enter */);
570 out << "\n";
571
572 out << "struct "
573 << "Bn"
574 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700575 << " : public ::android::hardware::BnInterface<I"
576 << baseName << ", IHw" << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700577 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700578
579 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700580 out << "explicit Bn"
581 << baseName
582 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
583 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700584 out << "::android::status_t onTransact(\n";
585 out.indent();
586 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700587 out << "uint32_t _hidl_code,\n";
588 out << "const ::android::hardware::Parcel &_hidl_data,\n";
589 out << "::android::hardware::Parcel *_hidl_reply,\n";
590 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700591 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700592 out.unindent();
593 out.unindent();
594
Yifan Hong068c5522016-10-31 14:07:25 -0700595 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
596 return generateStubMethod(out, method);
597 });
Steven Moreland9c387612016-09-07 09:54:26 -0700598
599 if (err != OK) {
600 return err;
601 }
602
Zhuoyao Zhangde578002016-09-07 18:24:17 -0700603
Andreas Huber881227d2016-08-02 14:20:21 -0700604 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700605 out << "};\n\n";
606
607 enterLeaveNamespace(out, false /* enter */);
608
609 out << "\n#endif // " << guard << "\n";
610
611 return OK;
612}
613
Andreas Huberb82318c2016-08-02 14:45:54 -0700614status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700615 std::string ifaceName;
616 if (!AST::isInterface(&ifaceName)) {
617 // types.hal does not get a proxy header.
618 return OK;
619 }
620
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700621 const Interface *iface = mRootScope->getInterface();
622 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700623
Andreas Huberb82318c2016-08-02 14:45:54 -0700624 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700625 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700626 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700627 path.append("Bp");
628 path.append(baseName);
629 path.append(".h");
630
Andreas Huberd2943e12016-08-05 11:59:31 -0700631 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700632 FILE *file = fopen(path.c_str(), "w");
633
634 if (file == NULL) {
635 return -errno;
636 }
637
638 Formatter out(file);
639
640 const std::string guard = makeHeaderGuard("Bp" + baseName);
641
642 out << "#ifndef " << guard << "\n";
643 out << "#define " << guard << "\n\n";
644
645 std::vector<std::string> packageComponents;
646 getPackageAndVersionComponents(
647 &packageComponents, false /* cpp_compatible */);
648
Steven Morelandee88eed2016-10-31 17:49:00 -0700649 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
650 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700651
652 enterLeaveNamespace(out, true /* enter */);
653 out << "\n";
654
655 out << "struct "
656 << "Bp"
657 << baseName
Steven Moreland40786312016-08-16 10:29:40 -0700658 << " : public ::android::hardware::BpInterface<IHw"
659 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700660 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700661
662 out.indent();
663
664 out << "explicit Bp"
665 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700666 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700667 << "\n\n";
668
Yifan Hong10fe0b52016-10-19 14:20:17 -0700669 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700670
Yifan Hong068c5522016-10-31 14:07:25 -0700671 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
672 method->generateCppSignature(out);
673 out << " override;\n";
674 return OK;
675 });
Steven Moreland9c387612016-09-07 09:54:26 -0700676
677 if (err != OK) {
678 return err;
679 }
Andreas Huber881227d2016-08-02 14:20:21 -0700680
681 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700682 out << "};\n\n";
683
684 enterLeaveNamespace(out, false /* enter */);
685
686 out << "\n#endif // " << guard << "\n";
687
688 return OK;
689}
690
Andreas Huberb82318c2016-08-02 14:45:54 -0700691status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700692
Andreas Huberb82318c2016-08-02 14:45:54 -0700693 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700694 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700695 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700696
697 std::string ifaceName;
698 std::string baseName;
699
Yifan Hongfe95aa22016-10-19 17:26:45 -0700700 const Interface *iface = nullptr;
701 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700702 if (!AST::isInterface(&ifaceName)) {
703 baseName = "types";
704 isInterface = false;
705 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700706 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700707 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700708 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700709 }
710
711 path.append(baseName);
712
713 if (baseName != "types") {
714 path.append("All");
715 }
716
717 path.append(".cpp");
718
Andreas Huberd2943e12016-08-05 11:59:31 -0700719 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700720 FILE *file = fopen(path.c_str(), "w");
721
722 if (file == NULL) {
723 return -errno;
724 }
725
726 Formatter out(file);
727
Andreas Huber881227d2016-08-02 14:20:21 -0700728 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700729 // This is a no-op for IServiceManager itself.
730 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
731
Steven Morelandee88eed2016-10-31 17:49:00 -0700732 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
733 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
734 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700735
736 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700737 generateCppPackageInclude(out,
738 superType->fqName(),
739 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700740 }
Andreas Huber881227d2016-08-02 14:20:21 -0700741 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700742 generateCppPackageInclude(out, mPackage, "types");
Andreas Huber881227d2016-08-02 14:20:21 -0700743 }
744
745 out << "\n";
746
747 enterLeaveNamespace(out, true /* enter */);
748 out << "\n";
749
750 status_t err = generateTypeSource(out, ifaceName);
751
752 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700753 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700754 out << "constexpr ::android::hardware::hidl_version "
755 << ifaceName
756 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700757
758 // need to be put here, generateStubSource is using this.
759 out << "const ::android::String16 I"
760 << iface->getBaseName()
761 << "::descriptor(\""
762 << iface->fqName().string()
763 << "\");\n\n";
764
Yifan Hong158655a2016-11-08 12:34:07 -0800765 out << "int I"
766 << iface->getBaseName()
767 << "::hidlStaticBlock = []() -> int {\n";
768 out.indentBlock([&] {
769 out << "::android::hardware::gBnConstructorMap[::android::String16::std_string(I"
770 << iface->getBaseName()
771 << "::descriptor)]\n";
772 out.indentBlock(2, [&] {
773 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
774 out.indentBlock([&] {
775 out << "return new Bn"
776 << iface->getBaseName()
777 << "(reinterpret_cast<I"
778 << iface->getBaseName()
779 << " *>(iIntf));\n";
780 });
781 out << "};\n";
782 });
783 out << "return 1;\n";
784 });
785 out << "}();\n\n";
786
Yifan Hongfe95aa22016-10-19 17:26:45 -0700787 err = generateInterfaceSource(out);
788 }
789
790 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -0700791 err = generateProxySource(out, baseName);
792 }
793
794 if (err == OK && isInterface) {
795 err = generateStubSource(out, baseName);
796 }
797
Steven Moreland40786312016-08-16 10:29:40 -0700798 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700799 err = generatePassthroughSource(out);
800 }
801
802 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -0700803 const Interface *iface = mRootScope->getInterface();
804
Steven Moreland0693f312016-11-09 15:06:14 -0800805 out << "IMPLEMENT_SERVICE_MANAGER_INTERACTIONS("
Steven Moreland9c387612016-09-07 09:54:26 -0700806 << baseName << ", "
807 << "\"" << iface->fqName().package()
Steven Moreland7e367bf2016-11-04 11:31:41 -0700808 << iface->fqName().atVersion()
809 << "\")\n";
Steven Moreland40786312016-08-16 10:29:40 -0700810 }
811
Andreas Huber881227d2016-08-02 14:20:21 -0700812 enterLeaveNamespace(out, false /* enter */);
813
814 return err;
815}
816
Steven Moreland67f67b42016-09-29 08:59:02 -0700817// static
818void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
819 out << "if (" << nonNull << " == nullptr) {\n";
820 out.indent();
821 out << "return ::android::hardware::Status::fromExceptionCode(\n";
822 out.indent();
823 out.indent();
824 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
825 out.unindent();
826 out.unindent();
827 out.unindent();
828 out << "}\n\n";
829}
830
Andreas Huber881227d2016-08-02 14:20:21 -0700831status_t AST::generateTypeSource(
832 Formatter &out, const std::string &ifaceName) const {
833 return mRootScope->emitTypeDefinitions(out, ifaceName);
834}
835
Andreas Hubere7ff2282016-08-16 13:50:03 -0700836void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -0700837 Formatter &out,
838 const std::vector<TypedVar *> &args,
839 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700840 if (args.empty()) {
841 return;
842 }
843
844 for (const auto &arg : args) {
845 const Type &type = arg->type();
846
Yifan Hong3b320f82016-11-01 15:15:54 -0700847 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700848 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -0700849 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -0700850 << ";\n";
851 }
852
853 out << "\n";
854}
855
Andreas Huber881227d2016-08-02 14:20:21 -0700856void AST::emitCppReaderWriter(
857 Formatter &out,
858 const std::string &parcelObj,
859 bool parcelObjIsPointer,
860 const TypedVar *arg,
861 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -0700862 Type::ErrorMode mode,
863 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700864 const Type &type = arg->type();
865
Andreas Huber881227d2016-08-02 14:20:21 -0700866 type.emitReaderWriter(
867 out,
Andreas Huber5e44a292016-09-27 14:52:39 -0700868 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -0700869 parcelObj,
870 parcelObjIsPointer,
871 isReader,
872 mode);
873}
874
Yifan Hongbf459bc2016-08-23 16:50:37 -0700875void AST::emitCppResolveReferences(
876 Formatter &out,
877 const std::string &parcelObj,
878 bool parcelObjIsPointer,
879 const TypedVar *arg,
880 bool isReader,
881 Type::ErrorMode mode,
882 bool addPrefixToName) const {
883 const Type &type = arg->type();
884 if(type.needsResolveReferences()) {
885 type.emitResolveReferences(
886 out,
887 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
888 isReader, // nameIsPointer
889 parcelObj,
890 parcelObjIsPointer,
891 isReader,
892 mode);
893 }
894}
895
Yifan Hong068c5522016-10-31 14:07:25 -0700896status_t AST::generateProxyMethodSource(Formatter &out,
897 const std::string &klassName,
898 const Method *method,
899 const Interface *superInterface) const {
900
901 method->generateCppSignature(out,
902 klassName,
903 true /* specify namespaces */);
904
905 const bool returnsValue = !method->results().empty();
906 const TypedVar *elidedReturn = method->canElideCallback();
907
Steven Moreland41c6d2e2016-11-07 12:26:54 -0800908 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -0700909
910 out.indent();
911
912 if (returnsValue && elidedReturn == nullptr) {
913 generateCheckNonNull(out, "_hidl_cb");
914 }
915
916 status_t status = generateCppInstrumentationCall(
917 out,
918 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -0700919 method);
920 if (status != OK) {
921 return status;
922 }
923
924 out << "::android::hardware::Parcel _hidl_data;\n";
925 out << "::android::hardware::Parcel _hidl_reply;\n";
926 out << "::android::status_t _hidl_err;\n";
927 out << "::android::hardware::Status _hidl_status;\n\n";
928
929 declareCppReaderLocals(
930 out, method->results(), true /* forResults */);
931
932 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
933 if (!method->isHidlReserved()) {
934 out << superInterface->fqName().cppNamespace()
935 << "::IHw"
936 << superInterface->getBaseName();
937 } else {
Yifan Hong5bd9aff2016-11-08 18:52:55 -0800938 out << "::android::hardware::IBase";
Yifan Hong068c5522016-10-31 14:07:25 -0700939 }
940 out << "::descriptor);\n";
941
942 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
943
944 // First DFS: write all buffers and resolve pointers for parent
945 for (const auto &arg : method->args()) {
946 emitCppReaderWriter(
947 out,
948 "_hidl_data",
949 false /* parcelObjIsPointer */,
950 arg,
951 false /* reader */,
952 Type::ErrorMode_Goto,
953 false /* addPrefixToName */);
954 }
955
956 // Second DFS: resolve references.
957 for (const auto &arg : method->args()) {
958 emitCppResolveReferences(
959 out,
960 "_hidl_data",
961 false /* parcelObjIsPointer */,
962 arg,
963 false /* reader */,
964 Type::ErrorMode_Goto,
965 false /* addPrefixToName */);
966 }
967
968 out << "_hidl_err = remote()->transact("
969 << method->getSerialId()
970 << " /* "
971 << method->name()
972 << " */, _hidl_data, &_hidl_reply";
973
974 if (method->isOneway()) {
975 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
976 }
977 out << ");\n";
978
979 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
980
981 if (!method->isOneway()) {
982 out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
983 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
984 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
985
986
987 // First DFS: write all buffers and resolve pointers for parent
988 for (const auto &arg : method->results()) {
989 emitCppReaderWriter(
990 out,
991 "_hidl_reply",
992 false /* parcelObjIsPointer */,
993 arg,
994 true /* reader */,
995 Type::ErrorMode_Goto,
996 true /* addPrefixToName */);
997 }
998
999 // Second DFS: resolve references.
1000 for (const auto &arg : method->results()) {
1001 emitCppResolveReferences(
1002 out,
1003 "_hidl_reply",
1004 false /* parcelObjIsPointer */,
1005 arg,
1006 true /* reader */,
1007 Type::ErrorMode_Goto,
1008 true /* addPrefixToName */);
1009 }
1010
1011 if (returnsValue && elidedReturn == nullptr) {
1012 out << "_hidl_cb(";
1013
1014 bool first = true;
1015 for (const auto &arg : method->results()) {
1016 if (!first) {
1017 out << ", ";
1018 }
1019
1020 if (arg->type().resultNeedsDeref()) {
1021 out << "*";
1022 }
1023 out << "_hidl_out_" << arg->name();
1024
1025 first = false;
1026 }
1027
1028 out << ");\n\n";
1029 }
1030 status_t status = generateCppInstrumentationCall(
1031 out,
1032 InstrumentationEvent::CLIENT_API_EXIT,
Yifan Hong068c5522016-10-31 14:07:25 -07001033 method);
1034 if (status != OK) {
1035 return status;
1036 }
1037 }
1038
1039 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001040 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1041 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001042 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001043 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1044 } else {
1045 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1046 out << "return ::android::hardware::Return<void>();\n\n";
1047 }
1048
1049 out.unindent();
1050 out << "_hidl_error:\n";
1051 out.indent();
1052 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1053 out << "return ::android::hardware::Return<";
1054 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001055 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001056 } else {
1057 out << "void";
1058 }
1059 out << ">(_hidl_status);\n";
1060
1061 out.unindent();
1062 out << "}\n\n";
1063 return OK;
1064}
1065
Andreas Huber881227d2016-08-02 14:20:21 -07001066status_t AST::generateProxySource(
1067 Formatter &out, const std::string &baseName) const {
1068 const std::string klassName = "Bp" + baseName;
1069
1070 out << klassName
1071 << "::"
1072 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001073 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001074
1075 out.indent();
1076 out.indent();
1077
1078 out << ": BpInterface"
Steven Moreland40786312016-08-16 10:29:40 -07001079 << "<IHw"
Andreas Huber881227d2016-08-02 14:20:21 -07001080 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001081 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001082 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001083 << mPackage.string()
1084 << "::I"
1085 << baseName
1086 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001087
Andreas Huber881227d2016-08-02 14:20:21 -07001088 out.unindent();
1089 out.unindent();
1090 out << "}\n\n";
1091
Yifan Hong068c5522016-10-31 14:07:25 -07001092 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1093 return generateProxyMethodSource(out, klassName, method, superInterface);
1094 });
Andreas Huber881227d2016-08-02 14:20:21 -07001095
Yifan Hong068c5522016-10-31 14:07:25 -07001096 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001097}
1098
1099status_t AST::generateStubSource(
1100 Formatter &out, const std::string &baseName) const {
1101 out << "IMPLEMENT_HWBINDER_META_INTERFACE("
1102 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001103 << ", "
1104 << mPackage.cppNamespace()
Andreas Huber881227d2016-08-02 14:20:21 -07001105 << "::I"
1106 << baseName
Yifan Hong10fe0b52016-10-19 14:20:17 -07001107 << "::descriptor);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001108
1109 const std::string klassName = "Bn" + baseName;
1110
Steven Moreland40786312016-08-16 10:29:40 -07001111 out << klassName
1112 << "::"
1113 << klassName
1114 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1115
1116 out.indent();
1117 out.indent();
1118
1119 out << ": BnInterface"
1120 << "<I"
1121 << baseName
1122 << ", IHw"
1123 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001124 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001125 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001126 << mPackage.string()
1127 << "::I"
1128 << baseName
1129 << "\") {\n";
Steven Moreland40786312016-08-16 10:29:40 -07001130
1131 out.unindent();
1132 out.unindent();
1133 out << "}\n\n";
1134
Andreas Huber881227d2016-08-02 14:20:21 -07001135 out << "::android::status_t " << klassName << "::onTransact(\n";
1136
1137 out.indent();
1138 out.indent();
1139
Iliyan Malchev549e2592016-08-10 08:59:12 -07001140 out << "uint32_t _hidl_code,\n"
1141 << "const ::android::hardware::Parcel &_hidl_data,\n"
1142 << "::android::hardware::Parcel *_hidl_reply,\n"
1143 << "uint32_t _hidl_flags,\n"
1144 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001145
1146 out.unindent();
1147
Iliyan Malchev549e2592016-08-10 08:59:12 -07001148 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001149 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001150 out.indent();
1151
1152 const Interface *iface = mRootScope->getInterface();
1153
Yifan Hong10fe0b52016-10-19 14:20:17 -07001154 for (const auto &tuple : iface->allMethodsFromRoot()) {
1155 const Method *method = tuple.method();
1156 const Interface *superInterface = tuple.interface();
1157 out << "case "
1158 << method->getSerialId()
1159 << " /* "
1160 << method->name()
1161 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001162
Yifan Hong10fe0b52016-10-19 14:20:17 -07001163 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001164
Yifan Hong10fe0b52016-10-19 14:20:17 -07001165 status_t err =
1166 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001167
Yifan Hong10fe0b52016-10-19 14:20:17 -07001168 if (err != OK) {
1169 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001170 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001171
1172 out.unindent();
1173 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001174 }
1175
1176 out << "default:\n{\n";
1177 out.indent();
1178
Andreas Huber8a82ff72016-08-04 10:29:39 -07001179 out << "return ::android::hardware::BnInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -07001180 << baseName << ", IHw" << baseName
Andreas Huber881227d2016-08-02 14:20:21 -07001181 << ">::onTransact(\n";
1182
1183 out.indent();
1184 out.indent();
1185
Iliyan Malchev549e2592016-08-10 08:59:12 -07001186 out << "_hidl_code, _hidl_data, _hidl_reply, "
1187 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001188
1189 out.unindent();
1190 out.unindent();
1191
1192 out.unindent();
1193 out << "}\n";
1194
1195 out.unindent();
1196 out << "}\n\n";
1197
Iliyan Malchev549e2592016-08-10 08:59:12 -07001198 out << "if (_hidl_err == ::android::UNEXPECTED_NULL) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001199 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001200 out << "_hidl_err = ::android::hardware::Status::fromExceptionCode(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001201 out.indent();
1202 out.indent();
Andreas Huber8a82ff72016-08-04 10:29:39 -07001203 out << "::android::hardware::Status::EX_NULL_POINTER)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001204 out.indent();
1205 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001206 out << ".writeToParcel(_hidl_reply);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001207 out.unindent();
1208 out.unindent();
1209 out.unindent();
1210 out.unindent();
1211
1212 out.unindent();
1213 out << "}\n\n";
1214
Iliyan Malchev549e2592016-08-10 08:59:12 -07001215 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001216
1217 out.unindent();
1218 out << "}\n\n";
1219
1220 return OK;
1221}
1222
1223status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001224 Formatter &out, const Interface *iface, const Method *method) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -07001225 out << "if (!_hidl_data.enforceInterface(";
1226
1227 if (!method->isHidlReserved()) {
1228 out << iface->fqName().cppNamespace()
1229 << "::IHw"
1230 << iface->getBaseName();
1231 } else {
Yifan Hong5bd9aff2016-11-08 18:52:55 -08001232 out << "::android::hardware::IBase";
Yifan Hong10fe0b52016-10-19 14:20:17 -07001233 }
1234
1235 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001236
Andreas Huber881227d2016-08-02 14:20:21 -07001237 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001238 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001239 out << "break;\n";
1240 out.unindent();
1241 out << "}\n\n";
1242
Andreas Huber5e44a292016-09-27 14:52:39 -07001243 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001244
Yifan Hongbf459bc2016-08-23 16:50:37 -07001245 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001246 for (const auto &arg : method->args()) {
1247 emitCppReaderWriter(
1248 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001249 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001250 false /* parcelObjIsPointer */,
1251 arg,
1252 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001253 Type::ErrorMode_Break,
1254 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001255 }
1256
Yifan Hongbf459bc2016-08-23 16:50:37 -07001257 // Second DFS: resolve references
1258 for (const auto &arg : method->args()) {
1259 emitCppResolveReferences(
1260 out,
1261 "_hidl_data",
1262 false /* parcelObjIsPointer */,
1263 arg,
1264 true /* reader */,
1265 Type::ErrorMode_Break,
1266 false /* addPrefixToName */);
1267 }
1268
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001269 status_t status = generateCppInstrumentationCall(
1270 out,
1271 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001272 method);
1273 if (status != OK) {
1274 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001275 }
1276
Andreas Huber881227d2016-08-02 14:20:21 -07001277 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001278 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001279
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001280 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001281 out << elidedReturn->type().getCppResultType()
1282 << " "
1283 << elidedReturn->name()
1284 << " = "
1285 << method->name()
1286 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001287
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001288 bool first = true;
1289 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001290 if (!first) {
1291 out << ", ";
1292 }
1293
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001294 if (arg->type().resultNeedsDeref()) {
1295 out << "*";
1296 }
1297
1298 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001299
1300 first = false;
1301 }
1302
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001303 out << ");\n\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001304 out << "::android::hardware::Status::ok()"
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001305 << ".writeToParcel(_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001306
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001307 elidedReturn->type().emitReaderWriter(
1308 out,
1309 elidedReturn->name(),
1310 "_hidl_reply",
1311 true, /* parcelObjIsPointer */
1312 false, /* isReader */
1313 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001314
Yifan Hongbf459bc2016-08-23 16:50:37 -07001315 emitCppResolveReferences(
1316 out,
1317 "_hidl_reply",
1318 true /* parcelObjIsPointer */,
1319 elidedReturn,
1320 false /* reader */,
1321 Type::ErrorMode_Ignore,
1322 false /* addPrefixToName */);
1323
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001324 status_t status = generateCppInstrumentationCall(
1325 out,
1326 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001327 method);
1328 if (status != OK) {
1329 return status;
1330 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001331
Iliyan Malchev549e2592016-08-10 08:59:12 -07001332 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001333 } else {
1334 if (returnsValue) {
1335 out << "bool _hidl_callbackCalled = false;\n\n";
1336 }
Andreas Huber881227d2016-08-02 14:20:21 -07001337
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001338 out << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001339
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001340 bool first = true;
1341 for (const auto &arg : method->args()) {
1342 if (!first) {
1343 out << ", ";
1344 }
Andreas Huber881227d2016-08-02 14:20:21 -07001345
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001346 if (arg->type().resultNeedsDeref()) {
1347 out << "*";
1348 }
1349
1350 out << arg->name();
1351
1352 first = false;
1353 }
1354
1355 if (returnsValue) {
1356 if (!first) {
1357 out << ", ";
1358 }
1359
1360 out << "[&](";
1361
1362 first = true;
1363 for (const auto &arg : method->results()) {
1364 if (!first) {
1365 out << ", ";
1366 }
1367
1368 out << "const auto &" << arg->name();
1369
1370 first = false;
1371 }
1372
1373 out << ") {\n";
1374 out.indent();
1375 out << "_hidl_callbackCalled = true;\n\n";
1376
1377 out << "::android::hardware::Status::ok()"
1378 << ".writeToParcel(_hidl_reply);\n\n";
1379
Yifan Hongbf459bc2016-08-23 16:50:37 -07001380 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001381 for (const auto &arg : method->results()) {
1382 emitCppReaderWriter(
1383 out,
1384 "_hidl_reply",
1385 true /* parcelObjIsPointer */,
1386 arg,
1387 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001388 Type::ErrorMode_Ignore,
1389 false /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001390 }
1391
Yifan Hongbf459bc2016-08-23 16:50:37 -07001392 // Second DFS: resolve references
1393 for (const auto &arg : method->results()) {
1394 emitCppResolveReferences(
1395 out,
1396 "_hidl_reply",
1397 true /* parcelObjIsPointer */,
1398 arg,
1399 false /* reader */,
1400 Type::ErrorMode_Ignore,
1401 false /* addPrefixToName */);
1402 }
1403
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001404 status_t status = generateCppInstrumentationCall(
1405 out,
1406 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001407 method);
1408 if (status != OK) {
1409 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001410 }
1411
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001412 out << "_hidl_cb(*_hidl_reply);\n";
1413
1414 out.unindent();
1415 out << "}\n";
1416 }
1417
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001418 out << ");\n\n";
1419
1420 // What to do if the stub implementation has a synchronous callback
1421 // which does not get invoked? This is not a transport error but a
1422 // service error of sorts. For now, return OK to the caller, as this is
1423 // not a transport error.
1424 //
1425 // TODO(b/31365311) Figure out how to deal with this later.
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001426
1427 if (returnsValue) {
1428 out << "if (!_hidl_callbackCalled) {\n";
1429 out.indent();
1430 }
1431
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001432 out << "::android::hardware::Status::ok()"
1433 << ".writeToParcel(_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001434
1435 if (returnsValue) {
1436 out.unindent();
1437 out << "}\n\n";
1438 }
Andreas Huber881227d2016-08-02 14:20:21 -07001439 }
1440
1441 out << "break;\n";
1442
1443 return OK;
1444}
1445
Steven Moreland69e7c702016-09-09 11:16:32 -07001446status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1447 std::string ifaceName;
1448 if (!AST::isInterface(&ifaceName)) {
1449 // types.hal does not get a stub header.
1450 return OK;
1451 }
1452
1453 const Interface *iface = mRootScope->getInterface();
1454
1455 const std::string baseName = iface->getBaseName();
1456 const std::string klassName = "Bs" + baseName;
1457
1458 bool supportOneway = iface->hasOnewayMethods();
1459
1460 std::string path = outputPath;
1461 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1462 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1463 path.append(klassName);
1464 path.append(".h");
1465
1466 CHECK(Coordinator::MakeParentHierarchy(path));
1467 FILE *file = fopen(path.c_str(), "w");
1468
1469 if (file == NULL) {
1470 return -errno;
1471 }
1472
1473 Formatter out(file);
1474
1475 const std::string guard = makeHeaderGuard(klassName);
1476
1477 out << "#ifndef " << guard << "\n";
1478 out << "#define " << guard << "\n\n";
1479
1480 std::vector<std::string> packageComponents;
1481 getPackageAndVersionComponents(
1482 &packageComponents, false /* cpp_compatible */);
1483
1484 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001485
1486 generateCppPackageInclude(out, mPackage, ifaceName);
1487 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001488
1489 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001490 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001491 }
1492
1493 enterLeaveNamespace(out, true /* enter */);
1494 out << "\n";
1495
1496 out << "struct "
1497 << klassName
1498 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001499 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001500
1501 out.indent();
1502 out << "explicit "
1503 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001504 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001505 << ifaceName
1506 << "> impl);\n";
1507
Yifan Hong068c5522016-10-31 14:07:25 -07001508 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1509 return generatePassthroughMethod(out, method);
1510 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001511
1512 if (err != OK) {
1513 return err;
1514 }
1515
1516 out.unindent();
1517 out << "private:\n";
1518 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001519 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001520
1521 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001522 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001523
1524 out << "\n";
1525
1526 out << "::android::hardware::Return<void> addOnewayTask("
1527 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001528 }
1529
1530 out.unindent();
1531
1532 out << "};\n\n";
1533
1534 enterLeaveNamespace(out, false /* enter */);
1535
1536 out << "\n#endif // " << guard << "\n";
1537
1538 return OK;
1539}
1540
Yifan Hongfe95aa22016-10-19 17:26:45 -07001541status_t AST::generateInterfaceSource(Formatter &out) const {
1542 const Interface *iface = mRootScope->getInterface();
1543
Yifan Hong2d7126b2016-10-20 15:12:57 -07001544 // generate castFrom functions
Yifan Hongfe95aa22016-10-19 17:26:45 -07001545 if (!iface->isRootType()) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001546 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001547
1548 for (const Interface *superType : iface->superTypeChain()) {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001549 out << "// static \n"
1550 << childTypeResult
1551 << " I"
1552 << iface->getBaseName()
1553 << "::castFrom("
Yifan Hong3b320f82016-11-01 15:15:54 -07001554 << superType->getCppArgumentType()
1555 << " parent) {\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001556 out.indent();
1557 out << "return ::android::hardware::castInterface<";
1558 out << "I" << iface->getBaseName() << ", "
1559 << superType->fqName().cppName() << ", "
Yifan Hong158655a2016-11-08 12:34:07 -08001560 << "Bp" << iface->getBaseName() << ", "
1561 << superType->getHwName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001562 << ">(\n";
1563 out.indent();
1564 out.indent();
1565 out << "parent, \""
1566 << iface->fqName().string()
1567 << "\");\n";
1568 out.unindent();
1569 out.unindent();
1570 out.unindent();
1571 out << "}\n\n";
1572 }
1573 }
1574
1575 return OK;
1576}
1577
Steven Moreland69e7c702016-09-09 11:16:32 -07001578status_t AST::generatePassthroughSource(Formatter &out) const {
1579 const Interface *iface = mRootScope->getInterface();
1580
1581 const std::string baseName = iface->getBaseName();
1582 const std::string klassName = "Bs" + baseName;
1583
1584 out << klassName
1585 << "::"
1586 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001587 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001588 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001589 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001590 << iface->fqName().string()
1591 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001592 if (iface->hasOnewayMethods()) {
1593 out << "\n";
1594 out.indentBlock([&] {
1595 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1596 });
1597 }
1598 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001599
1600 if (iface->hasOnewayMethods()) {
1601 out << "::android::hardware::Return<void> "
1602 << klassName
1603 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1604 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001605 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001606 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001607 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1608 out.indent();
1609 out.indent();
1610 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1611 out.unindent();
1612 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001613 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001614 out << "}\n";
1615
Steven Morelandd366c262016-10-11 15:29:10 -07001616 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001617
1618 out.unindent();
1619 out << "}\n\n";
1620
1621
1622 }
1623
1624 return OK;
1625}
1626
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001627status_t AST::generateCppInstrumentationCall(
1628 Formatter &out,
1629 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001630 const Method *method) const {
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001631 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1632 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001633 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001634 std::string event_str = "";
1635 switch (event) {
1636 case SERVER_API_ENTRY:
1637 {
1638 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1639 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001640 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001641 << (arg->type().resultNeedsDeref() ? "" : "&")
1642 << arg->name()
1643 << ");\n";
1644 }
1645 break;
1646 }
1647 case SERVER_API_EXIT:
1648 {
1649 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001650 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001651 out << "_hidl_args.push_back((void *)&"
Steven Moreland031ccf12016-10-31 15:54:38 -07001652 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001653 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001654 }
1655 break;
1656 }
1657 case CLIENT_API_ENTRY:
1658 {
1659 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1660 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001661 out << "_hidl_args.push_back((void *)&"
1662 << arg->name()
1663 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001664 }
1665 break;
1666 }
1667 case CLIENT_API_EXIT:
1668 {
1669 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1670 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001671 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001672 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001673 << "_hidl_out_"
1674 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001675 << ");\n";
1676 }
1677 break;
1678 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001679 case PASSTHROUGH_ENTRY:
1680 {
1681 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1682 for (const auto &arg : method->args()) {
1683 out << "_hidl_args.push_back((void *)&"
1684 << arg->name()
1685 << ");\n";
1686 }
1687 break;
1688 }
1689 case PASSTHROUGH_EXIT:
1690 {
1691 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
1692 // TODO(b/32576620): passthrough return values
1693 break;
1694 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001695 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001696 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001697 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001698 return UNKNOWN_ERROR;
1699 }
1700 }
1701
Steven Moreland031ccf12016-10-31 15:54:38 -07001702 const Interface *iface = mRootScope->getInterface();
1703
Steven Moreland1ab31442016-11-03 18:37:51 -07001704 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001705 out.indent();
1706 out << "callback("
1707 << event_str
1708 << ", \""
1709 << mPackage.package()
1710 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001711 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001712 << "\", \""
1713 << iface->localName()
1714 << "\", \""
1715 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001716 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001717 out.unindent();
1718 out << "}\n";
1719 out.unindent();
1720 out << "}\n\n";
1721
1722 return OK;
1723}
1724
Andreas Huber881227d2016-08-02 14:20:21 -07001725} // namespace android
1726