Home | History | Annotate | Download | only in hidl
      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 "Method.h"
     18 
     19 #include "Annotation.h"
     20 #include "ConstantExpression.h"
     21 #include "ScalarType.h"
     22 #include "Type.h"
     23 
     24 #include <android-base/logging.h>
     25 #include <hidl-util/Formatter.h>
     26 #include <algorithm>
     27 
     28 namespace android {
     29 
     30 Method::Method(const char* name, std::vector<NamedReference<Type>*>* args,
     31                std::vector<NamedReference<Type>*>* results, bool oneway,
     32                std::vector<Annotation*>* annotations, const Location& location)
     33     : mName(name),
     34       mArgs(args),
     35       mResults(results),
     36       mOneway(oneway),
     37       mAnnotations(annotations),
     38       mLocation(location) {}
     39 
     40 void Method::fillImplementation(
     41         size_t serial,
     42         MethodImpl cppImpl,
     43         MethodImpl javaImpl) {
     44     mIsHidlReserved = true;
     45     mSerial = serial;
     46     mCppImpl = cppImpl;
     47     mJavaImpl = javaImpl;
     48 
     49     CHECK(mJavaImpl.find(IMPL_STUB_IMPL) == mJavaImpl.end())
     50             << "FATAL: mJavaImpl should not use IMPL_STUB_IMPL; use IMPL_INTERFACE instead.";
     51     CHECK(mCppImpl.find(IMPL_STUB_IMPL) == mCppImpl.end() ||
     52           mCppImpl.find(IMPL_STUB) == mCppImpl.end())
     53             << "FATAL: mCppImpl IMPL_STUB will override IMPL_STUB_IMPL.";
     54 }
     55 
     56 std::string Method::name() const {
     57     return mName;
     58 }
     59 
     60 const std::vector<NamedReference<Type>*>& Method::args() const {
     61     return *mArgs;
     62 }
     63 
     64 const std::vector<NamedReference<Type>*>& Method::results() const {
     65     return *mResults;
     66 }
     67 
     68 const std::vector<Annotation *> &Method::annotations() const {
     69     return *mAnnotations;
     70 }
     71 
     72 std::vector<Reference<Type>*> Method::getReferences() {
     73     const auto& constRet = static_cast<const Method*>(this)->getReferences();
     74     std::vector<Reference<Type>*> ret(constRet.size());
     75     std::transform(constRet.begin(), constRet.end(), ret.begin(),
     76                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
     77     return ret;
     78 }
     79 
     80 std::vector<const Reference<Type>*> Method::getReferences() const {
     81     std::vector<const Reference<Type>*> ret;
     82     ret.insert(ret.end(), mArgs->begin(), mArgs->end());
     83     ret.insert(ret.end(), mResults->begin(), mResults->end());
     84     return ret;
     85 }
     86 
     87 std::vector<Reference<Type>*> Method::getStrongReferences() {
     88     const auto& constRet = static_cast<const Method*>(this)->getStrongReferences();
     89     std::vector<Reference<Type>*> ret(constRet.size());
     90     std::transform(constRet.begin(), constRet.end(), ret.begin(),
     91                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
     92     return ret;
     93 }
     94 
     95 std::vector<const Reference<Type>*> Method::getStrongReferences() const {
     96     std::vector<const Reference<Type>*> ret;
     97     for (const auto* ref : getReferences()) {
     98         if (!ref->shallowGet()->isNeverStrongReference()) {
     99             ret.push_back(ref);
    100         }
    101     }
    102     return ret;
    103 }
    104 
    105 std::vector<ConstantExpression*> Method::getConstantExpressions() {
    106     const auto& constRet = static_cast<const Method*>(this)->getConstantExpressions();
    107     std::vector<ConstantExpression*> ret(constRet.size());
    108     std::transform(constRet.begin(), constRet.end(), ret.begin(),
    109                    [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
    110     return ret;
    111 }
    112 
    113 std::vector<const ConstantExpression*> Method::getConstantExpressions() const {
    114     std::vector<const ConstantExpression*> ret;
    115     for (const auto* annotation : *mAnnotations) {
    116         const auto& retAnnotation = annotation->getConstantExpressions();
    117         ret.insert(ret.end(), retAnnotation.begin(), retAnnotation.end());
    118     }
    119     return ret;
    120 }
    121 
    122 void Method::cppImpl(MethodImplType type, Formatter &out) const {
    123     CHECK(mIsHidlReserved);
    124     auto it = mCppImpl.find(type);
    125     if (it != mCppImpl.end()) {
    126         if (it->second != nullptr) {
    127             it->second(out);
    128         }
    129     }
    130 }
    131 
    132 void Method::javaImpl(MethodImplType type, Formatter &out) const {
    133     CHECK(mIsHidlReserved);
    134     auto it = mJavaImpl.find(type);
    135     if (it != mJavaImpl.end()) {
    136         if (it->second != nullptr) {
    137             it->second(out);
    138         }
    139     }
    140 }
    141 
    142 bool Method::isHiddenFromJava() const {
    143     return isHidlReserved() && name() == "debug";
    144 }
    145 
    146 bool Method::overridesCppImpl(MethodImplType type) const {
    147     CHECK(mIsHidlReserved);
    148     return mCppImpl.find(type) != mCppImpl.end();
    149 }
    150 
    151 bool Method::overridesJavaImpl(MethodImplType type) const {
    152     CHECK(mIsHidlReserved);
    153     return mJavaImpl.find(type) != mJavaImpl.end();
    154 }
    155 
    156 Method *Method::copySignature() const {
    157     return new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations, Location());
    158 }
    159 
    160 void Method::setSerialId(size_t serial) {
    161     CHECK(!mIsHidlReserved);
    162     mSerial = serial;
    163 }
    164 
    165 size_t Method::getSerialId() const {
    166     return mSerial;
    167 }
    168 
    169 bool Method::hasEmptyCppArgSignature() const {
    170     return args().empty() && (results().empty() || canElideCallback() != nullptr);
    171 }
    172 
    173 void Method::generateCppReturnType(Formatter &out, bool specifyNamespaces) const {
    174     const NamedReference<Type>* elidedReturn = canElideCallback();
    175     const std::string space = (specifyNamespaces ? "::android::hardware::" : "");
    176 
    177     if (elidedReturn == nullptr) {
    178         out << space << "Return<void> ";
    179     } else {
    180         out << space
    181             << "Return<"
    182             << elidedReturn->type().getCppResultType( specifyNamespaces)
    183             << "> ";
    184     }
    185 }
    186 
    187 void Method::generateCppSignature(Formatter &out,
    188                                   const std::string &className,
    189                                   bool specifyNamespaces) const {
    190     generateCppReturnType(out, specifyNamespaces);
    191 
    192     if (!className.empty()) {
    193         out << className << "::";
    194     }
    195 
    196     out << name()
    197         << "(";
    198     emitCppArgSignature(out, specifyNamespaces);
    199     out << ")";
    200 }
    201 
    202 static void emitCppArgResultSignature(Formatter& out,
    203                                       const std::vector<NamedReference<Type>*>& args,
    204                                       bool specifyNamespaces) {
    205     out.join(args.begin(), args.end(), ", ", [&](auto arg) {
    206         out << arg->type().getCppArgumentType(specifyNamespaces);
    207         out << " ";
    208         out << arg->name();
    209     });
    210 }
    211 
    212 static void emitJavaArgResultSignature(Formatter& out,
    213                                        const std::vector<NamedReference<Type>*>& args) {
    214     out.join(args.begin(), args.end(), ", ", [&](auto arg) {
    215         out << arg->type().getJavaType();
    216         out << " ";
    217         out << arg->name();
    218     });
    219 }
    220 
    221 void Method::emitCppArgSignature(Formatter &out, bool specifyNamespaces) const {
    222     emitCppArgResultSignature(out, args(), specifyNamespaces);
    223 
    224     const bool returnsValue = !results().empty();
    225     const NamedReference<Type>* elidedReturn = canElideCallback();
    226     if (returnsValue && elidedReturn == nullptr) {
    227         if (!args().empty()) {
    228             out << ", ";
    229         }
    230 
    231         out << name() << "_cb _hidl_cb";
    232     }
    233 }
    234 void Method::emitCppResultSignature(Formatter &out, bool specifyNamespaces) const {
    235     emitCppArgResultSignature(out, results(), specifyNamespaces);
    236 }
    237 void Method::emitJavaArgSignature(Formatter &out) const {
    238     emitJavaArgResultSignature(out, args());
    239 }
    240 void Method::emitJavaResultSignature(Formatter &out) const {
    241     emitJavaArgResultSignature(out, results());
    242 }
    243 
    244 void Method::dumpAnnotations(Formatter &out) const {
    245     if (mAnnotations->size() == 0) {
    246         return;
    247     }
    248 
    249     out << "// ";
    250     for (size_t i = 0; i < mAnnotations->size(); ++i) {
    251         if (i > 0) {
    252             out << " ";
    253         }
    254         mAnnotations->at(i)->dump(out);
    255     }
    256     out << "\n";
    257 }
    258 
    259 bool Method::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
    260     if (isHiddenFromJava()) {
    261         return true;
    262     }
    263 
    264     if (!std::all_of(mArgs->begin(), mArgs->end(),
    265                      [&](const auto* arg) { return (*arg)->isJavaCompatible(visited); })) {
    266         return false;
    267     }
    268 
    269     if (!std::all_of(mResults->begin(), mResults->end(),
    270                      [&](const auto* arg) { return (*arg)->isJavaCompatible(visited); })) {
    271         return false;
    272     }
    273 
    274     return true;
    275 }
    276 
    277 const NamedReference<Type>* Method::canElideCallback() const {
    278     // Can't elide callback for void or tuple-returning methods
    279     if (mResults->size() != 1) {
    280         return nullptr;
    281     }
    282 
    283     const NamedReference<Type>* typedVar = mResults->at(0);
    284 
    285     if (typedVar->type().isElidableType()) {
    286         return typedVar;
    287     }
    288 
    289     return nullptr;
    290 }
    291 
    292 const Location& Method::location() const {
    293     return mLocation;
    294 }
    295 
    296 ////////////////////////////////////////////////////////////////////////////////
    297 
    298 bool TypedVarVector::add(NamedReference<Type>* v) {
    299     if (mNames.emplace(v->name()).second) {
    300         push_back(v);
    301         return true;
    302     }
    303     return false;
    304 }
    305 
    306 }  // namespace android
    307 
    308