blob: bdc59a1afb71ef786495efaf175c671a454a45f2 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huber881227d2016-08-02 14:20:21 -070017#include "AST.h"
18
19#include "Coordinator.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070020#include "EnumType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070021#include "Interface.h"
22#include "Method.h"
Iliyan Malchev40d474a2016-08-16 06:20:17 -070023#include "ScalarType.h"
Andreas Huber881227d2016-08-02 14:20:21 -070024#include "Scope.h"
25
Andreas Huberdca261f2016-08-04 13:47:51 -070026#include <algorithm>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070027#include <hidl-util/Formatter.h>
Steven Moreland5708edf2016-11-04 15:33:31 +000028#include <hidl-util/StringHelper.h>
Andreas Huber881227d2016-08-02 14:20:21 -070029#include <android-base/logging.h>
Andreas Huberdca261f2016-08-04 13:47:51 -070030#include <string>
Andreas Huber881227d2016-08-02 14:20:21 -070031#include <vector>
32
33namespace android {
34
Andreas Huberb82318c2016-08-02 14:45:54 -070035status_t AST::generateCpp(const std::string &outputPath) const {
36 status_t err = generateInterfaceHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070037
38 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070039 err = generateStubHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070040 }
41
42 if (err == OK) {
Steven Moreland40786312016-08-16 10:29:40 -070043 err = generateHwBinderHeader(outputPath);
44 }
45
46 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070047 err = generateProxyHeader(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070048 }
49
50 if (err == OK) {
Andreas Huberb82318c2016-08-02 14:45:54 -070051 err = generateAllSource(outputPath);
Andreas Huber881227d2016-08-02 14:20:21 -070052 }
53
Steven Moreland69e7c702016-09-09 11:16:32 -070054 if (err == OK) {
Yifan Hong7a118f52016-12-07 11:21:15 -080055 err = generatePassthroughHeader(outputPath);
Steven Moreland69e7c702016-09-09 11:16:32 -070056 }
57
Andreas Huber881227d2016-08-02 14:20:21 -070058 return err;
59}
60
Andreas Huber737080b2016-08-02 15:38:04 -070061void AST::getPackageComponents(
62 std::vector<std::string> *components) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070063 mPackage.getPackageComponents(components);
Andreas Huber737080b2016-08-02 15:38:04 -070064}
65
66void AST::getPackageAndVersionComponents(
67 std::vector<std::string> *components, bool cpp_compatible) const {
Andreas Huber0e00de42016-08-03 09:56:02 -070068 mPackage.getPackageAndVersionComponents(components, cpp_compatible);
Andreas Huber737080b2016-08-02 15:38:04 -070069}
70
Steven Moreland5708edf2016-11-04 15:33:31 +000071std::string AST::makeHeaderGuard(const std::string &baseName,
72 bool indicateGenerated) const {
73 std::string guard;
Andreas Huber881227d2016-08-02 14:20:21 -070074
Steven Moreland5708edf2016-11-04 15:33:31 +000075 if (indicateGenerated) {
76 guard += "HIDL_GENERATED_";
77 }
78
79 guard += StringHelper::Uppercase(mPackage.tokenName());
Andreas Huber881227d2016-08-02 14:20:21 -070080 guard += "_";
Steven Moreland5708edf2016-11-04 15:33:31 +000081 guard += StringHelper::Uppercase(baseName);
82 guard += "_H";
Andreas Huber881227d2016-08-02 14:20:21 -070083
84 return guard;
85}
86
Steven Morelandee88eed2016-10-31 17:49:00 -070087// static
88void AST::generateCppPackageInclude(
89 Formatter &out,
90 const FQName &package,
91 const std::string &klass) {
92
93 out << "#include <";
94
95 std::vector<std::string> components;
96 package.getPackageAndVersionComponents(&components, false /* cpp_compatible */);
97
98 for (const auto &component : components) {
99 out << component << "/";
100 }
101
102 out << klass
103 << ".h>\n";
104}
105
Andreas Huber881227d2016-08-02 14:20:21 -0700106void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
107 std::vector<std::string> packageComponents;
108 getPackageAndVersionComponents(
109 &packageComponents, true /* cpp_compatible */);
110
111 if (enter) {
112 for (const auto &component : packageComponents) {
113 out << "namespace " << component << " {\n";
114 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700115
Andreas Huber2831d512016-08-15 09:33:47 -0700116 out.setNamespace(mPackage.cppNamespace() + "::");
Andreas Huber881227d2016-08-02 14:20:21 -0700117 } else {
Andreas Huber0e00de42016-08-03 09:56:02 -0700118 out.setNamespace(std::string());
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120 for (auto it = packageComponents.rbegin();
121 it != packageComponents.rend();
122 ++it) {
123 out << "} // namespace " << *it << "\n";
124 }
125 }
126}
127
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800128static void declareServiceManagerInteractions(Formatter &out, const std::string &baseName) {
129 out << "static ::android::sp<I" << baseName << "> getService("
130 << "const std::string &serviceName, bool getStub=false);\n";
131 out << "::android::status_t registerAsService(const std::string &serviceName);\n";
132 out << "static bool registerForNotifications(\n";
133 out.indent(2, [&] {
134 out << "const std::string &serviceName,\n"
135 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
136 << "&notification);\n";
137 });
138
139}
140
141static void implementServiceManagerInteractions(Formatter &out,
142 const std::string &baseName, const std::string &package) {
143
144 out << "// static\n"
145 << "::android::sp<I" << baseName << "> I" << baseName << "::getService("
146 << "const std::string &serviceName, bool getStub) ";
147 out.block([&] {
148 out << "::android::sp<I" << baseName << "> iface;\n"
149 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
150 out.indent(2, [&] {
151 out << "= ::android::hardware::defaultServiceManager();\n";
152 });
153 out.sIf("sm != nullptr && !getStub", [&] {
154 out << "::android::sp<::android::hidl::base::V1_0::IBase> base;\n"
155 << "::android::hardware::Return<void> ret =\n";
156 out.indent(2, [&] {
157 out << "sm->get(\"" << package << "::I" << baseName << "\", serviceName.c_str(),\n";
158 out.indent(2, [&] {
159 out << "[&base](::android::sp<::android::hidl::base::V1_0::IBase> found) ";
160 out.block([&] {
161 out << "base = found;\n";
162 });
163 out << ");\n";
164 });
165 });
166 out.sIf("ret.getStatus().isOk()", [&] {
167 out << "iface = I" << baseName << "::castFrom(base);\n";
168 out.sIf("iface != nullptr", [&] {
169 out << "return iface;\n";
170 }).endl();
171 }).endl();
172 }).endl();
173 out << "const int dlMode = RTLD_LAZY;\n";
174 out << "void *handle = nullptr;\n";
175 for (const auto &path : std::vector<std::string>({
176 "HAL_LIBRARY_PATH_ODM", "HAL_LIBRARY_PATH_VENDOR", "HAL_LIBRARY_PATH_SYSTEM"
177 })) {
178 out.sIf("handle == nullptr", [&] {
179 out << "handle = dlopen("
180 << path << " \"" << package << "-impl.so\", dlMode);\n";
181 }).endl();
182 }
183 out.sIf("handle == nullptr", [&] {
184 out << "return iface;\n";
185 }).endl();
186 out << "I" << baseName << "* (*generator)(const char* name);\n"
187 << "*(void **)(&generator) = dlsym(handle, \"HIDL_FETCH_I" << baseName << "\");\n";
188 out.sIf("generator", [&] {
189 out << "iface = (*generator)(serviceName.c_str());\n";
190 out.sIf("iface != nullptr", [&] {
191 out << "iface = new Bs" << baseName << "(iface);\n";
192 }).endl();
193 }).endl();
194 out << "return iface;\n";
195 }).endl().endl();
196
197 out << "::android::status_t I" << baseName << "::registerAsService("
198 << "const std::string &serviceName) ";
199 out.block([&] {
200 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
201 out.indent(2, [&] {
202 out << "= ::android::hardware::defaultServiceManager();\n";
203 });
204 out.sIf("sm == nullptr", [&] {
205 out << "return ::android::INVALID_OPERATION;\n";
206 }).endl();
207 out << "bool success = false;\n"
208 << "::android::hardware::Return<void> ret =\n";
209 out.indent(2, [&] {
210 out << "this->interfaceChain("
211 << "[&success, &sm, &serviceName, this](const auto &chain) ";
212 out.block([&] {
213 out << "::android::hardware::Return<bool> addRet = "
214 << "sm->add(chain, serviceName.c_str(), this);\n";
215 out << "success = addRet.isOk() && addRet;\n";
216 });
217 out << ");\n";
218 out << "success = success && ret.getStatus().isOk();\n";
219 });
220 out << "return success ? ::android::OK : ::android::UNKNOWN_ERROR;\n";
221 }).endl().endl();
222
223 out << "bool I" << baseName << "::registerForNotifications(\n";
224 out.indent(2, [&] {
225 out << "const std::string &serviceName,\n"
226 << "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
227 << "&notification) ";
228 });
229 out.block([&] {
230 out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
231 out.indent(2, [&] {
232 out << "= ::android::hardware::defaultServiceManager();\n";
233 });
234 out.sIf("sm == nullptr", [&] {
235 out << "return false;\n";
236 }).endl();
237 out << "::android::hardware::Return<bool> success =\n";
238 out.indent(2, [&] {
239 out << "sm->registerForNotifications(\"" << package << "::I" << baseName << "\",\n";
240 out.indent(2, [&] {
241 out << "serviceName, notification);\n";
242 });
243 });
244 out << "return success.isOk() && success;\n";
245 }).endl().endl();
246}
247
Andreas Huberb82318c2016-08-02 14:45:54 -0700248status_t AST::generateInterfaceHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700249
Andreas Huberb82318c2016-08-02 14:45:54 -0700250 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700251 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700252 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700253
254 std::string ifaceName;
255 bool isInterface = true;
256 if (!AST::isInterface(&ifaceName)) {
257 ifaceName = "types";
258 isInterface = false;
259 }
260 path.append(ifaceName);
261 path.append(".h");
262
Andreas Huberd2943e12016-08-05 11:59:31 -0700263 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700264 FILE *file = fopen(path.c_str(), "w");
265
266 if (file == NULL) {
267 return -errno;
268 }
269
270 Formatter out(file);
271
272 const std::string guard = makeHeaderGuard(ifaceName);
273
274 out << "#ifndef " << guard << "\n";
275 out << "#define " << guard << "\n\n";
276
Andreas Huber737080b2016-08-02 15:38:04 -0700277 for (const auto &item : mImportedNames) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700278 generateCppPackageInclude(out, item, item.name());
Andreas Huber737080b2016-08-02 15:38:04 -0700279 }
280
281 if (!mImportedNames.empty()) {
282 out << "\n";
283 }
284
Steven Moreland0693f312016-11-09 15:06:14 -0800285 if (isInterface) {
Yifan Hongc8934042016-11-17 17:10:52 -0800286 if (isIBase()) {
287 out << "// skipped #include IServiceNotification.h\n\n";
288 } else {
289 out << "#include <android/hidl/manager/1.0/IServiceNotification.h>\n\n";
290 }
Steven Moreland0693f312016-11-09 15:06:14 -0800291 }
292
Yifan Hongc8934042016-11-17 17:10:52 -0800293 out << "#include <hidl/HidlSupport.h>\n";
Andreas Huber4bcf97d2016-08-30 11:27:49 -0700294 out << "#include <hidl/MQDescriptor.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700295
296 if (isInterface) {
Martijn Coenen93915102016-09-01 01:35:52 +0200297 out << "#include <hidl/Status.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700298 }
299
Martijn Coenenaf712c02016-11-16 15:26:27 +0100300 out << "#include <utils/NativeHandle.h>\n";
301 out << "#include <utils/misc.h>\n\n"; /* for report_sysprop_change() */
Andreas Huber881227d2016-08-02 14:20:21 -0700302
303 enterLeaveNamespace(out, true /* enter */);
304 out << "\n";
305
306 if (isInterface) {
307 out << "struct "
Steven Moreland40786312016-08-16 10:29:40 -0700308 << ifaceName;
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700309
310 const Interface *iface = mRootScope->getInterface();
311 const Interface *superType = iface->superType();
312
Steven Moreland40786312016-08-16 10:29:40 -0700313 if (superType == NULL) {
Yifan Hongc8934042016-11-17 17:10:52 -0800314 out << " : virtual public ::android::RefBase";
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700315 } else {
Steven Morelandd916a702016-10-26 22:23:09 +0000316 out << " : public "
Steven Moreland40786312016-08-16 10:29:40 -0700317 << superType->fullName();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700318 }
319
320 out << " {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700321
322 out.indent();
323
Andreas Huber881227d2016-08-02 14:20:21 -0700324 }
325
326 status_t err = emitTypeDeclarations(out);
327
328 if (err != OK) {
329 return err;
330 }
331
332 if (isInterface) {
333 const Interface *iface = mRootScope->getInterface();
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700334 const Interface *superType = iface->superType();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700335 const std::string baseName = iface->getBaseName();
Steven Moreland19d5c172016-10-20 19:20:25 -0700336 out << "constexpr static ::android::hardware::hidl_version version = {"
Yifan Hongd7200502016-12-21 15:01:27 -0800337 << mPackage.getPackageMajorVersion() << ", "
Martijn Coenena21f1492016-09-08 15:55:14 +0200338 << mPackage.getPackageMinorVersion() << "};\n";
Yifan Hongd7200502016-12-21 15:01:27 -0800339 out << "virtual const ::android::hardware::hidl_version &"
Steven Moreland19d5c172016-10-20 19:20:25 -0700340 << "getInterfaceVersion() const {\n";
Martijn Coenena21f1492016-09-08 15:55:14 +0200341 out.indent();
342 out << "return version;\n";
343 out.unindent();
344 out << "}\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800345 out << "virtual bool isRemote() const ";
346 if (!isIBase()) {
347 out << "override ";
348 }
349 out << "{ return false; }\n\n";
Steven Morelandd732ea12016-11-08 17:12:06 -0800350
Andreas Huber881227d2016-08-02 14:20:21 -0700351 for (const auto &method : iface->methods()) {
Andreas Huber881227d2016-08-02 14:20:21 -0700352 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700353
Andreas Huber881227d2016-08-02 14:20:21 -0700354 const bool returnsValue = !method->results().empty();
Steven Morelandd732ea12016-11-08 17:12:06 -0800355 const TypedVar *elidedReturn = method->canElideCallback();
356
357 if (elidedReturn == nullptr && returnsValue) {
358 out << "using "
359 << method->name()
360 << "_cb = std::function<void("
361 << Method::GetArgSignature(method->results(),
362 true /* specify namespaces */)
363 << ")>;\n";
364 }
Andreas Huber881227d2016-08-02 14:20:21 -0700365
Andreas Huber3599d922016-08-09 10:42:57 -0700366 method->dumpAnnotations(out);
367
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700368 if (elidedReturn) {
Iliyan Malchev2b6591b2016-08-18 19:15:19 -0700369 out << "virtual ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -0700370 out << elidedReturn->type().getCppResultType() << "> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700371 } else {
Iliyan Malchevd57066f2016-09-08 13:59:38 -0700372 out << "virtual ::android::hardware::Return<void> ";
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700373 }
374
375 out << method->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700376 << "("
Steven Moreland979e0992016-09-07 09:18:08 -0700377 << Method::GetArgSignature(method->args(),
378 true /* specify namespaces */);
Andreas Huber881227d2016-08-02 14:20:21 -0700379
Iliyan Malchev40d474a2016-08-16 06:20:17 -0700380 if (returnsValue && elidedReturn == nullptr) {
Andreas Huber881227d2016-08-02 14:20:21 -0700381 if (!method->args().empty()) {
382 out << ", ";
383 }
384
Steven Moreland67f67b42016-09-29 08:59:02 -0700385 out << method->name() << "_cb _hidl_cb";
Andreas Huber881227d2016-08-02 14:20:21 -0700386 }
387
Yifan Hong10fe0b52016-10-19 14:20:17 -0700388 out << ")";
389 if (method->isHidlReserved()) {
Yifan Hongc8934042016-11-17 17:10:52 -0800390 if (!isIBase()) {
391 out << " override";
392 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700393 out << " {\n";
394 out.indent();
Martijn Coenen115d4282016-12-19 05:14:04 +0100395 method->cppImpl(IMPL_HEADER, out);
Yifan Hong10fe0b52016-10-19 14:20:17 -0700396 out.unindent();
397 out << "\n}\n";
398 } else {
399 out << " = 0;\n";
400 }
Andreas Huber881227d2016-08-02 14:20:21 -0700401 }
Steven Moreland40786312016-08-16 10:29:40 -0700402
Yifan Hong3d746092016-12-07 14:26:33 -0800403 out << "// cast static functions\n";
404 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700405
Yifan Hong3d746092016-12-07 14:26:33 -0800406 for (const Interface *superType : iface->typeChain()) {
407 out << "static "
408 << childTypeResult
409 << " castFrom("
410 << superType->getCppArgumentType()
411 << " parent"
412 << ");\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -0700413 }
414
Steven Morelandd39133b2016-11-11 12:30:08 -0800415 out << "\nstatic const char* descriptor;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700416
Yifan Hongc8934042016-11-17 17:10:52 -0800417 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800418 out << "// skipped getService, registerAsService, registerForNotifications\n\n";
Yifan Hongc8934042016-11-17 17:10:52 -0800419 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -0800420 declareServiceManagerInteractions(out, baseName);
Yifan Hongc8934042016-11-17 17:10:52 -0800421 }
Yifan Hong158655a2016-11-08 12:34:07 -0800422
423 out << "private: static int hidlStaticBlock;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700424 }
425
426 if (isInterface) {
427 out.unindent();
428
Andreas Hubere3f769a2016-10-10 10:54:44 -0700429 out << "};\n\n";
430 }
431
432 err = mRootScope->emitGlobalTypeDeclarations(out);
433
434 if (err != OK) {
435 return err;
Andreas Huber881227d2016-08-02 14:20:21 -0700436 }
437
438 out << "\n";
439 enterLeaveNamespace(out, false /* enter */);
440
441 out << "\n#endif // " << guard << "\n";
442
443 return OK;
444}
445
Steven Moreland40786312016-08-16 10:29:40 -0700446status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
447 std::string ifaceName;
Yifan Hong244e82d2016-11-11 11:13:57 -0800448 bool isInterface = AST::isInterface(&ifaceName);
449 const Interface *iface = nullptr;
450 std::string baseName{};
451 std::string klassName{};
452
453 if(isInterface) {
454 iface = mRootScope->getInterface();
455 baseName = iface->getBaseName();
456 klassName = "IHw" + baseName;
457 } else {
458 klassName = "hwtypes";
Steven Moreland40786312016-08-16 10:29:40 -0700459 }
460
Steven Moreland40786312016-08-16 10:29:40 -0700461 std::string path = outputPath;
462 path.append(mCoordinator->convertPackageRootToPath(mPackage));
463 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
464 path.append(klassName + ".h");
465
Yifan Hong244e82d2016-11-11 11:13:57 -0800466 FILE *file = fopen(path.c_str(), "w");
Steven Moreland40786312016-08-16 10:29:40 -0700467
468 if (file == NULL) {
469 return -errno;
470 }
471
472 Formatter out(file);
473
474 const std::string guard = makeHeaderGuard(klassName);
475
476 out << "#ifndef " << guard << "\n";
477 out << "#define " << guard << "\n\n";
478
Yifan Hong244e82d2016-11-11 11:13:57 -0800479 if (isInterface) {
480 generateCppPackageInclude(out, mPackage, ifaceName);
481 } else {
482 generateCppPackageInclude(out, mPackage, "types");
483 }
Steven Moreland40786312016-08-16 10:29:40 -0700484
Steven Morelandee88eed2016-10-31 17:49:00 -0700485 out << "\n";
Steven Moreland40786312016-08-16 10:29:40 -0700486
487 for (const auto &item : mImportedNames) {
488 if (item.name() == "types") {
Yifan Hong244e82d2016-11-11 11:13:57 -0800489 generateCppPackageInclude(out, item, "hwtypes");
490 } else {
491 generateCppPackageInclude(out, item, "Bn" + item.getInterfaceBaseName());
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100492 generateCppPackageInclude(out, item, "Bp" + item.getInterfaceBaseName());
Steven Moreland40786312016-08-16 10:29:40 -0700493 }
Steven Moreland40786312016-08-16 10:29:40 -0700494 }
495
496 out << "\n";
497
Martijn Coenen93915102016-09-01 01:35:52 +0200498 out << "#include <hidl/Status.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700499 out << "#include <hwbinder/IBinder.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100500 out << "#include <hwbinder/Parcel.h>\n";
Steven Moreland40786312016-08-16 10:29:40 -0700501
502 out << "\n";
503
504 enterLeaveNamespace(out, true /* enter */);
Steven Moreland40786312016-08-16 10:29:40 -0700505
Yifan Hong244e82d2016-11-11 11:13:57 -0800506 status_t err = mRootScope->emitGlobalHwDeclarations(out);
507 if (err != OK) {
508 return err;
509 }
Steven Moreland40786312016-08-16 10:29:40 -0700510
511 enterLeaveNamespace(out, false /* enter */);
512
513 out << "\n#endif // " << guard << "\n";
514
515 return OK;
516}
517
Andreas Huber881227d2016-08-02 14:20:21 -0700518status_t AST::emitTypeDeclarations(Formatter &out) const {
519 return mRootScope->emitTypeDeclarations(out);
520}
521
Yifan Hong7a118f52016-12-07 11:21:15 -0800522static void wrapPassthroughArg(Formatter &out,
523 const TypedVar *arg, bool addPrefixToName,
524 std::function<void(void)> handleError) {
525 if (!arg->type().isInterface()) {
526 return;
527 }
528 std::string name = (addPrefixToName ? "_hidl_out_" : "") + arg->name();
529 std::string wrappedName = (addPrefixToName ? "_hidl_out_wrapped_" : "_hidl_wrapped_")
530 + arg->name();
531 const Interface &iface = static_cast<const Interface &>(arg->type());
532 out << iface.getCppStackType() << " " << wrappedName << ";\n";
533 // TODO(elsk): b/33754152 Should not wrap this if object is Bs*
534 out.sIf(name + " != nullptr && !" + name + "->isRemote()", [&] {
535 out << wrappedName
536 << " = "
537 << iface.fqName().cppName()
538 << "::castFrom(::android::hardware::wrapPassthrough("
539 << name << "));\n";
540 out.sIf(wrappedName + " == nullptr", [&] {
541 // Fatal error. Happens when the BsFoo class is not found in the binary
542 // or any dynamic libraries.
543 handleError();
544 }).endl();
545 }).sElse([&] {
546 out << wrappedName << " = " << name << ";\n";
547 }).endl().endl();
548}
549
Steven Moreland69e7c702016-09-09 11:16:32 -0700550status_t AST::generatePassthroughMethod(Formatter &out,
Yifan Hong068c5522016-10-31 14:07:25 -0700551 const Method *method) const {
552 method->generateCppSignature(out);
Steven Moreland69e7c702016-09-09 11:16:32 -0700553
554 out << " {\n";
555 out.indent();
556
557 const bool returnsValue = !method->results().empty();
558 const TypedVar *elidedReturn = method->canElideCallback();
559
Steven Moreland67f67b42016-09-29 08:59:02 -0700560 if (returnsValue && elidedReturn == nullptr) {
561 generateCheckNonNull(out, "_hidl_cb");
562 }
563
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700564 generateCppInstrumentationCall(
565 out,
566 InstrumentationEvent::PASSTHROUGH_ENTRY,
567 method);
568
Yifan Hong7a118f52016-12-07 11:21:15 -0800569
570 for (const auto &arg : method->args()) {
571 wrapPassthroughArg(out, arg, false /* addPrefixToName */, [&] {
572 out << "return ::android::hardware::Status::fromExceptionCode(\n";
573 out.indent(2, [&] {
574 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
Yifan Hong0abd7392016-12-20 16:43:26 -0800575 << "\"Cannot wrap passthrough interface.\");\n";
Yifan Hong7a118f52016-12-07 11:21:15 -0800576 });
577 });
578 }
579
580 out << "auto _hidl_error = ::android::hardware::Void();\n";
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700581 out << "auto _hidl_return = ";
Steven Moreland69e7c702016-09-09 11:16:32 -0700582
583 if (method->isOneway()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800584 out << "addOnewayTask([this, &_hidl_error";
Steven Moreland69e7c702016-09-09 11:16:32 -0700585 for (const auto &arg : method->args()) {
Yifan Hong7a118f52016-12-07 11:21:15 -0800586 out << ", "
587 << (arg->type().isInterface() ? "_hidl_wrapped_" : "")
588 << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700589 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700590 out << "] {\n";
591 out.indent();
592 out << "this->";
Steven Moreland69e7c702016-09-09 11:16:32 -0700593 }
594
595 out << "mImpl->"
596 << method->name()
597 << "(";
598
599 bool first = true;
600 for (const auto &arg : method->args()) {
601 if (!first) {
602 out << ", ";
603 }
604 first = false;
Yifan Hong7a118f52016-12-07 11:21:15 -0800605 out << (arg->type().isInterface() ? "_hidl_wrapped_" : "") << arg->name();
Steven Moreland69e7c702016-09-09 11:16:32 -0700606 }
607 if (returnsValue && elidedReturn == nullptr) {
608 if (!method->args().empty()) {
609 out << ", ";
610 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800611 out << "[&](";
612 first = true;
613 for (const auto &arg : method->results()) {
614 if (!first) {
615 out << ", ";
616 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700617
Yifan Hong7a118f52016-12-07 11:21:15 -0800618 out << "const auto &_hidl_out_"
619 << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800620
621 first = false;
622 }
623
624 out << ") {\n";
625 out.indent();
626 status_t status = generateCppInstrumentationCall(
627 out,
628 InstrumentationEvent::PASSTHROUGH_EXIT,
629 method);
630 if (status != OK) {
631 return status;
632 }
633
Yifan Hong7a118f52016-12-07 11:21:15 -0800634 for (const auto &arg : method->results()) {
635 wrapPassthroughArg(out, arg, true /* addPrefixToName */, [&] {
636 out << "_hidl_error = ::android::hardware::Status::fromExceptionCode(\n";
637 out.indent(2, [&] {
638 out << "::android::hardware::Status::EX_TRANSACTION_FAILED,\n"
Yifan Hong0abd7392016-12-20 16:43:26 -0800639 << "\"Cannot wrap passthrough interface.\");\n";
Yifan Hong7a118f52016-12-07 11:21:15 -0800640 });
641 out << "return;\n";
642 });
643 }
644
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800645 out << "_hidl_cb(";
646 first = true;
647 for (const auto &arg : method->results()) {
648 if (!first) {
649 out << ", ";
650 }
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800651 first = false;
Yifan Hong7a118f52016-12-07 11:21:15 -0800652 out << (arg->type().isInterface() ? "_hidl_out_wrapped_" : "_hidl_out_")
653 << arg->name();
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800654 }
655 out << ");\n";
656 out.unindent();
657 out << "});\n\n";
658 } else {
659 out << ");\n\n";
660 if (elidedReturn != nullptr) {
661 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -0800662 << " _hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800663 << elidedReturn->name()
Steven Moreland2ae5bca2016-12-01 05:56:49 +0000664 << " = _hidl_return;\n";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -0800665 }
666 status_t status = generateCppInstrumentationCall(
667 out,
668 InstrumentationEvent::PASSTHROUGH_EXIT,
669 method);
670 if (status != OK) {
671 return status;
672 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700673 }
Steven Moreland69e7c702016-09-09 11:16:32 -0700674
675 if (method->isOneway()) {
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700676 out.unindent();
677 out << "});\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700678 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -0700679
680 out << "return _hidl_return;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -0700681
682 out.unindent();
683 out << "}\n";
684
685 return OK;
686}
687
Yifan Hong068c5522016-10-31 14:07:25 -0700688status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
Steven Morelanda7a421a2016-09-07 08:35:18 -0700689
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700690 const Interface *iface = mRootScope->getInterface();
691
Yifan Hong10fe0b52016-10-19 14:20:17 -0700692 const Interface *prevIterface = nullptr;
693 for (const auto &tuple : iface->allMethodsFromRoot()) {
694 const Method *method = tuple.method();
695 const Interface *superInterface = tuple.interface();
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700696
Yifan Hong10fe0b52016-10-19 14:20:17 -0700697 if(prevIterface != superInterface) {
698 if (prevIterface != nullptr) {
699 out << "\n";
700 }
701 out << "// Methods from "
702 << superInterface->fullName()
703 << " follow.\n";
704 prevIterface = superInterface;
705 }
Yifan Hong068c5522016-10-31 14:07:25 -0700706 status_t err = gen(method, superInterface);
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700707
Yifan Hong10fe0b52016-10-19 14:20:17 -0700708 if (err != OK) {
709 return err;
710 }
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700711 }
712
Yifan Hong10fe0b52016-10-19 14:20:17 -0700713 out << "\n";
714
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700715 return OK;
716}
717
Andreas Huberb82318c2016-08-02 14:45:54 -0700718status_t AST::generateStubHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700719 std::string ifaceName;
720 if (!AST::isInterface(&ifaceName)) {
721 // types.hal does not get a stub header.
722 return OK;
723 }
724
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700725 const Interface *iface = mRootScope->getInterface();
726 const std::string baseName = iface->getBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700727 const std::string klassName = "Bn" + baseName;
Andreas Huber881227d2016-08-02 14:20:21 -0700728
Andreas Huberb82318c2016-08-02 14:45:54 -0700729 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700730 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700731 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Steven Moreland40786312016-08-16 10:29:40 -0700732 path.append(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700733 path.append(".h");
734
Andreas Huberd2943e12016-08-05 11:59:31 -0700735 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700736 FILE *file = fopen(path.c_str(), "w");
737
738 if (file == NULL) {
739 return -errno;
740 }
741
742 Formatter out(file);
743
Steven Moreland40786312016-08-16 10:29:40 -0700744 const std::string guard = makeHeaderGuard(klassName);
Andreas Huber881227d2016-08-02 14:20:21 -0700745
746 out << "#ifndef " << guard << "\n";
747 out << "#define " << guard << "\n\n";
748
Steven Morelandee88eed2016-10-31 17:49:00 -0700749 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
750 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700751
752 enterLeaveNamespace(out, true /* enter */);
753 out << "\n";
754
755 out << "struct "
756 << "Bn"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100757 << baseName;
758 if (iface->isIBase()) {
759 out << " : public ::android::hardware::BBinder";
760 out << ", public ::android::hardware::HidlInstrumentor {\n";
761 } else {
762 out << " : public ::android::hidl::base::V1_0::BnBase {\n";
763 }
Andreas Huber881227d2016-08-02 14:20:21 -0700764
765 out.indent();
Steven Moreland40786312016-08-16 10:29:40 -0700766 out << "explicit Bn"
767 << baseName
768 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100769 << "\n";
770 out << "explicit Bn"
771 << baseName
772 << "(const ::android::sp<" << ifaceName << "> &_hidl_impl,"
773 << " const std::string& prefix);"
Steven Moreland40786312016-08-16 10:29:40 -0700774 << "\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700775 out << "::android::status_t onTransact(\n";
776 out.indent();
777 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700778 out << "uint32_t _hidl_code,\n";
779 out << "const ::android::hardware::Parcel &_hidl_data,\n";
780 out << "::android::hardware::Parcel *_hidl_reply,\n";
781 out << "uint32_t _hidl_flags = 0,\n";
Iliyan Malchev62c3d182016-08-16 20:33:39 -0700782 out << "TransactCallback _hidl_cb = nullptr) override;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700783 out.unindent();
784 out.unindent();
785
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100786 out << "::android::sp<" << ifaceName << "> getImpl() { return _hidl_mImpl; };\n";
787 out.unindent();
788 out << "private:\n";
789 out.indent();
790 out << "::android::sp<" << ifaceName << "> _hidl_mImpl;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700791 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700792 out << "};\n\n";
793
794 enterLeaveNamespace(out, false /* enter */);
795
796 out << "\n#endif // " << guard << "\n";
797
798 return OK;
799}
800
Andreas Huberb82318c2016-08-02 14:45:54 -0700801status_t AST::generateProxyHeader(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700802 std::string ifaceName;
803 if (!AST::isInterface(&ifaceName)) {
804 // types.hal does not get a proxy header.
805 return OK;
806 }
807
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700808 const Interface *iface = mRootScope->getInterface();
809 const std::string baseName = iface->getBaseName();
Andreas Huber881227d2016-08-02 14:20:21 -0700810
Andreas Huberb82318c2016-08-02 14:45:54 -0700811 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700812 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700813 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700814 path.append("Bp");
815 path.append(baseName);
816 path.append(".h");
817
Andreas Huberd2943e12016-08-05 11:59:31 -0700818 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700819 FILE *file = fopen(path.c_str(), "w");
820
821 if (file == NULL) {
822 return -errno;
823 }
824
825 Formatter out(file);
826
827 const std::string guard = makeHeaderGuard("Bp" + baseName);
828
829 out << "#ifndef " << guard << "\n";
830 out << "#define " << guard << "\n\n";
831
Martijn Coenen115d4282016-12-19 05:14:04 +0100832 out << "#include <hidl/HidlTransportSupport.h>\n\n";
833
Andreas Huber881227d2016-08-02 14:20:21 -0700834 std::vector<std::string> packageComponents;
835 getPackageAndVersionComponents(
836 &packageComponents, false /* cpp_compatible */);
837
Steven Morelandee88eed2016-10-31 17:49:00 -0700838 generateCppPackageInclude(out, mPackage, "IHw" + baseName);
839 out << "\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700840
841 enterLeaveNamespace(out, true /* enter */);
842 out << "\n";
843
844 out << "struct "
845 << "Bp"
846 << baseName
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100847 << " : public ::android::hardware::BpInterface<I"
Steven Moreland40786312016-08-16 10:29:40 -0700848 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -0700849 << ">, public ::android::hardware::HidlInstrumentor {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700850
851 out.indent();
852
853 out << "explicit Bp"
854 << baseName
Iliyan Malchev549e2592016-08-10 08:59:12 -0700855 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
Andreas Huber881227d2016-08-02 14:20:21 -0700856 << "\n\n";
857
Yifan Hong10fe0b52016-10-19 14:20:17 -0700858 out << "virtual bool isRemote() const override { return true; }\n\n";
Steven Moreland40786312016-08-16 10:29:40 -0700859
Yifan Hong068c5522016-10-31 14:07:25 -0700860 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
861 method->generateCppSignature(out);
862 out << " override;\n";
863 return OK;
864 });
Steven Moreland9c387612016-09-07 09:54:26 -0700865
866 if (err != OK) {
867 return err;
868 }
Andreas Huber881227d2016-08-02 14:20:21 -0700869
870 out.unindent();
Martijn Coenen115d4282016-12-19 05:14:04 +0100871 out << "private:\n";
872 out.indent();
873 out << "std::mutex _hidl_mMutex;\n"
874 << "std::vector<::android::sp<::android::hardware::hidl_binder_death_recipient>>"
875 << " _hidl_mDeathRecipients;\n";
876 out.unindent();
Andreas Huber881227d2016-08-02 14:20:21 -0700877 out << "};\n\n";
878
879 enterLeaveNamespace(out, false /* enter */);
880
881 out << "\n#endif // " << guard << "\n";
882
883 return OK;
884}
885
Andreas Huberb82318c2016-08-02 14:45:54 -0700886status_t AST::generateAllSource(const std::string &outputPath) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700887
Andreas Huberb82318c2016-08-02 14:45:54 -0700888 std::string path = outputPath;
Andreas Huberd2943e12016-08-05 11:59:31 -0700889 path.append(mCoordinator->convertPackageRootToPath(mPackage));
Andreas Huberdca261f2016-08-04 13:47:51 -0700890 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
Andreas Huber881227d2016-08-02 14:20:21 -0700891
892 std::string ifaceName;
893 std::string baseName;
894
Yifan Hongfe95aa22016-10-19 17:26:45 -0700895 const Interface *iface = nullptr;
896 bool isInterface;
Andreas Huber881227d2016-08-02 14:20:21 -0700897 if (!AST::isInterface(&ifaceName)) {
898 baseName = "types";
899 isInterface = false;
900 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -0700901 iface = mRootScope->getInterface();
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700902 baseName = iface->getBaseName();
Yifan Hongfe95aa22016-10-19 17:26:45 -0700903 isInterface = true;
Andreas Huber881227d2016-08-02 14:20:21 -0700904 }
905
906 path.append(baseName);
907
908 if (baseName != "types") {
909 path.append("All");
910 }
911
912 path.append(".cpp");
913
Andreas Huberd2943e12016-08-05 11:59:31 -0700914 CHECK(Coordinator::MakeParentHierarchy(path));
Andreas Huber881227d2016-08-02 14:20:21 -0700915 FILE *file = fopen(path.c_str(), "w");
916
917 if (file == NULL) {
918 return -errno;
919 }
920
921 Formatter out(file);
922
Steven Moreland05cd4232016-11-21 16:01:12 -0800923 out << "#include <android/log.h>\n";
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +0100924 out << "#include <cutils/trace.h>\n";
925 out << "#include <hidl/HidlTransportSupport.h>\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700926 if (isInterface) {
Steven Moreland19d5c172016-10-20 19:20:25 -0700927 // This is a no-op for IServiceManager itself.
928 out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";
929
Steven Morelandee88eed2016-10-31 17:49:00 -0700930 generateCppPackageInclude(out, mPackage, "Bp" + baseName);
931 generateCppPackageInclude(out, mPackage, "Bn" + baseName);
932 generateCppPackageInclude(out, mPackage, "Bs" + baseName);
Yifan Hongfe95aa22016-10-19 17:26:45 -0700933
934 for (const Interface *superType : iface->superTypeChain()) {
Steven Morelandee88eed2016-10-31 17:49:00 -0700935 generateCppPackageInclude(out,
936 superType->fqName(),
937 "Bp" + superType->getBaseName());
Yifan Hongfe95aa22016-10-19 17:26:45 -0700938 }
Yifan Hong2cbbdf92016-12-05 15:20:50 -0800939
940 out << "#include <hidl/ServiceManagement.h>\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700941 } else {
Steven Morelandee88eed2016-10-31 17:49:00 -0700942 generateCppPackageInclude(out, mPackage, "types");
Yifan Hong244e82d2016-11-11 11:13:57 -0800943 generateCppPackageInclude(out, mPackage, "hwtypes");
Andreas Huber881227d2016-08-02 14:20:21 -0700944 }
945
946 out << "\n";
947
948 enterLeaveNamespace(out, true /* enter */);
949 out << "\n";
950
951 status_t err = generateTypeSource(out, ifaceName);
952
953 if (err == OK && isInterface) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700954 const Interface *iface = mRootScope->getInterface();
Steven Moreland19d5c172016-10-20 19:20:25 -0700955 out << "constexpr ::android::hardware::hidl_version "
956 << ifaceName
957 << "::version;\n\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700958
959 // need to be put here, generateStubSource is using this.
Steven Morelandd39133b2016-11-11 12:30:08 -0800960 out << "const char* I"
Yifan Hong10fe0b52016-10-19 14:20:17 -0700961 << iface->getBaseName()
962 << "::descriptor(\""
963 << iface->fqName().string()
964 << "\");\n\n";
965
Yifan Hong158655a2016-11-08 12:34:07 -0800966 out << "int I"
967 << iface->getBaseName()
968 << "::hidlStaticBlock = []() -> int {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800969 out.indent([&] {
Steven Morelandd39133b2016-11-11 12:30:08 -0800970 out << "::android::hardware::gBnConstructorMap[I"
Yifan Hong158655a2016-11-08 12:34:07 -0800971 << iface->getBaseName()
Steven Morelandd39133b2016-11-11 12:30:08 -0800972 << "::descriptor]\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800973 out.indent(2, [&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800974 out << "= [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800975 out.indent([&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800976 out << "return new Bn"
977 << iface->getBaseName()
978 << "(reinterpret_cast<I"
979 << iface->getBaseName()
980 << " *>(iIntf));\n";
981 });
982 out << "};\n";
983 });
Yifan Hong7a118f52016-12-07 11:21:15 -0800984 out << "::android::hardware::gBsConstructorMap[I"
985 << iface->getBaseName()
986 << "::descriptor]\n";
987 out.indent(2, [&] {
988 out << "= [](void *iIntf) -> ::android::sp<"
989 << gIBaseFqName.cppName()
990 << "> {\n";
991 out.indent([&] {
992 out << "return new Bs"
993 << iface->getBaseName()
994 << "(reinterpret_cast<I"
995 << iface->getBaseName()
996 << " *>(iIntf));\n";
997 });
998 out << "};\n";
999 });
Yifan Hong158655a2016-11-08 12:34:07 -08001000 out << "return 1;\n";
1001 });
1002 out << "}();\n\n";
1003
Yifan Hongfe95aa22016-10-19 17:26:45 -07001004 err = generateInterfaceSource(out);
1005 }
1006
1007 if (err == OK && isInterface) {
Andreas Huber881227d2016-08-02 14:20:21 -07001008 err = generateProxySource(out, baseName);
1009 }
1010
1011 if (err == OK && isInterface) {
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001012 err = generateStubSource(out, iface, baseName);
Andreas Huber881227d2016-08-02 14:20:21 -07001013 }
1014
Steven Moreland40786312016-08-16 10:29:40 -07001015 if (err == OK && isInterface) {
Steven Moreland69e7c702016-09-09 11:16:32 -07001016 err = generatePassthroughSource(out);
1017 }
1018
1019 if (err == OK && isInterface) {
Steven Moreland9c387612016-09-07 09:54:26 -07001020 const Interface *iface = mRootScope->getInterface();
1021
Yifan Hongc8934042016-11-17 17:10:52 -08001022 if (isIBase()) {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001023 out << "// skipped getService, registerAsService, registerForNotifications\n";
Yifan Hongc8934042016-11-17 17:10:52 -08001024 } else {
Yifan Hong83c8e5f2016-12-13 14:33:53 -08001025 std::string package = iface->fqName().package()
1026 + iface->fqName().atVersion();
1027
1028 implementServiceManagerInteractions(out, baseName, package);
Yifan Hongc8934042016-11-17 17:10:52 -08001029 }
Steven Moreland40786312016-08-16 10:29:40 -07001030 }
1031
Andreas Huber881227d2016-08-02 14:20:21 -07001032 enterLeaveNamespace(out, false /* enter */);
1033
1034 return err;
1035}
1036
Steven Moreland67f67b42016-09-29 08:59:02 -07001037// static
1038void AST::generateCheckNonNull(Formatter &out, const std::string &nonNull) {
Yifan Honga018ed52016-12-13 16:35:08 -08001039 out.sIf(nonNull + " == nullptr", [&] {
1040 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1041 out.indent(2, [&] {
1042 out << "::android::hardware::Status::EX_ILLEGAL_ARGUMENT);\n";
1043 });
1044 }).endl().endl();
Steven Moreland67f67b42016-09-29 08:59:02 -07001045}
1046
Andreas Huber881227d2016-08-02 14:20:21 -07001047status_t AST::generateTypeSource(
1048 Formatter &out, const std::string &ifaceName) const {
1049 return mRootScope->emitTypeDefinitions(out, ifaceName);
1050}
1051
Andreas Hubere7ff2282016-08-16 13:50:03 -07001052void AST::declareCppReaderLocals(
Andreas Huber5e44a292016-09-27 14:52:39 -07001053 Formatter &out,
1054 const std::vector<TypedVar *> &args,
1055 bool forResults) const {
Andreas Hubere7ff2282016-08-16 13:50:03 -07001056 if (args.empty()) {
1057 return;
1058 }
1059
1060 for (const auto &arg : args) {
1061 const Type &type = arg->type();
1062
Yifan Hong3b320f82016-11-01 15:15:54 -07001063 out << type.getCppResultType()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001064 << " "
Yifan Hong3b320f82016-11-01 15:15:54 -07001065 << (forResults ? "_hidl_out_" : "") + arg->name()
Andreas Hubere7ff2282016-08-16 13:50:03 -07001066 << ";\n";
1067 }
1068
1069 out << "\n";
1070}
1071
Andreas Huber881227d2016-08-02 14:20:21 -07001072void AST::emitCppReaderWriter(
1073 Formatter &out,
1074 const std::string &parcelObj,
1075 bool parcelObjIsPointer,
1076 const TypedVar *arg,
1077 bool isReader,
Andreas Huber5e44a292016-09-27 14:52:39 -07001078 Type::ErrorMode mode,
1079 bool addPrefixToName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001080 const Type &type = arg->type();
1081
Andreas Huber881227d2016-08-02 14:20:21 -07001082 type.emitReaderWriter(
1083 out,
Andreas Huber5e44a292016-09-27 14:52:39 -07001084 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
Andreas Huber881227d2016-08-02 14:20:21 -07001085 parcelObj,
1086 parcelObjIsPointer,
1087 isReader,
1088 mode);
1089}
1090
Yifan Hongbf459bc2016-08-23 16:50:37 -07001091void AST::emitCppResolveReferences(
1092 Formatter &out,
1093 const std::string &parcelObj,
1094 bool parcelObjIsPointer,
1095 const TypedVar *arg,
1096 bool isReader,
1097 Type::ErrorMode mode,
1098 bool addPrefixToName) const {
1099 const Type &type = arg->type();
1100 if(type.needsResolveReferences()) {
1101 type.emitResolveReferences(
1102 out,
1103 addPrefixToName ? ("_hidl_out_" + arg->name()) : arg->name(),
1104 isReader, // nameIsPointer
1105 parcelObj,
1106 parcelObjIsPointer,
1107 isReader,
1108 mode);
1109 }
1110}
1111
Yifan Hong068c5522016-10-31 14:07:25 -07001112status_t AST::generateProxyMethodSource(Formatter &out,
1113 const std::string &klassName,
1114 const Method *method,
1115 const Interface *superInterface) const {
1116
1117 method->generateCppSignature(out,
1118 klassName,
1119 true /* specify namespaces */);
1120
1121 const bool returnsValue = !method->results().empty();
1122 const TypedVar *elidedReturn = method->canElideCallback();
1123
Steven Moreland41c6d2e2016-11-07 12:26:54 -08001124 out << " {\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001125
1126 out.indent();
1127
Martijn Coenen115d4282016-12-19 05:14:04 +01001128 if (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
1129 method->cppImpl(IMPL_PROXY, out);
1130 out.unindent();
1131 out << "}\n\n";
1132 return OK;
1133 }
1134
Yifan Hong068c5522016-10-31 14:07:25 -07001135 if (returnsValue && elidedReturn == nullptr) {
1136 generateCheckNonNull(out, "_hidl_cb");
1137 }
1138
1139 status_t status = generateCppInstrumentationCall(
1140 out,
1141 InstrumentationEvent::CLIENT_API_ENTRY,
Yifan Hong068c5522016-10-31 14:07:25 -07001142 method);
1143 if (status != OK) {
1144 return status;
1145 }
1146
1147 out << "::android::hardware::Parcel _hidl_data;\n";
1148 out << "::android::hardware::Parcel _hidl_reply;\n";
1149 out << "::android::status_t _hidl_err;\n";
1150 out << "::android::hardware::Status _hidl_status;\n\n";
1151
1152 declareCppReaderLocals(
1153 out, method->results(), true /* forResults */);
1154
1155 out << "_hidl_err = _hidl_data.writeInterfaceToken(";
Yifan Hongc8934042016-11-17 17:10:52 -08001156 out << superInterface->fqName().cppNamespace()
1157 << "::I"
1158 << superInterface->getBaseName();
Yifan Hong068c5522016-10-31 14:07:25 -07001159 out << "::descriptor);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001160 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1161
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001162 bool hasInterfaceArgument;
Yifan Hong068c5522016-10-31 14:07:25 -07001163 // First DFS: write all buffers and resolve pointers for parent
1164 for (const auto &arg : method->args()) {
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001165 if (arg->type().isInterface()) {
1166 hasInterfaceArgument = true;
1167 }
Yifan Hong068c5522016-10-31 14:07:25 -07001168 emitCppReaderWriter(
1169 out,
1170 "_hidl_data",
1171 false /* parcelObjIsPointer */,
1172 arg,
1173 false /* reader */,
1174 Type::ErrorMode_Goto,
1175 false /* addPrefixToName */);
1176 }
1177
1178 // Second DFS: resolve references.
1179 for (const auto &arg : method->args()) {
1180 emitCppResolveReferences(
1181 out,
1182 "_hidl_data",
1183 false /* parcelObjIsPointer */,
1184 arg,
1185 false /* reader */,
1186 Type::ErrorMode_Goto,
1187 false /* addPrefixToName */);
1188 }
1189
Martijn Coenenfa55d6e2016-12-20 06:08:31 +01001190 if (hasInterfaceArgument) {
1191 // Start binder threadpool to handle incoming transactions
1192 out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
1193 }
Yifan Hong068c5522016-10-31 14:07:25 -07001194 out << "_hidl_err = remote()->transact("
1195 << method->getSerialId()
1196 << " /* "
1197 << method->name()
1198 << " */, _hidl_data, &_hidl_reply";
1199
1200 if (method->isOneway()) {
1201 out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
1202 }
1203 out << ");\n";
1204
1205 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1206
1207 if (!method->isOneway()) {
Yifan Hong859e53f2016-11-14 19:08:24 -08001208 out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
Yifan Hong068c5522016-10-31 14:07:25 -07001209 out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
1210 out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
1211
1212
1213 // First DFS: write all buffers and resolve pointers for parent
1214 for (const auto &arg : method->results()) {
1215 emitCppReaderWriter(
1216 out,
1217 "_hidl_reply",
1218 false /* parcelObjIsPointer */,
1219 arg,
1220 true /* reader */,
1221 Type::ErrorMode_Goto,
1222 true /* addPrefixToName */);
1223 }
1224
1225 // Second DFS: resolve references.
1226 for (const auto &arg : method->results()) {
1227 emitCppResolveReferences(
1228 out,
1229 "_hidl_reply",
1230 false /* parcelObjIsPointer */,
1231 arg,
1232 true /* reader */,
1233 Type::ErrorMode_Goto,
1234 true /* addPrefixToName */);
1235 }
1236
1237 if (returnsValue && elidedReturn == nullptr) {
1238 out << "_hidl_cb(";
1239
1240 bool first = true;
1241 for (const auto &arg : method->results()) {
1242 if (!first) {
1243 out << ", ";
1244 }
1245
1246 if (arg->type().resultNeedsDeref()) {
1247 out << "*";
1248 }
1249 out << "_hidl_out_" << arg->name();
1250
1251 first = false;
1252 }
1253
1254 out << ");\n\n";
1255 }
Martijn Coenen7b295242016-11-04 16:52:56 +01001256 }
1257 status = generateCppInstrumentationCall(
1258 out,
1259 InstrumentationEvent::CLIENT_API_EXIT,
1260 method);
1261 if (status != OK) {
1262 return status;
Yifan Hong068c5522016-10-31 14:07:25 -07001263 }
1264
1265 if (elidedReturn != nullptr) {
Yifan Hong068c5522016-10-31 14:07:25 -07001266 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1267 out << "return ::android::hardware::Return<";
Yifan Hong3b320f82016-11-01 15:15:54 -07001268 out << elidedReturn->type().getCppResultType()
Yifan Hong068c5522016-10-31 14:07:25 -07001269 << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
1270 } else {
1271 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1272 out << "return ::android::hardware::Return<void>();\n\n";
1273 }
1274
1275 out.unindent();
1276 out << "_hidl_error:\n";
1277 out.indent();
1278 out << "_hidl_status.setFromStatusT(_hidl_err);\n";
1279 out << "return ::android::hardware::Return<";
1280 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001281 out << method->results().at(0)->type().getCppResultType();
Yifan Hong068c5522016-10-31 14:07:25 -07001282 } else {
1283 out << "void";
1284 }
1285 out << ">(_hidl_status);\n";
1286
1287 out.unindent();
1288 out << "}\n\n";
1289 return OK;
1290}
1291
Andreas Huber881227d2016-08-02 14:20:21 -07001292status_t AST::generateProxySource(
1293 Formatter &out, const std::string &baseName) const {
1294 const std::string klassName = "Bp" + baseName;
1295
1296 out << klassName
1297 << "::"
1298 << klassName
Iliyan Malchev549e2592016-08-10 08:59:12 -07001299 << "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001300
1301 out.indent();
1302 out.indent();
1303
1304 out << ": BpInterface"
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001305 << "<I"
Andreas Huber881227d2016-08-02 14:20:21 -07001306 << baseName
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001307 << ">(_hidl_impl),\n"
Steven Moreland19d5c172016-10-20 19:20:25 -07001308 << " ::android::hardware::HidlInstrumentor(\""
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001309 << mPackage.string()
1310 << "::I"
1311 << baseName
1312 << "\") {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001313
Andreas Huber881227d2016-08-02 14:20:21 -07001314 out.unindent();
1315 out.unindent();
1316 out << "}\n\n";
1317
Yifan Hong068c5522016-10-31 14:07:25 -07001318 status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
1319 return generateProxyMethodSource(out, klassName, method, superInterface);
1320 });
Andreas Huber881227d2016-08-02 14:20:21 -07001321
Yifan Hong068c5522016-10-31 14:07:25 -07001322 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001323}
1324
1325status_t AST::generateStubSource(
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001326 Formatter &out,
1327 const Interface *iface,
1328 const std::string &baseName) const {
Andreas Huber881227d2016-08-02 14:20:21 -07001329 const std::string klassName = "Bn" + baseName;
1330
Steven Moreland40786312016-08-16 10:29:40 -07001331 out << klassName
1332 << "::"
1333 << klassName
1334 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
1335
1336 out.indent();
1337 out.indent();
1338
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001339 if (iface->isIBase()) {
1340 out << ": ::android::hardware::HidlInstrumentor(\"";
1341 } else {
1342 out << ": ::android::hidl::base::V1_0::BnBase(_hidl_impl, \"";
1343 }
1344
1345 out << mPackage.string()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001346 << "::I"
1347 << baseName
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001348 << "\") { \n";
1349 out.indent();
1350 out << "_hidl_mImpl = _hidl_impl;\n";
1351 out.unindent();
Steven Moreland40786312016-08-16 10:29:40 -07001352
1353 out.unindent();
1354 out.unindent();
1355 out << "}\n\n";
1356
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001357 if (iface->isIBase()) {
1358 // BnBase has a constructor to initialize the HidlInstrumentor
1359 // class properly.
1360 out << klassName
1361 << "::"
1362 << klassName
1363 << "(const ::android::sp<I" << baseName <<"> &_hidl_impl,"
1364 << " const std::string &prefix)\n";
1365
1366 out.indent();
1367 out.indent();
1368
1369 out << ": ::android::hardware::HidlInstrumentor(prefix) { \n";
1370 out.indent();
1371 out << "_hidl_mImpl = _hidl_impl;\n";
1372 out.unindent();
1373
1374 out.unindent();
1375 out.unindent();
1376 out << "}\n\n";
1377 }
1378
1379
Andreas Huber881227d2016-08-02 14:20:21 -07001380 out << "::android::status_t " << klassName << "::onTransact(\n";
1381
1382 out.indent();
1383 out.indent();
1384
Iliyan Malchev549e2592016-08-10 08:59:12 -07001385 out << "uint32_t _hidl_code,\n"
1386 << "const ::android::hardware::Parcel &_hidl_data,\n"
1387 << "::android::hardware::Parcel *_hidl_reply,\n"
1388 << "uint32_t _hidl_flags,\n"
1389 << "TransactCallback _hidl_cb) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001390
1391 out.unindent();
1392
Iliyan Malchev549e2592016-08-10 08:59:12 -07001393 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Iliyan Malchev549e2592016-08-10 08:59:12 -07001394 out << "switch (_hidl_code) {\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001395 out.indent();
1396
Yifan Hong10fe0b52016-10-19 14:20:17 -07001397 for (const auto &tuple : iface->allMethodsFromRoot()) {
1398 const Method *method = tuple.method();
1399 const Interface *superInterface = tuple.interface();
1400 out << "case "
1401 << method->getSerialId()
1402 << " /* "
1403 << method->name()
1404 << " */:\n{\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001405
Yifan Hong10fe0b52016-10-19 14:20:17 -07001406 out.indent();
Andreas Huber881227d2016-08-02 14:20:21 -07001407
Yifan Hong10fe0b52016-10-19 14:20:17 -07001408 status_t err =
1409 generateStubSourceForMethod(out, superInterface, method);
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001410
Yifan Hong10fe0b52016-10-19 14:20:17 -07001411 if (err != OK) {
1412 return err;
Andreas Huber881227d2016-08-02 14:20:21 -07001413 }
Yifan Hong10fe0b52016-10-19 14:20:17 -07001414
1415 out.unindent();
1416 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001417 }
1418
1419 out << "default:\n{\n";
1420 out.indent();
1421
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001422 out << "return onTransact(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001423
1424 out.indent();
1425 out.indent();
1426
Iliyan Malchev549e2592016-08-10 08:59:12 -07001427 out << "_hidl_code, _hidl_data, _hidl_reply, "
1428 << "_hidl_flags, _hidl_cb);\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001429
1430 out.unindent();
1431 out.unindent();
1432
1433 out.unindent();
1434 out << "}\n";
1435
1436 out.unindent();
1437 out << "}\n\n";
1438
Yifan Honga018ed52016-12-13 16:35:08 -08001439 out.sIf("_hidl_err == ::android::UNEXPECTED_NULL", [&] {
1440 out << "_hidl_err = ::android::hardware::writeToParcel(\n";
1441 out.indent(2, [&] {
1442 out << "::android::hardware::Status::fromExceptionCode(::android::hardware::Status::EX_NULL_POINTER),\n";
1443 out << "_hidl_reply);\n";
1444 });
1445 });
Andreas Huber881227d2016-08-02 14:20:21 -07001446
Iliyan Malchev549e2592016-08-10 08:59:12 -07001447 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001448
1449 out.unindent();
1450 out << "}\n\n";
1451
1452 return OK;
1453}
1454
1455status_t AST::generateStubSourceForMethod(
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001456 Formatter &out, const Interface *iface, const Method *method) const {
Martijn Coenen115d4282016-12-19 05:14:04 +01001457 if (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB)) {
1458 method->cppImpl(IMPL_STUB, out);
1459 out << "break;\n";
1460 return OK;
1461 }
1462
Yifan Hong10fe0b52016-10-19 14:20:17 -07001463 out << "if (!_hidl_data.enforceInterface(";
1464
Yifan Hongc8934042016-11-17 17:10:52 -08001465 out << iface->fqName().cppNamespace()
1466 << "::I"
1467 << iface->getBaseName();
Yifan Hong10fe0b52016-10-19 14:20:17 -07001468
1469 out << "::descriptor)) {\n";
Andreas Huber6cb08cf2016-08-03 15:44:51 -07001470
Andreas Huber881227d2016-08-02 14:20:21 -07001471 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -07001472 out << "_hidl_err = ::android::BAD_TYPE;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001473 out << "break;\n";
1474 out.unindent();
1475 out << "}\n\n";
1476
Andreas Huber5e44a292016-09-27 14:52:39 -07001477 declareCppReaderLocals(out, method->args(), false /* forResults */);
Andreas Hubere7ff2282016-08-16 13:50:03 -07001478
Yifan Hongbf459bc2016-08-23 16:50:37 -07001479 // First DFS: write buffers
Andreas Huber881227d2016-08-02 14:20:21 -07001480 for (const auto &arg : method->args()) {
1481 emitCppReaderWriter(
1482 out,
Iliyan Malchev549e2592016-08-10 08:59:12 -07001483 "_hidl_data",
Andreas Huber881227d2016-08-02 14:20:21 -07001484 false /* parcelObjIsPointer */,
1485 arg,
1486 true /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001487 Type::ErrorMode_Break,
1488 false /* addPrefixToName */);
Andreas Huber881227d2016-08-02 14:20:21 -07001489 }
1490
Yifan Hongbf459bc2016-08-23 16:50:37 -07001491 // Second DFS: resolve references
1492 for (const auto &arg : method->args()) {
1493 emitCppResolveReferences(
1494 out,
1495 "_hidl_data",
1496 false /* parcelObjIsPointer */,
1497 arg,
1498 true /* reader */,
1499 Type::ErrorMode_Break,
1500 false /* addPrefixToName */);
1501 }
1502
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001503 status_t status = generateCppInstrumentationCall(
1504 out,
1505 InstrumentationEvent::SERVER_API_ENTRY,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001506 method);
1507 if (status != OK) {
1508 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001509 }
1510
Andreas Huber881227d2016-08-02 14:20:21 -07001511 const bool returnsValue = !method->results().empty();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001512 const TypedVar *elidedReturn = method->canElideCallback();
Andreas Huber881227d2016-08-02 14:20:21 -07001513
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001514 if (elidedReturn != nullptr) {
Yifan Hong3b320f82016-11-01 15:15:54 -07001515 out << elidedReturn->type().getCppResultType()
Yifan Honga47eef32016-12-12 10:38:54 -08001516 << " _hidl_out_"
Yifan Hong3b320f82016-11-01 15:15:54 -07001517 << elidedReturn->name()
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001518 << " = "
1519 << "_hidl_mImpl->" << method->name()
Yifan Hong3b320f82016-11-01 15:15:54 -07001520 << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001521
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001522 bool first = true;
1523 for (const auto &arg : method->args()) {
Andreas Huber881227d2016-08-02 14:20:21 -07001524 if (!first) {
1525 out << ", ";
1526 }
1527
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001528 if (arg->type().resultNeedsDeref()) {
1529 out << "*";
1530 }
1531
1532 out << arg->name();
Andreas Huber881227d2016-08-02 14:20:21 -07001533
1534 first = false;
1535 }
1536
Steven Moreland2ae5bca2016-12-01 05:56:49 +00001537 out << ");\n\n";
Yifan Hong859e53f2016-11-14 19:08:24 -08001538 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1539 << "_hidl_reply);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001540
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001541 elidedReturn->type().emitReaderWriter(
1542 out,
Yifan Honga47eef32016-12-12 10:38:54 -08001543 "_hidl_out_" + elidedReturn->name(),
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001544 "_hidl_reply",
1545 true, /* parcelObjIsPointer */
1546 false, /* isReader */
1547 Type::ErrorMode_Ignore);
Andreas Huber881227d2016-08-02 14:20:21 -07001548
Yifan Hongbf459bc2016-08-23 16:50:37 -07001549 emitCppResolveReferences(
1550 out,
1551 "_hidl_reply",
1552 true /* parcelObjIsPointer */,
1553 elidedReturn,
1554 false /* reader */,
1555 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001556 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001557
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001558 status_t status = generateCppInstrumentationCall(
1559 out,
1560 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001561 method);
1562 if (status != OK) {
1563 return status;
1564 }
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001565
Iliyan Malchev549e2592016-08-10 08:59:12 -07001566 out << "_hidl_cb(*_hidl_reply);\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001567 } else {
1568 if (returnsValue) {
1569 out << "bool _hidl_callbackCalled = false;\n\n";
1570 }
Andreas Huber881227d2016-08-02 14:20:21 -07001571
Martijn Coenen6ec2f0b2016-12-11 01:04:55 +01001572 out << "_hidl_mImpl->" << method->name() << "(";
Andreas Huber881227d2016-08-02 14:20:21 -07001573
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001574 bool first = true;
1575 for (const auto &arg : method->args()) {
1576 if (!first) {
1577 out << ", ";
1578 }
Andreas Huber881227d2016-08-02 14:20:21 -07001579
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001580 if (arg->type().resultNeedsDeref()) {
1581 out << "*";
1582 }
1583
1584 out << arg->name();
1585
1586 first = false;
1587 }
1588
1589 if (returnsValue) {
1590 if (!first) {
1591 out << ", ";
1592 }
1593
1594 out << "[&](";
1595
1596 first = true;
1597 for (const auto &arg : method->results()) {
1598 if (!first) {
1599 out << ", ";
1600 }
1601
Yifan Honga47eef32016-12-12 10:38:54 -08001602 out << "const auto &_hidl_out_" << arg->name();
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001603
1604 first = false;
1605 }
1606
1607 out << ") {\n";
1608 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001609 out << "if (_hidl_callbackCalled) {\n";
1610 out.indent();
1611 out << "LOG_ALWAYS_FATAL(\""
1612 << method->name()
1613 << ": _hidl_cb called a second time, but must be called once.\");\n";
1614 out.unindent();
1615 out << "}\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001616 out << "_hidl_callbackCalled = true;\n\n";
1617
Yifan Hong859e53f2016-11-14 19:08:24 -08001618 out << "::android::hardware::writeToParcel(::android::hardware::Status::ok(), "
1619 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001620
Yifan Hongbf459bc2016-08-23 16:50:37 -07001621 // First DFS: buffers
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001622 for (const auto &arg : method->results()) {
1623 emitCppReaderWriter(
1624 out,
1625 "_hidl_reply",
1626 true /* parcelObjIsPointer */,
1627 arg,
1628 false /* reader */,
Andreas Huber5e44a292016-09-27 14:52:39 -07001629 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001630 true /* addPrefixToName */);
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001631 }
1632
Yifan Hongbf459bc2016-08-23 16:50:37 -07001633 // Second DFS: resolve references
1634 for (const auto &arg : method->results()) {
1635 emitCppResolveReferences(
1636 out,
1637 "_hidl_reply",
1638 true /* parcelObjIsPointer */,
1639 arg,
1640 false /* reader */,
1641 Type::ErrorMode_Ignore,
Yifan Honga47eef32016-12-12 10:38:54 -08001642 true /* addPrefixToName */);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001643 }
1644
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001645 status_t status = generateCppInstrumentationCall(
1646 out,
1647 InstrumentationEvent::SERVER_API_EXIT,
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001648 method);
1649 if (status != OK) {
1650 return status;
Zhuoyao Zhangde578002016-09-07 18:24:17 -07001651 }
1652
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001653 out << "_hidl_cb(*_hidl_reply);\n";
1654
1655 out.unindent();
1656 out << "}\n";
1657 }
Iliyan Malchevd57066f2016-09-08 13:59:38 -07001658 out << ");\n\n";
1659
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001660 if (returnsValue) {
1661 out << "if (!_hidl_callbackCalled) {\n";
1662 out.indent();
Steven Moreland05cd4232016-11-21 16:01:12 -08001663 out << "LOG_ALWAYS_FATAL(\""
1664 << method->name()
1665 << ": _hidl_cb not called, but must be called once.\");\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001666 out.unindent();
1667 out << "}\n\n";
Steven Moreland05cd4232016-11-21 16:01:12 -08001668 } else {
1669 out << "::android::hardware::writeToParcel("
1670 << "::android::hardware::Status::ok(), "
1671 << "_hidl_reply);\n\n";
Iliyan Malchev40d474a2016-08-16 06:20:17 -07001672 }
Andreas Huber881227d2016-08-02 14:20:21 -07001673 }
1674
1675 out << "break;\n";
1676
1677 return OK;
1678}
1679
Steven Moreland69e7c702016-09-09 11:16:32 -07001680status_t AST::generatePassthroughHeader(const std::string &outputPath) const {
1681 std::string ifaceName;
1682 if (!AST::isInterface(&ifaceName)) {
1683 // types.hal does not get a stub header.
1684 return OK;
1685 }
1686
1687 const Interface *iface = mRootScope->getInterface();
1688
1689 const std::string baseName = iface->getBaseName();
1690 const std::string klassName = "Bs" + baseName;
1691
1692 bool supportOneway = iface->hasOnewayMethods();
1693
1694 std::string path = outputPath;
1695 path.append(mCoordinator->convertPackageRootToPath(mPackage));
1696 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
1697 path.append(klassName);
1698 path.append(".h");
1699
1700 CHECK(Coordinator::MakeParentHierarchy(path));
1701 FILE *file = fopen(path.c_str(), "w");
1702
1703 if (file == NULL) {
1704 return -errno;
1705 }
1706
1707 Formatter out(file);
1708
1709 const std::string guard = makeHeaderGuard(klassName);
1710
1711 out << "#ifndef " << guard << "\n";
1712 out << "#define " << guard << "\n\n";
1713
1714 std::vector<std::string> packageComponents;
1715 getPackageAndVersionComponents(
1716 &packageComponents, false /* cpp_compatible */);
1717
Yifan Hongb0949432016-12-15 15:32:24 -08001718 out << "#include <cutils/trace.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001719 out << "#include <future>\n";
Steven Morelandee88eed2016-10-31 17:49:00 -07001720
1721 generateCppPackageInclude(out, mPackage, ifaceName);
1722 out << "\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001723
Yifan Hong7a118f52016-12-07 11:21:15 -08001724 out << "#include <hidl/HidlPassthroughSupport.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001725 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001726 out << "#include <hidl/TaskRunner.h>\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001727 }
1728
1729 enterLeaveNamespace(out, true /* enter */);
1730 out << "\n";
1731
1732 out << "struct "
1733 << klassName
1734 << " : " << ifaceName
Steven Moreland19d5c172016-10-20 19:20:25 -07001735 << ", ::android::hardware::HidlInstrumentor {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001736
1737 out.indent();
1738 out << "explicit "
1739 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001740 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001741 << ifaceName
1742 << "> impl);\n";
1743
Yifan Hong068c5522016-10-31 14:07:25 -07001744 status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
1745 return generatePassthroughMethod(out, method);
1746 });
Steven Moreland69e7c702016-09-09 11:16:32 -07001747
1748 if (err != OK) {
1749 return err;
1750 }
1751
1752 out.unindent();
1753 out << "private:\n";
1754 out.indent();
Steven Morelandc46e9842016-11-02 13:21:26 -07001755 out << "const ::android::sp<" << ifaceName << "> mImpl;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001756
1757 if (supportOneway) {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001758 out << "::android::hardware::TaskRunner mOnewayQueue;\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001759
1760 out << "\n";
1761
1762 out << "::android::hardware::Return<void> addOnewayTask("
1763 "std::function<void(void)>);\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001764 }
1765
1766 out.unindent();
1767
1768 out << "};\n\n";
1769
1770 enterLeaveNamespace(out, false /* enter */);
1771
1772 out << "\n#endif // " << guard << "\n";
1773
1774 return OK;
1775}
1776
Yifan Hongfe95aa22016-10-19 17:26:45 -07001777status_t AST::generateInterfaceSource(Formatter &out) const {
1778 const Interface *iface = mRootScope->getInterface();
1779
Yifan Hong2d7126b2016-10-20 15:12:57 -07001780 // generate castFrom functions
Yifan Hong3d746092016-12-07 14:26:33 -08001781 std::string childTypeResult = iface->getCppResultType();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001782
Yifan Hong3d746092016-12-07 14:26:33 -08001783 for (const Interface *superType : iface->typeChain()) {
1784 out << "// static \n"
1785 << childTypeResult
1786 << " I"
1787 << iface->getBaseName()
1788 << "::castFrom("
1789 << superType->getCppArgumentType()
1790 << " parent) {\n";
1791 out.indent();
1792 if (iface == superType) {
1793 out << "return parent;\n";
1794 } else {
Yifan Hongfe95aa22016-10-19 17:26:45 -07001795 out << "return ::android::hardware::castInterface<";
1796 out << "I" << iface->getBaseName() << ", "
1797 << superType->fqName().cppName() << ", "
Martijn Coenena63e0ad2016-12-07 17:29:00 +01001798 << iface->getProxyName().cppLocalName() << ", "
1799 << superType->getProxyName().cppName()
Yifan Hongfe95aa22016-10-19 17:26:45 -07001800 << ">(\n";
1801 out.indent();
1802 out.indent();
1803 out << "parent, \""
1804 << iface->fqName().string()
1805 << "\");\n";
1806 out.unindent();
1807 out.unindent();
Yifan Hongfe95aa22016-10-19 17:26:45 -07001808 }
Yifan Hong3d746092016-12-07 14:26:33 -08001809 out.unindent();
1810 out << "}\n\n";
Yifan Hongfe95aa22016-10-19 17:26:45 -07001811 }
1812
1813 return OK;
1814}
1815
Steven Moreland69e7c702016-09-09 11:16:32 -07001816status_t AST::generatePassthroughSource(Formatter &out) const {
1817 const Interface *iface = mRootScope->getInterface();
1818
1819 const std::string baseName = iface->getBaseName();
1820 const std::string klassName = "Bs" + baseName;
1821
1822 out << klassName
1823 << "::"
1824 << klassName
Steven Morelandc46e9842016-11-02 13:21:26 -07001825 << "(const ::android::sp<"
Steven Moreland69e7c702016-09-09 11:16:32 -07001826 << iface->fullName()
Steven Moreland19d5c172016-10-20 19:20:25 -07001827 << "> impl) : ::android::hardware::HidlInstrumentor(\""
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001828 << iface->fqName().string()
1829 << "\"), mImpl(impl) {";
Yifan Hong2cbc1472016-10-25 19:02:40 -07001830 if (iface->hasOnewayMethods()) {
1831 out << "\n";
Yifan Hong33223ca2016-12-13 15:07:35 -08001832 out.indent([&] {
Yifan Hong2cbc1472016-10-25 19:02:40 -07001833 out << "mOnewayQueue.setLimit(3000 /* similar limit to binderized */);\n";
1834 });
1835 }
1836 out << "}\n\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001837
1838 if (iface->hasOnewayMethods()) {
1839 out << "::android::hardware::Return<void> "
1840 << klassName
1841 << "::addOnewayTask(std::function<void(void)> fun) {\n";
1842 out.indent();
Yifan Hong2cbc1472016-10-25 19:02:40 -07001843 out << "if (!mOnewayQueue.push(fun)) {\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001844 out.indent();
Steven Moreland67f67b42016-09-29 08:59:02 -07001845 out << "return ::android::hardware::Status::fromExceptionCode(\n";
1846 out.indent();
1847 out.indent();
1848 out << "::android::hardware::Status::EX_TRANSACTION_FAILED);\n";
1849 out.unindent();
1850 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001851 out.unindent();
Steven Moreland69e7c702016-09-09 11:16:32 -07001852 out << "}\n";
1853
Steven Morelandd366c262016-10-11 15:29:10 -07001854 out << "return ::android::hardware::Status();\n";
Steven Moreland69e7c702016-09-09 11:16:32 -07001855
1856 out.unindent();
1857 out << "}\n\n";
1858
1859
1860 }
1861
1862 return OK;
1863}
1864
Martijn Coenen7b295242016-11-04 16:52:56 +01001865status_t AST::generateCppAtraceCall(Formatter &out,
1866 InstrumentationEvent event,
1867 const Method *method) const {
1868 const Interface *iface = mRootScope->getInterface();
1869 std::string baseString = "HIDL::I" + iface->getBaseName() + "::" + method->name();
1870 switch (event) {
1871 case SERVER_API_ENTRY:
1872 {
1873 out << "atrace_begin(ATRACE_TAG_HAL, \""
1874 << baseString + "::server\");\n";
1875 break;
1876 }
1877 case CLIENT_API_ENTRY:
1878 {
1879 out << "atrace_begin(ATRACE_TAG_HAL, \""
1880 << baseString + "::client\");\n";
1881 break;
1882 }
1883 case PASSTHROUGH_ENTRY:
1884 {
1885 out << "atrace_begin(ATRACE_TAG_HAL, \""
1886 << baseString + "::passthrough\");\n";
1887 break;
1888 }
1889 case SERVER_API_EXIT:
1890 case CLIENT_API_EXIT:
1891 case PASSTHROUGH_EXIT:
1892 {
1893 out << "atrace_end(ATRACE_TAG_HAL);\n";
1894 break;
1895 }
1896 default:
1897 {
1898 LOG(ERROR) << "Unsupported instrumentation event: " << event;
1899 return UNKNOWN_ERROR;
1900 }
1901 }
1902
1903 return OK;
1904}
1905
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001906status_t AST::generateCppInstrumentationCall(
1907 Formatter &out,
1908 InstrumentationEvent event,
Steven Moreland031ccf12016-10-31 15:54:38 -07001909 const Method *method) const {
Martijn Coenen7b295242016-11-04 16:52:56 +01001910 status_t err = generateCppAtraceCall(out, event, method);
1911 if (err != OK) {
1912 return err;
1913 }
1914
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001915 out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
1916 out.indent();
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001917 out << "std::vector<void *> _hidl_args;\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001918 std::string event_str = "";
1919 switch (event) {
1920 case SERVER_API_ENTRY:
1921 {
1922 event_str = "InstrumentationEvent::SERVER_API_ENTRY";
1923 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001924 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001925 << (arg->type().resultNeedsDeref() ? "" : "&")
1926 << arg->name()
1927 << ");\n";
1928 }
1929 break;
1930 }
1931 case SERVER_API_EXIT:
1932 {
1933 event_str = "InstrumentationEvent::SERVER_API_EXIT";
Steven Moreland031ccf12016-10-31 15:54:38 -07001934 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001935 out << "_hidl_args.push_back((void *)&_hidl_out_"
Steven Moreland031ccf12016-10-31 15:54:38 -07001936 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001937 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001938 }
1939 break;
1940 }
1941 case CLIENT_API_ENTRY:
1942 {
1943 event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
1944 for (const auto &arg : method->args()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001945 out << "_hidl_args.push_back((void *)&"
1946 << arg->name()
1947 << ");\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001948 }
1949 break;
1950 }
1951 case CLIENT_API_EXIT:
1952 {
1953 event_str = "InstrumentationEvent::CLIENT_API_EXIT";
1954 for (const auto &arg : method->results()) {
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001955 out << "_hidl_args.push_back((void *)"
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001956 << (arg->type().resultNeedsDeref() ? "" : "&")
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07001957 << "_hidl_out_"
1958 << arg->name()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001959 << ");\n";
1960 }
1961 break;
1962 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001963 case PASSTHROUGH_ENTRY:
1964 {
1965 event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
1966 for (const auto &arg : method->args()) {
1967 out << "_hidl_args.push_back((void *)&"
1968 << arg->name()
1969 << ");\n";
1970 }
1971 break;
1972 }
1973 case PASSTHROUGH_EXIT:
1974 {
1975 event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001976 for (const auto &arg : method->results()) {
Yifan Honga47eef32016-12-12 10:38:54 -08001977 out << "_hidl_args.push_back((void *)&_hidl_out_"
Zhuoyao Zhang085a8c32016-11-17 15:35:49 -08001978 << arg->name()
1979 << ");\n";
1980 }
Steven Moreland9b1cbdf2016-11-01 12:23:27 -07001981 break;
1982 }
Steven Moreland031ccf12016-10-31 15:54:38 -07001983 default:
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001984 {
Steven Moreland031ccf12016-10-31 15:54:38 -07001985 LOG(ERROR) << "Unsupported instrumentation event: " << event;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001986 return UNKNOWN_ERROR;
1987 }
1988 }
1989
Steven Moreland031ccf12016-10-31 15:54:38 -07001990 const Interface *iface = mRootScope->getInterface();
1991
Steven Moreland1ab31442016-11-03 18:37:51 -07001992 out << "for (const auto &callback: mInstrumentationCallbacks) {\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07001993 out.indent();
1994 out << "callback("
1995 << event_str
1996 << ", \""
1997 << mPackage.package()
1998 << "\", \""
Yifan Hong90ea87f2016-11-01 14:25:47 -07001999 << mPackage.version()
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002000 << "\", \""
2001 << iface->localName()
2002 << "\", \""
2003 << method->name()
Zhuoyao Zhang964f72f2016-10-21 11:12:03 -07002004 << "\", &_hidl_args);\n";
Zhuoyao Zhang8f492942016-09-28 14:27:56 -07002005 out.unindent();
2006 out << "}\n";
2007 out.unindent();
2008 out << "}\n\n";
2009
2010 return OK;
2011}
2012
Andreas Huber881227d2016-08-02 14:20:21 -07002013} // namespace android
2014