blob: 5951f87c193914c5dd9cd638f3f0ca6c68885b8a [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
Steven Moreland14ee6742016-10-18 12:58:28 -070022#include <android-base/logging.h>
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070023#include <hidl-util/Formatter.h>
Zhuoyao Zhang864c7712016-08-16 15:35:28 -070024#include <iostream>
25
Andreas Huberc9410c72016-07-28 12:18:40 -070026namespace android {
27
Andreas Huber7c5ddfb2016-09-29 13:45:22 -070028Interface::Interface(const char *localName, Interface *super)
Andreas Huber9ed827c2016-08-22 12:31:13 -070029 : Scope(localName),
30 mSuperType(super),
Andreas Huberea081b32016-08-17 15:57:47 -070031 mIsJavaCompatibleInProgress(false) {
Andreas Huberc9410c72016-07-28 12:18:40 -070032}
33
Steven Moreland14ee6742016-10-18 12:58:28 -070034bool Interface::addMethod(Method *method) {
35 if (lookupMethod(method->name()) != nullptr) {
36 LOG(ERROR) << "Redefinition of method " << method->name();
37 return false;
38 }
39
Steven Morelandef1a9fe2016-10-06 17:19:09 -070040 /* It is very important that these values NEVER change. These values
41 * must remain unchanged over the lifetime of android. This is
42 * because the framework on a device will be updated independently of
43 * the hals on a device. If the hals are compiled with one set of
44 * transaction values, and the framework with another, then the
45 * interface between them will be destroyed, and the device will not
46 * work.
47 */
48 size_t serial = 1; // hardware::IBinder::FIRST_CALL_TRANSACTION;
49
Steven Moreland14ee6742016-10-18 12:58:28 -070050 const Interface *ancestor = this;
Steven Morelandef1a9fe2016-10-06 17:19:09 -070051 while (ancestor != nullptr) {
52 serial += ancestor->methods().size();
53 ancestor = ancestor->superType();
54 }
55
56 method->setSerialId(serial);
Andreas Huberc9410c72016-07-28 12:18:40 -070057 mMethods.push_back(method);
Steven Moreland14ee6742016-10-18 12:58:28 -070058
59 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070060}
61
Andreas Huber6cb08cf2016-08-03 15:44:51 -070062const Interface *Interface::superType() const {
Andreas Huberc9410c72016-07-28 12:18:40 -070063 return mSuperType;
64}
65
Andreas Hubera2723d22016-07-29 15:36:07 -070066bool Interface::isInterface() const {
67 return true;
68}
69
Andreas Huber295ad302016-08-16 11:35:00 -070070bool Interface::isBinder() const {
71 return true;
72}
73
Andreas Huber881227d2016-08-02 14:20:21 -070074const std::vector<Method *> &Interface::methods() const {
75 return mMethods;
76}
77
Steven Moreland14ee6742016-10-18 12:58:28 -070078Method *Interface::lookupMethod(std::string name) const {
79 const Interface *ancestor = this;
80 while (ancestor != nullptr) {
81 for (const auto &method : mMethods) {
82 if (method->name() == name) {
83 return method;
84 }
85 }
86 ancestor = ancestor->superType();
87 }
88
89 return nullptr;
90}
91
Steven Moreland40786312016-08-16 10:29:40 -070092std::string Interface::getBaseName() const {
Jayant Chowdhary3f32c1f2016-09-15 16:53:56 -070093 return fqName().getInterfaceBaseName();
Steven Moreland40786312016-08-16 10:29:40 -070094}
95
Steven Moreland979e0992016-09-07 09:18:08 -070096std::string Interface::getCppType(StorageMode mode,
97 std::string *extra,
98 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070099 extra->clear();
Steven Moreland979e0992016-09-07 09:18:08 -0700100 const std::string base =
101 std::string(specifyNamespaces ? "::android::" : "")
102 + "sp<"
103 + (specifyNamespaces ? fullName() : partialCppName())
104 + ">";
Andreas Huber881227d2016-08-02 14:20:21 -0700105
106 switch (mode) {
107 case StorageMode_Stack:
108 case StorageMode_Result:
109 return base;
110
111 case StorageMode_Argument:
112 return "const " + base + "&";
113 }
114}
115
Andreas Huber4c865b72016-09-14 15:26:27 -0700116std::string Interface::getJavaType(
117 std::string *extra, bool /* forInitializer */) const {
118 extra->clear();
Andreas Huber2831d512016-08-15 09:33:47 -0700119 return fullJavaName();
120}
121
Andreas Huber881227d2016-08-02 14:20:21 -0700122void Interface::emitReaderWriter(
123 Formatter &out,
124 const std::string &name,
125 const std::string &parcelObj,
126 bool parcelObjIsPointer,
127 bool isReader,
128 ErrorMode mode) const {
129 const std::string parcelObjDeref =
130 parcelObj + (parcelObjIsPointer ? "->" : ".");
131
132 if (isReader) {
Andreas Hubere7ff2282016-08-16 13:50:03 -0700133 out << "{\n";
134 out.indent();
135
Iliyan Malchev549e2592016-08-10 08:59:12 -0700136 const std::string binderName = "_hidl_" + name + "_binder";
Andreas Huber881227d2016-08-02 14:20:21 -0700137
Andreas Huber8a82ff72016-08-04 10:29:39 -0700138 out << "::android::sp<::android::hardware::IBinder> "
Andreas Huber881227d2016-08-02 14:20:21 -0700139 << binderName << ";\n";
140
Iliyan Malchev549e2592016-08-10 08:59:12 -0700141 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700142 out << parcelObjDeref
143 << "readNullableStrongBinder(&"
144 << binderName
145 << ");\n";
146
147 handleError(out, mode);
148
149 out << name
150 << " = "
Steven Moreland40786312016-08-16 10:29:40 -0700151 << fqName().cppNamespace()
152 << "::IHw"
153 << getBaseName()
Andreas Huber881227d2016-08-02 14:20:21 -0700154 << "::asInterface("
155 << binderName
156 << ");\n";
Andreas Hubere7ff2282016-08-16 13:50:03 -0700157
158 out.unindent();
159 out << "}\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700160 } else {
Steven Moreland40786312016-08-16 10:29:40 -0700161
162 out << "if (" << name << "->isRemote()) {\n";
163 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700164 out << "_hidl_err = ";
Andreas Huber881227d2016-08-02 14:20:21 -0700165 out << parcelObjDeref
166 << "writeStrongBinder("
Steven Moreland40786312016-08-16 10:29:40 -0700167 << fqName().cppNamespace()
168 << "::IHw"
169 << getBaseName()
170 << "::asBinder(static_cast<"
171 << fqName().cppNamespace()
172 << "::IHw"
173 << getBaseName()
174 << "*>("
175 << name << ".get()"
176 << ")));\n";
177 out.unindent();
178 out << "} else {\n";
179 out.indent();
180 out << "_hidl_err = ";
181 out << parcelObjDeref
182 << "writeStrongBinder("
183 << "new " << fqName().cppNamespace()
184 << "::Bn" << getBaseName() << " "
185 << "(" << name <<"));\n";
186 out.unindent();
187 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700188 handleError(out, mode);
189 }
190}
191
Andreas Huber2831d512016-08-15 09:33:47 -0700192void Interface::emitJavaReaderWriter(
193 Formatter &out,
194 const std::string &parcelObj,
195 const std::string &argName,
196 bool isReader) const {
197 if (isReader) {
198 out << fullJavaName()
199 << ".asInterface("
200 << parcelObj
201 << ".readStrongBinder());\n";
202 } else {
203 out << parcelObj
204 << ".writeStrongBinder("
205 << argName
206 << " == null ? null : "
207 << argName
208 << ".asBinder());\n";
209 }
210}
211
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700212status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
213 for (const auto &type : getSubTypes()) {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700214 // Skip for TypeDef as it is just an alias of a defined type.
215 if (type->isTypeDef()) {
216 continue;
217 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700218 out << "attribute: {\n";
219 out.indent();
220 status_t status = type->emitVtsTypeDeclarations(out);
221 if (status != OK) {
222 return status;
223 }
224 out.unindent();
225 out << "}\n\n";
226 }
227 return OK;
228}
229
230status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
231 for (const auto &method : mMethods) {
232 out << "api: {\n";
233 out.indent();
234 out << "name: \"" << method->name() << "\"\n";
235 // Generate declaration for each return value.
236 for (const auto &result : method->results()) {
237 out << "return_type_hidl: {\n";
238 out.indent();
239 status_t status = result->type().emitVtsAttributeType(out);
240 if (status != OK) {
241 return status;
242 }
243 out.unindent();
244 out << "}\n";
245 }
246 // Generate declaration for each input argument
247 for (const auto &arg : method->args()) {
248 out << "arg: {\n";
249 out.indent();
250 status_t status = arg->type().emitVtsAttributeType(out);
251 if (status != OK) {
252 return status;
253 }
254 out.unindent();
255 out << "}\n";
256 }
257 // Generate declaration for each annotation.
Steven Morelandd537ab02016-09-12 10:32:01 -0700258 for (const auto &annotation : method->annotations()) {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700259 out << "callflow: {\n";
260 out.indent();
Steven Morelandd537ab02016-09-12 10:32:01 -0700261 std::string name = annotation->name();
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700262 if (name == "entry") {
263 out << "entry: true\n";
264 } else if (name == "exit") {
265 out << "exit: true\n";
266 } else if (name == "callflow") {
Steven Morelandd537ab02016-09-12 10:32:01 -0700267 const AnnotationParam *param =
268 annotation->getParam("next");
269 if (param != nullptr) {
270 for (auto value : *param->getValues()) {
271 out << "next: " << value << "\n";
272 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700273 }
274 } else {
275 std::cerr << "Invalid annotation '"
276 << name << "' for method: " << method->name()
277 << ". Should be one of: entry, exit, callflow. \n";
278 return UNKNOWN_ERROR;
279 }
280 out.unindent();
281 out << "}\n";
282 }
283 out.unindent();
284 out << "}\n\n";
285 }
286 return OK;
287}
288
289status_t Interface::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700290 out << "type: TYPE_HIDL_CALLBACK\n"
291 << "predefined_type: \""
292 << localName()
Zhuoyao Zhang19933522016-08-29 15:06:38 -0700293 << "\"\n"
294 << "is_callback: true\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700295 return OK;
296}
297
Steven Moreland69e7c702016-09-09 11:16:32 -0700298
299bool Interface::hasOnewayMethods() const {
300 for (auto const &method : mMethods) {
301 if (method->isOneway()) {
302 return true;
303 }
304 }
305
306 const Interface* superClass = superType();
307
308 if (superClass != nullptr) {
309 return superClass->hasOnewayMethods();
310 }
311
312 return false;
313}
314
Andreas Huber70a59e12016-08-16 12:57:01 -0700315bool Interface::isJavaCompatible() const {
Andreas Huberea081b32016-08-17 15:57:47 -0700316 if (mIsJavaCompatibleInProgress) {
317 // We're currently trying to determine if this Interface is
318 // java-compatible and something is referencing this interface through
319 // one of its methods. Assume we'll ultimately succeed, if we were wrong
320 // the original invocation of Interface::isJavaCompatible() will then
321 // return the correct "false" result.
322 return true;
323 }
324
Andreas Huber0fa9e392016-08-31 09:05:44 -0700325 if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
326 mIsJavaCompatibleInProgress = false;
327 return false;
328 }
329
Andreas Huberea081b32016-08-17 15:57:47 -0700330 mIsJavaCompatibleInProgress = true;
331
Andreas Huber70a59e12016-08-16 12:57:01 -0700332 if (!Scope::isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700333 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700334 return false;
335 }
336
337 for (const auto &method : mMethods) {
338 if (!method->isJavaCompatible()) {
Andreas Huberea081b32016-08-17 15:57:47 -0700339 mIsJavaCompatibleInProgress = false;
Andreas Huber70a59e12016-08-16 12:57:01 -0700340 return false;
341 }
342 }
343
Andreas Huberea081b32016-08-17 15:57:47 -0700344 mIsJavaCompatibleInProgress = false;
345
Andreas Huber70a59e12016-08-16 12:57:01 -0700346 return true;
347}
348
Andreas Huberc9410c72016-07-28 12:18:40 -0700349} // namespace android
350