blob: e4a2535a92b0021bcd287a76f4d8466fcd9cbe3d [file] [log] [blame]
Marissa Wall65341642019-06-20 13:21:06 -07001/*
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
Alec Mouri38ccfd72022-05-16 20:20:28 +000017#include <aidlcommonsupport/NativeHandle.h>
Alec Mouri18339992022-04-04 21:53:57 +000018#include <android-base/properties.h>
Alec Mouri38ccfd72022-05-16 20:20:28 +000019#include <android/binder_manager.h>
Marissa Wall88d87fa2019-11-05 14:57:51 -080020#include <gralloctypes/Gralloc4.h>
Marissa Wall65341642019-06-20 13:21:06 -070021#include <mapper-vts/4.0/MapperVts.h>
22
Marissa Wall65341642019-06-20 13:21:06 -070023namespace android {
24namespace hardware {
25namespace graphics {
26namespace mapper {
27namespace V4_0 {
28namespace vts {
29
30Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
31 bool errOnFailure) {
32 if (errOnFailure) {
33 init(allocatorServiceName, mapperServiceName);
34 } else {
35 initNoErr(allocatorServiceName, mapperServiceName);
36 }
37}
38
39void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
Alec Mouri38ccfd72022-05-16 20:20:28 +000040 mAidlAllocator = aidl::android::hardware::graphics::allocator::IAllocator::fromBinder(
41 ndk::SpAIBinder(AServiceManager_checkService(allocatorServiceName.c_str())));
42
43 if (mAidlAllocator == nullptr) {
44 mHidlAllocator = IAllocator::getService(allocatorServiceName);
45 }
46 ASSERT_TRUE(nullptr != mAidlAllocator || mHidlAllocator != nullptr)
47 << "failed to get allocator service";
Marissa Wall65341642019-06-20 13:21:06 -070048
Dan Shi46245c52019-12-06 16:12:53 -080049 mMapper = IMapper::getService(mapperServiceName);
Marissa Wall65341642019-06-20 13:21:06 -070050 ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
51 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
52}
53
54void Gralloc::initNoErr(const std::string& allocatorServiceName,
55 const std::string& mapperServiceName) {
Alec Mouri38ccfd72022-05-16 20:20:28 +000056 mAidlAllocator = aidl::android::hardware::graphics::allocator::IAllocator::fromBinder(
57 ndk::SpAIBinder(AServiceManager_checkService(allocatorServiceName.c_str())));
58
59 if (mAidlAllocator == nullptr) {
60 mHidlAllocator = IAllocator::getService(allocatorServiceName);
61 }
Marissa Wall65341642019-06-20 13:21:06 -070062
Dan Shi46245c52019-12-06 16:12:53 -080063 mMapper = IMapper::getService(mapperServiceName);
Marissa Wall65341642019-06-20 13:21:06 -070064 if (mMapper.get()) {
65 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
66 }
67}
68
69Gralloc::~Gralloc() {
70 for (auto bufferHandle : mClonedBuffers) {
71 auto buffer = const_cast<native_handle_t*>(bufferHandle);
72 native_handle_close(buffer);
73 native_handle_delete(buffer);
74 }
75 mClonedBuffers.clear();
76
77 for (auto bufferHandle : mImportedBuffers) {
78 auto buffer = const_cast<native_handle_t*>(bufferHandle);
79 EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
80 }
81 mImportedBuffers.clear();
82}
83
Yichi Chenc6394ff2020-05-12 08:58:08 +080084const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle,
85 enum Tolerance /*tolerance*/) {
Marissa Wall65341642019-06-20 13:21:06 -070086 const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
87 EXPECT_NE(nullptr, bufferHandle);
88
89 if (bufferHandle) {
90 mClonedBuffers.insert(bufferHandle);
91 }
92
93 return bufferHandle;
94}
95
96std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
97 uint32_t count, bool import,
Yichi Chenc6394ff2020-05-12 08:58:08 +080098 enum Tolerance tolerance,
99 uint32_t* outStride) {
Marissa Wall65341642019-06-20 13:21:06 -0700100 std::vector<const native_handle_t*> bufferHandles;
101 bufferHandles.reserve(count);
Marissa Wall65341642019-06-20 13:21:06 -0700102
Alec Mouri38ccfd72022-05-16 20:20:28 +0000103 auto callback = [&](Error error, uint32_t stride,
104 const hidl_vec<hidl_handle>& buffers) -> void {
105 if (canTolerate(tolerance, error)) {
106 return;
107 }
Marissa Wall65341642019-06-20 13:21:06 -0700108
Alec Mouri38ccfd72022-05-16 20:20:28 +0000109 if (error != Error::NONE) {
110 if (base::GetIntProperty("ro.vendor.build.version.sdk", 0, 0, INT_MAX) < 33) {
111 GTEST_SKIP() << "Old vendor grallocs may not support P010";
112 } else {
113 GTEST_FAIL() << "failed to allocate buffers";
114 }
115 }
116 ASSERT_EQ(count, buffers.size()) << "invalid buffer array";
Yichi Chenc6394ff2020-05-12 08:58:08 +0800117
Alec Mouri38ccfd72022-05-16 20:20:28 +0000118 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);
Marissa Wall65341642019-06-20 13:21:06 -0700136
137 if (::testing::Test::HasFatalFailure()) {
138 bufferHandles.clear();
139 }
140
141 return bufferHandles;
142}
143
144const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
Yichi Chenc6394ff2020-05-12 08:58:08 +0800145 bool import, enum Tolerance tolerance,
146 uint32_t* outStride) {
Marissa Wall65341642019-06-20 13:21:06 -0700147 BufferDescriptor descriptor = createDescriptor(descriptorInfo);
148 if (::testing::Test::HasFatalFailure()) {
149 return nullptr;
150 }
151
Yichi Chenc6394ff2020-05-12 08:58:08 +0800152 auto buffers = allocate(descriptor, 1, import, tolerance, outStride);
Alec Mouri18339992022-04-04 21:53:57 +0000153 if (::testing::Test::HasFatalFailure() || ::testing::Test::IsSkipped() || buffers.size() != 1) {
Marissa Wall88d87fa2019-11-05 14:57:51 -0800154 return nullptr;
155 }
Marissa Wall65341642019-06-20 13:21:06 -0700156 return buffers[0];
157}
158
Alec Mouri38ccfd72022-05-16 20:20:28 +0000159void 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
Marissa Wall65341642019-06-20 13:21:06 -0700176sp<IMapper> Gralloc::getMapper() const {
177 return mMapper;
178}
179
180BufferDescriptor 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
Yichi Chenc6394ff2020-05-12 08:58:08 +0800190const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle,
191 enum Tolerance tolerance) {
Marissa Wall65341642019-06-20 13:21:06 -0700192 const native_handle_t* bufferHandle = nullptr;
193 mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
Yichi Chenc6394ff2020-05-12 08:58:08 +0800194 if (!canTolerate(tolerance, tmpError)) {
195 ASSERT_EQ(Error::NONE, tmpError)
196 << "failed to import buffer %p" << rawHandle.getNativeHandle();
197 }
Marissa Wall65341642019-06-20 13:21:06 -0700198 bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
199 });
200
201 if (bufferHandle) {
202 mImportedBuffers.insert(bufferHandle);
203 }
204
205 return bufferHandle;
206}
207
208void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
Marissa Wall88d87fa2019-11-05 14:57:51 -0800209 if (bufferHandle == nullptr) {
210 return;
211 }
212
Marissa Wall65341642019-06-20 13:21:06 -0700213 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
225void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800226 const IMapper::Rect& accessRegion, int acquireFence) {
Marissa Wall65341642019-06-20 13:21:06 -0700227 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
Marissa Wall65341642019-06-20 13:21:06 -0700237 void* data = nullptr;
238 mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
Marissa Wall9c5ebfc2019-11-05 14:59:27 -0800239 [&](const auto& tmpError, const auto& tmpData) {
Marissa Wall65341642019-06-20 13:21:06 -0700240 ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
241 data = tmpData;
Marissa Wall65341642019-06-20 13:21:06 -0700242 });
243
244 if (acquireFence >= 0) {
245 close(acquireFence);
246 }
247
248 return data;
249}
250
Marissa Wall65341642019-06-20 13:21:06 -0700251int 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
Marissa Wall2c45bb12019-10-18 13:31:36 -0700273int 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
295void 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
Marissa Wall65341642019-06-20 13:21:06 -0700301bool 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
310void 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
327bool 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
Leon Scroggins IIIcd5e4692022-02-16 16:36:27 -0500336bool 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
Marissa Wall88d87fa2019-11-05 14:57:51 -0800344Error 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
355Error 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
360Error 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
Marissa Walld36e1272019-11-26 11:33:32 -0800373Error 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
Marissa Wall65341642019-06-20 13:21:06 -0700386} // namespace vts
387} // namespace V4_0
388} // namespace mapper
389} // namespace graphics
390} // namespace hardware
391} // namespace android