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