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