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