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
MemoryType(Scope * parent)26 MemoryType::MemoryType(Scope* parent) : Type(parent, "memory") {}
27
getCppType(StorageMode mode,bool specifyNamespaces) const28 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
typeName() const46 std::string MemoryType::typeName() const {
47 return "memory";
48 }
49
getVtsType() const50 std::string MemoryType::getVtsType() const {
51 return "TYPE_HIDL_MEMORY";
52 }
53
getJavaType(bool) const54 std::string MemoryType::getJavaType(bool /* forInitializer */) const {
55 return "android.os.HidlMemory";
56 }
57
getJavaSuffix() const58 std::string MemoryType::getJavaSuffix() const {
59 return "HidlMemory";
60 }
61
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const62 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
emitJavaFieldDefaultInitialValue(Formatter & out,const std::string & declaredFieldName) const68 void MemoryType::emitJavaFieldDefaultInitialValue(
69 Formatter &out, const std::string &declaredFieldName) const {
70 out << declaredFieldName
71 << " = null;\n";
72 }
73
emitJavaFieldReaderWriter(Formatter & out,size_t,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const74 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
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader) const111 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
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const140 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
emitReaderWriterEmbedded(Formatter & out,size_t,const std::string & name,const std::string &,bool nameIsPointer,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode,const std::string & parentName,const std::string & offsetText) const195 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
needsEmbeddedReadWrite() const222 bool MemoryType::needsEmbeddedReadWrite() const {
223 return true;
224 }
225
resultNeedsDeref() const226 bool MemoryType::resultNeedsDeref() const {
227 return true;
228 }
229
isMemory() const230 bool MemoryType::isMemory() const {
231 return true;
232 }
233
deepIsJavaCompatible(std::unordered_set<const Type * > *) const234 bool MemoryType::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const {
235 return true;
236 }
237
238 static HidlTypeAssertion assertion("hidl_memory", 40 /* size */);
getAlignmentAndSize(size_t * align,size_t * size) const239 void MemoryType::getAlignmentAndSize(size_t *align, size_t *size) const {
240 *align = 8; // hidl_memory
241 *size = assertion.size();
242 }
243
emitVtsTypeDeclarations(Formatter & out) const244 void MemoryType::emitVtsTypeDeclarations(Formatter& out) const {
245 out << "type: " << getVtsType() << "\n";
246 }
247
248 } // namespace android
249
250