blob: e1999c997a715e871ff0a196c750744b70639fb3 [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 Huberc9410c72016-07-28 12:18:40 -070017#include "Interface.h"
18
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -070019#include "Annotation.h"
Martijn Coenen115d4282016-12-19 05:14:04 +010020#include "DeathRecipientType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070021#include "Method.h"
Martijn Coenen115d4282016-12-19 05:14:04 +010022#include "ScalarType.h"
Yifan Hong10fe0b52016-10-19 14:20:17 -070023#include "StringType.h"
24#include "VectorType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070025
Steven Moreland14ee6742016-10-18 12:58:28 -070026#include <android-base/logging.h>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070027#include <hidl-util/Formatter.h>
Yifan Hong10fe0b52016-10-19 14:20:17 -070028#include <hidl-util/StringHelper.h>
Zhuoyao Zhang864c7712016-08-16 15:35:28 -070029#include <iostream>
Yifan Hong10fe0b52016-10-19 14:20:17 -070030#include <sstream>
Zhuoyao Zhang864c7712016-08-16 15:35:28 -070031
Andreas Huberc9410c72016-07-28 12:18:40 -070032namespace android {
33
Yifan Hong10fe0b52016-10-19 14:20:17 -070034/* It is very important that these values NEVER change. These values
35 * must remain unchanged over the lifetime of android. This is
36 * because the framework on a device will be updated independently of
37 * the hals on a device. If the hals are compiled with one set of
38 * transaction values, and the framework with another, then the
39 * interface between them will be destroyed, and the device will not
40 * work.
41 */
42enum {
43 // These values are defined in hardware::IBinder.
44 /////////////////// User defined transactions
45 FIRST_CALL_TRANSACTION = 0x00000001,
46 LAST_CALL_TRANSACTION = 0x00efffff,
47 /////////////////// HIDL reserved
48 FIRST_HIDL_TRANSACTION = 0x00f00000,
Steven Moreland424a9482017-02-13 19:20:40 -080049 HIDL_PING_TRANSACTION = FIRST_HIDL_TRANSACTION,
50 HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
Yifan Hongc75fd472017-01-11 12:37:31 -080051 HIDL_GET_DESCRIPTOR_TRANSACTION,
Martijn Coenenaf712c02016-11-16 15:26:27 +010052 HIDL_SYSPROPS_CHANGED_TRANSACTION,
Martijn Coenen115d4282016-12-19 05:14:04 +010053 HIDL_LINK_TO_DEATH_TRANSACTION,
54 HIDL_UNLINK_TO_DEATH_TRANSACTION,
Zhuoyao Zhangdd85c5c2017-01-03 17:30:24 -080055 HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION,
Yifan Hongcd2ae452017-01-31 14:33:40 -080056 HIDL_GET_REF_INFO_TRANSACTION,
Andreas Huber37065d62017-02-07 14:36:54 -080057 HIDL_DEBUG_TRANSACTION,
Yifan Hong10fe0b52016-10-19 14:20:17 -070058 LAST_HIDL_TRANSACTION = 0x00ffffff,
59};
60
Yifan Honga4b53d02016-10-31 17:29:10 -070061Interface::Interface(const char *localName, const Location &location, Interface *super)
62 : Scope(localName, location),
Andreas Huber9ed827c2016-08-22 12:31:13 -070063 mSuperType(super),
Andreas Huberea081b32016-08-17 15:57:47 -070064 mIsJavaCompatibleInProgress(false) {
Martijn Coenenaf712c02016-11-16 15:26:27 +010065}
66
Steven Moreland30bb6a82016-11-30 09:18:34 -080067std::string Interface::typeName() const {
68 return "interface " + localName();
69}
70
Steven Moreland424a9482017-02-13 19:20:40 -080071bool Interface::fillPingMethod(Method *method) const {
72 if (method->name() != "ping") {
73 return false;
74 }
75
76 method->fillImplementation(
77 HIDL_PING_TRANSACTION,
78 {
79 {IMPL_HEADER,
80 [](auto &out) {
81 out << "return ::android::hardware::Void();\n";
82 }
83 },
84 {IMPL_STUB_IMPL,
85 [](auto &out) {
86 out << "return ::android::hardware::Void();\n";
87 }
88 }
89 }, /*cppImpl*/
90 {
91 {IMPL_HEADER,
92 [this](auto &out) {
93 out << "return;\n";
94 }
95 },
96 {IMPL_STUB, nullptr /* don't generate code */}
97 } /*javaImpl*/
98 );
99
100 return true;
101}
102
Yifan Hongffa91392017-01-31 13:41:23 -0800103bool Interface::fillLinkToDeathMethod(Method *method) const {
104 if (method->name() != "linkToDeath") {
105 return false;
106 }
Martijn Coenen115d4282016-12-19 05:14:04 +0100107
Yifan Hongffa91392017-01-31 13:41:23 -0800108 method->fillImplementation(
Martijn Coenen115d4282016-12-19 05:14:04 +0100109 HIDL_LINK_TO_DEATH_TRANSACTION,
110 {
111 {IMPL_HEADER,
112 [](auto &out) {
113 out << "(void)cookie;\n"
114 << "return (recipient != nullptr);\n";
115 }
116 },
117 {IMPL_PROXY,
118 [](auto &out) {
Martijn Coenenfa55d6e2016-12-20 06:08:31 +0100119 out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
Martijn Coenen115d4282016-12-19 05:14:04 +0100120 out << "::android::hardware::hidl_binder_death_recipient *binder_recipient"
121 << " = new ::android::hardware::hidl_binder_death_recipient(recipient, cookie, this);\n"
122 << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
123 << "_hidl_mDeathRecipients.push_back(binder_recipient);\n"
124 << "return (remote()->linkToDeath(binder_recipient)"
125 << " == ::android::OK);\n";
126 }
127 },
Martijn Coenen8d12b502016-12-27 14:30:27 +0100128 {IMPL_STUB, nullptr}
Martijn Coenen115d4282016-12-19 05:14:04 +0100129 }, /*cppImpl*/
130 {
131 {IMPL_HEADER,
132 [this](auto &out) {
133 out << "return true;";
134 }
135 },
136 {IMPL_PROXY,
137 [this](auto &out) {
Martijn Coenen8d12b502016-12-27 14:30:27 +0100138 out << "return mRemote.linkToDeath(recipient, cookie);\n";
Martijn Coenen115d4282016-12-19 05:14:04 +0100139 }
140 },
Martijn Coenen8d12b502016-12-27 14:30:27 +0100141 {IMPL_STUB, nullptr}
Martijn Coenen115d4282016-12-19 05:14:04 +0100142 } /*javaImpl*/
143 );
Yifan Hongffa91392017-01-31 13:41:23 -0800144 return true;
Martijn Coenen115d4282016-12-19 05:14:04 +0100145}
146
Yifan Hongffa91392017-01-31 13:41:23 -0800147bool Interface::fillUnlinkToDeathMethod(Method *method) const {
148 if (method->name() != "unlinkToDeath") {
149 return false;
150 }
Martijn Coenen115d4282016-12-19 05:14:04 +0100151
Yifan Hongffa91392017-01-31 13:41:23 -0800152 method->fillImplementation(
Martijn Coenen115d4282016-12-19 05:14:04 +0100153 HIDL_UNLINK_TO_DEATH_TRANSACTION,
154 {
155 {IMPL_HEADER,
156 [](auto &out) {
157 out << "return (recipient != nullptr);\n";
158 }
159 },
160 {IMPL_PROXY,
161 [](auto &out) {
162 out << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
163 << "for (auto it = _hidl_mDeathRecipients.begin();"
164 << "it != _hidl_mDeathRecipients.end();"
165 << "++it) {\n";
166 out.indent([&] {
167 out.sIf("(*it)->getRecipient() == recipient", [&] {
168 out << "::android::status_t status = remote()->unlinkToDeath(*it);\n"
169 << "_hidl_mDeathRecipients.erase(it);\n"
170 << "return status == ::android::OK;\n";
171 });
172 });
173 out << "}\n";
174 out << "return false;\n";
175 }
176 },
Martijn Coenen8d12b502016-12-27 14:30:27 +0100177 {IMPL_STUB, nullptr /* don't generate code */}
Martijn Coenen115d4282016-12-19 05:14:04 +0100178 }, /*cppImpl*/
179 {
180 {IMPL_HEADER,
181 [this](auto &out) {
Martijn Coenen8d12b502016-12-27 14:30:27 +0100182 out << "return true;\n";
Martijn Coenen115d4282016-12-19 05:14:04 +0100183 }
184 },
185 {IMPL_PROXY,
186 [this](auto &out) {
Martijn Coenen8d12b502016-12-27 14:30:27 +0100187 out << "return mRemote.unlinkToDeath(recipient);\n";
Martijn Coenen115d4282016-12-19 05:14:04 +0100188 }
189 },
Martijn Coenen8d12b502016-12-27 14:30:27 +0100190 {IMPL_STUB, nullptr /* don't generate code */}
Martijn Coenen115d4282016-12-19 05:14:04 +0100191 } /*javaImpl*/
192 );
Yifan Hongffa91392017-01-31 13:41:23 -0800193 return true;
Martijn Coenen115d4282016-12-19 05:14:04 +0100194}
Yifan Hongffa91392017-01-31 13:41:23 -0800195bool Interface::fillSyspropsChangedMethod(Method *method) const {
196 if (method->name() != "notifySyspropsChanged") {
197 return false;
198 }
199
200 method->fillImplementation(
Martijn Coenenaf712c02016-11-16 15:26:27 +0100201 HIDL_SYSPROPS_CHANGED_TRANSACTION,
Martijn Coenen115d4282016-12-19 05:14:04 +0100202 { { IMPL_HEADER, [this](auto &out) {
Martijn Coenenaf712c02016-11-16 15:26:27 +0100203 out << "::android::report_sysprop_change();\n";
204 out << "return ::android::hardware::Void();";
Martijn Coenen115d4282016-12-19 05:14:04 +0100205 } } }, /*cppImpl */
206 { { IMPL_HEADER, [](auto &out) { /* javaImpl */
Martijn Coenenaf712c02016-11-16 15:26:27 +0100207 out << "android.os.SystemProperties.reportSyspropChanged();";
Martijn Coenen115d4282016-12-19 05:14:04 +0100208 } } } /*javaImpl */
Martijn Coenenaf712c02016-11-16 15:26:27 +0100209 );
Yifan Hongffa91392017-01-31 13:41:23 -0800210 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -0700211}
212
Yifan Hongffa91392017-01-31 13:41:23 -0800213bool Interface::fillSetHALInstrumentationMethod(Method *method) const {
214 if (method->name() != "setHALInstrumentation") {
215 return false;
216 }
217
218 method->fillImplementation(
Zhuoyao Zhangdd85c5c2017-01-03 17:30:24 -0800219 HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION,
220 {
221 {IMPL_HEADER,
222 [this](auto &out) {
223 // do nothing for base class.
224 out << "return ::android::hardware::Void();\n";
225 }
226 },
Zhuoyao Zhangdd85c5c2017-01-03 17:30:24 -0800227 {IMPL_STUB,
228 [](auto &out) {
229 out << "configureInstrumentation();\n";
230 }
231 },
232 {IMPL_PASSTHROUGH,
233 [](auto &out) {
234 out << "configureInstrumentation();\n";
235 out << "return ::android::hardware::Void();\n";
236 }
237 },
238 }, /*cppImpl */
239 { { IMPL_HEADER, [](auto & /*out*/) { /* javaImpl */
240 // Not support for Java Impl for now.
241 } } } /*javaImpl */
242 );
Yifan Hongffa91392017-01-31 13:41:23 -0800243 return true;
Zhuoyao Zhangdd85c5c2017-01-03 17:30:24 -0800244}
245
Yifan Hongffa91392017-01-31 13:41:23 -0800246bool Interface::fillDescriptorChainMethod(Method *method) const {
247 if (method->name() != "interfaceChain") {
248 return false;
249 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700250
Yifan Hongffa91392017-01-31 13:41:23 -0800251 method->fillImplementation(
Yifan Hong10fe0b52016-10-19 14:20:17 -0700252 HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
Martijn Coenen115d4282016-12-19 05:14:04 +0100253 { { IMPL_HEADER, [this](auto &out) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700254 std::vector<const Interface *> chain = typeChain();
Yifan Hong03935122016-12-19 11:10:40 -0800255 out << "_hidl_cb(";
256 out.block([&] {
257 for (const Interface *iface : chain) {
258 out << iface->fullName() << "::descriptor,\n";
259 }
260 });
261 out << ");\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700262 out << "return ::android::hardware::Void();";
Martijn Coenen115d4282016-12-19 05:14:04 +0100263 } } }, /* cppImpl */
264 { { IMPL_HEADER, [this](auto &out) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700265 std::vector<const Interface *> chain = typeChain();
Yifan Hong1af73532016-11-09 14:32:58 -0800266 out << "return new java.util.ArrayList<String>(java.util.Arrays.asList(\n";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700267 out.indent(); out.indent();
268 for (size_t i = 0; i < chain.size(); ++i) {
269 if (i != 0)
270 out << ",\n";
Steven Morelandd39133b2016-11-11 12:30:08 -0800271 out << chain[i]->fullJavaName() << ".kInterfaceName";
Yifan Hong10fe0b52016-10-19 14:20:17 -0700272 }
273 out << "));";
274 out.unindent(); out.unindent();
Yifan Hongffa91392017-01-31 13:41:23 -0800275 } } } /* javaImpl */
Martijn Coenen115d4282016-12-19 05:14:04 +0100276 );
Yifan Hongffa91392017-01-31 13:41:23 -0800277 return true;
Yifan Hong10fe0b52016-10-19 14:20:17 -0700278}
279
Yifan Hongffa91392017-01-31 13:41:23 -0800280bool Interface::fillGetDescriptorMethod(Method *method) const {
281 if (method->name() != "interfaceDescriptor") {
282 return false;
283 }
Yifan Hongc75fd472017-01-11 12:37:31 -0800284
Yifan Hongffa91392017-01-31 13:41:23 -0800285 method->fillImplementation(
Yifan Hongc75fd472017-01-11 12:37:31 -0800286 HIDL_GET_DESCRIPTOR_TRANSACTION,
287 { { IMPL_HEADER, [this](auto &out) {
288 out << "_hidl_cb("
289 << fullName()
290 << "::descriptor);\n"
291 << "return ::android::hardware::Void();";
292 } } }, /* cppImpl */
293 { { IMPL_HEADER, [this](auto &out) {
294 out << "return "
295 << fullJavaName()
296 << ".kInterfaceName;\n";
Yifan Hongffa91392017-01-31 13:41:23 -0800297 } } } /* javaImpl */
Yifan Hongc75fd472017-01-11 12:37:31 -0800298 );
Yifan Hongffa91392017-01-31 13:41:23 -0800299 return true;
Yifan Hongc75fd472017-01-11 12:37:31 -0800300}
Yifan Hong10fe0b52016-10-19 14:20:17 -0700301
Yifan Hongbcffce22017-02-01 15:52:06 -0800302bool Interface::fillGetDebugInfoMethod(Method *method) const {
303 if (method->name() != "getDebugInfo") {
Yifan Hongcd2ae452017-01-31 14:33:40 -0800304 return false;
305 }
306
307 method->fillImplementation(
308 HIDL_GET_REF_INFO_TRANSACTION,
309 {
310 {IMPL_HEADER,
311 [this](auto &out) {
Yifan Hongbcffce22017-02-01 15:52:06 -0800312 // getDebugInfo returns N/A for local objects.
313 out << "_hidl_cb({ -1 /* pid */, 0 /* ptr */ });\n"
Yifan Hongcd2ae452017-01-31 14:33:40 -0800314 << "return ::android::hardware::Void();";
315 }
316 },
317 {IMPL_STUB_IMPL,
318 [this](auto &out) {
Yifan Hongbcffce22017-02-01 15:52:06 -0800319 out << "_hidl_cb({ getpid(), reinterpret_cast<uint64_t>(this) });\n"
Yifan Hongcd2ae452017-01-31 14:33:40 -0800320 << "return ::android::hardware::Void();";
321 }
322 }
323 }, /* cppImpl */
324 { { IMPL_HEADER, [this, method](auto &out) {
325 const Type &refInfo = method->results().front()->type();
326 out << refInfo.getJavaType(false /* forInitializer */) << " info = new "
327 << refInfo.getJavaType(true /* forInitializer */) << "();\n"
Yifan Hongbcffce22017-02-01 15:52:06 -0800328 // TODO(b/34777099): PID for java.
329 << "info.pid = -1;\n"
330 << "info.ptr = 0;\n"
Yifan Hongcd2ae452017-01-31 14:33:40 -0800331 << "return info;";
332 } } } /* javaImpl */
333 );
334
335 return true;
336}
337
Andreas Huber37065d62017-02-07 14:36:54 -0800338bool Interface::fillDebugMethod(Method *method) const {
339 if (method->name() != "debug") {
340 return false;
341 }
342
343 method->fillImplementation(
344 HIDL_DEBUG_TRANSACTION,
345 {
346 {IMPL_HEADER,
347 [this](auto &out) {
348 out << "(void)fd;\n"
349 << "(void)options;\n"
350 << "return ::android::hardware::Void();";
351 }
352 },
353 }, /* cppImpl */
354 {
355 /* unused, as the debug method is hidden from Java */
356 } /* javaImpl */
357 );
358
359 return true;
360}
361
Yifan Hongffa91392017-01-31 13:41:23 -0800362static std::map<std::string, Method *> gAllReservedMethods;
363
Steven Moreland14ee6742016-10-18 12:58:28 -0700364bool Interface::addMethod(Method *method) {
Yifan Hongc8934042016-11-17 17:10:52 -0800365 if (isIBase()) {
Yifan Hongffa91392017-01-31 13:41:23 -0800366 if (!gAllReservedMethods.emplace(method->name(), method).second) {
367 LOG(ERROR) << "ERROR: hidl-gen encountered duplicated reserved method "
368 << method->name();
369 return false;
370 }
371 // will add it in addAllReservedMethods
Yifan Hongc8934042016-11-17 17:10:52 -0800372 return true;
373 }
374
Yifan Hong10fe0b52016-10-19 14:20:17 -0700375 CHECK(!method->isHidlReserved());
Steven Moreland14ee6742016-10-18 12:58:28 -0700376 if (lookupMethod(method->name()) != nullptr) {
377 LOG(ERROR) << "Redefinition of method " << method->name();
378 return false;
379 }
Yifan Hong10fe0b52016-10-19 14:20:17 -0700380 size_t serial = FIRST_CALL_TRANSACTION;
Steven Moreland14ee6742016-10-18 12:58:28 -0700381
Yifan Hong10fe0b52016-10-19 14:20:17 -0700382 serial += userDefinedMethods().size();
Steven Morelandef1a9fe2016-10-06 17:19:09 -0700383
Yifan Hong10fe0b52016-10-19 14:20:17 -0700384 const Interface *ancestor = mSuperType;
Steven Morelandef1a9fe2016-10-06 17:19:09 -0700385 while (ancestor != nullptr) {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700386 serial += ancestor->userDefinedMethods().size();
Steven Morelandef1a9fe2016-10-06 17:19:09 -0700387 ancestor = ancestor->superType();
388 }
389
Yifan Hong10fe0b52016-10-19 14:20:17 -0700390 CHECK(serial <= LAST_CALL_TRANSACTION) << "More than "
391 << LAST_CALL_TRANSACTION << " methods are not allowed.";
Steven Morelandef1a9fe2016-10-06 17:19:09 -0700392 method->setSerialId(serial);
Yifan Hong10fe0b52016-10-19 14:20:17 -0700393 mUserMethods.push_back(method);
Steven Moreland14ee6742016-10-18 12:58:28 -0700394
395 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -0700396}
397
Yifan Hongffa91392017-01-31 13:41:23 -0800398bool Interface::addAllReservedMethods() {
399 // use a sorted map to insert them in serial ID order.
400 std::map<int32_t, Method *> reservedMethodsById;
401 for (const auto &pair : gAllReservedMethods) {
402 Method *method = pair.second->copySignature();
Steven Moreland424a9482017-02-13 19:20:40 -0800403 bool fillSuccess = fillPingMethod(method)
404 || fillDescriptorChainMethod(method)
Yifan Hongffa91392017-01-31 13:41:23 -0800405 || fillGetDescriptorMethod(method)
406 || fillSyspropsChangedMethod(method)
407 || fillLinkToDeathMethod(method)
408 || fillUnlinkToDeathMethod(method)
Yifan Hongcd2ae452017-01-31 14:33:40 -0800409 || fillSetHALInstrumentationMethod(method)
Andreas Huber37065d62017-02-07 14:36:54 -0800410 || fillGetDebugInfoMethod(method)
411 || fillDebugMethod(method);
412
Yifan Hongffa91392017-01-31 13:41:23 -0800413 if (!fillSuccess) {
414 LOG(ERROR) << "ERROR: hidl-gen does not recognize a reserved method "
415 << method->name();
416 return false;
417 }
418 if (!reservedMethodsById.emplace(method->getSerialId(), method).second) {
419 LOG(ERROR) << "ERROR: hidl-gen uses duplicated serial id for "
420 << method->name() << " and "
421 << reservedMethodsById[method->getSerialId()]->name()
422 << ", serialId = " << method->getSerialId();
423 return false;
424 }
425 }
426 for (const auto &pair : reservedMethodsById) {
427 this->mReservedMethods.push_back(pair.second);
428 }
429 return true;
430}
Yifan Hong10fe0b52016-10-19 14:20:17 -0700431
Andreas Huber6cb08cf2016-08-03 15:44:51 -0700432const Interface *Interface::superType() const {
Andreas Huberc9410c72016-07-28 12:18:40 -0700433 return mSuperType;
434}
435
Yifan Hong10fe0b52016-10-19 14:20:17 -0700436std::vector<const Interface *> Interface::typeChain() const {
437 std::vector<const Interface *> v;
438 const Interface *iface = this;
439 while (iface != nullptr) {
440 v.push_back(iface);
441 iface = iface->mSuperType;
442 }
443 return v;
444}
445
Yifan Hongfe95aa22016-10-19 17:26:45 -0700446std::vector<const Interface *> Interface::superTypeChain() const {
447 return superType()->typeChain(); // should work even if superType is nullptr
448}
449
Martijn Coenenb40ef022017-01-02 15:21:46 +0100450bool Interface::isElidableType() const {
451 return true;
452}
453
Andreas Hubera2723d22016-07-29 15:36:07 -0700454bool Interface::isInterface() const {
455 return true;
456}
457
Andreas Huber295ad302016-08-16 11:35:00 -0700458bool Interface::isBinder() const {
459 return true;
460}
461
Yifan Hong10fe0b52016-10-19 14:20:17 -0700462const std::vector<Method *> &Interface::userDefinedMethods() const {
463 return mUserMethods;
464}
465
466const std::vector<Method *> &Interface::hidlReservedMethods() const {
467 return mReservedMethods;
468}
469
470std::vector<Method *> Interface::methods() const {
471 std::vector<Method *> v(mUserMethods);
472 v.insert(v.end(), mReservedMethods.begin(), mReservedMethods.end());
473 return v;
474}
475
476std::vector<InterfaceAndMethod> Interface::allMethodsFromRoot() const {
477 std::vector<InterfaceAndMethod> v;
478 std::vector<const Interface *> chain = typeChain();
479 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
480 const Interface *iface = *it;
481 for (Method *userMethod : iface->userDefinedMethods()) {
482 v.push_back(InterfaceAndMethod(iface, userMethod));
483 }
484 }
485 for (Method *reservedMethod : hidlReservedMethods()) {
Yifan Hongc8934042016-11-17 17:10:52 -0800486 v.push_back(InterfaceAndMethod(
487 *chain.rbegin(), // IBase
488 reservedMethod));
Yifan Hong10fe0b52016-10-19 14:20:17 -0700489 }
490 return v;
Andreas Huber881227d2016-08-02 14:20:21 -0700491}
492
Steven Moreland14ee6742016-10-18 12:58:28 -0700493Method *Interface::lookupMethod(std::string name) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700494 for (const auto &tuple : allMethodsFromRoot()) {
495 Method *method = tuple.method();
496 if (method->name() == name) {
497 return method;
Steven Moreland14ee6742016-10-18 12:58:28 -0700498 }
Steven Moreland14ee6742016-10-18 12:58:28 -0700499 }
500
501 return nullptr;
502}
503
Steven Moreland40786312016-08-16 10:29:40 -0700504std::string Interface::getBaseName() const {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -0700505 return fqName().getInterfaceBaseName();
Steven Moreland40786312016-08-16 10:29:40 -0700506}
507
Yifan Hongeefe4f22017-01-04 15:32:42 -0800508std::string Interface::getProxyName() const {
509 return fqName().getInterfaceProxyName();
510}
511
512std::string Interface::getStubName() const {
513 return fqName().getInterfaceStubName();
514}
515
516std::string Interface::getHwName() const {
517 return fqName().getInterfaceHwName();
518}
519
520std::string Interface::getPassthroughName() const {
521 return fqName().getInterfacePassthroughName();
522}
523
Yifan Hong51a65092017-01-04 15:41:44 -0800524FQName Interface::getProxyFqName() const {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800525 return fqName().getInterfaceProxyFqName();
Yifan Hong158655a2016-11-08 12:34:07 -0800526}
527
Yifan Hong51a65092017-01-04 15:41:44 -0800528FQName Interface::getStubFqName() const {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800529 return fqName().getInterfaceStubFqName();
Yifan Hong158655a2016-11-08 12:34:07 -0800530}
531
Yifan Hong51a65092017-01-04 15:41:44 -0800532FQName Interface::getPassthroughFqName() const {
Yifan Hongeefe4f22017-01-04 15:32:42 -0800533 return fqName().getInterfacePassthroughFqName();
Yifan Hong158655a2016-11-08 12:34:07 -0800534}
535
Steven Moreland979e0992016-09-07 09:18:08 -0700536std::string Interface::getCppType(StorageMode mode,
Steven Moreland979e0992016-09-07 09:18:08 -0700537 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -0700538 const std::string base =
539 std::string(specifyNamespaces ? "::android::" : "")
540 + "sp<"
541 + (specifyNamespaces ? fullName() : partialCppName())
542 + ">";
Andreas Huber881227d2016-08-02 14:20:21 -0700543
544 switch (mode) {
545 case StorageMode_Stack:
546 case StorageMode_Result:
547 return base;
548
549 case StorageMode_Argument:
550 return "const " + base + "&";
551 }
552}
553
Yifan Hong4ed13472016-11-02 10:44:11 -0700554std::string Interface::getJavaType(bool /* forInitializer */) const {
Andreas Huber2831d512016-08-15 09:33:47 -0700555 return fullJavaName();
556}
557
Zhuoyao Zhanga588b232016-11-10 14:37:35 -0800558std::string Interface::getVtsType() const {
559 if (StringHelper::EndsWith(localName(), "Callback")) {
560 return "TYPE_HIDL_CALLBACK";
561 } else {
562 return "TYPE_HIDL_INTERFACE";
563 }
564}
565
Andreas Huber881227d2016-08-02 14:20:21 -0700566void Interface::emitReaderWriter(
567 Formatter &out,
568 const std::string &name,
569 const std::string &parcelObj,
570 bool parcelObjIsPointer,
571 bool isReader,
572 ErrorMode mode) const {
573 const std::string parcelObjDeref =
574 parcelObj + (parcelObjIsPointer ? "->" : ".");
575
576 if (isReader) {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700577 out << "{\n";
578 out.indent();
579
Iliyan Malchev549e2592016-08-10 08:59:12 -0700580 const std::string binderName = "_hidl_" + name + "_binder";
Andreas Huber881227d2016-08-02 14:20:21 -0700581
Andreas Huber8a82ff72016-08-04 10:29:39 -0700582 out << "::android::sp<::android::hardware::IBinder> "
Andreas Huber881227d2016-08-02 14:20:21 -0700583 << binderName << ";\n";
584
Iliyan Malchev549e2592016-08-10 08:59:12 -0700585 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700586 out << parcelObjDeref
587 << "readNullableStrongBinder(&"
588 << binderName
589 << ");\n";
590
591 handleError(out, mode);
592
593 out << name
594 << " = "
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100595 << "::android::hardware::fromBinder<"
596 << fqName().cppName()
597 << ","
Yifan Hong51a65092017-01-04 15:41:44 -0800598 << getProxyFqName().cppName()
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100599 << ","
Yifan Hong51a65092017-01-04 15:41:44 -0800600 << getStubFqName().cppName()
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100601 << ">("
Andreas Huber881227d2016-08-02 14:20:21 -0700602 << binderName
603 << ");\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700604
605 out.unindent();
606 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700607 } else {
Martijn Coenene1638232016-10-26 12:51:34 +0200608 out << "if (" << name << " == nullptr) {\n";
609 out.indent();
610 out << "_hidl_err = ";
611 out << parcelObjDeref
612 << "writeStrongBinder(nullptr);\n";
613 out.unindent();
614 out << "} else {\n";
615 out.indent();
Yifan Hong158655a2016-11-08 12:34:07 -0800616 out << "::android::sp<::android::hardware::IBinder> _hidl_binder = "
617 << "::android::hardware::toBinder<\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800618 out.indent(2, [&] {
Martijn Coenena63e0ad2016-12-07 17:29:00 +0100619 out << fqName().cppName()
Yifan Hong158655a2016-11-08 12:34:07 -0800620 << ", "
Yifan Hong51a65092017-01-04 15:41:44 -0800621 << getProxyFqName().cppName()
Yifan Hong158655a2016-11-08 12:34:07 -0800622 << ">("
623 << name
624 << ");\n";
625 });
626 out << "if (_hidl_binder.get() != nullptr) {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800627 out.indent([&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800628 out << "_hidl_err = "
629 << parcelObjDeref
630 << "writeStrongBinder(_hidl_binder);\n";
631 });
632 out << "} else {\n";
Yifan Hong33223ca2016-12-13 15:07:35 -0800633 out.indent([&] {
Yifan Hong158655a2016-11-08 12:34:07 -0800634 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
635 });
636 out << "}\n";
Martijn Coenene1638232016-10-26 12:51:34 +0200637 out.unindent();
638 out << "}\n";
Steven Moreland40786312016-08-16 10:29:40 -0700639
Andreas Huber881227d2016-08-02 14:20:21 -0700640 handleError(out, mode);
641 }
642}
643
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800644status_t Interface::emitGlobalTypeDeclarations(Formatter &out) const {
645 status_t status = Scope::emitGlobalTypeDeclarations(out);
646 if (status != OK) {
647 return status;
648 }
649 out << "std::string toString("
650 << getCppArgumentType()
651 << ");\n";
652 return OK;
653}
654
655
656status_t Interface::emitTypeDefinitions(
657 Formatter &out, const std::string prefix) const {
658 std::string space = prefix.empty() ? "" : (prefix + "::");
659 status_t err = Scope::emitTypeDefinitions(out, space + localName());
660 if (err != OK) {
661 return err;
662 }
663
664 out << "std::string toString("
665 << getCppArgumentType()
666 << " o) ";
667
668 out.block([&] {
669 out << "std::string os;\nbool ok = false;\n";
670 // TODO b/34136228 use interfaceDescriptor instead
671 out << "auto ret = o->interfaceChain([&os, &ok] (const auto &chain) ";
672 out.block([&] {
673 out.sIf("chain.size() >= 1", [&] {
674 out << "os += chain[0].c_str();\n"
675 << "ok = true;\n";
676 }).endl();
677 });
678 out << ");\n";
679 out.sIf("!ret.isOk() || !ok", [&] {
680 out << "os += \"[class or subclass of \";\n"
681 << "os += " << fullName() << "::descriptor;\n"
682 << "os += \"]\";\n";
683 }).endl();
684 out << "os += o->isRemote() ? \"@remote\" : \"@local\";\n"
685 << "return os;\n";
686 }).endl().endl();
687
688 return OK;
689}
690
Andreas Huber2831d512016-08-15 09:33:47 -0700691void Interface::emitJavaReaderWriter(
692 Formatter &out,
693 const std::string &parcelObj,
694 const std::string &argName,
695 bool isReader) const {
696 if (isReader) {
697 out << fullJavaName()
698 << ".asInterface("
699 << parcelObj
700 << ".readStrongBinder());\n";
701 } else {
702 out << parcelObj
703 << ".writeStrongBinder("
704 << argName
705 << " == null ? null : "
706 << argName
707 << ".asBinder());\n";
708 }
709}
710
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700711status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
712 for (const auto &type : getSubTypes()) {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700713 // Skip for TypeDef as it is just an alias of a defined type.
714 if (type->isTypeDef()) {
715 continue;
716 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700717 out << "attribute: {\n";
718 out.indent();
719 status_t status = type->emitVtsTypeDeclarations(out);
720 if (status != OK) {
721 return status;
722 }
723 out.unindent();
724 out << "}\n\n";
725 }
726 return OK;
727}
728
729status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700730 for (const auto &method : methods()) {
Steven Morelandcea24782016-11-07 11:40:48 -0800731 if (method->isHidlReserved()) {
732 continue;
733 }
734
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700735 out << "api: {\n";
736 out.indent();
737 out << "name: \"" << method->name() << "\"\n";
738 // Generate declaration for each return value.
739 for (const auto &result : method->results()) {
740 out << "return_type_hidl: {\n";
741 out.indent();
742 status_t status = result->type().emitVtsAttributeType(out);
743 if (status != OK) {
744 return status;
745 }
746 out.unindent();
747 out << "}\n";
748 }
749 // Generate declaration for each input argument
750 for (const auto &arg : method->args()) {
751 out << "arg: {\n";
752 out.indent();
753 status_t status = arg->type().emitVtsAttributeType(out);
754 if (status != OK) {
755 return status;
756 }
757 out.unindent();
758 out << "}\n";
759 }
760 // Generate declaration for each annotation.
Steven Morelandd537ab02016-09-12 10:32:01 -0700761 for (const auto &annotation : method->annotations()) {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700762 out << "callflow: {\n";
763 out.indent();
Steven Morelandd537ab02016-09-12 10:32:01 -0700764 std::string name = annotation->name();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700765 if (name == "entry") {
766 out << "entry: true\n";
767 } else if (name == "exit") {
768 out << "exit: true\n";
769 } else if (name == "callflow") {
Steven Morelandd537ab02016-09-12 10:32:01 -0700770 const AnnotationParam *param =
771 annotation->getParam("next");
772 if (param != nullptr) {
773 for (auto value : *param->getValues()) {
774 out << "next: " << value << "\n";
775 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700776 }
777 } else {
Keun Soo Yima5a57e92017-02-04 11:32:06 -0800778 std::cerr << "Unrecognized annotation '"
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700779 << name << "' for method: " << method->name()
Keun Soo Yima5a57e92017-02-04 11:32:06 -0800780 << ". A VTS annotation should be one of: "
781 << "entry, exit, callflow. \n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700782 }
783 out.unindent();
784 out << "}\n";
785 }
786 out.unindent();
787 out << "}\n\n";
788 }
789 return OK;
790}
791
792status_t Interface::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhanga588b232016-11-10 14:37:35 -0800793 out << "type: " << getVtsType() << "\n"
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700794 << "predefined_type: \""
Zhuoyao Zhangc4e10602017-01-27 16:48:05 -0800795 << fullName()
796 << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700797 return OK;
798}
799
Steven Moreland69e7c702016-09-09 11:16:32 -0700800bool Interface::hasOnewayMethods() const {
Yifan Hong10fe0b52016-10-19 14:20:17 -0700801 for (auto const &method : methods()) {
Steven Moreland69e7c702016-09-09 11:16:32 -0700802 if (method->isOneway()) {
803 return true;
804 }
805 }
806
807 const Interface* superClass = superType();
808
809 if (superClass != nullptr) {
810 return superClass->hasOnewayMethods();
811 }
812
813 return false;
814}
815
Andreas Huber70a59e12016-08-16 12:57:01 -0700816bool Interface::isJavaCompatible() const {
Andreas Huberea081b32016-08-17 15:57:47 -0700817 if (mIsJavaCompatibleInProgress) {
818 // We're currently trying to determine if this Interface is
819 // java-compatible and something is referencing this interface through
820 // one of its methods. Assume we'll ultimately succeed, if we were wrong
821 // the original invocation of Interface::isJavaCompatible() will then
822 // return the correct "false" result.
823 return true;
824 }
825
Andreas Huber0fa9e392016-08-31 09:05:44 -0700826 if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
827 mIsJavaCompatibleInProgress = false;
828 return false;
829 }
830
Andreas Huberea081b32016-08-17 15:57:47 -0700831 mIsJavaCompatibleInProgress = true;
832
Andreas Huber70a59e12016-08-16 12:57:01 -0700833 if (!Scope::isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700834 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700835 return false;
836 }
837
Yifan Hong10fe0b52016-10-19 14:20:17 -0700838 for (const auto &method : methods()) {
Andreas Huber70a59e12016-08-16 12:57:01 -0700839 if (!method->isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700840 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700841 return false;
842 }
843 }
844
Andreas Huberea081b32016-08-17 15:57:47 -0700845 mIsJavaCompatibleInProgress = false;
846
Andreas Huber70a59e12016-08-16 12:57:01 -0700847 return true;
848}
849
Andreas Huberc9410c72016-07-28 12:18:40 -0700850} // namespace android
851