blob: 4d22c5c281e7b81549925a9906b8ed80414851b4 [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 Huber7c5ddfb2016-09-29 13:45:22 -070027Interface::Interface(const char *localName, Interface *super)
Andreas Huber9ed827c2016-08-22 12:31:13 -070028 : Scope(localName),
29 mSuperType(super),
Andreas Huberea081b32016-08-17 15:57:47 -070030 mIsJavaCompatibleInProgress(false) {
Andreas Huberc9410c72016-07-28 12:18:40 -070031}
32
33void Interface::addMethod(Method *method) {
Steven Morelandef1a9fe2016-10-06 17:19:09 -070034 /* It is very important that these values NEVER change. These values
35 * must remain unchanged over the lifetime of android. This is
36 * because the framework on a device will be updated independently of
37 * the hals on a device. If the hals are compiled with one set of
38 * transaction values, and the framework with another, then the
39 * interface between them will be destroyed, and the device will not
40 * work.
41 */
42 size_t serial = 1; // hardware::IBinder::FIRST_CALL_TRANSACTION;
43
44 serial += methods().size();
45
46 const Interface *ancestor = mSuperType;
47 while (ancestor != nullptr) {
48 serial += ancestor->methods().size();
49 ancestor = ancestor->superType();
50 }
51
52 method->setSerialId(serial);
53
Andreas Huberc9410c72016-07-28 12:18:40 -070054 mMethods.push_back(method);
55}
56
Andreas Huber6cb08cf2016-08-03 15:44:51 -070057const Interface *Interface::superType() const {
Andreas Huberc9410c72016-07-28 12:18:40 -070058 return mSuperType;
59}
60
Andreas Hubera2723d22016-07-29 15:36:07 -070061bool Interface::isInterface() const {
62 return true;
63}
64
Andreas Huber295ad302016-08-16 11:35:00 -070065bool Interface::isBinder() const {
66 return true;
67}
68
Andreas Huber881227d2016-08-02 14:20:21 -070069const std::vector<Method *> &Interface::methods() const {
70 return mMethods;
71}
72
Steven Moreland40786312016-08-16 10:29:40 -070073std::string Interface::getBaseName() const {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -070074 return fqName().getInterfaceBaseName();
Steven Moreland40786312016-08-16 10:29:40 -070075}
76
Steven Moreland979e0992016-09-07 09:18:08 -070077std::string Interface::getCppType(StorageMode mode,
78 std::string *extra,
79 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070080 extra->clear();
Steven Moreland979e0992016-09-07 09:18:08 -070081 const std::string base =
82 std::string(specifyNamespaces ? "::android::" : "")
83 + "sp<"
84 + (specifyNamespaces ? fullName() : partialCppName())
85 + ">";
Andreas Huber881227d2016-08-02 14:20:21 -070086
87 switch (mode) {
88 case StorageMode_Stack:
89 case StorageMode_Result:
90 return base;
91
92 case StorageMode_Argument:
93 return "const " + base + "&";
94 }
95}
96
Andreas Huber4c865b72016-09-14 15:26:27 -070097std::string Interface::getJavaType(
98 std::string *extra, bool /* forInitializer */) const {
99 extra->clear();
Andreas Huber2831d512016-08-15 09:33:47 -0700100 return fullJavaName();
101}
102
Andreas Huber881227d2016-08-02 14:20:21 -0700103void Interface::emitReaderWriter(
104 Formatter &out,
105 const std::string &name,
106 const std::string &parcelObj,
107 bool parcelObjIsPointer,
108 bool isReader,
109 ErrorMode mode) const {
110 const std::string parcelObjDeref =
111 parcelObj + (parcelObjIsPointer ? "->" : ".");
112
113 if (isReader) {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700114 out << "{\n";
115 out.indent();
116
Iliyan Malchev549e2592016-08-10 08:59:12 -0700117 const std::string binderName = "_hidl_" + name + "_binder";
Andreas Huber881227d2016-08-02 14:20:21 -0700118
Andreas Huber8a82ff72016-08-04 10:29:39 -0700119 out << "::android::sp<::android::hardware::IBinder> "
Andreas Huber881227d2016-08-02 14:20:21 -0700120 << binderName << ";\n";
121
Iliyan Malchev549e2592016-08-10 08:59:12 -0700122 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700123 out << parcelObjDeref
124 << "readNullableStrongBinder(&"
125 << binderName
126 << ");\n";
127
128 handleError(out, mode);
129
130 out << name
131 << " = "
Steven Moreland40786312016-08-16 10:29:40 -0700132 << fqName().cppNamespace()
133 << "::IHw"
134 << getBaseName()
Andreas Huber881227d2016-08-02 14:20:21 -0700135 << "::asInterface("
136 << binderName
137 << ");\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700138
139 out.unindent();
140 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700141 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700142
143 out << "if (" << name << "->isRemote()) {\n";
144 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700145 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700146 out << parcelObjDeref
147 << "writeStrongBinder("
Steven Moreland40786312016-08-16 10:29:40 -0700148 << fqName().cppNamespace()
149 << "::IHw"
150 << getBaseName()
151 << "::asBinder(static_cast<"
152 << fqName().cppNamespace()
153 << "::IHw"
154 << getBaseName()
155 << "*>("
156 << name << ".get()"
157 << ")));\n";
158 out.unindent();
159 out << "} else {\n";
160 out.indent();
161 out << "_hidl_err = ";
162 out << parcelObjDeref
163 << "writeStrongBinder("
164 << "new " << fqName().cppNamespace()
165 << "::Bn" << getBaseName() << " "
166 << "(" << name <<"));\n";
167 out.unindent();
168 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700169 handleError(out, mode);
170 }
171}
172
Andreas Huber2831d512016-08-15 09:33:47 -0700173void Interface::emitJavaReaderWriter(
174 Formatter &out,
175 const std::string &parcelObj,
176 const std::string &argName,
177 bool isReader) const {
178 if (isReader) {
179 out << fullJavaName()
180 << ".asInterface("
181 << parcelObj
182 << ".readStrongBinder());\n";
183 } else {
184 out << parcelObj
185 << ".writeStrongBinder("
186 << argName
187 << " == null ? null : "
188 << argName
189 << ".asBinder());\n";
190 }
191}
192
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700193status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
194 for (const auto &type : getSubTypes()) {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700195 // Skip for TypeDef as it is just an alias of a defined type.
196 if (type->isTypeDef()) {
197 continue;
198 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700199 out << "attribute: {\n";
200 out.indent();
201 status_t status = type->emitVtsTypeDeclarations(out);
202 if (status != OK) {
203 return status;
204 }
205 out.unindent();
206 out << "}\n\n";
207 }
208 return OK;
209}
210
211status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
212 for (const auto &method : mMethods) {
213 out << "api: {\n";
214 out.indent();
215 out << "name: \"" << method->name() << "\"\n";
216 // Generate declaration for each return value.
217 for (const auto &result : method->results()) {
218 out << "return_type_hidl: {\n";
219 out.indent();
220 status_t status = result->type().emitVtsAttributeType(out);
221 if (status != OK) {
222 return status;
223 }
224 out.unindent();
225 out << "}\n";
226 }
227 // Generate declaration for each input argument
228 for (const auto &arg : method->args()) {
229 out << "arg: {\n";
230 out.indent();
231 status_t status = arg->type().emitVtsAttributeType(out);
232 if (status != OK) {
233 return status;
234 }
235 out.unindent();
236 out << "}\n";
237 }
238 // Generate declaration for each annotation.
Steven Morelandd537ab02016-09-12 10:32:01 -0700239 for (const auto &annotation : method->annotations()) {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700240 out << "callflow: {\n";
241 out.indent();
Steven Morelandd537ab02016-09-12 10:32:01 -0700242 std::string name = annotation->name();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700243 if (name == "entry") {
244 out << "entry: true\n";
245 } else if (name == "exit") {
246 out << "exit: true\n";
247 } else if (name == "callflow") {
Steven Morelandd537ab02016-09-12 10:32:01 -0700248 const AnnotationParam *param =
249 annotation->getParam("next");
250 if (param != nullptr) {
251 for (auto value : *param->getValues()) {
252 out << "next: " << value << "\n";
253 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700254 }
255 } else {
256 std::cerr << "Invalid annotation '"
257 << name << "' for method: " << method->name()
258 << ". Should be one of: entry, exit, callflow. \n";
259 return UNKNOWN_ERROR;
260 }
261 out.unindent();
262 out << "}\n";
263 }
264 out.unindent();
265 out << "}\n\n";
266 }
267 return OK;
268}
269
270status_t Interface::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700271 out << "type: TYPE_HIDL_CALLBACK\n"
272 << "predefined_type: \""
273 << localName()
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700274 << "\"\n"
275 << "is_callback: true\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700276 return OK;
277}
278
Steven Moreland69e7c702016-09-09 11:16:32 -0700279
280bool Interface::hasOnewayMethods() const {
281 for (auto const &method : mMethods) {
282 if (method->isOneway()) {
283 return true;
284 }
285 }
286
287 const Interface* superClass = superType();
288
289 if (superClass != nullptr) {
290 return superClass->hasOnewayMethods();
291 }
292
293 return false;
294}
295
Andreas Huber70a59e12016-08-16 12:57:01 -0700296bool Interface::isJavaCompatible() const {
Andreas Huberea081b32016-08-17 15:57:47 -0700297 if (mIsJavaCompatibleInProgress) {
298 // We're currently trying to determine if this Interface is
299 // java-compatible and something is referencing this interface through
300 // one of its methods. Assume we'll ultimately succeed, if we were wrong
301 // the original invocation of Interface::isJavaCompatible() will then
302 // return the correct "false" result.
303 return true;
304 }
305
Andreas Huber0fa9e392016-08-31 09:05:44 -0700306 if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
307 mIsJavaCompatibleInProgress = false;
308 return false;
309 }
310
Andreas Huberea081b32016-08-17 15:57:47 -0700311 mIsJavaCompatibleInProgress = true;
312
Andreas Huber70a59e12016-08-16 12:57:01 -0700313 if (!Scope::isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700314 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700315 return false;
316 }
317
318 for (const auto &method : mMethods) {
319 if (!method->isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700320 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700321 return false;
322 }
323 }
324
Andreas Huberea081b32016-08-17 15:57:47 -0700325 mIsJavaCompatibleInProgress = false;
326
Andreas Huber70a59e12016-08-16 12:57:01 -0700327 return true;
328}
329
Andreas Huberc9410c72016-07-28 12:18:40 -0700330} // namespace android
331