1 /*
2 * Copyright 2018 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 <mapper-vts/3.0/MapperVts.h>
18
19 #include <VtsHalHidlTargetTestBase.h>
20
21 namespace android {
22 namespace hardware {
23 namespace graphics {
24 namespace mapper {
25 namespace V3_0 {
26 namespace vts {
27
Gralloc(const std::string & allocatorServiceName,const std::string & mapperServiceName,bool errOnFailure)28 Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
29 bool errOnFailure) {
30 if (errOnFailure) {
31 init(allocatorServiceName, mapperServiceName);
32 } else {
33 initNoErr(allocatorServiceName, mapperServiceName);
34 }
35 }
36
init(const std::string & allocatorServiceName,const std::string & mapperServiceName)37 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
38 mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
39 ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
40
41 mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
42 ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
43 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
44 }
45
initNoErr(const std::string & allocatorServiceName,const std::string & mapperServiceName)46 void Gralloc::initNoErr(const std::string& allocatorServiceName,
47 const std::string& mapperServiceName) {
48 mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
49
50 mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
51 if (mMapper.get()) {
52 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
53 }
54 }
55
~Gralloc()56 Gralloc::~Gralloc() {
57 for (auto bufferHandle : mClonedBuffers) {
58 auto buffer = const_cast<native_handle_t*>(bufferHandle);
59 native_handle_close(buffer);
60 native_handle_delete(buffer);
61 }
62 mClonedBuffers.clear();
63
64 for (auto bufferHandle : mImportedBuffers) {
65 auto buffer = const_cast<native_handle_t*>(bufferHandle);
66 EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
67 }
68 mImportedBuffers.clear();
69 }
70
getAllocator() const71 sp<IAllocator> Gralloc::getAllocator() const {
72 return mAllocator;
73 }
74
dumpDebugInfo()75 std::string Gralloc::dumpDebugInfo() {
76 std::string debugInfo;
77 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
78
79 return debugInfo;
80 }
81
cloneBuffer(const hidl_handle & rawHandle)82 const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
83 const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
84 EXPECT_NE(nullptr, bufferHandle);
85
86 if (bufferHandle) {
87 mClonedBuffers.insert(bufferHandle);
88 }
89
90 return bufferHandle;
91 }
92
allocate(const BufferDescriptor & descriptor,uint32_t count,bool import,uint32_t * outStride)93 std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
94 uint32_t count, bool import,
95 uint32_t* outStride) {
96 std::vector<const native_handle_t*> bufferHandles;
97 bufferHandles.reserve(count);
98 mAllocator->allocate(
99 descriptor, count,
100 [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
101 ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
102 ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
103
104 for (uint32_t i = 0; i < count; i++) {
105 if (import) {
106 ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(importBuffer(tmpBuffers[i])));
107 } else {
108 ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
109 }
110 }
111
112 if (outStride) {
113 *outStride = tmpStride;
114 }
115 });
116
117 if (::testing::Test::HasFatalFailure()) {
118 bufferHandles.clear();
119 }
120
121 return bufferHandles;
122 }
123
allocate(const IMapper::BufferDescriptorInfo & descriptorInfo,bool import,uint32_t * outStride)124 const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
125 bool import, uint32_t* outStride) {
126 BufferDescriptor descriptor = createDescriptor(descriptorInfo);
127 if (::testing::Test::HasFatalFailure()) {
128 return nullptr;
129 }
130
131 auto buffers = allocate(descriptor, 1, import, outStride);
132 if (::testing::Test::HasFatalFailure()) {
133 return nullptr;
134 }
135
136 return buffers[0];
137 }
138
getMapper() const139 sp<IMapper> Gralloc::getMapper() const {
140 return mMapper;
141 }
142
createDescriptor(const IMapper::BufferDescriptorInfo & descriptorInfo)143 BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
144 BufferDescriptor descriptor;
145 mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
146 ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
147 descriptor = tmpDescriptor;
148 });
149
150 return descriptor;
151 }
152
importBuffer(const hidl_handle & rawHandle)153 const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
154 const native_handle_t* bufferHandle = nullptr;
155 mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
156 ASSERT_EQ(Error::NONE, tmpError)
157 << "failed to import buffer %p" << rawHandle.getNativeHandle();
158 bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
159 });
160
161 if (bufferHandle) {
162 mImportedBuffers.insert(bufferHandle);
163 }
164
165 return bufferHandle;
166 }
167
freeBuffer(const native_handle_t * bufferHandle)168 void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
169 auto buffer = const_cast<native_handle_t*>(bufferHandle);
170
171 if (mImportedBuffers.erase(bufferHandle)) {
172 Error error = mMapper->freeBuffer(buffer);
173 ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
174 } else {
175 mClonedBuffers.erase(bufferHandle);
176 native_handle_close(buffer);
177 native_handle_delete(buffer);
178 }
179 }
180
lock(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int acquireFence,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)181 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
182 const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
183 int32_t* outBytesPerStride) {
184 auto buffer = const_cast<native_handle_t*>(bufferHandle);
185
186 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
187 hidl_handle acquireFenceHandle;
188 if (acquireFence >= 0) {
189 auto h = native_handle_init(acquireFenceStorage, 1, 0);
190 h->data[0] = acquireFence;
191 acquireFenceHandle = h;
192 }
193
194 *outBytesPerPixel = -1;
195 *outBytesPerStride = -1;
196
197 void* data = nullptr;
198 mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
199 [&](const auto& tmpError, const auto& tmpData, int32_t tmpBytesPerPixel,
200 int32_t tmpBytesPerStride) {
201 ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
202 data = tmpData;
203 *outBytesPerPixel = tmpBytesPerPixel;
204 *outBytesPerStride = tmpBytesPerStride;
205 });
206
207 if (acquireFence >= 0) {
208 close(acquireFence);
209 }
210
211 return data;
212 }
213
lockYCbCr(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int acquireFence)214 YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
215 const IMapper::Rect& accessRegion, int acquireFence) {
216 auto buffer = const_cast<native_handle_t*>(bufferHandle);
217
218 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
219 hidl_handle acquireFenceHandle;
220 if (acquireFence >= 0) {
221 auto h = native_handle_init(acquireFenceStorage, 1, 0);
222 h->data[0] = acquireFence;
223 acquireFenceHandle = h;
224 }
225
226 YCbCrLayout layout = {};
227 mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
228 [&](const auto& tmpError, const auto& tmpLayout) {
229 ASSERT_EQ(Error::NONE, tmpError)
230 << "failed to lockYCbCr buffer " << buffer;
231 layout = tmpLayout;
232 });
233
234 if (acquireFence >= 0) {
235 close(acquireFence);
236 }
237
238 return layout;
239 }
240
unlock(const native_handle_t * bufferHandle)241 int Gralloc::unlock(const native_handle_t* bufferHandle) {
242 auto buffer = const_cast<native_handle_t*>(bufferHandle);
243
244 int releaseFence = -1;
245 mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
246 ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
247
248 auto fenceHandle = tmpReleaseFence.getNativeHandle();
249 if (fenceHandle) {
250 ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
251 if (fenceHandle->numFds == 1) {
252 releaseFence = dup(fenceHandle->data[0]);
253 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
254 } else {
255 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
256 }
257 }
258 });
259
260 return releaseFence;
261 }
262
validateBufferSize(const native_handle_t * bufferHandle,const IMapper::BufferDescriptorInfo & descriptorInfo,uint32_t stride)263 bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
264 const IMapper::BufferDescriptorInfo& descriptorInfo,
265 uint32_t stride) {
266 auto buffer = const_cast<native_handle_t*>(bufferHandle);
267
268 Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
269 return error == Error::NONE;
270 }
271
getTransportSize(const native_handle_t * bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts)272 void Gralloc::getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
273 uint32_t* outNumInts) {
274 auto buffer = const_cast<native_handle_t*>(bufferHandle);
275
276 *outNumFds = 0;
277 *outNumInts = 0;
278 mMapper->getTransportSize(
279 buffer, [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
280 ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
281 ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
282 ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
283
284 *outNumFds = tmpNumFds;
285 *outNumInts = tmpNumInts;
286 });
287 }
288
isSupported(const IMapper::BufferDescriptorInfo & descriptorInfo)289 bool Gralloc::isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) {
290 bool supported = false;
291 mMapper->isSupported(descriptorInfo, [&](const auto& tmpError, const auto& tmpSupported) {
292 ASSERT_EQ(Error::NONE, tmpError) << "failed to check is supported";
293 supported = tmpSupported;
294 });
295 return supported;
296 }
297
298 } // namespace vts
299 } // namespace V3_0
300 } // namespace mapper
301 } // namespace graphics
302 } // namespace hardware
303 } // namespace android
304