blob: 994739927e0016ed40094b57fd860575b5303664 [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
Timur Iskhakov63f39902017-08-29 15:47:29 -070027RefType::RefType(Scope* parent) : TemplatedType(parent) {}
Yifan Hongbf459bc2016-08-23 16:50:37 -070028
Timur Iskhakov3f1d26e2017-08-30 15:35:53 -070029std::string RefType::templatedTypeName() const {
30 return "ref";
Steven Moreland30bb6a82016-11-30 09:18:34 -080031}
32
Timur Iskhakovb58f4182017-08-29 15:19:24 -070033std::vector<const Reference<Type>*> RefType::getStrongReferences() const {
Timur Iskhakov40731af2017-08-24 14:18:35 -070034 return {};
35}
36
Zhuoyao Zhange9667842017-01-19 12:35:32 -080037std::string RefType::getVtsType() const {
38 return "TYPE_REF";
39}
40
41std::string RefType::getVtsValueName() const {
42 return "ref_value";
43}
44
Timur Iskhakov24e605b2017-08-30 14:02:55 -070045bool RefType::isCompatibleElementType(const Type* elementType) const {
Yifan Hong51f9c8a2016-12-05 18:47:33 -080046 if (elementType->isScalar()) {
47 return true;
48 }
49 if (elementType->isString()) {
50 return true;
51 }
52 if (elementType->isEnum()) {
53 return true;
54 }
55 if (elementType->isBitField()) {
56 return true;
57 }
Timur Iskhakov24e605b2017-08-30 14:02:55 -070058 if (elementType->isCompoundType() &&
59 static_cast<const CompoundType*>(elementType)->style() == CompoundType::STYLE_STRUCT) {
Yifan Hong51f9c8a2016-12-05 18:47:33 -080060 return true;
61 }
62 if (elementType->isTemplatedType()) {
Timur Iskhakov24e605b2017-08-30 14:02:55 -070063 return this->isCompatibleElementType(
64 static_cast<const TemplatedType*>(elementType)->getElementType());
Yifan Hong51f9c8a2016-12-05 18:47:33 -080065 }
66 if (elementType->isArray()) {
Timur Iskhakov24e605b2017-08-30 14:02:55 -070067 return this->isCompatibleElementType(
68 static_cast<const ArrayType*>(elementType)->getElementType());
Yifan Hong51f9c8a2016-12-05 18:47:33 -080069 }
70 return false;
Steven Moreland30bb6a82016-11-30 09:18:34 -080071}
72
Yifan Hongbf459bc2016-08-23 16:50:37 -070073/* return something like "T const *".
74 * The reason we don't return "const T *" is to handle cases like
75 * ref<ref<ref<T>>> t_3ptr;
76 * in this case the const's will get stacked on the left (const const const T *** t_3ptr)
77 * but in this implementation it would be clearer (T const* const* const* t_3ptr) */
Yifan Hong3b320f82016-11-01 15:15:54 -070078std::string RefType::getCppType(StorageMode /*mode*/, bool specifyNamespaces) const {
79 return mElementType->getCppStackType(specifyNamespaces)
80 + " const*";
Yifan Hongbf459bc2016-08-23 16:50:37 -070081}
82
Yifan Hongbf459bc2016-08-23 16:50:37 -070083void RefType::emitReaderWriter(
84 Formatter &,
85 const std::string &,
86 const std::string &,
87 bool,
88 bool,
89 ErrorMode) const {
90 // RefType doesn't get read / written at this stage.
91 return;
92}
93
94void RefType::emitResolveReferences(
95 Formatter &out,
96 const std::string &name,
97 bool nameIsPointer,
98 const std::string &parcelObj,
99 bool parcelObjIsPointer,
100 bool isReader,
101 ErrorMode mode) const {
102
103 emitResolveReferencesEmbedded(
104 out,
105 0 /* depth */,
106 name,
107 name /* sanitizedName */,
108 nameIsPointer,
109 parcelObj,
110 parcelObjIsPointer,
111 isReader,
112 mode,
113 "", // parentName
114 ""); // offsetText
115}
116
117void RefType::emitResolveReferencesEmbedded(
118 Formatter &out,
119 size_t /* depth */,
120 const std::string &name,
121 const std::string &sanitizedName,
122 bool /*nameIsPointer*/,
123 const std::string &parcelObj,
124 bool parcelObjIsPointer,
125 bool isReader,
126 ErrorMode mode,
127 const std::string &parentName,
128 const std::string &offsetText) const {
129
Yifan Hong3b320f82016-11-01 15:15:54 -0700130 std::string elementType = mElementType->getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700131
Yifan Hong3b320f82016-11-01 15:15:54 -0700132 std::string baseType = getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700133
134 const std::string parcelObjDeref =
135 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
136
137 const std::string parcelObjPointer =
138 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
139
140 // as if nameIsPointer is false. Pointers are always pass by values,
141 // so name is always the pointer value itself. Hence nameIsPointer = false.
142 const std::string namePointer = "&" + name;
143 const std::string handleName = "_hidl_" + sanitizedName + "__ref_handle";
144 const std::string resolveBufName = "_hidl_" + sanitizedName + "__ref_resolve_buf";
145
146 bool isEmbedded = (!parentName.empty() && !offsetText.empty());
147
148 out << "size_t " << handleName << ";\n"
149 << "bool " << resolveBufName << ";\n\n";
150
151 out << "_hidl_err = ";
152
153 if (isReader) {
154 out << "::android::hardware::read"
155 << (isEmbedded ? "Embedded" : "")
156 << "ReferenceFromParcel<"
157 << elementType
158 << ">(const_cast<"
159 << baseType
Yifan Hong3b320f82016-11-01 15:15:54 -0700160 << " *>("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700161 << namePointer
162 << "),";
163 } else {
164 out << "::android::hardware::write"
165 << (isEmbedded ? "Embedded" : "")
166 << "ReferenceToParcel<"
167 << elementType
168 << ">("
169 << name
170 << ",";
171 }
172
173 out.indent();
174 out.indent();
175
176 out << (isReader ? parcelObjDeref : parcelObjPointer);
177 if(isEmbedded)
178 out << ",\n"
179 << parentName
180 << ",\n"
181 << offsetText;
182
183 out << ",\n&" + handleName;
184 out << ",\n&" + resolveBufName;
185 out << ");\n\n";
186
187 out.unindent();
188 out.unindent();
189
190 handleError(out, mode);
191
192 if(!mElementType->needsResolveReferences() && !mElementType->needsEmbeddedReadWrite())
193 return; // no need to deal with element type recursively.
194
195 out << "if(" << resolveBufName << ") {\n";
196 out.indent();
197
198 if(mElementType->needsEmbeddedReadWrite()) {
199 mElementType->emitReaderWriterEmbedded(
200 out,
201 0 /* depth */,
202 name,
Yifan Hong244e82d2016-11-11 11:13:57 -0800203 sanitizedName,
Yifan Hongbf459bc2016-08-23 16:50:37 -0700204 true /* nameIsPointer */, // for element type, name is a pointer.
205 parcelObj,
206 parcelObjIsPointer,
207 isReader,
208 mode,
209 handleName,
210 "0 /* parentOffset */");
211 }
212
213 if(mElementType->needsResolveReferences()) {
214 mElementType->emitResolveReferencesEmbedded(
215 out,
216 0 /* depth */,
217 "(*" + name + ")",
218 sanitizedName + "_deref",
219 false /* nameIsPointer */,
220 // must deref it and say false here, otherwise pointer to pointers don't work
221 parcelObj,
222 parcelObjIsPointer,
223 isReader,
224 mode,
225 handleName,
226 "0 /* parentOffset */");
227 }
228
229 out.unindent();
230 out << "}\n\n";
231}
232
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700233bool RefType::deepNeedsResolveReferences(std::unordered_set<const Type*>* /* visited */) const {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700234 return true;
235}
236
237bool RefType::needsEmbeddedReadWrite() const {
238 return false;
239}
240
241bool RefType::resultNeedsDeref() const {
242 return false;
243}
244
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700245bool RefType::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700246 return false;
247}
248
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700249bool RefType::deepContainsPointer(std::unordered_set<const Type*>* /* visited */) const {
Andreas Huber60d3b222017-03-30 09:10:56 -0700250 return true;
251}
252
Yifan Hongbf459bc2016-08-23 16:50:37 -0700253} // namespace android
254