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