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 "MemoryType.h" 18 19 #include "HidlTypeAssertion.h" 20 21 #include <hidl-util/Formatter.h> 22 #include <android-base/logging.h> 23 24 namespace android { 25 26 MemoryType::MemoryType(Scope* parent) : Type(parent, "memory") {} 27 28 std::string MemoryType::getCppType(StorageMode mode, 29 bool specifyNamespaces) const { 30 const std::string base = 31 std::string(specifyNamespaces ? "::android::hardware::" : "") 32 + "hidl_memory"; 33 34 switch (mode) { 35 case StorageMode_Stack: 36 return base; 37 38 case StorageMode_Argument: 39 return "const " + base + "&"; 40 41 case StorageMode_Result: 42 return "const " + base + "*"; 43 } 44 } 45 46 std::string MemoryType::typeName() const { 47 return "memory"; 48 } 49 50 std::string MemoryType::getVtsType() const { 51 return "TYPE_HIDL_MEMORY"; 52 } 53 54 std::string MemoryType::getJavaType(bool /* forInitializer */) const { 55 return "android.os.HidlMemory"; 56 } 57 58 std::string MemoryType::getJavaSuffix() const { 59 return "HidlMemory"; 60 } 61 62 void MemoryType::emitJavaFieldInitializer( 63 Formatter &out, const std::string &fieldName) const { 64 const std::string fieldDeclaration = getJavaType(false) + " " + fieldName; 65 emitJavaFieldDefaultInitialValue(out, fieldDeclaration); 66 } 67 68 void MemoryType::emitJavaFieldDefaultInitialValue( 69 Formatter &out, const std::string &declaredFieldName) const { 70 out << declaredFieldName 71 << " = null;\n"; 72 } 73 74 void MemoryType::emitJavaFieldReaderWriter(Formatter& out, 75 size_t /* depth */, 76 const std::string& parcelName, 77 const std::string& blobName, 78 const std::string& fieldName, 79 const std::string& offset, 80 bool isReader) const { 81 if (isReader) { 82 out << "try {\n"; 83 out.indent(); 84 out << fieldName 85 << " = " 86 << parcelName 87 << ".readEmbeddedHidlMemory(\n"; 88 89 out << blobName << ".getFieldHandle(" << offset << "),\n" 90 << blobName << ".handle(),\n" 91 << offset 92 << ").dup();\n"; 93 out.unindent(); 94 out << "} catch (java.io.IOException e) {\n"; 95 out.indent(); 96 out << "throw new RuntimeException(e);\n"; 97 out.unindent(); 98 out << "}\n"; 99 100 return; 101 } 102 103 out << blobName 104 << ".putHidlMemory(" 105 << offset 106 << ", " 107 << fieldName 108 << ");\n"; 109 } 110 111 void MemoryType::emitJavaReaderWriter(Formatter& out, 112 const std::string& parcelObj, 113 const std::string& argName, 114 bool isReader) const { 115 if (isReader) { 116 // The weird-looking lambda code below is intended to replace an 117 // IOException with a RuntimeException within an expression context. 118 out << "((java.util.function.Function<android.os.HwParcel, android.os.HidlMemory>)" 119 " _parcel -> {\n"; 120 out.indent(); 121 out << "try {\n"; 122 out.indent(); 123 out << "return _parcel.readHidlMemory().dup();\n"; 124 out.unindent(); 125 out << "} catch (java.io.IOException e) {\n"; 126 out.indent(); 127 out << "throw new RuntimeException(e);\n"; 128 out.unindent(); 129 out << "}\n"; 130 out.unindent(); 131 out << "}).apply(" << parcelObj << ");\n"; 132 } else { 133 out << parcelObj 134 << ".writeHidlMemory(" 135 << argName 136 << ");\n"; 137 } 138 } 139 140 void MemoryType::emitReaderWriter( 141 Formatter &out, 142 const std::string &name, 143 const std::string &parcelObj, 144 bool parcelObjIsPointer, 145 bool isReader, 146 ErrorMode mode) const { 147 const std::string parentName = "_hidl_" + name + "_parent"; 148 out << "size_t " << parentName << ";\n\n"; 149 150 const std::string parcelObjDeref = 151 parcelObj + (parcelObjIsPointer ? "->" : "."); 152 153 if (isReader) { 154 out << "_hidl_err = " 155 << parcelObjDeref 156 << "readBuffer(" 157 << "sizeof(*" 158 << name 159 << "), &" 160 << parentName 161 << ", " 162 << " reinterpret_cast<const void **>(" 163 << "&" << name 164 << "));\n\n"; 165 166 handleError(out, mode); 167 } else { 168 out << "_hidl_err = " 169 << parcelObjDeref 170 << "writeBuffer(&" 171 << name 172 << ", sizeof(" 173 << name 174 << "), &" 175 << parentName 176 << ");\n"; 177 178 handleError(out, mode); 179 } 180 181 emitReaderWriterEmbedded( 182 out, 183 0 /* depth */, 184 name, 185 name /* sanitizedName */, 186 isReader /* nameIsPointer */, 187 parcelObj, 188 parcelObjIsPointer, 189 isReader, 190 mode, 191 parentName, 192 "0 /* parentOffset */"); 193 } 194 195 void MemoryType::emitReaderWriterEmbedded( 196 Formatter &out, 197 size_t /* depth */, 198 const std::string &name, 199 const std::string & /*sanitizedName*/, 200 bool nameIsPointer, 201 const std::string &parcelObj, 202 bool parcelObjIsPointer, 203 bool isReader, 204 ErrorMode mode, 205 const std::string &parentName, 206 const std::string &offsetText) const { 207 emitReaderWriterEmbeddedForTypeName( 208 out, 209 name, 210 nameIsPointer, 211 parcelObj, 212 parcelObjIsPointer, 213 isReader, 214 mode, 215 parentName, 216 offsetText, 217 "::android::hardware::hidl_memory", 218 "" /* childName */, 219 "::android::hardware"); 220 } 221 222 bool MemoryType::needsEmbeddedReadWrite() const { 223 return true; 224 } 225 226 bool MemoryType::resultNeedsDeref() const { 227 return true; 228 } 229 230 bool MemoryType::isMemory() const { 231 return true; 232 } 233 234 bool MemoryType::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const { 235 return true; 236 } 237 238 static HidlTypeAssertion assertion("hidl_memory", 40 /* size */); 239 void MemoryType::getAlignmentAndSize(size_t *align, size_t *size) const { 240 *align = 8; // hidl_memory 241 *size = assertion.size(); 242 } 243 244 void MemoryType::emitVtsTypeDeclarations(Formatter& out) const { 245 out << "type: " << getVtsType() << "\n"; 246 } 247 248 } // namespace android 249 250