1 /*
2 * Copyright 2019 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 <gralloctypes/Gralloc4.h>
18 #include <mapper-vts/4.0/MapperVts.h>
19
20 namespace android {
21 namespace hardware {
22 namespace graphics {
23 namespace mapper {
24 namespace V4_0 {
25 namespace vts {
26
Gralloc(const std::string & allocatorServiceName,const std::string & mapperServiceName,bool errOnFailure)27 Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
28 bool errOnFailure) {
29 if (errOnFailure) {
30 init(allocatorServiceName, mapperServiceName);
31 } else {
32 initNoErr(allocatorServiceName, mapperServiceName);
33 }
34 }
35
init(const std::string & allocatorServiceName,const std::string & mapperServiceName)36 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
37 mAllocator = IAllocator::getService(allocatorServiceName);
38 ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
39
40 mMapper = IMapper::getService(mapperServiceName);
41 ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
42 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
43 }
44
initNoErr(const std::string & allocatorServiceName,const std::string & mapperServiceName)45 void Gralloc::initNoErr(const std::string& allocatorServiceName,
46 const std::string& mapperServiceName) {
47 mAllocator = IAllocator::getService(allocatorServiceName);
48
49 mMapper = IMapper::getService(mapperServiceName);
50 if (mMapper.get()) {
51 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
52 }
53 }
54
~Gralloc()55 Gralloc::~Gralloc() {
56 for (auto bufferHandle : mClonedBuffers) {
57 auto buffer = const_cast<native_handle_t*>(bufferHandle);
58 native_handle_close(buffer);
59 native_handle_delete(buffer);
60 }
61 mClonedBuffers.clear();
62
63 for (auto bufferHandle : mImportedBuffers) {
64 auto buffer = const_cast<native_handle_t*>(bufferHandle);
65 EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
66 }
67 mImportedBuffers.clear();
68 }
69
getAllocator() const70 sp<IAllocator> Gralloc::getAllocator() const {
71 return mAllocator;
72 }
73
cloneBuffer(const hidl_handle & rawHandle,enum Tolerance)74 const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle,
75 enum Tolerance /*tolerance*/) {
76 const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
77 EXPECT_NE(nullptr, bufferHandle);
78
79 if (bufferHandle) {
80 mClonedBuffers.insert(bufferHandle);
81 }
82
83 return bufferHandle;
84 }
85
allocate(const BufferDescriptor & descriptor,uint32_t count,bool import,enum Tolerance tolerance,uint32_t * outStride)86 std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
87 uint32_t count, bool import,
88 enum Tolerance tolerance,
89 uint32_t* outStride) {
90 std::vector<const native_handle_t*> bufferHandles;
91 bufferHandles.reserve(count);
92 mAllocator->allocate(descriptor, count,
93 [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
94 if (canTolerate(tolerance, tmpError)) {
95 return;
96 }
97
98 ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
99 ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
100
101 for (uint32_t i = 0; i < count; i++) {
102 const native_handle_t* bufferHandle = nullptr;
103 if (import) {
104 ASSERT_NO_FATAL_FAILURE(
105 bufferHandle = importBuffer(tmpBuffers[i], tolerance));
106 } else {
107 ASSERT_NO_FATAL_FAILURE(
108 bufferHandle = cloneBuffer(tmpBuffers[i], tolerance));
109 }
110 if (bufferHandle) {
111 bufferHandles.push_back(bufferHandle);
112 }
113 }
114
115 if (outStride) {
116 *outStride = tmpStride;
117 }
118 });
119
120 if (::testing::Test::HasFatalFailure()) {
121 bufferHandles.clear();
122 }
123
124 return bufferHandles;
125 }
126
allocate(const IMapper::BufferDescriptorInfo & descriptorInfo,bool import,enum Tolerance tolerance,uint32_t * outStride)127 const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
128 bool import, enum Tolerance tolerance,
129 uint32_t* outStride) {
130 BufferDescriptor descriptor = createDescriptor(descriptorInfo);
131 if (::testing::Test::HasFatalFailure()) {
132 return nullptr;
133 }
134
135 auto buffers = allocate(descriptor, 1, import, tolerance, outStride);
136 if (::testing::Test::HasFatalFailure()) {
137 return nullptr;
138 }
139
140 if (buffers.size() != 1) {
141 return nullptr;
142 }
143 return buffers[0];
144 }
145
getMapper() const146 sp<IMapper> Gralloc::getMapper() const {
147 return mMapper;
148 }
149
createDescriptor(const IMapper::BufferDescriptorInfo & descriptorInfo)150 BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
151 BufferDescriptor descriptor;
152 mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
153 ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
154 descriptor = tmpDescriptor;
155 });
156
157 return descriptor;
158 }
159
importBuffer(const hidl_handle & rawHandle,enum Tolerance tolerance)160 const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle,
161 enum Tolerance tolerance) {
162 const native_handle_t* bufferHandle = nullptr;
163 mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
164 if (!canTolerate(tolerance, tmpError)) {
165 ASSERT_EQ(Error::NONE, tmpError)
166 << "failed to import buffer %p" << rawHandle.getNativeHandle();
167 }
168 bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
169 });
170
171 if (bufferHandle) {
172 mImportedBuffers.insert(bufferHandle);
173 }
174
175 return bufferHandle;
176 }
177
freeBuffer(const native_handle_t * bufferHandle)178 void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
179 if (bufferHandle == nullptr) {
180 return;
181 }
182
183 auto buffer = const_cast<native_handle_t*>(bufferHandle);
184
185 if (mImportedBuffers.erase(bufferHandle)) {
186 Error error = mMapper->freeBuffer(buffer);
187 ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
188 } else {
189 mClonedBuffers.erase(bufferHandle);
190 native_handle_close(buffer);
191 native_handle_delete(buffer);
192 }
193 }
194
lock(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int acquireFence)195 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
196 const IMapper::Rect& accessRegion, int acquireFence) {
197 auto buffer = const_cast<native_handle_t*>(bufferHandle);
198
199 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
200 hidl_handle acquireFenceHandle;
201 if (acquireFence >= 0) {
202 auto h = native_handle_init(acquireFenceStorage, 1, 0);
203 h->data[0] = acquireFence;
204 acquireFenceHandle = h;
205 }
206
207 void* data = nullptr;
208 mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
209 [&](const auto& tmpError, const auto& tmpData) {
210 ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
211 data = tmpData;
212 });
213
214 if (acquireFence >= 0) {
215 close(acquireFence);
216 }
217
218 return data;
219 }
220
unlock(const native_handle_t * bufferHandle)221 int Gralloc::unlock(const native_handle_t* bufferHandle) {
222 auto buffer = const_cast<native_handle_t*>(bufferHandle);
223
224 int releaseFence = -1;
225 mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
226 ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
227
228 auto fenceHandle = tmpReleaseFence.getNativeHandle();
229 if (fenceHandle) {
230 ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
231 if (fenceHandle->numFds == 1) {
232 releaseFence = dup(fenceHandle->data[0]);
233 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
234 } else {
235 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
236 }
237 }
238 });
239
240 return releaseFence;
241 }
242
flushLockedBuffer(const native_handle_t * bufferHandle)243 int Gralloc::flushLockedBuffer(const native_handle_t* bufferHandle) {
244 auto buffer = const_cast<native_handle_t*>(bufferHandle);
245
246 int releaseFence = -1;
247 mMapper->flushLockedBuffer(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
248 ASSERT_EQ(Error::NONE, tmpError) << "failed to flush locked buffer " << buffer;
249
250 auto fenceHandle = tmpReleaseFence.getNativeHandle();
251 if (fenceHandle) {
252 ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
253 if (fenceHandle->numFds == 1) {
254 releaseFence = dup(fenceHandle->data[0]);
255 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
256 } else {
257 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
258 }
259 }
260 });
261
262 return releaseFence;
263 }
264
rereadLockedBuffer(const native_handle_t * bufferHandle)265 void Gralloc::rereadLockedBuffer(const native_handle_t* bufferHandle) {
266 auto buffer = const_cast<native_handle_t*>(bufferHandle);
267
268 ASSERT_EQ(Error::NONE, mMapper->rereadLockedBuffer(buffer));
269 }
270
validateBufferSize(const native_handle_t * bufferHandle,const IMapper::BufferDescriptorInfo & descriptorInfo,uint32_t stride)271 bool 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
getTransportSize(const native_handle_t * bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts)280 void 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(buffer, [&](const auto& tmpError, const auto& tmpNumFds,
287 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
isSupported(const IMapper::BufferDescriptorInfo & descriptorInfo)297 bool 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
get(const native_handle_t * bufferHandle,const IMapper::MetadataType & metadataType,hidl_vec<uint8_t> * outVec)306 Error Gralloc::get(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
307 hidl_vec<uint8_t>* outVec) {
308 Error err;
309 mMapper->get(const_cast<native_handle_t*>(bufferHandle), metadataType,
310 [&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
311 err = tmpError;
312 *outVec = tmpVec;
313 });
314 return err;
315 }
316
set(const native_handle_t * bufferHandle,const IMapper::MetadataType & metadataType,const hidl_vec<uint8_t> & vec)317 Error Gralloc::set(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
318 const hidl_vec<uint8_t>& vec) {
319 return mMapper->set(const_cast<native_handle_t*>(bufferHandle), metadataType, vec);
320 }
321
getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo & descriptorInfo,const IMapper::MetadataType & metadataType,hidl_vec<uint8_t> * outVec)322 Error Gralloc::getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& descriptorInfo,
323 const IMapper::MetadataType& metadataType,
324 hidl_vec<uint8_t>* outVec) {
325 Error err;
326 mMapper->getFromBufferDescriptorInfo(
327 descriptorInfo, metadataType,
328 [&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
329 err = tmpError;
330 *outVec = tmpVec;
331 });
332 return err;
333 }
334
getReservedRegion(const native_handle_t * bufferHandle,void ** outReservedRegion,uint64_t * outReservedSize)335 Error Gralloc::getReservedRegion(const native_handle_t* bufferHandle, void** outReservedRegion,
336 uint64_t* outReservedSize) {
337 Error err;
338 mMapper->getReservedRegion(
339 const_cast<native_handle_t*>(bufferHandle),
340 [&](const auto& tmpError, const auto& tmpReservedRegion, const auto& tmpReservedSize) {
341 err = tmpError;
342 *outReservedRegion = tmpReservedRegion;
343 *outReservedSize = tmpReservedSize;
344 });
345 return err;
346 }
347
348 } // namespace vts
349 } // namespace V4_0
350 } // namespace mapper
351 } // namespace graphics
352 } // namespace hardware
353 } // namespace android
354