blob: dd5b0d2b257d0283ad0bd9990fa61dfaccea704e [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
19#include <hidl-util/Formatter.h>
20#include <android-base/logging.h>
21
22namespace android {
23
24RefType::RefType() {
25}
26
27/* return something like "T const *".
28 * The reason we don't return "const T *" is to handle cases like
29 * ref<ref<ref<T>>> t_3ptr;
30 * in this case the const's will get stacked on the left (const const const T *** t_3ptr)
31 * but in this implementation it would be clearer (T const* const* const* t_3ptr) */
Yifan Hong3b320f82016-11-01 15:15:54 -070032std::string RefType::getCppType(StorageMode /*mode*/, bool specifyNamespaces) const {
33 return mElementType->getCppStackType(specifyNamespaces)
34 + " const*";
Yifan Hongbf459bc2016-08-23 16:50:37 -070035}
36
37void RefType::addNamedTypesToSet(std::set<const FQName> &set) const {
38 mElementType->addNamedTypesToSet(set);
39}
40
41void RefType::emitReaderWriter(
42 Formatter &,
43 const std::string &,
44 const std::string &,
45 bool,
46 bool,
47 ErrorMode) const {
48 // RefType doesn't get read / written at this stage.
49 return;
50}
51
52void RefType::emitResolveReferences(
53 Formatter &out,
54 const std::string &name,
55 bool nameIsPointer,
56 const std::string &parcelObj,
57 bool parcelObjIsPointer,
58 bool isReader,
59 ErrorMode mode) const {
60
61 emitResolveReferencesEmbedded(
62 out,
63 0 /* depth */,
64 name,
65 name /* sanitizedName */,
66 nameIsPointer,
67 parcelObj,
68 parcelObjIsPointer,
69 isReader,
70 mode,
71 "", // parentName
72 ""); // offsetText
73}
74
75void RefType::emitResolveReferencesEmbedded(
76 Formatter &out,
77 size_t /* depth */,
78 const std::string &name,
79 const std::string &sanitizedName,
80 bool /*nameIsPointer*/,
81 const std::string &parcelObj,
82 bool parcelObjIsPointer,
83 bool isReader,
84 ErrorMode mode,
85 const std::string &parentName,
86 const std::string &offsetText) const {
87
Yifan Hong3b320f82016-11-01 15:15:54 -070088 std::string elementType = mElementType->getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -070089
Yifan Hong3b320f82016-11-01 15:15:54 -070090 std::string baseType = getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -070091
92 const std::string parcelObjDeref =
93 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
94
95 const std::string parcelObjPointer =
96 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
97
98 // as if nameIsPointer is false. Pointers are always pass by values,
99 // so name is always the pointer value itself. Hence nameIsPointer = false.
100 const std::string namePointer = "&" + name;
101 const std::string handleName = "_hidl_" + sanitizedName + "__ref_handle";
102 const std::string resolveBufName = "_hidl_" + sanitizedName + "__ref_resolve_buf";
103
104 bool isEmbedded = (!parentName.empty() && !offsetText.empty());
105
106 out << "size_t " << handleName << ";\n"
107 << "bool " << resolveBufName << ";\n\n";
108
109 out << "_hidl_err = ";
110
111 if (isReader) {
112 out << "::android::hardware::read"
113 << (isEmbedded ? "Embedded" : "")
114 << "ReferenceFromParcel<"
115 << elementType
116 << ">(const_cast<"
117 << baseType
Yifan Hong3b320f82016-11-01 15:15:54 -0700118 << " *>("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700119 << namePointer
120 << "),";
121 } else {
122 out << "::android::hardware::write"
123 << (isEmbedded ? "Embedded" : "")
124 << "ReferenceToParcel<"
125 << elementType
126 << ">("
127 << name
128 << ",";
129 }
130
131 out.indent();
132 out.indent();
133
134 out << (isReader ? parcelObjDeref : parcelObjPointer);
135 if(isEmbedded)
136 out << ",\n"
137 << parentName
138 << ",\n"
139 << offsetText;
140
141 out << ",\n&" + handleName;
142 out << ",\n&" + resolveBufName;
143 out << ");\n\n";
144
145 out.unindent();
146 out.unindent();
147
148 handleError(out, mode);
149
150 if(!mElementType->needsResolveReferences() && !mElementType->needsEmbeddedReadWrite())
151 return; // no need to deal with element type recursively.
152
153 out << "if(" << resolveBufName << ") {\n";
154 out.indent();
155
156 if(mElementType->needsEmbeddedReadWrite()) {
157 mElementType->emitReaderWriterEmbedded(
158 out,
159 0 /* depth */,
160 name,
Yifan Hong244e82d2016-11-11 11:13:57 -0800161 sanitizedName,
Yifan Hongbf459bc2016-08-23 16:50:37 -0700162 true /* nameIsPointer */, // for element type, name is a pointer.
163 parcelObj,
164 parcelObjIsPointer,
165 isReader,
166 mode,
167 handleName,
168 "0 /* parentOffset */");
169 }
170
171 if(mElementType->needsResolveReferences()) {
172 mElementType->emitResolveReferencesEmbedded(
173 out,
174 0 /* depth */,
175 "(*" + name + ")",
176 sanitizedName + "_deref",
177 false /* nameIsPointer */,
178 // must deref it and say false here, otherwise pointer to pointers don't work
179 parcelObj,
180 parcelObjIsPointer,
181 isReader,
182 mode,
183 handleName,
184 "0 /* parentOffset */");
185 }
186
187 out.unindent();
188 out << "}\n\n";
189}
190
Yifan Hongbf459bc2016-08-23 16:50:37 -0700191bool RefType::needsResolveReferences() const {
192 return true;
193}
194
195bool RefType::needsEmbeddedReadWrite() const {
196 return false;
197}
198
199bool RefType::resultNeedsDeref() const {
200 return false;
201}
202
203status_t RefType::emitVtsTypeDeclarations(Formatter &out) const {
204 out << "type: TYPE_REF\n" << "ref_value: {\n";
205 out.indent();
206 status_t err = mElementType->emitVtsTypeDeclarations(out);
207 if (err != OK) {
208 return err;
209 }
210 out.unindent();
211 out << "}\n";
212 return OK;
213}
214
215status_t RefType::emitVtsAttributeType(Formatter &out) const {
216 out << "type: TYPE_REF\n" << "ref_value: {\n";
217 out.indent();
218 status_t status = mElementType->emitVtsAttributeType(out);
219 if (status != OK) {
220 return status;
221 }
222 out.unindent();
223 out << "}\n";
224 return OK;
225}
226
227bool RefType::isJavaCompatible() const {
228 return false;
229}
230
231} // namespace android
232