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 bool Method::hasEmptyCppArgSignature() const { 120 return args().empty() && (results().empty() || canElideCallback() != nullptr); 121 } 122 123 void Method::generateCppReturnType(Formatter &out, bool specifyNamespaces) const { 124 const TypedVar *elidedReturn = canElideCallback(); 125 const std::string space = (specifyNamespaces ? "::android::hardware::" : ""); 126 127 if (elidedReturn == nullptr) { 128 out << space << "Return<void> "; 129 } else { 130 out << space 131 << "Return<" 132 << elidedReturn->type().getCppResultType( specifyNamespaces) 133 << "> "; 134 } 135 } 136 137 void Method::generateCppSignature(Formatter &out, 138 const std::string &className, 139 bool specifyNamespaces) const { 140 generateCppReturnType(out, specifyNamespaces); 141 142 if (!className.empty()) { 143 out << className << "::"; 144 } 145 146 out << name() 147 << "("; 148 emitCppArgSignature(out, specifyNamespaces); 149 out << ")"; 150 } 151 152 static void emitCppArgResultSignature(Formatter &out, 153 const std::vector<TypedVar *> &args, 154 bool specifyNamespaces) { 155 out.join(args.begin(), args.end(), ", ", [&](auto arg) { 156 out << arg->type().getCppArgumentType(specifyNamespaces); 157 out << " "; 158 out << arg->name(); 159 }); 160 } 161 162 static void emitJavaArgResultSignature(Formatter &out, const std::vector<TypedVar *> &args) { 163 out.join(args.begin(), args.end(), ", ", [&](auto arg) { 164 out << arg->type().getJavaType(); 165 out << " "; 166 out << arg->name(); 167 }); 168 } 169 170 void Method::emitCppArgSignature(Formatter &out, bool specifyNamespaces) const { 171 emitCppArgResultSignature(out, args(), specifyNamespaces); 172 173 const bool returnsValue = !results().empty(); 174 const TypedVar *elidedReturn = canElideCallback(); 175 if (returnsValue && elidedReturn == nullptr) { 176 if (!args().empty()) { 177 out << ", "; 178 } 179 180 out << name() << "_cb _hidl_cb"; 181 } 182 } 183 void Method::emitCppResultSignature(Formatter &out, bool specifyNamespaces) const { 184 emitCppArgResultSignature(out, results(), specifyNamespaces); 185 } 186 void Method::emitJavaArgSignature(Formatter &out) const { 187 emitJavaArgResultSignature(out, args()); 188 } 189 void Method::emitJavaResultSignature(Formatter &out) const { 190 emitJavaArgResultSignature(out, results()); 191 } 192 193 void Method::dumpAnnotations(Formatter &out) const { 194 if (mAnnotations->size() == 0) { 195 return; 196 } 197 198 out << "// "; 199 for (size_t i = 0; i < mAnnotations->size(); ++i) { 200 if (i > 0) { 201 out << " "; 202 } 203 mAnnotations->at(i)->dump(out); 204 } 205 out << "\n"; 206 } 207 208 bool Method::isJavaCompatible() const { 209 if (isHiddenFromJava()) { 210 return true; 211 } 212 213 for (const auto &arg : *mArgs) { 214 if (!arg->isJavaCompatible()) { 215 return false; 216 } 217 } 218 219 for (const auto &result : *mResults) { 220 if (!result->isJavaCompatible()) { 221 return false; 222 } 223 } 224 225 return true; 226 } 227 228 const TypedVar* Method::canElideCallback() const { 229 // Can't elide callback for void or tuple-returning methods 230 if (mResults->size() != 1) { 231 return nullptr; 232 } 233 234 const TypedVar *typedVar = mResults->at(0); 235 236 if (typedVar->type().isElidableType()) { 237 return typedVar; 238 } 239 240 return nullptr; 241 } 242 243 //////////////////////////////////////////////////////////////////////////////// 244 245 TypedVar::TypedVar(const char *name, Type *type) 246 : mName(name), 247 mType(type) { 248 } 249 250 std::string TypedVar::name() const { 251 return mName; 252 } 253 254 const Type &TypedVar::type() const { 255 return *mType; 256 } 257 258 bool TypedVar::isJavaCompatible() const { 259 return mType->isJavaCompatible(); 260 } 261 262 //////////////////////////////////////////////////////////////////////////////// 263 bool TypedVarVector::add(TypedVar *v) { 264 if (mNames.emplace(v->name()).second) { 265 push_back(v); 266 return true; 267 } 268 return false; 269 } 270 271 } // namespace android 272 273