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
isHiddenFromJava() const142 bool Method::isHiddenFromJava() const {
143 return isHidlReserved() && name() == "debug";
144 }
145
overridesCppImpl(MethodImplType type) const146 bool Method::overridesCppImpl(MethodImplType type) const {
147 CHECK(mIsHidlReserved);
148 return mCppImpl.find(type) != mCppImpl.end();
149 }
150
overridesJavaImpl(MethodImplType type) const151 bool Method::overridesJavaImpl(MethodImplType type) const {
152 CHECK(mIsHidlReserved);
153 return mJavaImpl.find(type) != mJavaImpl.end();
154 }
155
copySignature() const156 Method *Method::copySignature() const {
157 return new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations, Location());
158 }
159
setSerialId(size_t serial)160 void Method::setSerialId(size_t serial) {
161 CHECK(!mIsHidlReserved);
162 mSerial = serial;
163 }
164
getSerialId() const165 size_t Method::getSerialId() const {
166 return mSerial;
167 }
168
hasEmptyCppArgSignature() const169 bool Method::hasEmptyCppArgSignature() const {
170 return args().empty() && (results().empty() || canElideCallback() != nullptr);
171 }
172
generateCppReturnType(Formatter & out,bool specifyNamespaces) const173 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
generateCppSignature(Formatter & out,const std::string & className,bool specifyNamespaces) const187 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
emitCppArgResultSignature(Formatter & out,const std::vector<NamedReference<Type> * > & args,bool specifyNamespaces)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
emitJavaArgResultSignature(Formatter & out,const std::vector<NamedReference<Type> * > & args)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
emitCppArgSignature(Formatter & out,bool specifyNamespaces) const221 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 }
emitCppResultSignature(Formatter & out,bool specifyNamespaces) const234 void Method::emitCppResultSignature(Formatter &out, bool specifyNamespaces) const {
235 emitCppArgResultSignature(out, results(), specifyNamespaces);
236 }
emitJavaArgSignature(Formatter & out) const237 void Method::emitJavaArgSignature(Formatter &out) const {
238 emitJavaArgResultSignature(out, args());
239 }
emitJavaResultSignature(Formatter & out) const240 void Method::emitJavaResultSignature(Formatter &out) const {
241 emitJavaArgResultSignature(out, results());
242 }
243
dumpAnnotations(Formatter & out) const244 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
deepIsJavaCompatible(std::unordered_set<const Type * > * visited) const259 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
canElideCallback() const277 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
location() const292 const Location& Method::location() const {
293 return mLocation;
294 }
295
296 ////////////////////////////////////////////////////////////////////////////////
297
add(NamedReference<Type> * v)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