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