• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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