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
Method(const char * name,std::vector<NamedReference<Type> * > * args,std::vector<NamedReference<Type> * > * results,bool oneway,std::vector<Annotation * > * annotations,const Location & location)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
fillImplementation(size_t serial,MethodImpl cppImpl,MethodImpl javaImpl)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
name() const56 std::string Method::name() const {
57 return mName;
58 }
59
args() const60 const std::vector<NamedReference<Type>*>& Method::args() const {
61 return *mArgs;
62 }
63
results() const64 const std::vector<NamedReference<Type>*>& Method::results() const {
65 return *mResults;
66 }
67
annotations() const68 const std::vector<Annotation *> &Method::annotations() const {
69 return *mAnnotations;
70 }
71
getReferences()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
getReferences() const80 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
getStrongReferences()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
getStrongReferences() const95 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
getConstantExpressions()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
getConstantExpressions() const113 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
cppImpl(MethodImplType type,Formatter & out) const122 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
javaImpl(MethodImplType type,Formatter & out) const132 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
overridesCppImpl(MethodImplType type) const142 bool Method::overridesCppImpl(MethodImplType type) const {
143 CHECK(mIsHidlReserved);
144 return mCppImpl.find(type) != mCppImpl.end();
145 }
146
overridesJavaImpl(MethodImplType type) const147 bool Method::overridesJavaImpl(MethodImplType type) const {
148 CHECK(mIsHidlReserved);
149 return mJavaImpl.find(type) != mJavaImpl.end();
150 }
151
copySignature() const152 Method* Method::copySignature() const {
153 Method* method = new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations, location());
154 method->setDocComment(getDocComment());
155 return method;
156 }
157
setSerialId(size_t serial)158 void Method::setSerialId(size_t serial) {
159 CHECK(!mIsHidlReserved);
160 mSerial = serial;
161 }
162
getSerialId() const163 size_t Method::getSerialId() const {
164 return mSerial;
165 }
166
hasEmptyCppArgSignature() const167 bool Method::hasEmptyCppArgSignature() const {
168 return args().empty() && (results().empty() || canElideCallback() != nullptr);
169 }
170
generateCppReturnType(Formatter & out,bool specifyNamespaces) const171 void Method::generateCppReturnType(Formatter &out, bool specifyNamespaces) const {
172 const NamedReference<Type>* elidedReturn = canElideCallback();
173 const std::string space = (specifyNamespaces ? "::android::hardware::" : "");
174
175 if (elidedReturn == nullptr) {
176 out << space << "Return<void> ";
177 } else {
178 out << space
179 << "Return<"
180 << elidedReturn->type().getCppResultType( specifyNamespaces)
181 << "> ";
182 }
183 }
184
generateCppSignature(Formatter & out,const std::string & className,bool specifyNamespaces) const185 void Method::generateCppSignature(Formatter &out,
186 const std::string &className,
187 bool specifyNamespaces) const {
188 generateCppReturnType(out, specifyNamespaces);
189
190 if (!className.empty()) {
191 out << className << "::";
192 }
193
194 out << name()
195 << "(";
196 emitCppArgSignature(out, specifyNamespaces);
197 out << ")";
198 }
199
emitCppArgResultSignature(Formatter & out,const std::vector<NamedReference<Type> * > & args,bool specifyNamespaces)200 static void emitCppArgResultSignature(Formatter& out,
201 const std::vector<NamedReference<Type>*>& args,
202 bool specifyNamespaces) {
203 out.join(args.begin(), args.end(), ", ", [&](auto arg) {
204 out << arg->type().getCppArgumentType(specifyNamespaces);
205 out << " ";
206 out << arg->name();
207 });
208 }
209
emitJavaArgResultSignature(Formatter & out,const std::vector<NamedReference<Type> * > & args)210 static void emitJavaArgResultSignature(Formatter& out,
211 const std::vector<NamedReference<Type>*>& args) {
212 out.join(args.begin(), args.end(), ", ", [&](auto arg) {
213 out << arg->type().getJavaType();
214 out << " ";
215 out << arg->name();
216 });
217 }
218
emitCppArgSignature(Formatter & out,bool specifyNamespaces) const219 void Method::emitCppArgSignature(Formatter &out, bool specifyNamespaces) const {
220 emitCppArgResultSignature(out, args(), specifyNamespaces);
221
222 const bool returnsValue = !results().empty();
223 const NamedReference<Type>* elidedReturn = canElideCallback();
224 if (returnsValue && elidedReturn == nullptr) {
225 if (!args().empty()) {
226 out << ", ";
227 }
228
229 out << name() << "_cb _hidl_cb";
230 }
231 }
emitCppResultSignature(Formatter & out,bool specifyNamespaces) const232 void Method::emitCppResultSignature(Formatter &out, bool specifyNamespaces) const {
233 emitCppArgResultSignature(out, results(), specifyNamespaces);
234 }
emitJavaArgSignature(Formatter & out) const235 void Method::emitJavaArgSignature(Formatter &out) const {
236 emitJavaArgResultSignature(out, args());
237 }
emitJavaResultSignature(Formatter & out) const238 void Method::emitJavaResultSignature(Formatter &out) const {
239 emitJavaArgResultSignature(out, results());
240 }
241
dumpAnnotations(Formatter & out) const242 void Method::dumpAnnotations(Formatter &out) const {
243 if (mAnnotations->size() == 0) {
244 return;
245 }
246
247 out << "// ";
248 for (size_t i = 0; i < mAnnotations->size(); ++i) {
249 if (i > 0) {
250 out << " ";
251 }
252 mAnnotations->at(i)->dump(out);
253 }
254 out << "\n";
255 }
256
deepIsJavaCompatible(std::unordered_set<const Type * > * visited) const257 bool Method::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
258 if (!std::all_of(mArgs->begin(), mArgs->end(),
259 [&](const auto* arg) { return (*arg)->isJavaCompatible(visited); })) {
260 return false;
261 }
262
263 if (!std::all_of(mResults->begin(), mResults->end(),
264 [&](const auto* arg) { return (*arg)->isJavaCompatible(visited); })) {
265 return false;
266 }
267
268 return true;
269 }
270
canElideCallback() const271 const NamedReference<Type>* Method::canElideCallback() const {
272 // Can't elide callback for void or tuple-returning methods
273 if (mResults->size() != 1) {
274 return nullptr;
275 }
276
277 const NamedReference<Type>* typedVar = mResults->at(0);
278
279 if (typedVar->type().isElidableType()) {
280 return typedVar;
281 }
282
283 return nullptr;
284 }
285
location() const286 const Location& Method::location() const {
287 return mLocation;
288 }
289
290 ////////////////////////////////////////////////////////////////////////////////
291
add(NamedReference<Type> * v)292 bool TypedVarVector::add(NamedReference<Type>* v) {
293 if (mNames.emplace(v->name()).second) {
294 push_back(v);
295 return true;
296 }
297 return false;
298 }
299
300 } // namespace android
301
302