• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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