| Andreas Huber | 1aec397 | 2016-08-26 09:26:32 -0700 | [diff] [blame] | 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 |  | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 17 | #include "Interface.h" | 
 | 18 |  | 
| Zhuoyao Zhang | ba7e6e9 | 2016-08-10 12:19:02 -0700 | [diff] [blame] | 19 | #include "Annotation.h" | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 20 | #include "Method.h" | 
 | 21 |  | 
| Iliyan Malchev | a72e0d2 | 2016-09-09 11:03:08 -0700 | [diff] [blame] | 22 | #include <hidl-util/Formatter.h> | 
| Zhuoyao Zhang | 864c771 | 2016-08-16 15:35:28 -0700 | [diff] [blame] | 23 | #include <iostream> | 
 | 24 |  | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 25 | namespace android { | 
 | 26 |  | 
| Andreas Huber | 9ed827c | 2016-08-22 12:31:13 -0700 | [diff] [blame] | 27 | Interface::Interface( | 
| Steven Moreland | d537ab0 | 2016-09-12 10:32:01 -0700 | [diff] [blame^] | 28 |         const char *localName, Interface *super, | 
 | 29 |         std::vector<Annotation *> *annotations) | 
| Andreas Huber | 9ed827c | 2016-08-22 12:31:13 -0700 | [diff] [blame] | 30 |     : Scope(localName), | 
 | 31 |       mSuperType(super), | 
| Steven Moreland | d537ab0 | 2016-09-12 10:32:01 -0700 | [diff] [blame^] | 32 |       mAnnotations(annotations), | 
| Andreas Huber | ea081b3 | 2016-08-17 15:57:47 -0700 | [diff] [blame] | 33 |       mIsJavaCompatibleInProgress(false) { | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 34 | } | 
 | 35 |  | 
 | 36 | void Interface::addMethod(Method *method) { | 
 | 37 |     mMethods.push_back(method); | 
 | 38 | } | 
 | 39 |  | 
| Andreas Huber | 6cb08cf | 2016-08-03 15:44:51 -0700 | [diff] [blame] | 40 | const Interface *Interface::superType() const { | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 41 |     return mSuperType; | 
 | 42 | } | 
 | 43 |  | 
| Andreas Huber | a2723d2 | 2016-07-29 15:36:07 -0700 | [diff] [blame] | 44 | bool Interface::isInterface() const { | 
 | 45 |     return true; | 
 | 46 | } | 
 | 47 |  | 
| Andreas Huber | 295ad30 | 2016-08-16 11:35:00 -0700 | [diff] [blame] | 48 | bool Interface::isBinder() const { | 
 | 49 |     return true; | 
 | 50 | } | 
 | 51 |  | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 52 | const std::vector<Method *> &Interface::methods() const { | 
 | 53 |     return mMethods; | 
 | 54 | } | 
 | 55 |  | 
| Steven Moreland | d537ab0 | 2016-09-12 10:32:01 -0700 | [diff] [blame^] | 56 | const std::vector<Annotation *> &Interface::annotations() const { | 
 | 57 |     return *mAnnotations; | 
| Zhuoyao Zhang | ba7e6e9 | 2016-08-10 12:19:02 -0700 | [diff] [blame] | 58 | } | 
 | 59 |  | 
| Steven Moreland | 4078631 | 2016-08-16 10:29:40 -0700 | [diff] [blame] | 60 | std::string Interface::getBaseName() const { | 
 | 61 |     // cut off the leading 'I'. | 
 | 62 |     return localName().substr(1); | 
 | 63 | } | 
 | 64 |  | 
| Steven Moreland | 979e099 | 2016-09-07 09:18:08 -0700 | [diff] [blame] | 65 | std::string Interface::getCppType(StorageMode mode, | 
 | 66 |                                   std::string *extra, | 
 | 67 |                                   bool specifyNamespaces) const { | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 68 |     extra->clear(); | 
| Steven Moreland | 979e099 | 2016-09-07 09:18:08 -0700 | [diff] [blame] | 69 |     const std::string base = | 
 | 70 |           std::string(specifyNamespaces ? "::android::" : "") | 
 | 71 |         + "sp<" | 
 | 72 |         + (specifyNamespaces ? fullName() : partialCppName()) | 
 | 73 |         + ">"; | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 74 |  | 
 | 75 |     switch (mode) { | 
 | 76 |         case StorageMode_Stack: | 
 | 77 |         case StorageMode_Result: | 
 | 78 |             return base; | 
 | 79 |  | 
 | 80 |         case StorageMode_Argument: | 
 | 81 |             return "const " + base + "&"; | 
 | 82 |     } | 
 | 83 | } | 
 | 84 |  | 
| Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 85 | std::string Interface::getJavaType() const { | 
 | 86 |     return fullJavaName(); | 
 | 87 | } | 
 | 88 |  | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 89 | void Interface::emitReaderWriter( | 
 | 90 |         Formatter &out, | 
 | 91 |         const std::string &name, | 
 | 92 |         const std::string &parcelObj, | 
 | 93 |         bool parcelObjIsPointer, | 
 | 94 |         bool isReader, | 
 | 95 |         ErrorMode mode) const { | 
 | 96 |     const std::string parcelObjDeref = | 
 | 97 |         parcelObj + (parcelObjIsPointer ? "->" : "."); | 
 | 98 |  | 
 | 99 |     if (isReader) { | 
| Andreas Huber | e7ff228 | 2016-08-16 13:50:03 -0700 | [diff] [blame] | 100 |         out << "{\n"; | 
 | 101 |         out.indent(); | 
 | 102 |  | 
| Iliyan Malchev | 549e259 | 2016-08-10 08:59:12 -0700 | [diff] [blame] | 103 |         const std::string binderName = "_hidl_" + name + "_binder"; | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 104 |  | 
| Andreas Huber | 8a82ff7 | 2016-08-04 10:29:39 -0700 | [diff] [blame] | 105 |         out << "::android::sp<::android::hardware::IBinder> " | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 106 |             << binderName << ";\n"; | 
 | 107 |  | 
| Iliyan Malchev | 549e259 | 2016-08-10 08:59:12 -0700 | [diff] [blame] | 108 |         out << "_hidl_err = "; | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 109 |         out << parcelObjDeref | 
 | 110 |             << "readNullableStrongBinder(&" | 
 | 111 |             << binderName | 
 | 112 |             << ");\n"; | 
 | 113 |  | 
 | 114 |         handleError(out, mode); | 
 | 115 |  | 
 | 116 |         out << name | 
 | 117 |             << " = " | 
| Steven Moreland | 4078631 | 2016-08-16 10:29:40 -0700 | [diff] [blame] | 118 |             << fqName().cppNamespace() | 
 | 119 |             << "::IHw" | 
 | 120 |             << getBaseName() | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 121 |             << "::asInterface(" | 
 | 122 |             << binderName | 
 | 123 |             << ");\n"; | 
| Andreas Huber | e7ff228 | 2016-08-16 13:50:03 -0700 | [diff] [blame] | 124 |  | 
 | 125 |         out.unindent(); | 
 | 126 |         out << "}\n\n"; | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 127 |     } else { | 
| Steven Moreland | 4078631 | 2016-08-16 10:29:40 -0700 | [diff] [blame] | 128 |  | 
 | 129 |         out << "if (" << name << "->isRemote()) {\n"; | 
 | 130 |         out.indent(); | 
| Iliyan Malchev | 549e259 | 2016-08-10 08:59:12 -0700 | [diff] [blame] | 131 |         out << "_hidl_err = "; | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 132 |         out << parcelObjDeref | 
 | 133 |             << "writeStrongBinder(" | 
| Steven Moreland | 4078631 | 2016-08-16 10:29:40 -0700 | [diff] [blame] | 134 |             << fqName().cppNamespace() | 
 | 135 |             << "::IHw" | 
 | 136 |             << getBaseName() | 
 | 137 |             << "::asBinder(static_cast<" | 
 | 138 |             << fqName().cppNamespace() | 
 | 139 |             << "::IHw" | 
 | 140 |             << getBaseName() | 
 | 141 |             << "*>(" | 
 | 142 |             << name << ".get()" | 
 | 143 |             << ")));\n"; | 
 | 144 |         out.unindent(); | 
 | 145 |         out << "} else {\n"; | 
 | 146 |         out.indent(); | 
 | 147 |         out << "_hidl_err = "; | 
 | 148 |         out << parcelObjDeref | 
 | 149 |             << "writeStrongBinder(" | 
 | 150 |             << "new " << fqName().cppNamespace() | 
 | 151 |             << "::Bn" << getBaseName() << " " | 
 | 152 |             << "(" << name <<"));\n"; | 
 | 153 |         out.unindent(); | 
 | 154 |         out << "}\n"; | 
| Andreas Huber | 881227d | 2016-08-02 14:20:21 -0700 | [diff] [blame] | 155 |         handleError(out, mode); | 
 | 156 |     } | 
 | 157 | } | 
 | 158 |  | 
| Andreas Huber | 2831d51 | 2016-08-15 09:33:47 -0700 | [diff] [blame] | 159 | void Interface::emitJavaReaderWriter( | 
 | 160 |         Formatter &out, | 
 | 161 |         const std::string &parcelObj, | 
 | 162 |         const std::string &argName, | 
 | 163 |         bool isReader) const { | 
 | 164 |     if (isReader) { | 
 | 165 |         out << fullJavaName() | 
 | 166 |             << ".asInterface(" | 
 | 167 |             << parcelObj | 
 | 168 |             << ".readStrongBinder());\n"; | 
 | 169 |     } else { | 
 | 170 |         out << parcelObj | 
 | 171 |             << ".writeStrongBinder(" | 
 | 172 |             << argName | 
 | 173 |             << " == null ? null : " | 
 | 174 |             << argName | 
 | 175 |             << ".asBinder());\n"; | 
 | 176 |     } | 
 | 177 | } | 
 | 178 |  | 
| Zhuoyao Zhang | 864c771 | 2016-08-16 15:35:28 -0700 | [diff] [blame] | 179 | status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const { | 
 | 180 |     for (const auto &type : getSubTypes()) { | 
 | 181 |         out << "attribute: {\n"; | 
 | 182 |         out.indent(); | 
 | 183 |         status_t status = type->emitVtsTypeDeclarations(out); | 
 | 184 |         if (status != OK) { | 
 | 185 |             return status; | 
 | 186 |         } | 
 | 187 |         out.unindent(); | 
 | 188 |         out << "}\n\n"; | 
 | 189 |     } | 
 | 190 |     return OK; | 
 | 191 | } | 
 | 192 |  | 
 | 193 | status_t Interface::emitVtsMethodDeclaration(Formatter &out) const { | 
 | 194 |     for (const auto &method : mMethods) { | 
 | 195 |         out << "api: {\n"; | 
 | 196 |         out.indent(); | 
 | 197 |         out << "name: \"" << method->name() << "\"\n"; | 
 | 198 |         // Generate declaration for each return value. | 
 | 199 |         for (const auto &result : method->results()) { | 
 | 200 |             out << "return_type_hidl: {\n"; | 
 | 201 |             out.indent(); | 
 | 202 |             status_t status = result->type().emitVtsAttributeType(out); | 
 | 203 |             if (status != OK) { | 
 | 204 |                 return status; | 
 | 205 |             } | 
 | 206 |             out.unindent(); | 
 | 207 |             out << "}\n"; | 
 | 208 |         } | 
 | 209 |         // Generate declaration for each input argument | 
 | 210 |         for (const auto &arg : method->args()) { | 
 | 211 |             out << "arg: {\n"; | 
 | 212 |             out.indent(); | 
 | 213 |             status_t status = arg->type().emitVtsAttributeType(out); | 
 | 214 |             if (status != OK) { | 
 | 215 |                 return status; | 
 | 216 |             } | 
 | 217 |             out.unindent(); | 
 | 218 |             out << "}\n"; | 
 | 219 |         } | 
 | 220 |         // Generate declaration for each annotation. | 
| Steven Moreland | d537ab0 | 2016-09-12 10:32:01 -0700 | [diff] [blame^] | 221 |         for (const auto &annotation : method->annotations()) { | 
| Zhuoyao Zhang | 864c771 | 2016-08-16 15:35:28 -0700 | [diff] [blame] | 222 |             out << "callflow: {\n"; | 
 | 223 |             out.indent(); | 
| Steven Moreland | d537ab0 | 2016-09-12 10:32:01 -0700 | [diff] [blame^] | 224 |             std::string name = annotation->name(); | 
| Zhuoyao Zhang | 864c771 | 2016-08-16 15:35:28 -0700 | [diff] [blame] | 225 |             if (name == "entry") { | 
 | 226 |                 out << "entry: true\n"; | 
 | 227 |             } else if (name == "exit") { | 
 | 228 |                 out << "exit: true\n"; | 
 | 229 |             } else if (name == "callflow") { | 
| Steven Moreland | d537ab0 | 2016-09-12 10:32:01 -0700 | [diff] [blame^] | 230 |                 const AnnotationParam *param = | 
 | 231 |                         annotation->getParam("next"); | 
 | 232 |                 if (param != nullptr) { | 
 | 233 |                     for (auto value : *param->getValues()) { | 
 | 234 |                         out << "next: " << value << "\n"; | 
 | 235 |                     } | 
| Zhuoyao Zhang | 864c771 | 2016-08-16 15:35:28 -0700 | [diff] [blame] | 236 |                 } | 
 | 237 |             } else { | 
 | 238 |                 std::cerr << "Invalid annotation '" | 
 | 239 |                           << name << "' for method: " << method->name() | 
 | 240 |                           << ". Should be one of: entry, exit, callflow. \n"; | 
 | 241 |                 return UNKNOWN_ERROR; | 
 | 242 |             } | 
 | 243 |             out.unindent(); | 
 | 244 |             out << "}\n"; | 
 | 245 |         } | 
 | 246 |         out.unindent(); | 
 | 247 |         out << "}\n\n"; | 
 | 248 |     } | 
 | 249 |     return OK; | 
 | 250 | } | 
 | 251 |  | 
 | 252 | status_t Interface::emitVtsAttributeType(Formatter &out) const { | 
| Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 253 |     out << "type: TYPE_HIDL_CALLBACK\n" | 
 | 254 |         << "predefined_type: \"" | 
 | 255 |         << localName() | 
| Zhuoyao Zhang | 1993352 | 2016-08-29 15:06:38 -0700 | [diff] [blame] | 256 |         << "\"\n" | 
 | 257 |         << "is_callback: true\n"; | 
| Zhuoyao Zhang | 5158db4 | 2016-08-10 10:25:20 -0700 | [diff] [blame] | 258 |     return OK; | 
 | 259 | } | 
 | 260 |  | 
| Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 261 | bool Interface::isJavaCompatible() const { | 
| Andreas Huber | ea081b3 | 2016-08-17 15:57:47 -0700 | [diff] [blame] | 262 |     if (mIsJavaCompatibleInProgress) { | 
 | 263 |         // We're currently trying to determine if this Interface is | 
 | 264 |         // java-compatible and something is referencing this interface through | 
 | 265 |         // one of its methods. Assume we'll ultimately succeed, if we were wrong | 
 | 266 |         // the original invocation of Interface::isJavaCompatible() will then | 
 | 267 |         // return the correct "false" result. | 
 | 268 |         return true; | 
 | 269 |     } | 
 | 270 |  | 
| Andreas Huber | 0fa9e39 | 2016-08-31 09:05:44 -0700 | [diff] [blame] | 271 |     if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) { | 
 | 272 |         mIsJavaCompatibleInProgress = false; | 
 | 273 |         return false; | 
 | 274 |     } | 
 | 275 |  | 
| Andreas Huber | ea081b3 | 2016-08-17 15:57:47 -0700 | [diff] [blame] | 276 |     mIsJavaCompatibleInProgress = true; | 
 | 277 |  | 
| Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 278 |     if (!Scope::isJavaCompatible()) { | 
| Andreas Huber | ea081b3 | 2016-08-17 15:57:47 -0700 | [diff] [blame] | 279 |         mIsJavaCompatibleInProgress = false; | 
| Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 280 |         return false; | 
 | 281 |     } | 
 | 282 |  | 
 | 283 |     for (const auto &method : mMethods) { | 
 | 284 |         if (!method->isJavaCompatible()) { | 
| Andreas Huber | ea081b3 | 2016-08-17 15:57:47 -0700 | [diff] [blame] | 285 |             mIsJavaCompatibleInProgress = false; | 
| Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 286 |             return false; | 
 | 287 |         } | 
 | 288 |     } | 
 | 289 |  | 
| Andreas Huber | ea081b3 | 2016-08-17 15:57:47 -0700 | [diff] [blame] | 290 |     mIsJavaCompatibleInProgress = false; | 
 | 291 |  | 
| Andreas Huber | 70a59e1 | 2016-08-16 12:57:01 -0700 | [diff] [blame] | 292 |     return true; | 
 | 293 | } | 
 | 294 |  | 
| Andreas Huber | c9410c7 | 2016-07-28 12:18:40 -0700 | [diff] [blame] | 295 | }  // namespace android | 
 | 296 |  |