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 "ScalarType.h" 21 #include "Type.h" 22 23 #include <android-base/logging.h> 24 #include <hidl-util/Formatter.h> 25 26 namespace android { 27 28 Method::Method(const char *name, 29 std::vector<TypedVar *> *args, 30 std::vector<TypedVar *> *results, 31 bool oneway, 32 std::vector<Annotation *> *annotations) 33 : mName(name), 34 mArgs(args), 35 mResults(results), 36 mOneway(oneway), 37 mAnnotations(annotations) { 38 } 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<TypedVar *> &Method::args() const { 61 return *mArgs; 62 } 63 64 const std::vector<TypedVar *> &Method::results() const { 65 return *mResults; 66 } 67 68 const std::vector<Annotation *> &Method::annotations() const { 69 return *mAnnotations; 70 } 71 72 void Method::cppImpl(MethodImplType type, Formatter &out) const { 73 CHECK(mIsHidlReserved); 74 auto it = mCppImpl.find(type); 75 if (it != mCppImpl.end()) { 76 if (it->second != nullptr) { 77 it->second(out); 78 } 79 } 80 } 81 82 void Method::javaImpl(MethodImplType type, Formatter &out) const { 83 CHECK(mIsHidlReserved); 84 auto it = mJavaImpl.find(type); 85 if (it != mJavaImpl.end()) { 86 if (it->second != nullptr) { 87 it->second(out); 88 } 89 } 90 } 91 92 bool Method::isHiddenFromJava() const { 93 return isHidlReserved() && name() == "debug"; 94 } 95 96 bool Method::overridesCppImpl(MethodImplType type) const { 97 CHECK(mIsHidlReserved); 98 return mCppImpl.find(type) != mCppImpl.end(); 99 } 100 101 bool Method::overridesJavaImpl(MethodImplType type) const { 102 CHECK(mIsHidlReserved); 103 return mJavaImpl.find(type) != mJavaImpl.end(); 104 } 105 106 Method *Method::copySignature() const { 107 return new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations); 108 } 109 110 void Method::setSerialId(size_t serial) { 111 CHECK(!mIsHidlReserved); 112 mSerial = serial; 113 } 114 115 size_t Method::getSerialId() const { 116 return mSerial; 117 } 118 119 void Method::generateCppSignature(Formatter &out, 120 const std::string &className, 121 bool specifyNamespaces) const { 122 const bool returnsValue = !results().empty(); 123 124 const TypedVar *elidedReturn = canElideCallback(); 125 126 std::string space = (specifyNamespaces ? "::android::hardware::" : ""); 127 128 if (elidedReturn == nullptr) { 129 out << space << "Return<void> "; 130 } else { 131 out << space 132 << "Return<" 133 << elidedReturn->type().getCppResultType( specifyNamespaces) 134 << "> "; 135 } 136 137 if (!className.empty()) { 138 out << className << "::"; 139 } 140 141 out << name() 142 << "("; 143 emitCppArgSignature(out, specifyNamespaces); 144 145 if (returnsValue && elidedReturn == nullptr) { 146 if (!args().empty()) { 147 out << ", "; 148 } 149 150 out << name() << "_cb _hidl_cb"; 151 } 152 153 out << ")"; 154 } 155 156 static void emitCppArgResultSignature(Formatter &out, 157 const std::vector<TypedVar *> &args, 158 bool specifyNamespaces) { 159 out.join(args.begin(), args.end(), ", ", [&](auto arg) { 160 out << arg->type().getCppArgumentType(specifyNamespaces); 161 out << " "; 162 out << arg->name(); 163 }); 164 } 165 166 static void emitJavaArgResultSignature(Formatter &out, const std::vector<TypedVar *> &args) { 167 out.join(args.begin(), args.end(), ", ", [&](auto arg) { 168 out << arg->type().getJavaType(); 169 out << " "; 170 out << arg->name(); 171 }); 172 } 173 174 void Method::emitCppArgSignature(Formatter &out, bool specifyNamespaces) const { 175 emitCppArgResultSignature(out, args(), specifyNamespaces); 176 } 177 void Method::emitCppResultSignature(Formatter &out, bool specifyNamespaces) const { 178 emitCppArgResultSignature(out, results(), specifyNamespaces); 179 } 180 void Method::emitJavaArgSignature(Formatter &out) const { 181 emitJavaArgResultSignature(out, args()); 182 } 183 void Method::emitJavaResultSignature(Formatter &out) const { 184 emitJavaArgResultSignature(out, results()); 185 } 186 187 void Method::dumpAnnotations(Formatter &out) const { 188 if (mAnnotations->size() == 0) { 189 return; 190 } 191 192 out << "// "; 193 for (size_t i = 0; i < mAnnotations->size(); ++i) { 194 if (i > 0) { 195 out << " "; 196 } 197 mAnnotations->at(i)->dump(out); 198 } 199 out << "\n"; 200 } 201 202 bool Method::isJavaCompatible() const { 203 if (isHiddenFromJava()) { 204 return true; 205 } 206 207 for (const auto &arg : *mArgs) { 208 if (!arg->isJavaCompatible()) { 209 return false; 210 } 211 } 212 213 for (const auto &result : *mResults) { 214 if (!result->isJavaCompatible()) { 215 return false; 216 } 217 } 218 219 return true; 220 } 221 222 const TypedVar* Method::canElideCallback() const { 223 // Can't elide callback for void or tuple-returning methods 224 if (mResults->size() != 1) { 225 return nullptr; 226 } 227 228 const TypedVar *typedVar = mResults->at(0); 229 230 if (typedVar->type().isElidableType()) { 231 return typedVar; 232 } 233 234 return nullptr; 235 } 236 237 //////////////////////////////////////////////////////////////////////////////// 238 239 TypedVar::TypedVar(const char *name, Type *type) 240 : mName(name), 241 mType(type) { 242 } 243 244 std::string TypedVar::name() const { 245 return mName; 246 } 247 248 const Type &TypedVar::type() const { 249 return *mType; 250 } 251 252 bool TypedVar::isJavaCompatible() const { 253 return mType->isJavaCompatible(); 254 } 255 256 //////////////////////////////////////////////////////////////////////////////// 257 bool TypedVarVector::add(TypedVar *v) { 258 if (mNames.emplace(v->name()).second) { 259 push_back(v); 260 return true; 261 } 262 return false; 263 } 264 265 } // namespace android 266 267