blob: a4059d0b0bcf3bd80dd4b88703bff39ef43b9f14 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "Interface.h"
18
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -070019#include "Annotation.h"
Andreas Huberc9410c72016-07-28 12:18:40 -070020#include "Method.h"
21
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070022#include <hidl-util/Formatter.h>
Zhuoyao Zhang864c7712016-08-16 15:35:28 -070023#include <iostream>
24
Andreas Huberc9410c72016-07-28 12:18:40 -070025namespace android {
26
Andreas Huber9ed827c2016-08-22 12:31:13 -070027Interface::Interface(
28 const char *localName, Interface *super, AnnotationVector *annotations)
29 : Scope(localName),
30 mSuperType(super),
Andreas Huberea081b32016-08-17 15:57:47 -070031 mAnnotationsByName(annotations),
32 mIsJavaCompatibleInProgress(false) {
Andreas Huberc9410c72016-07-28 12:18:40 -070033}
34
35void Interface::addMethod(Method *method) {
36 mMethods.push_back(method);
37}
38
Andreas Huber6cb08cf2016-08-03 15:44:51 -070039const Interface *Interface::superType() const {
Andreas Huberc9410c72016-07-28 12:18:40 -070040 return mSuperType;
41}
42
Andreas Hubera2723d22016-07-29 15:36:07 -070043bool Interface::isInterface() const {
44 return true;
45}
46
Andreas Huber295ad302016-08-16 11:35:00 -070047bool Interface::isBinder() const {
48 return true;
49}
50
Andreas Huber881227d2016-08-02 14:20:21 -070051const std::vector<Method *> &Interface::methods() const {
52 return mMethods;
53}
54
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070055const AnnotationVector &Interface::annotations() const {
Zhuoyao Zhangba7e6e92016-08-10 12:19:02 -070056 return *mAnnotationsByName;
57}
58
Steven Moreland40786312016-08-16 10:29:40 -070059std::string Interface::getBaseName() const {
60 // cut off the leading 'I'.
61 return localName().substr(1);
62}
63
Steven Moreland979e0992016-09-07 09:18:08 -070064std::string Interface::getCppType(StorageMode mode,
65 std::string *extra,
66 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070067 extra->clear();
Steven Moreland979e0992016-09-07 09:18:08 -070068 const std::string base =
69 std::string(specifyNamespaces ? "::android::" : "")
70 + "sp<"
71 + (specifyNamespaces ? fullName() : partialCppName())
72 + ">";
Andreas Huber881227d2016-08-02 14:20:21 -070073
74 switch (mode) {
75 case StorageMode_Stack:
76 case StorageMode_Result:
77 return base;
78
79 case StorageMode_Argument:
80 return "const " + base + "&";
81 }
82}
83
Andreas Huber2831d512016-08-15 09:33:47 -070084std::string Interface::getJavaType() const {
85 return fullJavaName();
86}
87
Andreas Huber881227d2016-08-02 14:20:21 -070088void Interface::emitReaderWriter(
89 Formatter &out,
90 const std::string &name,
91 const std::string &parcelObj,
92 bool parcelObjIsPointer,
93 bool isReader,
94 ErrorMode mode) const {
95 const std::string parcelObjDeref =
96 parcelObj + (parcelObjIsPointer ? "->" : ".");
97
98 if (isReader) {
Andreas Hubere7ff2282016-08-16 13:50:03 -070099 out << "{\n";
100 out.indent();
101
Iliyan Malchev549e2592016-08-10 08:59:12 -0700102 const std::string binderName = "_hidl_" + name + "_binder";
Andreas Huber881227d2016-08-02 14:20:21 -0700103
Andreas Huber8a82ff72016-08-04 10:29:39 -0700104 out << "::android::sp<::android::hardware::IBinder> "
Andreas Huber881227d2016-08-02 14:20:21 -0700105 << binderName << ";\n";
106
Iliyan Malchev549e2592016-08-10 08:59:12 -0700107 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700108 out << parcelObjDeref
109 << "readNullableStrongBinder(&"
110 << binderName
111 << ");\n";
112
113 handleError(out, mode);
114
115 out << name
116 << " = "
Steven Moreland40786312016-08-16 10:29:40 -0700117 << fqName().cppNamespace()
118 << "::IHw"
119 << getBaseName()
Andreas Huber881227d2016-08-02 14:20:21 -0700120 << "::asInterface("
121 << binderName
122 << ");\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700123
124 out.unindent();
125 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700126 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700127
128 out << "if (" << name << "->isRemote()) {\n";
129 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700130 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700131 out << parcelObjDeref
132 << "writeStrongBinder("
Steven Moreland40786312016-08-16 10:29:40 -0700133 << fqName().cppNamespace()
134 << "::IHw"
135 << getBaseName()
136 << "::asBinder(static_cast<"
137 << fqName().cppNamespace()
138 << "::IHw"
139 << getBaseName()
140 << "*>("
141 << name << ".get()"
142 << ")));\n";
143 out.unindent();
144 out << "} else {\n";
145 out.indent();
146 out << "_hidl_err = ";
147 out << parcelObjDeref
148 << "writeStrongBinder("
149 << "new " << fqName().cppNamespace()
150 << "::Bn" << getBaseName() << " "
151 << "(" << name <<"));\n";
152 out.unindent();
153 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700154 handleError(out, mode);
155 }
156}
157
Andreas Huber2831d512016-08-15 09:33:47 -0700158void Interface::emitJavaReaderWriter(
159 Formatter &out,
160 const std::string &parcelObj,
161 const std::string &argName,
162 bool isReader) const {
163 if (isReader) {
164 out << fullJavaName()
165 << ".asInterface("
166 << parcelObj
167 << ".readStrongBinder());\n";
168 } else {
169 out << parcelObj
170 << ".writeStrongBinder("
171 << argName
172 << " == null ? null : "
173 << argName
174 << ".asBinder());\n";
175 }
176}
177
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700178status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
179 for (const auto &type : getSubTypes()) {
180 out << "attribute: {\n";
181 out.indent();
182 status_t status = type->emitVtsTypeDeclarations(out);
183 if (status != OK) {
184 return status;
185 }
186 out.unindent();
187 out << "}\n\n";
188 }
189 return OK;
190}
191
192status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
193 for (const auto &method : mMethods) {
194 out << "api: {\n";
195 out.indent();
196 out << "name: \"" << method->name() << "\"\n";
197 // Generate declaration for each return value.
198 for (const auto &result : method->results()) {
199 out << "return_type_hidl: {\n";
200 out.indent();
201 status_t status = result->type().emitVtsAttributeType(out);
202 if (status != OK) {
203 return status;
204 }
205 out.unindent();
206 out << "}\n";
207 }
208 // Generate declaration for each input argument
209 for (const auto &arg : method->args()) {
210 out << "arg: {\n";
211 out.indent();
212 status_t status = arg->type().emitVtsAttributeType(out);
213 if (status != OK) {
214 return status;
215 }
216 out.unindent();
217 out << "}\n";
218 }
219 // Generate declaration for each annotation.
220 const AnnotationVector & annotations = method->annotations();
221 for (size_t i = 0; i < annotations.size(); i++) {
222 out << "callflow: {\n";
223 out.indent();
224 std::string name = annotations.keyAt(i);
225 if (name == "entry") {
226 out << "entry: true\n";
227 } else if (name == "exit") {
228 out << "exit: true\n";
229 } else if (name == "callflow") {
230 Annotation* annotation = annotations.valueAt(i);
231 std::vector<std::string> * values = annotation->params()
232 .valueFor("next");
233 for (auto value : *values) {
234 out << "next: " << value << "\n";
235 }
236 } else {
237 std::cerr << "Invalid annotation '"
238 << name << "' for method: " << method->name()
239 << ". Should be one of: entry, exit, callflow. \n";
240 return UNKNOWN_ERROR;
241 }
242 out.unindent();
243 out << "}\n";
244 }
245 out.unindent();
246 out << "}\n\n";
247 }
248 return OK;
249}
250
251status_t Interface::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700252 out << "type: TYPE_HIDL_CALLBACK\n"
253 << "predefined_type: \""
254 << localName()
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700255 << "\"\n"
256 << "is_callback: true\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700257 return OK;
258}
259
Andreas Huber70a59e12016-08-16 12:57:01 -0700260bool Interface::isJavaCompatible() const {
Andreas Huberea081b32016-08-17 15:57:47 -0700261 if (mIsJavaCompatibleInProgress) {
262 // We're currently trying to determine if this Interface is
263 // java-compatible and something is referencing this interface through
264 // one of its methods. Assume we'll ultimately succeed, if we were wrong
265 // the original invocation of Interface::isJavaCompatible() will then
266 // return the correct "false" result.
267 return true;
268 }
269
Andreas Huber0fa9e392016-08-31 09:05:44 -0700270 if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
271 mIsJavaCompatibleInProgress = false;
272 return false;
273 }
274
Andreas Huberea081b32016-08-17 15:57:47 -0700275 mIsJavaCompatibleInProgress = true;
276
Andreas Huber70a59e12016-08-16 12:57:01 -0700277 if (!Scope::isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700278 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700279 return false;
280 }
281
282 for (const auto &method : mMethods) {
283 if (!method->isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700284 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700285 return false;
286 }
287 }
288
Andreas Huberea081b32016-08-17 15:57:47 -0700289 mIsJavaCompatibleInProgress = false;
290
Andreas Huber70a59e12016-08-16 12:57:01 -0700291 return true;
292}
293
Andreas Huberc9410c72016-07-28 12:18:40 -0700294} // namespace android
295