| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "Method.h" |
| |
| #include "Annotation.h" |
| #include "ScalarType.h" |
| #include "Type.h" |
| |
| #include <android-base/logging.h> |
| #include <hidl-util/Formatter.h> |
| |
| namespace android { |
| |
| Method::Method(const char *name, |
| std::vector<TypedVar *> *args, |
| std::vector<TypedVar *> *results, |
| bool oneway, |
| std::vector<Annotation *> *annotations) |
| : mName(name), |
| mArgs(args), |
| mResults(results), |
| mOneway(oneway), |
| mAnnotations(annotations) { |
| } |
| |
| // HIDL reserved methods. |
| Method::Method(const char *name, |
| std::vector<TypedVar *> *args, |
| std::vector<TypedVar *> *results, |
| bool oneway, |
| std::vector<Annotation *> *annotations, |
| size_t serial, |
| MethodImpl cppImpl, |
| MethodImpl javaImpl) |
| : Method(name, args, results, oneway, annotations) { |
| |
| mIsHidlReserved = true; |
| mSerial = serial; |
| mCppImpl = cppImpl; |
| mJavaImpl = javaImpl; |
| } |
| |
| |
| std::string Method::name() const { |
| return mName; |
| } |
| |
| const std::vector<TypedVar *> &Method::args() const { |
| return *mArgs; |
| } |
| |
| const std::vector<TypedVar *> &Method::results() const { |
| return *mResults; |
| } |
| |
| const std::vector<Annotation *> &Method::annotations() const { |
| return *mAnnotations; |
| } |
| |
| void Method::cppImpl(Formatter &out) const { |
| CHECK(mIsHidlReserved); |
| if (mCppImpl) { |
| mCppImpl(out); |
| } |
| } |
| |
| void Method::javaImpl(Formatter &out) const { |
| CHECK(mIsHidlReserved); |
| if (mJavaImpl) { |
| mJavaImpl(out); |
| } |
| } |
| |
| void Method::setSerialId(size_t serial) { |
| CHECK(!mIsHidlReserved); |
| mSerial = serial; |
| } |
| |
| size_t Method::getSerialId() const { |
| return mSerial; |
| } |
| |
| void Method::generateCppSignature(Formatter &out, |
| const std::string &className, |
| bool specifyNamespaces) const { |
| const bool returnsValue = !results().empty(); |
| |
| const TypedVar *elidedReturn = canElideCallback(); |
| |
| std::string space = (specifyNamespaces ? "::android::hardware::" : ""); |
| |
| if (elidedReturn == nullptr) { |
| out << space << "Return<void> "; |
| } else { |
| out << space |
| << "Return<" |
| << elidedReturn->type().getCppResultType( specifyNamespaces) |
| << "> "; |
| } |
| |
| if (!className.empty()) { |
| out << className << "::"; |
| } |
| |
| out << name() |
| << "(" |
| << GetArgSignature(args(), specifyNamespaces); |
| |
| if (returnsValue && elidedReturn == nullptr) { |
| if (!args().empty()) { |
| out << ", "; |
| } |
| |
| out << name() << "_cb _hidl_cb"; |
| } |
| |
| out << ")"; |
| } |
| |
| // static |
| std::string Method::GetArgSignature(const std::vector<TypedVar *> &args, |
| bool specifyNamespaces) { |
| bool first = true; |
| std::string out; |
| for (const auto &arg : args) { |
| if (!first) { |
| out += ", "; |
| } |
| |
| out += arg->type().getCppArgumentType(specifyNamespaces); |
| out += " "; |
| out += arg->name(); |
| |
| first = false; |
| } |
| |
| return out; |
| } |
| |
| // static |
| std::string Method::GetJavaArgSignature(const std::vector<TypedVar *> &args) { |
| bool first = true; |
| std::string out; |
| for (const auto &arg : args) { |
| if (!first) { |
| out += ", "; |
| } |
| |
| out += arg->type().getJavaType(); |
| out += " "; |
| out += arg->name(); |
| |
| first = false; |
| } |
| |
| return out; |
| } |
| |
| void Method::dumpAnnotations(Formatter &out) const { |
| if (mAnnotations->size() == 0) { |
| return; |
| } |
| |
| out << "// "; |
| for (size_t i = 0; i < mAnnotations->size(); ++i) { |
| if (i > 0) { |
| out << " "; |
| } |
| mAnnotations->at(i)->dump(out); |
| } |
| out << "\n"; |
| } |
| |
| bool Method::isJavaCompatible() const { |
| for (const auto &arg : *mArgs) { |
| if (!arg->isJavaCompatible()) { |
| return false; |
| } |
| } |
| |
| for (const auto &result : *mResults) { |
| if (!result->isJavaCompatible()) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| const TypedVar* Method::canElideCallback() const { |
| auto &res = results(); |
| |
| // Can't elide callback for void or tuple-returning methods |
| if (res.size() != 1) { |
| return nullptr; |
| } |
| |
| const TypedVar *typedVar = res.at(0); |
| |
| // We only elide callbacks for methods returning a single scalar. |
| if (typedVar->type().resolveToScalarType() != nullptr) { |
| return typedVar; |
| } |
| |
| return nullptr; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| TypedVar::TypedVar(const char *name, Type *type) |
| : mName(name), |
| mType(type) { |
| } |
| |
| std::string TypedVar::name() const { |
| return mName; |
| } |
| |
| const Type &TypedVar::type() const { |
| return *mType; |
| } |
| |
| bool TypedVar::isJavaCompatible() const { |
| return mType->isJavaCompatible(); |
| } |
| |
| } // namespace android |
| |