blob: c470a4aca09525b24f8661bb5bfeb0da9ca2395a [file] [log] [blame]
Marissa Wallbd1ca512018-12-30 10:59:41 -08001/*
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
Alec Mouri18339992022-04-04 21:53:57 +000017#include <android-base/properties.h>
Marissa Wallbd1ca512018-12-30 10:59:41 -080018#include <mapper-vts/3.0/MapperVts.h>
Alec Mouri18339992022-04-04 21:53:57 +000019#include "gtest/gtest.h"
Marissa Wallbd1ca512018-12-30 10:59:41 -080020
Marissa Wallbd1ca512018-12-30 10:59:41 -080021namespace android {
22namespace hardware {
23namespace graphics {
24namespace mapper {
25namespace V3_0 {
26namespace vts {
27
Valerie Haudca469c2019-06-13 09:49:44 -070028Gralloc::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 }
Marissa Wallbd1ca512018-12-30 10:59:41 -080035}
36
37void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
Dan Shi5a955bc2019-12-06 15:43:01 -080038 mAllocator = IAllocator::getService(allocatorServiceName);
Marissa Wallbd1ca512018-12-30 10:59:41 -080039 ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
40
Dan Shi5a955bc2019-12-06 15:43:01 -080041 mMapper = IMapper::getService(mapperServiceName);
Marissa Wallbd1ca512018-12-30 10:59:41 -080042 ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
43 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
44}
45
Valerie Haudca469c2019-06-13 09:49:44 -070046void Gralloc::initNoErr(const std::string& allocatorServiceName,
47 const std::string& mapperServiceName) {
Dan Shi5a955bc2019-12-06 15:43:01 -080048 mAllocator = IAllocator::getService(allocatorServiceName);
Valerie Haudca469c2019-06-13 09:49:44 -070049
Dan Shi5a955bc2019-12-06 15:43:01 -080050 mMapper = IMapper::getService(mapperServiceName);
Valerie Haudca469c2019-06-13 09:49:44 -070051 if (mMapper.get()) {
52 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
53 }
54}
55
Marissa Wallbd1ca512018-12-30 10:59:41 -080056Gralloc::~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
71sp<IAllocator> Gralloc::getAllocator() const {
72 return mAllocator;
73}
74
75std::string Gralloc::dumpDebugInfo() {
76 std::string debugInfo;
77 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
78
79 return debugInfo;
80}
81
82const 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
93std::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(
Alec Mouri18339992022-04-04 21:53:57 +000099 descriptor, count,
100 [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
101 if (tmpError != Error::NONE) {
102 if (base::GetIntProperty("ro.vendor.build.version.sdk", 0, 0, INT_MAX) < 33) {
103 GTEST_SKIP() << "Old vendor grallocs may not support P010";
104 } else {
105 GTEST_FAIL() << "failed to allocate buffers";
106 }
Marissa Wallbd1ca512018-12-30 10:59:41 -0800107 }
Alec Mouri18339992022-04-04 21:53:57 +0000108 ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
Marissa Wallbd1ca512018-12-30 10:59:41 -0800109
Alec Mouri18339992022-04-04 21:53:57 +0000110 for (uint32_t i = 0; i < count; i++) {
111 if (import) {
112 ASSERT_NO_FATAL_FAILURE(
113 bufferHandles.push_back(importBuffer(tmpBuffers[i])));
114 } else {
115 ASSERT_NO_FATAL_FAILURE(
116 bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
117 }
118 }
119
120 if (outStride) {
121 *outStride = tmpStride;
122 }
123 });
Marissa Wallbd1ca512018-12-30 10:59:41 -0800124
125 if (::testing::Test::HasFatalFailure()) {
126 bufferHandles.clear();
127 }
128
129 return bufferHandles;
130}
131
132const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
133 bool import, uint32_t* outStride) {
134 BufferDescriptor descriptor = createDescriptor(descriptorInfo);
135 if (::testing::Test::HasFatalFailure()) {
136 return nullptr;
137 }
138
139 auto buffers = allocate(descriptor, 1, import, outStride);
Alec Mouri18339992022-04-04 21:53:57 +0000140 if (::testing::Test::HasFatalFailure() || ::testing::Test::IsSkipped()) {
Marissa Wallbd1ca512018-12-30 10:59:41 -0800141 return nullptr;
142 }
143
144 return buffers[0];
145}
146
147sp<IMapper> Gralloc::getMapper() const {
148 return mMapper;
149}
150
151BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
152 BufferDescriptor descriptor;
153 mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
154 ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
155 descriptor = tmpDescriptor;
156 });
157
158 return descriptor;
159}
160
161const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
162 const native_handle_t* bufferHandle = nullptr;
163 mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
164 ASSERT_EQ(Error::NONE, tmpError)
165 << "failed to import buffer %p" << rawHandle.getNativeHandle();
166 bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
167 });
168
169 if (bufferHandle) {
170 mImportedBuffers.insert(bufferHandle);
171 }
172
173 return bufferHandle;
174}
175
176void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
177 auto buffer = const_cast<native_handle_t*>(bufferHandle);
178
179 if (mImportedBuffers.erase(bufferHandle)) {
180 Error error = mMapper->freeBuffer(buffer);
181 ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
182 } else {
183 mClonedBuffers.erase(bufferHandle);
184 native_handle_close(buffer);
185 native_handle_delete(buffer);
186 }
187}
188
189void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
Marissa Wall69292fa2018-12-30 12:37:18 -0800190 const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
191 int32_t* outBytesPerStride) {
Marissa Wallbd1ca512018-12-30 10:59:41 -0800192 auto buffer = const_cast<native_handle_t*>(bufferHandle);
193
194 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
195 hidl_handle acquireFenceHandle;
196 if (acquireFence >= 0) {
197 auto h = native_handle_init(acquireFenceStorage, 1, 0);
198 h->data[0] = acquireFence;
199 acquireFenceHandle = h;
200 }
201
Marissa Walla6a30b12018-12-30 12:48:46 -0800202 *outBytesPerPixel = -1;
203 *outBytesPerStride = -1;
204
Marissa Wallbd1ca512018-12-30 10:59:41 -0800205 void* data = nullptr;
206 mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
Marissa Wall69292fa2018-12-30 12:37:18 -0800207 [&](const auto& tmpError, const auto& tmpData, int32_t tmpBytesPerPixel,
208 int32_t tmpBytesPerStride) {
Marissa Wallbd1ca512018-12-30 10:59:41 -0800209 ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
210 data = tmpData;
Marissa Wall69292fa2018-12-30 12:37:18 -0800211 *outBytesPerPixel = tmpBytesPerPixel;
212 *outBytesPerStride = tmpBytesPerStride;
Marissa Wallbd1ca512018-12-30 10:59:41 -0800213 });
214
215 if (acquireFence >= 0) {
216 close(acquireFence);
217 }
218
219 return data;
220}
221
222YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
223 const IMapper::Rect& accessRegion, int acquireFence) {
224 auto buffer = const_cast<native_handle_t*>(bufferHandle);
225
226 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
227 hidl_handle acquireFenceHandle;
228 if (acquireFence >= 0) {
229 auto h = native_handle_init(acquireFenceStorage, 1, 0);
230 h->data[0] = acquireFence;
231 acquireFenceHandle = h;
232 }
233
234 YCbCrLayout layout = {};
235 mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
236 [&](const auto& tmpError, const auto& tmpLayout) {
237 ASSERT_EQ(Error::NONE, tmpError)
238 << "failed to lockYCbCr buffer " << buffer;
239 layout = tmpLayout;
240 });
241
242 if (acquireFence >= 0) {
243 close(acquireFence);
244 }
245
246 return layout;
247}
248
249int Gralloc::unlock(const native_handle_t* bufferHandle) {
250 auto buffer = const_cast<native_handle_t*>(bufferHandle);
251
252 int releaseFence = -1;
253 mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
254 ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
255
256 auto fenceHandle = tmpReleaseFence.getNativeHandle();
257 if (fenceHandle) {
258 ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
259 if (fenceHandle->numFds == 1) {
260 releaseFence = dup(fenceHandle->data[0]);
261 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
262 } else {
263 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
264 }
265 }
266 });
267
268 return releaseFence;
269}
270
271bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
272 const IMapper::BufferDescriptorInfo& descriptorInfo,
273 uint32_t stride) {
274 auto buffer = const_cast<native_handle_t*>(bufferHandle);
275
276 Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
277 return error == Error::NONE;
278}
279
280void Gralloc::getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
281 uint32_t* outNumInts) {
282 auto buffer = const_cast<native_handle_t*>(bufferHandle);
283
284 *outNumFds = 0;
285 *outNumInts = 0;
286 mMapper->getTransportSize(
287 buffer, [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
288 ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
289 ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
290 ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
291
292 *outNumFds = tmpNumFds;
293 *outNumInts = tmpNumInts;
294 });
295}
296
Marissa Walla6a30b12018-12-30 12:48:46 -0800297bool Gralloc::isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) {
298 bool supported = false;
299 mMapper->isSupported(descriptorInfo, [&](const auto& tmpError, const auto& tmpSupported) {
300 ASSERT_EQ(Error::NONE, tmpError) << "failed to check is supported";
301 supported = tmpSupported;
302 });
303 return supported;
304}
305
Marissa Wallbd1ca512018-12-30 10:59:41 -0800306} // namespace vts
307} // namespace V3_0
308} // namespace mapper
309} // namespace graphics
310} // namespace hardware
311} // namespace android