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
38namespace 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 */
51enum {
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
70Interface::Interface(const char* localName, const Location& location, Scope* parent,
71                     Interface* super)
72    : Scope(localName, location, parent), mSuperType(super), mIsJavaCompatibleInProgress(false) {}
73
74std::string Interface::typeName() const {
75    return "interface " + localName();
76}
77
78bool 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
110bool 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
154bool 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}
202bool 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
220bool 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
253bool 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
287static 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
307bool 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
342bool 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
364bool 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 << "_hidl_cb({ -1 /* pid */, 0 /* ptr */, \n"
383                        << sArch
384                        << "});\n"
385                        << "return ::android::hardware::Void();";
386                }
387            },
388            {IMPL_STUB_IMPL,
389                [](auto &out) {
390                    out << "_hidl_cb(";
391                    out.block([&] {
392                        out << "::android::hardware::details::debuggable()"
393                            << "? getpid() : -1 /* pid */,\n"
394                            << "::android::hardware::details::debuggable()"
395                            << "? reinterpret_cast<uint64_t>(this) : 0 /* ptr */,\n"
396                            << sArch << "\n";
397                    });
398                    out << ");\n"
399                        << "return ::android::hardware::Void();";
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
418bool 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
442static std::map<std::string, Method *> gAllReservedMethods;
443
444bool 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
478bool 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
513const Interface *Interface::superType() const {
514    return mSuperType;
515}
516
517std::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
527std::vector<const Interface *> Interface::superTypeChain() const {
528    return superType()->typeChain(); // should work even if superType is nullptr
529}
530
531bool Interface::isElidableType() const {
532    return true;
533}
534
535bool Interface::isInterface() const {
536    return true;
537}
538
539bool Interface::isBinder() const {
540    return true;
541}
542
543const std::vector<Method *> &Interface::userDefinedMethods() const {
544    return mUserMethods;
545}
546
547const std::vector<Method *> &Interface::hidlReservedMethods() const {
548    return mReservedMethods;
549}
550
551std::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
557std::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
574Method *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
585std::string Interface::getBaseName() const {
586    return fqName().getInterfaceBaseName();
587}
588
589std::string Interface::getProxyName() const {
590    return fqName().getInterfaceProxyName();
591}
592
593std::string Interface::getStubName() const {
594    return fqName().getInterfaceStubName();
595}
596
597std::string Interface::getHwName() const {
598    return fqName().getInterfaceHwName();
599}
600
601std::string Interface::getPassthroughName() const {
602    return fqName().getInterfacePassthroughName();
603}
604
605FQName Interface::getProxyFqName() const {
606    return fqName().getInterfaceProxyFqName();
607}
608
609FQName Interface::getStubFqName() const {
610    return fqName().getInterfaceStubFqName();
611}
612
613FQName Interface::getPassthroughFqName() const {
614    return fqName().getInterfacePassthroughFqName();
615}
616
617std::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
635std::string Interface::getJavaType(bool /* forInitializer */) const {
636    return fullJavaName();
637}
638
639std::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
647void 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
723status_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
735status_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
758void 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
778status_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
796status_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
859status_t Interface::emitVtsAttributeType(Formatter &out) const {
860    out << "type: " << getVtsType() << "\n"
861        << "predefined_type: \""
862        << fullName()
863        << "\"\n";
864    return OK;
865}
866
867bool 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
883bool 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