blob: b43c8325bf3ce5960ed8a65a9b55ee112115915a [file] [log] [blame]
Yifan Hongbf459bc2016-08-23 16:50:37 -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
17#include "RefType.h"
18
Yifan Hong51f9c8a2016-12-05 18:47:33 -080019#include "ArrayType.h"
20#include "CompoundType.h"
21
Yifan Hongbf459bc2016-08-23 16:50:37 -070022#include <hidl-util/Formatter.h>
23#include <android-base/logging.h>
24
25namespace android {
26
27RefType::RefType() {
28}
29
Steven Moreland30bb6a82016-11-30 09:18:34 -080030std::string RefType::typeName() const {
31 return "ref" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
32}
33
Zhuoyao Zhange9667842017-01-19 12:35:32 -080034std::string RefType::getVtsType() const {
35 return "TYPE_REF";
36}
37
38std::string RefType::getVtsValueName() const {
39 return "ref_value";
40}
41
Steven Moreland30bb6a82016-11-30 09:18:34 -080042bool RefType::isCompatibleElementType(Type *elementType) const {
Yifan Hong51f9c8a2016-12-05 18:47:33 -080043 if (elementType->isScalar()) {
44 return true;
45 }
46 if (elementType->isString()) {
47 return true;
48 }
49 if (elementType->isEnum()) {
50 return true;
51 }
52 if (elementType->isBitField()) {
53 return true;
54 }
55 if (elementType->isCompoundType()
56 && static_cast<CompoundType *>(elementType)->style() == CompoundType::STYLE_STRUCT) {
57 return true;
58 }
59 if (elementType->isTemplatedType()) {
60 return this->isCompatibleElementType(static_cast<TemplatedType *>(elementType)->getElementType());
61 }
62 if (elementType->isArray()) {
63 return this->isCompatibleElementType(static_cast<ArrayType *>(elementType)->getElementType());
64 }
65 return false;
Steven Moreland30bb6a82016-11-30 09:18:34 -080066}
67
Yifan Hongbf459bc2016-08-23 16:50:37 -070068/* return something like "T const *".
69 * The reason we don't return "const T *" is to handle cases like
70 * ref<ref<ref<T>>> t_3ptr;
71 * in this case the const's will get stacked on the left (const const const T *** t_3ptr)
72 * but in this implementation it would be clearer (T const* const* const* t_3ptr) */
Yifan Hong3b320f82016-11-01 15:15:54 -070073std::string RefType::getCppType(StorageMode /*mode*/, bool specifyNamespaces) const {
74 return mElementType->getCppStackType(specifyNamespaces)
75 + " const*";
Yifan Hongbf459bc2016-08-23 16:50:37 -070076}
77
Yifan Hongbf459bc2016-08-23 16:50:37 -070078void RefType::emitReaderWriter(
79 Formatter &,
80 const std::string &,
81 const std::string &,
82 bool,
83 bool,
84 ErrorMode) const {
85 // RefType doesn't get read / written at this stage.
86 return;
87}
88
89void RefType::emitResolveReferences(
90 Formatter &out,
91 const std::string &name,
92 bool nameIsPointer,
93 const std::string &parcelObj,
94 bool parcelObjIsPointer,
95 bool isReader,
96 ErrorMode mode) const {
97
98 emitResolveReferencesEmbedded(
99 out,
100 0 /* depth */,
101 name,
102 name /* sanitizedName */,
103 nameIsPointer,
104 parcelObj,
105 parcelObjIsPointer,
106 isReader,
107 mode,
108 "", // parentName
109 ""); // offsetText
110}
111
112void RefType::emitResolveReferencesEmbedded(
113 Formatter &out,
114 size_t /* depth */,
115 const std::string &name,
116 const std::string &sanitizedName,
117 bool /*nameIsPointer*/,
118 const std::string &parcelObj,
119 bool parcelObjIsPointer,
120 bool isReader,
121 ErrorMode mode,
122 const std::string &parentName,
123 const std::string &offsetText) const {
124
Yifan Hong3b320f82016-11-01 15:15:54 -0700125 std::string elementType = mElementType->getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700126
Yifan Hong3b320f82016-11-01 15:15:54 -0700127 std::string baseType = getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700128
129 const std::string parcelObjDeref =
130 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
131
132 const std::string parcelObjPointer =
133 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
134
135 // as if nameIsPointer is false. Pointers are always pass by values,
136 // so name is always the pointer value itself. Hence nameIsPointer = false.
137 const std::string namePointer = "&" + name;
138 const std::string handleName = "_hidl_" + sanitizedName + "__ref_handle";
139 const std::string resolveBufName = "_hidl_" + sanitizedName + "__ref_resolve_buf";
140
141 bool isEmbedded = (!parentName.empty() && !offsetText.empty());
142
143 out << "size_t " << handleName << ";\n"
144 << "bool " << resolveBufName << ";\n\n";
145
146 out << "_hidl_err = ";
147
148 if (isReader) {
149 out << "::android::hardware::read"
150 << (isEmbedded ? "Embedded" : "")
151 << "ReferenceFromParcel<"
152 << elementType
153 << ">(const_cast<"
154 << baseType
Yifan Hong3b320f82016-11-01 15:15:54 -0700155 << " *>("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700156 << namePointer
157 << "),";
158 } else {
159 out << "::android::hardware::write"
160 << (isEmbedded ? "Embedded" : "")
161 << "ReferenceToParcel<"
162 << elementType
163 << ">("
164 << name
165 << ",";
166 }
167
168 out.indent();
169 out.indent();
170
171 out << (isReader ? parcelObjDeref : parcelObjPointer);
172 if(isEmbedded)
173 out << ",\n"
174 << parentName
175 << ",\n"
176 << offsetText;
177
178 out << ",\n&" + handleName;
179 out << ",\n&" + resolveBufName;
180 out << ");\n\n";
181
182 out.unindent();
183 out.unindent();
184
185 handleError(out, mode);
186
187 if(!mElementType->needsResolveReferences() && !mElementType->needsEmbeddedReadWrite())
188 return; // no need to deal with element type recursively.
189
190 out << "if(" << resolveBufName << ") {\n";
191 out.indent();
192
193 if(mElementType->needsEmbeddedReadWrite()) {
194 mElementType->emitReaderWriterEmbedded(
195 out,
196 0 /* depth */,
197 name,
Yifan Hong244e82d2016-11-11 11:13:57 -0800198 sanitizedName,
Yifan Hongbf459bc2016-08-23 16:50:37 -0700199 true /* nameIsPointer */, // for element type, name is a pointer.
200 parcelObj,
201 parcelObjIsPointer,
202 isReader,
203 mode,
204 handleName,
205 "0 /* parentOffset */");
206 }
207
208 if(mElementType->needsResolveReferences()) {
209 mElementType->emitResolveReferencesEmbedded(
210 out,
211 0 /* depth */,
212 "(*" + name + ")",
213 sanitizedName + "_deref",
214 false /* nameIsPointer */,
215 // must deref it and say false here, otherwise pointer to pointers don't work
216 parcelObj,
217 parcelObjIsPointer,
218 isReader,
219 mode,
220 handleName,
221 "0 /* parentOffset */");
222 }
223
224 out.unindent();
225 out << "}\n\n";
226}
227
Yifan Hongbf459bc2016-08-23 16:50:37 -0700228bool RefType::needsResolveReferences() const {
229 return true;
230}
231
232bool RefType::needsEmbeddedReadWrite() const {
233 return false;
234}
235
236bool RefType::resultNeedsDeref() const {
237 return false;
238}
239
Yifan Hongbf459bc2016-08-23 16:50:37 -0700240bool RefType::isJavaCompatible() const {
241 return false;
242}
243
Andreas Huber60d3b222017-03-30 09:10:56 -0700244bool RefType::containsPointer() const {
245 return true;
246}
247
Yifan Hongbf459bc2016-08-23 16:50:37 -0700248} // namespace android
249