1 /*
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
17 #include "Interface.h"
18
19 #include "Annotation.h"
20 #include "ArrayType.h"
21 #include "ConstantExpression.h"
22 #include "DeathRecipientType.h"
23 #include "Method.h"
24 #include "ScalarType.h"
25 #include "StringType.h"
26 #include "VectorType.h"
27
28 #include <unistd.h>
29
30 #include <iostream>
31 #include <sstream>
32
33 #include <android-base/logging.h>
34 #include <hidl-hash/Hash.h>
35 #include <hidl-util/Formatter.h>
36 #include <hidl-util/StringHelper.h>
37
38 namespace android {
39
40 #define B_PACK_CHARS(c1, c2, c3, c4) \
41 ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
42
43 /* It is very important that these values NEVER change. These values
44 * must remain unchanged over the lifetime of android. This is
45 * because the framework on a device will be updated independently of
46 * the hals on a device. If the hals are compiled with one set of
47 * transaction values, and the framework with another, then the
48 * interface between them will be destroyed, and the device will not
49 * work.
50 */
51 enum {
52 /////////////////// User defined transactions
53 FIRST_CALL_TRANSACTION = 0x00000001,
54 LAST_CALL_TRANSACTION = 0x0effffff,
55 /////////////////// HIDL reserved
56 FIRST_HIDL_TRANSACTION = 0x0f000000,
57 HIDL_PING_TRANSACTION = B_PACK_CHARS(0x0f, 'P', 'N', 'G'),
58 HIDL_DESCRIPTOR_CHAIN_TRANSACTION = B_PACK_CHARS(0x0f, 'C', 'H', 'N'),
59 HIDL_GET_DESCRIPTOR_TRANSACTION = B_PACK_CHARS(0x0f, 'D', 'S', 'C'),
60 HIDL_SYSPROPS_CHANGED_TRANSACTION = B_PACK_CHARS(0x0f, 'S', 'Y', 'S'),
61 HIDL_LINK_TO_DEATH_TRANSACTION = B_PACK_CHARS(0x0f, 'L', 'T', 'D'),
62 HIDL_UNLINK_TO_DEATH_TRANSACTION = B_PACK_CHARS(0x0f, 'U', 'T', 'D'),
63 HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION = B_PACK_CHARS(0x0f, 'I', 'N', 'T'),
64 HIDL_GET_REF_INFO_TRANSACTION = B_PACK_CHARS(0x0f, 'R', 'E', 'F'),
65 HIDL_DEBUG_TRANSACTION = B_PACK_CHARS(0x0f, 'D', 'B', 'G'),
66 HIDL_HASH_CHAIN_TRANSACTION = B_PACK_CHARS(0x0f, 'H', 'S', 'H'),
67 LAST_HIDL_TRANSACTION = 0x0fffffff,
68 };
69
Interface(const char * localName,const Location & location,Scope * parent,Interface * super)70 Interface::Interface(const char* localName, const Location& location, Scope* parent,
71 Interface* super)
72 : Scope(localName, location, parent), mSuperType(super), mIsJavaCompatibleInProgress(false) {}
73
typeName() const74 std::string Interface::typeName() const {
75 return "interface " + localName();
76 }
77
fillPingMethod(Method * method) const78 bool Interface::fillPingMethod(Method *method) const {
79 if (method->name() != "ping") {
80 return false;
81 }
82
83 method->fillImplementation(
84 HIDL_PING_TRANSACTION,
85 {
86 {IMPL_INTERFACE,
87 [](auto &out) {
88 out << "return ::android::hardware::Void();\n";
89 }
90 },
91 {IMPL_STUB_IMPL,
92 [](auto &out) {
93 out << "return ::android::hardware::Void();\n";
94 }
95 }
96 }, /*cppImpl*/
97 {
98 {IMPL_INTERFACE,
99 [](auto &out) {
100 out << "return;\n";
101 }
102 },
103 {IMPL_STUB, nullptr /* don't generate code */}
104 } /*javaImpl*/
105 );
106
107 return true;
108 }
109
fillLinkToDeathMethod(Method * method) const110 bool Interface::fillLinkToDeathMethod(Method *method) const {
111 if (method->name() != "linkToDeath") {
112 return false;
113 }
114
115 method->fillImplementation(
116 HIDL_LINK_TO_DEATH_TRANSACTION,
117 {
118 {IMPL_INTERFACE,
119 [](auto &out) {
120 out << "(void)cookie;\n"
121 << "return (recipient != nullptr);\n";
122 }
123 },
124 {IMPL_PROXY,
125 [](auto &out) {
126 out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
127 out << "::android::hardware::hidl_binder_death_recipient *binder_recipient"
128 << " = new ::android::hardware::hidl_binder_death_recipient(recipient, cookie, this);\n"
129 << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
130 << "_hidl_mDeathRecipients.push_back(binder_recipient);\n"
131 << "return (remote()->linkToDeath(binder_recipient)"
132 << " == ::android::OK);\n";
133 }
134 },
135 {IMPL_STUB, nullptr}
136 }, /*cppImpl*/
137 {
138 {IMPL_INTERFACE,
139 [](auto &out) {
140 out << "return true;";
141 }
142 },
143 {IMPL_PROXY,
144 [](auto &out) {
145 out << "return mRemote.linkToDeath(recipient, cookie);\n";
146 }
147 },
148 {IMPL_STUB, nullptr}
149 } /*javaImpl*/
150 );
151 return true;
152 }
153
fillUnlinkToDeathMethod(Method * method) const154 bool Interface::fillUnlinkToDeathMethod(Method *method) const {
155 if (method->name() != "unlinkToDeath") {
156 return false;
157 }
158
159 method->fillImplementation(
160 HIDL_UNLINK_TO_DEATH_TRANSACTION,
161 {
162 {IMPL_INTERFACE,
163 [](auto &out) {
164 out << "return (recipient != nullptr);\n";
165 }
166 },
167 {IMPL_PROXY,
168 [](auto &out) {
169 out << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
170 << "for (auto it = _hidl_mDeathRecipients.begin();"
171 << "it != _hidl_mDeathRecipients.end();"
172 << "++it) {\n";
173 out.indent([&] {
174 out.sIf("(*it)->getRecipient() == recipient", [&] {
175 out << "::android::status_t status = remote()->unlinkToDeath(*it);\n"
176 << "_hidl_mDeathRecipients.erase(it);\n"
177 << "return status == ::android::OK;\n";
178 });
179 });
180 out << "}\n";
181 out << "return false;\n";
182 }
183 },
184 {IMPL_STUB, nullptr /* don't generate code */}
185 }, /*cppImpl*/
186 {
187 {IMPL_INTERFACE,
188 [](auto &out) {
189 out << "return true;\n";
190 }
191 },
192 {IMPL_PROXY,
193 [](auto &out) {
194 out << "return mRemote.unlinkToDeath(recipient);\n";
195 }
196 },
197 {IMPL_STUB, nullptr /* don't generate code */}
198 } /*javaImpl*/
199 );
200 return true;
201 }
fillSyspropsChangedMethod(Method * method) const202 bool Interface::fillSyspropsChangedMethod(Method *method) const {
203 if (method->name() != "notifySyspropsChanged") {
204 return false;
205 }
206
207 method->fillImplementation(
208 HIDL_SYSPROPS_CHANGED_TRANSACTION,
209 { { IMPL_INTERFACE, [](auto &out) {
210 out << "::android::report_sysprop_change();\n";
211 out << "return ::android::hardware::Void();";
212 } } }, /*cppImpl */
213 { { IMPL_INTERFACE, [](auto &out) { /* javaImpl */
214 out << "android.os.SystemProperties.reportSyspropChanged();";
215 } } } /*javaImpl */
216 );
217 return true;
218 }
219
fillSetHALInstrumentationMethod(Method * method) const220 bool Interface::fillSetHALInstrumentationMethod(Method *method) const {
221 if (method->name() != "setHALInstrumentation") {
222 return false;
223 }
224
225 method->fillImplementation(
226 HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION,
227 {
228 {IMPL_INTERFACE,
229 [](auto &out) {
230 // do nothing for base class.
231 out << "return ::android::hardware::Void();\n";
232 }
233 },
234 {IMPL_STUB,
235 [](auto &out) {
236 out << "configureInstrumentation();\n";
237 }
238 },
239 {IMPL_PASSTHROUGH,
240 [](auto &out) {
241 out << "configureInstrumentation();\n";
242 out << "return ::android::hardware::Void();\n";
243 }
244 },
245 }, /*cppImpl */
246 { { IMPL_INTERFACE, [](auto & /*out*/) { /* javaImpl */
247 // Not support for Java Impl for now.
248 } } } /*javaImpl */
249 );
250 return true;
251 }
252
fillDescriptorChainMethod(Method * method) const253 bool Interface::fillDescriptorChainMethod(Method *method) const {
254 if (method->name() != "interfaceChain") {
255 return false;
256 }
257
258 method->fillImplementation(
259 HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
260 { { IMPL_INTERFACE, [this](auto &out) {
261 std::vector<const Interface *> chain = typeChain();
262 out << "_hidl_cb(";
263 out.block([&] {
264 for (const Interface *iface : chain) {
265 out << iface->fullName() << "::descriptor,\n";
266 }
267 });
268 out << ");\n";
269 out << "return ::android::hardware::Void();";
270 } } }, /* cppImpl */
271 { { IMPL_INTERFACE, [this](auto &out) {
272 std::vector<const Interface *> chain = typeChain();
273 out << "return new java.util.ArrayList<String>(java.util.Arrays.asList(\n";
274 out.indent(); out.indent();
275 for (size_t i = 0; i < chain.size(); ++i) {
276 if (i != 0)
277 out << ",\n";
278 out << chain[i]->fullJavaName() << ".kInterfaceName";
279 }
280 out << "));";
281 out.unindent(); out.unindent();
282 } } } /* javaImpl */
283 );
284 return true;
285 }
286
emitDigestChain(Formatter & out,const std::string & prefix,const std::vector<const Interface * > & chain,std::function<std::string (const ConstantExpression &)> byteToString)287 static void emitDigestChain(
288 Formatter &out,
289 const std::string &prefix,
290 const std::vector<const Interface *> &chain,
291 std::function<std::string(const ConstantExpression &)> byteToString) {
292 out.join(chain.begin(), chain.end(), ",\n", [&] (const auto &iface) {
293 const Hash &hash = Hash::getHash(iface->location().begin().filename());
294 out << prefix;
295 out << "{";
296 out.join(hash.raw().begin(), hash.raw().end(), ",", [&](const auto &e) {
297 // Use ConstantExpression::cppValue / javaValue
298 // because Java used signed byte for uint8_t.
299 out << byteToString(ConstantExpression::ValueOf(ScalarType::Kind::KIND_UINT8, e));
300 });
301 out << "} /* ";
302 out << hash.hexString();
303 out << " */";
304 });
305 }
306
fillHashChainMethod(Method * method) const307 bool Interface::fillHashChainMethod(Method *method) const {
308 if (method->name() != "getHashChain") {
309 return false;
310 }
311 const VectorType *chainType = static_cast<const VectorType *>(&method->results()[0]->type());
312 const ArrayType *digestType = static_cast<const ArrayType *>(chainType->getElementType());
313
314 method->fillImplementation(
315 HIDL_HASH_CHAIN_TRANSACTION,
316 { { IMPL_INTERFACE, [this, digestType](auto &out) {
317 std::vector<const Interface *> chain = typeChain();
318 out << "_hidl_cb(";
319 out.block([&] {
320 emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")",
321 chain, [](const auto &e){return e.cppValue();});
322 });
323 out << ");\n";
324 out << "return ::android::hardware::Void();\n";
325 } } }, /* cppImpl */
326 { { IMPL_INTERFACE, [this, digestType, chainType](auto &out) {
327 std::vector<const Interface *> chain = typeChain();
328 out << "return new "
329 << chainType->getJavaType(false /* forInitializer */)
330 << "(java.util.Arrays.asList(\n";
331 out.indent(2, [&] {
332 // No need for dimensions when elements are explicitly provided.
333 emitDigestChain(out, "new " + digestType->getJavaType(false /* forInitializer */),
334 chain, [](const auto &e){return e.javaValue();});
335 });
336 out << "));\n";
337 } } } /* javaImpl */
338 );
339 return true;
340 }
341
fillGetDescriptorMethod(Method * method) const342 bool Interface::fillGetDescriptorMethod(Method *method) const {
343 if (method->name() != "interfaceDescriptor") {
344 return false;
345 }
346
347 method->fillImplementation(
348 HIDL_GET_DESCRIPTOR_TRANSACTION,
349 { { IMPL_INTERFACE, [this](auto &out) {
350 out << "_hidl_cb("
351 << fullName()
352 << "::descriptor);\n"
353 << "return ::android::hardware::Void();";
354 } } }, /* cppImpl */
355 { { IMPL_INTERFACE, [this](auto &out) {
356 out << "return "
357 << fullJavaName()
358 << ".kInterfaceName;\n";
359 } } } /* javaImpl */
360 );
361 return true;
362 }
363
fillGetDebugInfoMethod(Method * method) const364 bool Interface::fillGetDebugInfoMethod(Method *method) const {
365 if (method->name() != "getDebugInfo") {
366 return false;
367 }
368
369 static const std::string sArch =
370 "#if defined(__LP64__)\n"
371 "::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT\n"
372 "#else\n"
373 "::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT\n"
374 "#endif\n";
375
376 method->fillImplementation(
377 HIDL_GET_REF_INFO_TRANSACTION,
378 {
379 {IMPL_INTERFACE,
380 [](auto &out) {
381 // getDebugInfo returns N/A for local objects.
382 out << "::android::hidl::base::V1_0::DebugInfo info = {};\n";
383 out << "info.pid = -1;\n";
384 out << "info.ptr = 0;\n";
385 out << "info.arch = \n" << sArch << ";\n";
386 out << "_hidl_cb(info);\n";
387 out << "return ::android::hardware::Void();\n";
388 }
389 },
390 {IMPL_STUB_IMPL,
391 [](auto &out) {
392 out << "::android::hidl::base::V1_0::DebugInfo info = {};\n";
393 out << "info.pid = ::android::hardware::details::debuggable()"
394 << "? getpid() : -1 /* pid */,\n";
395 out << "info.ptr = ::android::hardware::details::debuggable()"
396 << "? reinterpret_cast<uint64_t>(this) : 0;\n";
397 out << "info.arch = \n" << sArch << ";\n";
398 out << "_hidl_cb(info);\n";
399 out << "return ::android::hardware::Void();\n";
400 }
401 }
402 }, /* cppImpl */
403 { { IMPL_INTERFACE, [method](auto &out) {
404 const Type &refInfo = method->results().front()->type();
405 out << refInfo.getJavaType(false /* forInitializer */) << " info = new "
406 << refInfo.getJavaType(true /* forInitializer */) << "();\n"
407 // TODO(b/34777099): PID for java.
408 << "info.pid = -1;\n"
409 << "info.ptr = 0;\n"
410 << "info.arch = android.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;"
411 << "return info;";
412 } } } /* javaImpl */
413 );
414
415 return true;
416 }
417
fillDebugMethod(Method * method) const418 bool Interface::fillDebugMethod(Method *method) const {
419 if (method->name() != "debug") {
420 return false;
421 }
422
423 method->fillImplementation(
424 HIDL_DEBUG_TRANSACTION,
425 {
426 {IMPL_INTERFACE,
427 [](auto &out) {
428 out << "(void)fd;\n"
429 << "(void)options;\n"
430 << "return ::android::hardware::Void();";
431 }
432 },
433 }, /* cppImpl */
434 {
435 /* unused, as the debug method is hidden from Java */
436 } /* javaImpl */
437 );
438
439 return true;
440 }
441
442 static std::map<std::string, Method *> gAllReservedMethods;
443
addMethod(Method * method)444 bool Interface::addMethod(Method *method) {
445 if (isIBase()) {
446 if (!gAllReservedMethods.emplace(method->name(), method).second) {
447 LOG(ERROR) << "ERROR: hidl-gen encountered duplicated reserved method "
448 << method->name();
449 return false;
450 }
451 // will add it in addAllReservedMethods
452 return true;
453 }
454
455 CHECK(!method->isHidlReserved());
456 if (lookupMethod(method->name()) != nullptr) {
457 LOG(ERROR) << "Redefinition of method " << method->name();
458 return false;
459 }
460 size_t serial = FIRST_CALL_TRANSACTION;
461
462 serial += userDefinedMethods().size();
463
464 const Interface *ancestor = mSuperType;
465 while (ancestor != nullptr) {
466 serial += ancestor->userDefinedMethods().size();
467 ancestor = ancestor->superType();
468 }
469
470 CHECK(serial <= LAST_CALL_TRANSACTION) << "More than "
471 << LAST_CALL_TRANSACTION << " methods are not allowed.";
472 method->setSerialId(serial);
473 mUserMethods.push_back(method);
474
475 return true;
476 }
477
addAllReservedMethods()478 bool Interface::addAllReservedMethods() {
479 // use a sorted map to insert them in serial ID order.
480 std::map<int32_t, Method *> reservedMethodsById;
481 for (const auto &pair : gAllReservedMethods) {
482 Method *method = pair.second->copySignature();
483 bool fillSuccess = fillPingMethod(method)
484 || fillDescriptorChainMethod(method)
485 || fillGetDescriptorMethod(method)
486 || fillHashChainMethod(method)
487 || fillSyspropsChangedMethod(method)
488 || fillLinkToDeathMethod(method)
489 || fillUnlinkToDeathMethod(method)
490 || fillSetHALInstrumentationMethod(method)
491 || fillGetDebugInfoMethod(method)
492 || fillDebugMethod(method);
493
494 if (!fillSuccess) {
495 LOG(ERROR) << "ERROR: hidl-gen does not recognize a reserved method "
496 << method->name();
497 return false;
498 }
499 if (!reservedMethodsById.emplace(method->getSerialId(), method).second) {
500 LOG(ERROR) << "ERROR: hidl-gen uses duplicated serial id for "
501 << method->name() << " and "
502 << reservedMethodsById[method->getSerialId()]->name()
503 << ", serialId = " << method->getSerialId();
504 return false;
505 }
506 }
507 for (const auto &pair : reservedMethodsById) {
508 this->mReservedMethods.push_back(pair.second);
509 }
510 return true;
511 }
512
superType() const513 const Interface *Interface::superType() const {
514 return mSuperType;
515 }
516
typeChain() const517 std::vector<const Interface *> Interface::typeChain() const {
518 std::vector<const Interface *> v;
519 const Interface *iface = this;
520 while (iface != nullptr) {
521 v.push_back(iface);
522 iface = iface->mSuperType;
523 }
524 return v;
525 }
526
superTypeChain() const527 std::vector<const Interface *> Interface::superTypeChain() const {
528 return superType()->typeChain(); // should work even if superType is nullptr
529 }
530
isElidableType() const531 bool Interface::isElidableType() const {
532 return true;
533 }
534
isInterface() const535 bool Interface::isInterface() const {
536 return true;
537 }
538
isBinder() const539 bool Interface::isBinder() const {
540 return true;
541 }
542
userDefinedMethods() const543 const std::vector<Method *> &Interface::userDefinedMethods() const {
544 return mUserMethods;
545 }
546
hidlReservedMethods() const547 const std::vector<Method *> &Interface::hidlReservedMethods() const {
548 return mReservedMethods;
549 }
550
methods() const551 std::vector<Method *> Interface::methods() const {
552 std::vector<Method *> v(mUserMethods);
553 v.insert(v.end(), mReservedMethods.begin(), mReservedMethods.end());
554 return v;
555 }
556
allMethodsFromRoot() const557 std::vector<InterfaceAndMethod> Interface::allMethodsFromRoot() const {
558 std::vector<InterfaceAndMethod> v;
559 std::vector<const Interface *> chain = typeChain();
560 for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
561 const Interface *iface = *it;
562 for (Method *userMethod : iface->userDefinedMethods()) {
563 v.push_back(InterfaceAndMethod(iface, userMethod));
564 }
565 }
566 for (Method *reservedMethod : hidlReservedMethods()) {
567 v.push_back(InterfaceAndMethod(
568 *chain.rbegin(), // IBase
569 reservedMethod));
570 }
571 return v;
572 }
573
lookupMethod(std::string name) const574 Method *Interface::lookupMethod(std::string name) const {
575 for (const auto &tuple : allMethodsFromRoot()) {
576 Method *method = tuple.method();
577 if (method->name() == name) {
578 return method;
579 }
580 }
581
582 return nullptr;
583 }
584
getBaseName() const585 std::string Interface::getBaseName() const {
586 return fqName().getInterfaceBaseName();
587 }
588
getProxyName() const589 std::string Interface::getProxyName() const {
590 return fqName().getInterfaceProxyName();
591 }
592
getStubName() const593 std::string Interface::getStubName() const {
594 return fqName().getInterfaceStubName();
595 }
596
getHwName() const597 std::string Interface::getHwName() const {
598 return fqName().getInterfaceHwName();
599 }
600
getPassthroughName() const601 std::string Interface::getPassthroughName() const {
602 return fqName().getInterfacePassthroughName();
603 }
604
getProxyFqName() const605 FQName Interface::getProxyFqName() const {
606 return fqName().getInterfaceProxyFqName();
607 }
608
getStubFqName() const609 FQName Interface::getStubFqName() const {
610 return fqName().getInterfaceStubFqName();
611 }
612
getPassthroughFqName() const613 FQName Interface::getPassthroughFqName() const {
614 return fqName().getInterfacePassthroughFqName();
615 }
616
getCppType(StorageMode mode,bool specifyNamespaces) const617 std::string Interface::getCppType(StorageMode mode,
618 bool specifyNamespaces) const {
619 const std::string base =
620 std::string(specifyNamespaces ? "::android::" : "")
621 + "sp<"
622 + fullName()
623 + ">";
624
625 switch (mode) {
626 case StorageMode_Stack:
627 case StorageMode_Result:
628 return base;
629
630 case StorageMode_Argument:
631 return "const " + base + "&";
632 }
633 }
634
getJavaType(bool) const635 std::string Interface::getJavaType(bool /* forInitializer */) const {
636 return fullJavaName();
637 }
638
getVtsType() const639 std::string Interface::getVtsType() const {
640 if (StringHelper::EndsWith(localName(), "Callback")) {
641 return "TYPE_HIDL_CALLBACK";
642 } else {
643 return "TYPE_HIDL_INTERFACE";
644 }
645 }
646
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const647 void Interface::emitReaderWriter(
648 Formatter &out,
649 const std::string &name,
650 const std::string &parcelObj,
651 bool parcelObjIsPointer,
652 bool isReader,
653 ErrorMode mode) const {
654 const std::string parcelObjDeref =
655 parcelObj + (parcelObjIsPointer ? "->" : ".");
656
657 if (isReader) {
658 out << "{\n";
659 out.indent();
660
661 const std::string binderName = "_hidl_" + name + "_binder";
662
663 out << "::android::sp<::android::hardware::IBinder> "
664 << binderName << ";\n";
665
666 out << "_hidl_err = ";
667 out << parcelObjDeref
668 << "readNullableStrongBinder(&"
669 << binderName
670 << ");\n";
671
672 handleError(out, mode);
673
674 out << name
675 << " = "
676 << "::android::hardware::fromBinder<"
677 << fqName().cppName()
678 << ","
679 << getProxyFqName().cppName()
680 << ","
681 << getStubFqName().cppName()
682 << ">("
683 << binderName
684 << ");\n";
685
686 out.unindent();
687 out << "}\n\n";
688 } else {
689 out << "if (" << name << " == nullptr) {\n";
690 out.indent();
691 out << "_hidl_err = ";
692 out << parcelObjDeref
693 << "writeStrongBinder(nullptr);\n";
694 out.unindent();
695 out << "} else {\n";
696 out.indent();
697 out << "::android::sp<::android::hardware::IBinder> _hidl_binder = "
698 << "::android::hardware::toBinder<\n";
699 out.indent(2, [&] {
700 out << fqName().cppName()
701 << ">("
702 << name
703 << ");\n";
704 });
705 out << "if (_hidl_binder.get() != nullptr) {\n";
706 out.indent([&] {
707 out << "_hidl_err = "
708 << parcelObjDeref
709 << "writeStrongBinder(_hidl_binder);\n";
710 });
711 out << "} else {\n";
712 out.indent([&] {
713 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
714 });
715 out << "}\n";
716 out.unindent();
717 out << "}\n";
718
719 handleError(out, mode);
720 }
721 }
722
emitGlobalTypeDeclarations(Formatter & out) const723 status_t Interface::emitGlobalTypeDeclarations(Formatter &out) const {
724 status_t status = Scope::emitGlobalTypeDeclarations(out);
725 if (status != OK) {
726 return status;
727 }
728 out << "std::string toString("
729 << getCppArgumentType()
730 << ");\n";
731 return OK;
732 }
733
734
emitTypeDefinitions(Formatter & out,const std::string prefix) const735 status_t Interface::emitTypeDefinitions(
736 Formatter &out, const std::string prefix) const {
737 std::string space = prefix.empty() ? "" : (prefix + "::");
738 status_t err = Scope::emitTypeDefinitions(out, space + localName());
739 if (err != OK) {
740 return err;
741 }
742
743 out << "std::string toString("
744 << getCppArgumentType()
745 << " o) ";
746
747 out.block([&] {
748 out << "std::string os = \"[class or subclass of \";\n"
749 << "os += " << fullName() << "::descriptor;\n"
750 << "os += \"]\";\n"
751 << "os += o->isRemote() ? \"@remote\" : \"@local\";\n"
752 << "return os;\n";
753 }).endl().endl();
754
755 return OK;
756 }
757
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader) const758 void Interface::emitJavaReaderWriter(
759 Formatter &out,
760 const std::string &parcelObj,
761 const std::string &argName,
762 bool isReader) const {
763 if (isReader) {
764 out << fullJavaName()
765 << ".asInterface("
766 << parcelObj
767 << ".readStrongBinder());\n";
768 } else {
769 out << parcelObj
770 << ".writeStrongBinder("
771 << argName
772 << " == null ? null : "
773 << argName
774 << ".asBinder());\n";
775 }
776 }
777
emitVtsAttributeDeclaration(Formatter & out) const778 status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
779 for (const auto &type : getSubTypes()) {
780 // Skip for TypeDef as it is just an alias of a defined type.
781 if (type->isTypeDef()) {
782 continue;
783 }
784 out << "attribute: {\n";
785 out.indent();
786 status_t status = type->emitVtsTypeDeclarations(out);
787 if (status != OK) {
788 return status;
789 }
790 out.unindent();
791 out << "}\n\n";
792 }
793 return OK;
794 }
795
emitVtsMethodDeclaration(Formatter & out) const796 status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
797 for (const auto &method : methods()) {
798 if (method->isHidlReserved()) {
799 continue;
800 }
801
802 out << "api: {\n";
803 out.indent();
804 out << "name: \"" << method->name() << "\"\n";
805 // Generate declaration for each return value.
806 for (const auto &result : method->results()) {
807 out << "return_type_hidl: {\n";
808 out.indent();
809 status_t status = result->type().emitVtsAttributeType(out);
810 if (status != OK) {
811 return status;
812 }
813 out.unindent();
814 out << "}\n";
815 }
816 // Generate declaration for each input argument
817 for (const auto &arg : method->args()) {
818 out << "arg: {\n";
819 out.indent();
820 status_t status = arg->type().emitVtsAttributeType(out);
821 if (status != OK) {
822 return status;
823 }
824 out.unindent();
825 out << "}\n";
826 }
827 // Generate declaration for each annotation.
828 for (const auto &annotation : method->annotations()) {
829 out << "callflow: {\n";
830 out.indent();
831 std::string name = annotation->name();
832 if (name == "entry") {
833 out << "entry: true\n";
834 } else if (name == "exit") {
835 out << "exit: true\n";
836 } else if (name == "callflow") {
837 const AnnotationParam *param =
838 annotation->getParam("next");
839 if (param != nullptr) {
840 for (auto value : *param->getValues()) {
841 out << "next: " << value << "\n";
842 }
843 }
844 } else {
845 std::cerr << "Unrecognized annotation '"
846 << name << "' for method: " << method->name()
847 << ". A VTS annotation should be one of: "
848 << "entry, exit, callflow. \n";
849 }
850 out.unindent();
851 out << "}\n";
852 }
853 out.unindent();
854 out << "}\n\n";
855 }
856 return OK;
857 }
858
emitVtsAttributeType(Formatter & out) const859 status_t Interface::emitVtsAttributeType(Formatter &out) const {
860 out << "type: " << getVtsType() << "\n"
861 << "predefined_type: \""
862 << fullName()
863 << "\"\n";
864 return OK;
865 }
866
hasOnewayMethods() const867 bool Interface::hasOnewayMethods() const {
868 for (auto const &method : methods()) {
869 if (method->isOneway()) {
870 return true;
871 }
872 }
873
874 const Interface* superClass = superType();
875
876 if (superClass != nullptr) {
877 return superClass->hasOnewayMethods();
878 }
879
880 return false;
881 }
882
isJavaCompatible() const883 bool Interface::isJavaCompatible() const {
884 if (mIsJavaCompatibleInProgress) {
885 // We're currently trying to determine if this Interface is
886 // java-compatible and something is referencing this interface through
887 // one of its methods. Assume we'll ultimately succeed, if we were wrong
888 // the original invocation of Interface::isJavaCompatible() will then
889 // return the correct "false" result.
890 return true;
891 }
892
893 if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
894 mIsJavaCompatibleInProgress = false;
895 return false;
896 }
897
898 mIsJavaCompatibleInProgress = true;
899
900 if (!Scope::isJavaCompatible()) {
901 mIsJavaCompatibleInProgress = false;
902 return false;
903 }
904
905 for (const auto &method : methods()) {
906 if (!method->isJavaCompatible()) {
907 mIsJavaCompatibleInProgress = false;
908 return false;
909 }
910 }
911
912 mIsJavaCompatibleInProgress = false;
913
914 return true;
915 }
916
917 } // namespace android
918
919