blob: 6ab11a305da7c2f6e40bdbf52e19f8514ef976fb [file] [log] [blame]
John Reck48c546c2022-11-15 16:29:21 -05001/*
2 * Copyright 2022 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#undef LOG_TAG
18#define LOG_TAG "VtsHalGraphicsMapperStableC_TargetTest"
19
20#include <aidl/Vintf.h>
21#include <aidl/android/hardware/graphics/allocator/AllocationError.h>
22#include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
23#include <aidl/android/hardware/graphics/allocator/IAllocator.h>
24#include <aidl/android/hardware/graphics/common/BufferUsage.h>
25#include <aidl/android/hardware/graphics/common/PixelFormat.h>
26#include <aidlcommonsupport/NativeHandle.h>
27#include <android/binder_manager.h>
28#include <android/dlext.h>
29#include <android/hardware/graphics/mapper/IMapper.h>
30#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
31#include <gralloctypes/Gralloc4.h>
32#include <hidl/GtestPrinter.h>
33#include <system/graphics.h>
34
35#include <dlfcn.h>
36#include <drm/drm_fourcc.h>
37#include <gtest/gtest.h>
38#include <vndksupport/linker.h>
39#include <initializer_list>
40#include <optional>
41#include <string>
42#include <tuple>
43#include <vector>
44
45using namespace aidl::android::hardware::graphics::allocator;
46using namespace aidl::android::hardware::graphics::common;
47using namespace android;
48using namespace android::hardware;
49using namespace ::android::hardware::graphics::mapper;
50
51typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper* _Nullable* _Nonnull outImplementation);
52
53inline constexpr BufferUsage operator|(BufferUsage lhs, BufferUsage rhs) {
54 using T = std::underlying_type_t<BufferUsage>;
55 return static_cast<BufferUsage>(static_cast<T>(lhs) | static_cast<T>(rhs));
56}
57
58inline BufferUsage& operator|=(BufferUsage& lhs, BufferUsage rhs) {
59 lhs = lhs | rhs;
60 return lhs;
61}
62
63struct YCbCr {
64 android_ycbcr yCbCr;
65 int64_t horizontalSubSampling;
66 int64_t verticalSubSampling;
67};
68
69class BufferHandle {
70 AIMapper* mIMapper;
71 buffer_handle_t mHandle = nullptr;
72
73 public:
74 explicit BufferHandle(AIMapper* mapper, native_handle_t* rawHandle) : mIMapper(mapper) {
75 EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.importBuffer(rawHandle, &mHandle));
76 }
77
78 explicit BufferHandle(BufferHandle&& other) { *this = std::move(other); }
79
80 BufferHandle& operator=(BufferHandle&& other) noexcept {
81 reset();
82 mIMapper = other.mIMapper;
83 mHandle = other.mHandle;
84 other.mHandle = nullptr;
85 return *this;
86 }
87
88 ~BufferHandle() { reset(); }
89
90 constexpr explicit operator bool() const noexcept { return mHandle != nullptr; }
91
92 buffer_handle_t operator*() const noexcept { return mHandle; }
93
94 void reset() {
95 if (mHandle != nullptr) {
96 EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.freeBuffer(mHandle));
97 mHandle = nullptr;
98 }
99 }
100};
101
102class BufferAllocation {
103 AIMapper* mIMapper;
104 native_handle_t* mRawHandle;
105 uint32_t mStride;
106 const BufferDescriptorInfo mInfo;
107
108 public:
109 BufferAllocation(const BufferAllocation&) = delete;
110 void operator=(const BufferAllocation&) = delete;
111
112 BufferAllocation(AIMapper* mapper, native_handle_t* handle, uint32_t stride,
113 const BufferDescriptorInfo& info)
114 : mIMapper(mapper), mRawHandle(handle), mStride(stride), mInfo(info) {}
115
116 ~BufferAllocation() {
117 if (mRawHandle == nullptr) return;
118
119 native_handle_close(mRawHandle);
120 native_handle_delete(mRawHandle);
121 }
122
123 uint32_t stride() const { return mStride; }
124 const BufferDescriptorInfo& info() const { return mInfo; }
125
126 BufferHandle import() { return BufferHandle{mIMapper, mRawHandle}; }
127
128 const native_handle_t* rawHandle() const { return mRawHandle; }
129};
130
131class GraphicsTestsBase {
132 private:
133 friend class BufferAllocation;
134 int32_t mIAllocatorVersion = 1;
135 std::shared_ptr<IAllocator> mAllocator;
136 AIMapper* mIMapper = nullptr;
137 AIMapper_loadIMapperFn mIMapperLoader;
138
139 protected:
140 void Initialize(std::shared_ptr<IAllocator> allocator) {
141 mAllocator = allocator;
142 ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
143 ASSERT_TRUE(mAllocator->getInterfaceVersion(&mIAllocatorVersion).isOk());
144 ASSERT_GE(mIAllocatorVersion, 2);
145 std::string mapperSuffix;
146 auto status = mAllocator->getIMapperLibrarySuffix(&mapperSuffix);
147 ASSERT_TRUE(status.isOk()) << "Failed to get IMapper library suffix";
148 std::string lib_name = "mapper." + mapperSuffix + ".so";
149 void* so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
150 ASSERT_NE(nullptr, so) << "Failed to load " << lib_name;
151 mIMapperLoader = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
152 ASSERT_NE(nullptr, mIMapperLoader) << "AIMapper_locaIMapper missing from " << lib_name;
153 ASSERT_EQ(AIMAPPER_ERROR_NONE, mIMapperLoader(&mIMapper));
154 ASSERT_NE(mIMapper, nullptr);
155 }
156
157 public:
158 AIMapper_loadIMapperFn getIMapperLoader() const { return mIMapperLoader; }
159
160 std::unique_ptr<BufferAllocation> allocate(const BufferDescriptorInfo& descriptorInfo) {
161 AllocationResult result;
162 ::ndk::ScopedAStatus status = mAllocator->allocate2(descriptorInfo, 1, &result);
163 if (!status.isOk()) {
164 status_t error = status.getExceptionCode();
165 if (error == EX_SERVICE_SPECIFIC) {
166 error = status.getServiceSpecificError();
167 EXPECT_NE(OK, error) << "Failed to set error properly";
168 } else {
169 EXPECT_EQ(OK, error) << "Allocation transport failure";
170 }
171 return nullptr;
172 } else {
173 return std::make_unique<BufferAllocation>(mIMapper, dupFromAidl(result.buffers[0]),
174 result.stride, descriptorInfo);
175 }
176 }
177
178 std::unique_ptr<BufferAllocation> allocateGeneric() {
179 return allocate({
180 .name = {"VTS_TEMP"},
181 .width = 64,
182 .height = 64,
183 .layerCount = 1,
184 .format = PixelFormat::RGBA_8888,
185 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
186 .reservedSize = 0,
187 });
188 }
189
190 bool isSupported(const BufferDescriptorInfo& descriptorInfo) {
191 bool ret = false;
192 EXPECT_TRUE(mAllocator->isSupported(descriptorInfo, &ret).isOk());
193 return ret;
194 }
195
196 AIMapper* mapper() const { return mIMapper; }
197
198 template <StandardMetadataType T>
199 auto getStandardMetadata(buffer_handle_t bufferHandle)
200 -> decltype(StandardMetadata<T>::value::decode(nullptr, 0)) {
201 using Value = typename StandardMetadata<T>::value;
202 std::vector<uint8_t> buffer;
203 // Initial guess
204 buffer.resize(512);
205 int32_t sizeRequired = mapper()->v5.getStandardMetadata(
206 bufferHandle, static_cast<int64_t>(T), buffer.data(), buffer.size());
207 if (sizeRequired < 0) {
208 EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, sizeRequired)
209 << "Received something other than UNSUPPORTED from valid getStandardMetadata "
210 "call";
211 return std::nullopt;
212 }
213 if (sizeRequired > buffer.size()) {
214 buffer.resize(sizeRequired);
215 sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
216 buffer.data(), buffer.size());
217 }
218 if (sizeRequired < 0 || sizeRequired >= buffer.size()) {
219 ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
220 << " with buffer size " << buffer.size();
221 // Generate a fail type
222 return std::nullopt;
223 }
224 return Value::decode(buffer.data(), sizeRequired);
225 }
226
227 template <StandardMetadataType T>
228 AIMapper_Error setStandardMetadata(buffer_handle_t bufferHandle,
229 const typename StandardMetadata<T>::value_type& value) {
230 using Value = typename StandardMetadata<T>::value;
231 int32_t sizeRequired = Value::encode(value, nullptr, 0);
232 if (sizeRequired < 0) {
233 EXPECT_GE(sizeRequired, 0) << "Failed to calculate required size";
234 return static_cast<AIMapper_Error>(-sizeRequired);
235 }
236 std::vector<uint8_t> buffer;
237 buffer.resize(sizeRequired);
238 sizeRequired = Value::encode(value, buffer.data(), buffer.size());
239 if (sizeRequired < 0 || sizeRequired > buffer.size()) {
240 ADD_FAILURE() << "Failed to encode with calculated size " << sizeRequired
241 << "; buffer size" << buffer.size();
242 return static_cast<AIMapper_Error>(-sizeRequired);
243 }
244 return mapper()->v5.setStandardMetadata(bufferHandle, static_cast<int64_t>(T),
245 buffer.data(), sizeRequired);
246 }
247
248 void verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout>& planeLayouts) {
249 ASSERT_EQ(1, planeLayouts.size());
250
251 const auto& planeLayout = planeLayouts.front();
252
253 ASSERT_EQ(4, planeLayout.components.size());
254
255 int64_t offsetInBitsR = -1;
256 int64_t offsetInBitsG = -1;
257 int64_t offsetInBitsB = -1;
258 int64_t offsetInBitsA = -1;
259
260 for (const auto& component : planeLayout.components) {
261 if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) {
262 continue;
263 }
264 EXPECT_EQ(8, component.sizeInBits);
265 if (component.type.value == gralloc4::PlaneLayoutComponentType_R.value) {
266 offsetInBitsR = component.offsetInBits;
267 }
268 if (component.type.value == gralloc4::PlaneLayoutComponentType_G.value) {
269 offsetInBitsG = component.offsetInBits;
270 }
271 if (component.type.value == gralloc4::PlaneLayoutComponentType_B.value) {
272 offsetInBitsB = component.offsetInBits;
273 }
274 if (component.type.value == gralloc4::PlaneLayoutComponentType_A.value) {
275 offsetInBitsA = component.offsetInBits;
276 }
277 }
278
279 EXPECT_EQ(0, offsetInBitsR);
280 EXPECT_EQ(8, offsetInBitsG);
281 EXPECT_EQ(16, offsetInBitsB);
282 EXPECT_EQ(24, offsetInBitsA);
283
284 EXPECT_EQ(0, planeLayout.offsetInBytes);
285 EXPECT_EQ(32, planeLayout.sampleIncrementInBits);
286 // Skip testing stride because any stride is valid
287 EXPECT_LE(planeLayout.widthInSamples * planeLayout.heightInSamples * 4,
288 planeLayout.totalSizeInBytes);
289 EXPECT_EQ(1, planeLayout.horizontalSubsampling);
290 EXPECT_EQ(1, planeLayout.verticalSubsampling);
291 }
292
293 void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes) {
294 for (uint32_t y = 0; y < height; y++) {
295 memset(data, y, widthInBytes);
296 data += strideInBytes;
297 }
298 }
299
300 void verifyRGBA8888(const buffer_handle_t bufferHandle, const uint8_t* data, uint32_t height,
301 size_t strideInBytes, size_t widthInBytes) {
302 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
303 ASSERT_TRUE(decodeResult.has_value());
304 const auto& planeLayouts = *decodeResult;
305 ASSERT_TRUE(planeLayouts.size() > 0);
306
307 verifyRGBA8888PlaneLayouts(planeLayouts);
308
309 for (uint32_t y = 0; y < height; y++) {
310 for (size_t i = 0; i < widthInBytes; i++) {
311 EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
312 }
313 data += strideInBytes;
314 }
315 }
316
317 void traverseYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
318 int64_t hSubsampling, int64_t vSubsampling,
319 std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
320 auto yData = static_cast<uint8_t*>(yCbCr.y);
321 auto cbData = static_cast<uint8_t*>(yCbCr.cb);
322 auto crData = static_cast<uint8_t*>(yCbCr.cr);
323 auto yStride = yCbCr.ystride;
324 auto cStride = yCbCr.cstride;
325 auto chromaStep = yCbCr.chroma_step;
326
327 for (uint32_t y = 0; y < height; y++) {
328 for (uint32_t x = 0; x < width; x++) {
329 auto val = static_cast<uint8_t>(height * y + x);
330
331 traverseFuncion(yData + yStride * y + x, val);
332
333 if (y % vSubsampling == 0 && x % hSubsampling == 0) {
334 uint32_t subSampleX = x / hSubsampling;
335 uint32_t subSampleY = y / vSubsampling;
336 const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
337 const auto subSampleVal =
338 static_cast<uint8_t>(height * subSampleY + subSampleX);
339
340 traverseFuncion(cbData + subSampleOffset, subSampleVal);
341 traverseFuncion(crData + subSampleOffset, subSampleVal + 1);
342 }
343 }
344 }
345 }
346
347 void fillYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
348 int64_t hSubsampling, int64_t vSubsampling) {
349 traverseYCbCrData(yCbCr, width, height, hSubsampling, vSubsampling,
350 [](auto address, auto fillingData) { *address = fillingData; });
351 }
352
353 void verifyYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
354 int64_t hSubsampling, int64_t vSubsampling) {
355 traverseYCbCrData(
356 yCbCr, width, height, hSubsampling, vSubsampling,
357 [](auto address, auto expectedData) { EXPECT_EQ(*address, expectedData); });
358 }
359
360 constexpr uint64_t bitsToBytes(int64_t bits) { return bits / 8; }
361 constexpr uint64_t bytesToBits(int64_t bytes) { return bytes * 8; }
362
363 void getAndroidYCbCr(buffer_handle_t bufferHandle, uint8_t* data, android_ycbcr* outYCbCr,
364 int64_t* hSubsampling, int64_t* vSubsampling) {
365 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
366 ASSERT_TRUE(decodeResult.has_value());
367 const auto& planeLayouts = *decodeResult;
368 ASSERT_TRUE(planeLayouts.size() > 0);
369
370 outYCbCr->y = nullptr;
371 outYCbCr->cb = nullptr;
372 outYCbCr->cr = nullptr;
373 outYCbCr->ystride = 0;
374 outYCbCr->cstride = 0;
375 outYCbCr->chroma_step = 0;
376
377 for (const auto& planeLayout : planeLayouts) {
378 for (const auto& planeLayoutComponent : planeLayout.components) {
379 if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
380 continue;
381 }
382 ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8);
383
384 uint8_t* tmpData = data + planeLayout.offsetInBytes +
385 bitsToBytes(planeLayoutComponent.offsetInBits);
386 uint64_t sampleIncrementInBytes;
387
388 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
389 switch (type) {
390 case PlaneLayoutComponentType::Y:
391 ASSERT_EQ(nullptr, outYCbCr->y);
392 ASSERT_EQ(8, planeLayoutComponent.sizeInBits);
393 ASSERT_EQ(8, planeLayout.sampleIncrementInBits);
394 outYCbCr->y = tmpData;
395 outYCbCr->ystride = planeLayout.strideInBytes;
396 break;
397
398 case PlaneLayoutComponentType::CB:
399 case PlaneLayoutComponentType::CR:
400 ASSERT_EQ(0, planeLayout.sampleIncrementInBits % 8);
401
402 sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
403 ASSERT_TRUE(sampleIncrementInBytes == 1 || sampleIncrementInBytes == 2);
404
405 if (outYCbCr->cstride == 0 && outYCbCr->chroma_step == 0) {
406 outYCbCr->cstride = planeLayout.strideInBytes;
407 outYCbCr->chroma_step = sampleIncrementInBytes;
408 } else {
409 ASSERT_EQ(outYCbCr->cstride, planeLayout.strideInBytes);
410 ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes);
411 }
412
413 if (*hSubsampling == 0 && *vSubsampling == 0) {
414 *hSubsampling = planeLayout.horizontalSubsampling;
415 *vSubsampling = planeLayout.verticalSubsampling;
416 } else {
417 ASSERT_EQ(*hSubsampling, planeLayout.horizontalSubsampling);
418 ASSERT_EQ(*vSubsampling, planeLayout.verticalSubsampling);
419 }
420
421 if (type == PlaneLayoutComponentType::CB) {
422 ASSERT_EQ(nullptr, outYCbCr->cb);
423 outYCbCr->cb = tmpData;
424 } else {
425 ASSERT_EQ(nullptr, outYCbCr->cr);
426 outYCbCr->cr = tmpData;
427 }
428 break;
429 default:
430 break;
431 };
432 }
433 }
434
435 ASSERT_NE(nullptr, outYCbCr->y);
436 ASSERT_NE(nullptr, outYCbCr->cb);
437 ASSERT_NE(nullptr, outYCbCr->cr);
438 }
439
440 YCbCr getAndroidYCbCr_P010(const native_handle_t* bufferHandle, uint8_t* data) {
441 YCbCr yCbCr_P010;
442 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
443 if (!decodeResult.has_value()) {
444 ADD_FAILURE() << "failed to get plane layout";
445 return YCbCr{};
446 }
447 const auto& planeLayouts = *decodeResult;
448 EXPECT_EQ(2, planeLayouts.size());
449 EXPECT_EQ(1, planeLayouts[0].components.size());
450 EXPECT_EQ(2, planeLayouts[1].components.size());
451
452 yCbCr_P010.yCbCr.y = nullptr;
453 yCbCr_P010.yCbCr.cb = nullptr;
454 yCbCr_P010.yCbCr.cr = nullptr;
455 yCbCr_P010.yCbCr.ystride = 0;
456 yCbCr_P010.yCbCr.cstride = 0;
457 yCbCr_P010.yCbCr.chroma_step = 0;
458 int64_t cb_offset = 0;
459 int64_t cr_offset = 0;
460
461 for (const auto& planeLayout : planeLayouts) {
462 for (const auto& planeLayoutComponent : planeLayout.components) {
463 if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
464 continue;
465 }
466
467 uint8_t* tmpData = data + planeLayout.offsetInBytes +
468 bitsToBytes(planeLayoutComponent.offsetInBits);
469 uint64_t sampleIncrementInBytes = 0;
470 auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
471 switch (type) {
472 case PlaneLayoutComponentType::Y:
473 // For specs refer:
474 // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats
475 EXPECT_EQ(6, planeLayoutComponent.offsetInBits);
476 EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.y);
477 EXPECT_EQ(10, planeLayoutComponent.sizeInBits);
478 EXPECT_EQ(16, planeLayout.sampleIncrementInBits);
479
480 yCbCr_P010.yCbCr.y = tmpData;
481 yCbCr_P010.yCbCr.ystride = planeLayout.strideInBytes;
482 break;
483
484 case PlaneLayoutComponentType::CB:
485 case PlaneLayoutComponentType::CR:
486 sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits);
487 EXPECT_EQ(4, sampleIncrementInBytes);
488
489 if (yCbCr_P010.yCbCr.cstride == 0 && yCbCr_P010.yCbCr.chroma_step == 0) {
490 yCbCr_P010.yCbCr.cstride = planeLayout.strideInBytes;
491 yCbCr_P010.yCbCr.chroma_step = sampleIncrementInBytes;
492 } else {
493 EXPECT_EQ(yCbCr_P010.yCbCr.cstride, planeLayout.strideInBytes);
494 EXPECT_EQ(yCbCr_P010.yCbCr.chroma_step, sampleIncrementInBytes);
495 }
496
497 if (yCbCr_P010.horizontalSubSampling == 0 &&
498 yCbCr_P010.verticalSubSampling == 0) {
499 yCbCr_P010.horizontalSubSampling = planeLayout.horizontalSubsampling;
500 yCbCr_P010.verticalSubSampling = planeLayout.verticalSubsampling;
501 } else {
502 EXPECT_EQ(yCbCr_P010.horizontalSubSampling,
503 planeLayout.horizontalSubsampling);
504 EXPECT_EQ(yCbCr_P010.verticalSubSampling,
505 planeLayout.verticalSubsampling);
506 }
507
508 if (type == PlaneLayoutComponentType::CB) {
509 EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cb);
510 yCbCr_P010.yCbCr.cb = tmpData;
511 cb_offset = planeLayoutComponent.offsetInBits;
512 } else {
513 EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cr);
514 yCbCr_P010.yCbCr.cr = tmpData;
515 cr_offset = planeLayoutComponent.offsetInBits;
516 }
517 break;
518 default:
519 break;
520 };
521 }
522 }
523
524 EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset);
525 EXPECT_NE(nullptr, yCbCr_P010.yCbCr.y);
526 EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cb);
527 EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cr);
528 return yCbCr_P010;
529 }
530};
531
532class GraphicsMapperStableCTests
533 : public GraphicsTestsBase,
534 public ::testing::TestWithParam<std::tuple<std::string, std::shared_ptr<IAllocator>>> {
535 public:
536 void SetUp() override { Initialize(std::get<1>(GetParam())); }
537
538 void TearDown() override {}
539};
540
541TEST_P(GraphicsMapperStableCTests, AllV5CallbacksDefined) {
542 ASSERT_GE(mapper()->version, AIMAPPER_VERSION_5);
543
544 EXPECT_TRUE(mapper()->v5.importBuffer);
545 EXPECT_TRUE(mapper()->v5.freeBuffer);
546 EXPECT_TRUE(mapper()->v5.getTransportSize);
547 EXPECT_TRUE(mapper()->v5.lock);
548 EXPECT_TRUE(mapper()->v5.unlock);
549 EXPECT_TRUE(mapper()->v5.flushLockedBuffer);
550 EXPECT_TRUE(mapper()->v5.rereadLockedBuffer);
551 EXPECT_TRUE(mapper()->v5.getMetadata);
552 EXPECT_TRUE(mapper()->v5.getStandardMetadata);
553 EXPECT_TRUE(mapper()->v5.setMetadata);
554 EXPECT_TRUE(mapper()->v5.setStandardMetadata);
555 EXPECT_TRUE(mapper()->v5.listSupportedMetadataTypes);
556 EXPECT_TRUE(mapper()->v5.dumpBuffer);
557 EXPECT_TRUE(mapper()->v5.getReservedRegion);
558}
559
560TEST_P(GraphicsMapperStableCTests, DualLoadIsIdentical) {
561 ASSERT_GE(mapper()->version, AIMAPPER_VERSION_5);
562 AIMapper* secondMapper;
563 ASSERT_EQ(AIMAPPER_ERROR_NONE, getIMapperLoader()(&secondMapper));
564
565 EXPECT_EQ(secondMapper->v5.importBuffer, mapper()->v5.importBuffer);
566 EXPECT_EQ(secondMapper->v5.freeBuffer, mapper()->v5.freeBuffer);
567 EXPECT_EQ(secondMapper->v5.getTransportSize, mapper()->v5.getTransportSize);
568 EXPECT_EQ(secondMapper->v5.lock, mapper()->v5.lock);
569 EXPECT_EQ(secondMapper->v5.unlock, mapper()->v5.unlock);
570 EXPECT_EQ(secondMapper->v5.flushLockedBuffer, mapper()->v5.flushLockedBuffer);
571 EXPECT_EQ(secondMapper->v5.rereadLockedBuffer, mapper()->v5.rereadLockedBuffer);
572 EXPECT_EQ(secondMapper->v5.getMetadata, mapper()->v5.getMetadata);
573 EXPECT_EQ(secondMapper->v5.getStandardMetadata, mapper()->v5.getStandardMetadata);
574 EXPECT_EQ(secondMapper->v5.setMetadata, mapper()->v5.setMetadata);
575 EXPECT_EQ(secondMapper->v5.setStandardMetadata, mapper()->v5.setStandardMetadata);
576 EXPECT_EQ(secondMapper->v5.listSupportedMetadataTypes, mapper()->v5.listSupportedMetadataTypes);
577 EXPECT_EQ(secondMapper->v5.dumpBuffer, mapper()->v5.dumpBuffer);
578 EXPECT_EQ(secondMapper->v5.getReservedRegion, mapper()->v5.getReservedRegion);
579}
580
581TEST_P(GraphicsMapperStableCTests, CanAllocate) {
582 auto buffer = allocate({
583 .name = {"VTS_TEMP"},
584 .width = 64,
585 .height = 64,
586 .layerCount = 1,
587 .format = PixelFormat::RGBA_8888,
588 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
589 .reservedSize = 0,
590 });
591 ASSERT_NE(nullptr, buffer.get());
592 EXPECT_GE(buffer->stride(), 64);
593}
594
595TEST_P(GraphicsMapperStableCTests, ImportFreeBuffer) {
596 auto buffer = allocate({
597 .name = {"VTS_TEMP"},
598 .width = 64,
599 .height = 64,
600 .layerCount = 1,
601 .format = PixelFormat::RGBA_8888,
602 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
603 .reservedSize = 0,
604 });
605 ASSERT_NE(nullptr, buffer.get());
606 EXPECT_GE(buffer->stride(), 64);
607
608 {
609 auto import1 = buffer->import();
610 auto import2 = buffer->import();
611 EXPECT_TRUE(import1);
612 EXPECT_TRUE(import2);
613 EXPECT_NE(*import1, *import2);
614 }
615}
616
617/**
618 * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
619 */
620TEST_P(GraphicsMapperStableCTests, ImportFreeBufferSingleton) {
621 auto buffer = allocate({
622 .name = {"VTS_TEMP"},
623 .width = 64,
624 .height = 64,
625 .layerCount = 1,
626 .format = PixelFormat::RGBA_8888,
627 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
628 .reservedSize = 0,
629 });
630 ASSERT_NE(nullptr, buffer.get());
631 EXPECT_GE(buffer->stride(), 64);
632
633 buffer_handle_t bufferHandle = nullptr;
634 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.importBuffer(buffer->rawHandle(), &bufferHandle));
635 ASSERT_NE(nullptr, bufferHandle);
636
637 AIMapper* secondMapper;
638 ASSERT_EQ(AIMAPPER_ERROR_NONE, getIMapperLoader()(&secondMapper));
639 ASSERT_EQ(AIMAPPER_ERROR_NONE, secondMapper->v5.freeBuffer(bufferHandle));
640}
641
642/**
643 * Test IMapper::importBuffer with invalid buffers.
644 */
645TEST_P(GraphicsMapperStableCTests, ImportBufferNegative) {
646 native_handle_t* invalidHandle = nullptr;
647 buffer_handle_t bufferHandle = nullptr;
648 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.importBuffer(invalidHandle, &bufferHandle))
649 << "importBuffer with nullptr did not fail with BAD_BUFFER";
650
651 invalidHandle = native_handle_create(0, 0);
652 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.importBuffer(invalidHandle, &bufferHandle))
653 << "importBuffer with invalid handle did not fail with BAD_BUFFER";
654 native_handle_delete(invalidHandle);
655}
656
657/**
658 * Test IMapper::freeBuffer with invalid buffers.
659 */
660TEST_P(GraphicsMapperStableCTests, FreeBufferNegative) {
661 native_handle_t* bufferHandle = nullptr;
662 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(bufferHandle))
663 << "freeBuffer with nullptr did not fail with BAD_BUFFER";
664
665 bufferHandle = native_handle_create(0, 0);
666 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(bufferHandle))
667 << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
668 native_handle_delete(bufferHandle);
669
670 auto buffer = allocateGeneric();
671 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(buffer->rawHandle()))
672 << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
673}
674
675/**
676 * Test IMapper::lock and IMapper::unlock.
677 */
678TEST_P(GraphicsMapperStableCTests, LockUnlockBasic) {
679 constexpr auto usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN;
680 auto buffer = allocate({
681 .name = {"VTS_TEMP"},
682 .width = 64,
683 .height = 64,
684 .layerCount = 1,
685 .format = PixelFormat::RGBA_8888,
686 .usage = usage,
687 .reservedSize = 0,
688 });
689 ASSERT_NE(nullptr, buffer.get());
690
691 // lock buffer for writing
692 const auto& info = buffer->info();
693 const auto stride = buffer->stride();
694 const ARect region{0, 0, info.width, info.height};
695 auto handle = buffer->import();
696 uint8_t* data = nullptr;
697 ASSERT_EQ(AIMAPPER_ERROR_NONE,
698 mapper()->v5.lock(*handle, static_cast<int64_t>(usage), region, -1, (void**)&data));
699
700 // RGBA_8888
701 fillRGBA8888(data, info.height, stride * 4, info.width * 4);
702
703 int releaseFence = -1;
704 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
705
706 // lock again for reading
707 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(usage), region,
708 releaseFence, (void**)&data));
709 releaseFence = -1;
710
711 ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(*handle, data, info.height, stride * 4, info.width * 4));
712
713 releaseFence = -1;
714 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
715 if (releaseFence != -1) {
716 close(releaseFence);
717 }
718}
719
720/**
721 * Test multiple operations associated with different color formats
722 */
723TEST_P(GraphicsMapperStableCTests, Lock_YCRCB_420_SP) {
724 BufferDescriptorInfo info{
725 .name = {"VTS_TEMP"},
726 .width = 64,
727 .height = 64,
728 .layerCount = 1,
729 .format = PixelFormat::YCRCB_420_SP,
730 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
731 .reservedSize = 0,
732 };
733 auto buffer = allocate(info);
734 if (!buffer) {
735 ASSERT_FALSE(isSupported(info));
736 GTEST_SUCCEED() << "YCRCB_420_SP format is unsupported";
737 return;
738 }
739
740 // lock buffer for writing
741 const ARect region{0, 0, info.width, info.height};
742 auto handle = buffer->import();
743 uint8_t* data = nullptr;
744 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
745 region, -1, (void**)&data));
746
747 android_ycbcr yCbCr;
748 int64_t hSubsampling = 0;
749 int64_t vSubsampling = 0;
750 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
751
752 constexpr uint32_t kCbCrSubSampleFactor = 2;
753 ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
754 ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
755
756 auto cbData = static_cast<uint8_t*>(yCbCr.cb);
757 auto crData = static_cast<uint8_t*>(yCbCr.cr);
758 ASSERT_EQ(crData + 1, cbData);
759 ASSERT_EQ(2, yCbCr.chroma_step);
760
761 fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
762
763 int releaseFence = -1;
764 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
765
766 // lock again for reading
767 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
768 region, releaseFence, (void**)&data));
769 releaseFence = -1;
770
771 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
772
773 verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
774
775 releaseFence = -1;
776 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
777 if (releaseFence != -1) {
778 close(releaseFence);
779 }
780}
781
782TEST_P(GraphicsMapperStableCTests, YV12SubsampleMetadata) {
783 BufferDescriptorInfo info{
784 .name = {"VTS_TEMP"},
785 .width = 64,
786 .height = 64,
787 .layerCount = 1,
788 .format = PixelFormat::YV12,
789 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
790 .reservedSize = 0,
791 };
792 auto buffer = allocate(info);
793 ASSERT_NE(nullptr, buffer.get());
794
795 // lock buffer for writing
796 const ARect region{0, 0, info.width, info.height};
797 auto handle = buffer->import();
798 uint8_t* data = nullptr;
799 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
800 region, -1, (void**)&data));
801
802 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
803 ASSERT_TRUE(decodeResult.has_value());
804 const auto& planeLayouts = *decodeResult;
805
806 ASSERT_EQ(3, planeLayouts.size());
807
808 auto yPlane = planeLayouts[0];
809 auto crPlane = planeLayouts[1];
810 auto cbPlane = planeLayouts[2];
811
812 constexpr uint32_t kCbCrSubSampleFactor = 2;
813 EXPECT_EQ(kCbCrSubSampleFactor, crPlane.horizontalSubsampling);
814 EXPECT_EQ(kCbCrSubSampleFactor, crPlane.verticalSubsampling);
815
816 EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.horizontalSubsampling);
817 EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.verticalSubsampling);
818
819 const long chromaSampleWidth = info.width / kCbCrSubSampleFactor;
820 const long chromaSampleHeight = info.height / kCbCrSubSampleFactor;
821
822 EXPECT_EQ(info.width, yPlane.widthInSamples);
823 EXPECT_EQ(info.height, yPlane.heightInSamples);
824
825 EXPECT_EQ(chromaSampleWidth, crPlane.widthInSamples);
826 EXPECT_EQ(chromaSampleHeight, crPlane.heightInSamples);
827
828 EXPECT_EQ(chromaSampleWidth, cbPlane.widthInSamples);
829 EXPECT_EQ(chromaSampleHeight, cbPlane.heightInSamples);
830
831 EXPECT_LE(crPlane.widthInSamples, crPlane.strideInBytes);
832 EXPECT_LE(cbPlane.widthInSamples, cbPlane.strideInBytes);
833
834 int releaseFence = -1;
835 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
836 if (releaseFence != -1) {
837 close(releaseFence);
838 }
839}
840
841TEST_P(GraphicsMapperStableCTests, Lock_YV12) {
842 BufferDescriptorInfo info{
843 .name = {"VTS_TEMP"},
844 .width = 64,
845 .height = 64,
846 .layerCount = 1,
847 .format = PixelFormat::YV12,
848 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
849 .reservedSize = 0,
850 };
851 auto buffer = allocate(info);
852 ASSERT_NE(nullptr, buffer.get());
853
854 // lock buffer for writing
855 const ARect region{0, 0, info.width, info.height};
856 auto handle = buffer->import();
857 uint8_t* data = nullptr;
858 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
859 region, -1, (void**)&data));
860
861 android_ycbcr yCbCr;
862 int64_t hSubsampling = 0;
863 int64_t vSubsampling = 0;
864 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
865
866 constexpr uint32_t kCbCrSubSampleFactor = 2;
867 ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
868 ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
869
870 auto cbData = static_cast<uint8_t*>(yCbCr.cb);
871 auto crData = static_cast<uint8_t*>(yCbCr.cr);
872 ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData);
873 ASSERT_EQ(1, yCbCr.chroma_step);
874
875 fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
876
877 int releaseFence = -1;
878 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
879
880 // lock again for reading
881 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
882 region, releaseFence, (void**)&data));
883 releaseFence = -1;
884
885 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
886
887 verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
888
889 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
890 if (releaseFence != -1) {
891 close(releaseFence);
892 }
893}
894
895TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_420_888) {
896 BufferDescriptorInfo info{
897 .name = {"VTS_TEMP"},
898 .width = 64,
899 .height = 64,
900 .layerCount = 1,
901 .format = PixelFormat::YCBCR_420_888,
902 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
903 .reservedSize = 0,
904 };
905 auto buffer = allocate(info);
906 ASSERT_NE(nullptr, buffer.get());
907
908 // lock buffer for writing
909 const ARect region{0, 0, info.width, info.height};
910 auto handle = buffer->import();
911 uint8_t* data = nullptr;
912 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
913 region, -1, (void**)&data));
914
915 android_ycbcr yCbCr;
916 int64_t hSubsampling = 0;
917 int64_t vSubsampling = 0;
918 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
919
920 constexpr uint32_t kCbCrSubSampleFactor = 2;
921 ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
922 ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
923
924 fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
925
926 int releaseFence = -1;
927 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
928
929 // lock again for reading
930 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
931 region, releaseFence, (void**)&data));
932 releaseFence = -1;
933
934 ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
935
936 verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
937
938 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
939 if (releaseFence != -1) {
940 close(releaseFence);
941 }
942}
943
944TEST_P(GraphicsMapperStableCTests, Lock_RAW10) {
945 BufferDescriptorInfo info{
946 .name = {"VTS_TEMP"},
947 .width = 64,
948 .height = 64,
949 .layerCount = 1,
950 .format = PixelFormat::RAW10,
951 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
952 .reservedSize = 0,
953 };
954 auto buffer = allocate(info);
955 if (!buffer) {
956 ASSERT_FALSE(isSupported(info));
957 GTEST_SUCCEED() << "RAW10 format is unsupported";
958 return;
959 }
960
961 // lock buffer for writing
962 const ARect region{0, 0, info.width, info.height};
963 auto handle = buffer->import();
964 uint8_t* data = nullptr;
965 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
966 region, -1, (void**)&data));
967
968 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
969 ASSERT_TRUE(decodeResult.has_value());
970 const auto& planeLayouts = *decodeResult;
971
972 ASSERT_EQ(1, planeLayouts.size());
973 auto planeLayout = planeLayouts[0];
974
975 EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
976 EXPECT_EQ(1, planeLayout.horizontalSubsampling);
977 EXPECT_EQ(1, planeLayout.verticalSubsampling);
978
979 ASSERT_EQ(1, planeLayout.components.size());
980 auto planeLayoutComponent = planeLayout.components[0];
981
982 EXPECT_EQ(PlaneLayoutComponentType::RAW,
983 static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
984 EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
985 EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
986
987 int releaseFence = -1;
988 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
989 if (releaseFence != -1) {
990 close(releaseFence);
991 }
992}
993
994TEST_P(GraphicsMapperStableCTests, Lock_RAW12) {
995 BufferDescriptorInfo info{
996 .name = {"VTS_TEMP"},
997 .width = 64,
998 .height = 64,
999 .layerCount = 1,
1000 .format = PixelFormat::RAW12,
1001 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1002 .reservedSize = 0,
1003 };
1004 auto buffer = allocate(info);
1005 if (!buffer) {
1006 ASSERT_FALSE(isSupported(info));
1007 GTEST_SUCCEED() << "RAW12 format is unsupported";
1008 return;
1009 }
1010
1011 // lock buffer for writing
1012 const ARect region{0, 0, info.width, info.height};
1013 auto handle = buffer->import();
1014 uint8_t* data = nullptr;
1015 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1016 region, -1, (void**)&data));
1017
1018 auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
1019 ASSERT_TRUE(decodeResult.has_value());
1020 const auto& planeLayouts = *decodeResult;
1021
1022 ASSERT_EQ(1, planeLayouts.size());
1023 auto planeLayout = planeLayouts[0];
1024
1025 EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
1026 EXPECT_EQ(1, planeLayout.horizontalSubsampling);
1027 EXPECT_EQ(1, planeLayout.verticalSubsampling);
1028
1029 ASSERT_EQ(1, planeLayout.components.size());
1030 auto planeLayoutComponent = planeLayout.components[0];
1031
1032 EXPECT_EQ(PlaneLayoutComponentType::RAW,
1033 static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
1034 EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
1035 EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
1036
1037 int releaseFence = -1;
1038 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1039 if (releaseFence != -1) {
1040 close(releaseFence);
1041 }
1042}
1043
1044TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_P010) {
1045 BufferDescriptorInfo info{
1046 .name = {"VTS_TEMP"},
1047 .width = 64,
1048 .height = 64,
1049 .layerCount = 1,
1050 .format = PixelFormat::YCBCR_P010,
1051 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1052 .reservedSize = 0,
1053 };
1054 auto buffer = allocate(info);
1055 if (!buffer) {
1056 ASSERT_FALSE(isSupported(info));
1057 GTEST_SUCCEED() << "YCBCR_P010 format is unsupported";
1058 return;
1059 }
1060
1061 // lock buffer for writing
1062 const ARect region{0, 0, info.width, info.height};
1063 auto handle = buffer->import();
1064 uint8_t* data = nullptr;
1065 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1066 region, -1, (void**)&data));
1067
1068 YCbCr yCbCr;
1069 ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_P010(*handle, data));
1070
1071 constexpr uint32_t kCbCrSubSampleFactor = 2;
1072 ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
1073 ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.verticalSubSampling);
1074
1075 ASSERT_EQ(0, info.height % 2);
1076
1077 // fill the data
1078 fillYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
1079 yCbCr.verticalSubSampling);
1080 // verify the YCbCr data
1081 verifyYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
1082 yCbCr.verticalSubSampling);
1083
1084 int releaseFence = -1;
1085 ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1086 if (releaseFence != -1) {
1087 close(releaseFence);
1088 }
1089}
1090
1091TEST_P(GraphicsMapperStableCTests, LockBadAccessRegion) {
1092 auto buffer = allocateGeneric();
1093 ASSERT_NE(nullptr, buffer);
1094 const auto& info = buffer->info();
1095
1096 // lock buffer for writing
1097 const ARect region{0, 0, info.width * 2, info.height * 2};
1098 auto handle = buffer->import();
1099 uint8_t* data = nullptr;
1100 EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
1101 region, -1, (void**)&data));
1102}
1103
1104TEST_P(GraphicsMapperStableCTests, UnlockNegative) {
1105 native_handle_t* invalidHandle = nullptr;
1106 int releaseFence = -1;
1107 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(invalidHandle, &releaseFence))
1108 << "unlock with nullptr did not fail with BAD_BUFFER";
1109
1110 invalidHandle = native_handle_create(0, 0);
1111 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(invalidHandle, &releaseFence))
1112 << "unlock with invalid handle did not fail with BAD_BUFFER";
1113 native_handle_delete(invalidHandle);
1114
1115 auto buffer = allocateGeneric();
1116 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(buffer->rawHandle(), &releaseFence))
1117 << "unlock with un-imported handle did not fail with BAD_BUFFER";
1118}
1119
1120TEST_P(GraphicsMapperStableCTests, UnlockNotImported) {
1121 int releaseFence = -1;
1122 auto buffer = allocateGeneric();
1123 ASSERT_TRUE(buffer);
1124 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(buffer->rawHandle(), &releaseFence))
1125 << "unlock with un-imported handle did not fail with BAD_BUFFER";
1126}
1127
1128TEST_P(GraphicsMapperStableCTests, UnlockNotLocked) {
1129 int releaseFence = -1;
1130 auto buffer = allocateGeneric();
1131 ASSERT_TRUE(buffer);
1132 auto bufferHandle = buffer->import();
1133 ASSERT_TRUE(bufferHandle);
1134 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*bufferHandle, &releaseFence))
1135 << "unlock with unlocked handle did not fail with BAD_BUFFER";
1136}
1137
1138TEST_P(GraphicsMapperStableCTests, LockUnlockNested) {
1139 auto buffer = allocateGeneric();
1140 ASSERT_TRUE(buffer);
1141 auto bufferHandle = buffer->import();
1142 ASSERT_TRUE(bufferHandle);
1143 const ARect region{0, 0, buffer->info().width, buffer->info().height};
1144 auto usage = static_cast<int64_t>(buffer->info().usage);
1145 auto handle = buffer->import();
1146 uint8_t* data = nullptr;
1147 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, usage, region, -1, (void**)&data));
1148 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, usage, region, -1, (void**)&data))
1149 << "Second lock failed";
1150 int releaseFence = -1;
1151 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
1152 if (releaseFence != -1) {
1153 close(releaseFence);
1154 releaseFence = -1;
1155 }
1156 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence))
1157 << "Second unlock failed";
1158 if (releaseFence != -1) {
1159 close(releaseFence);
1160 releaseFence = -1;
1161 }
1162 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*handle, &releaseFence))
1163 << "Third, unmatched, unlock should have failed with BAD_BUFFER";
1164}
1165
1166TEST_P(GraphicsMapperStableCTests, FlushRereadBasic) {
1167 auto buffer = allocateGeneric();
1168 ASSERT_TRUE(buffer);
1169 auto bufferHandle = buffer->import();
1170 ASSERT_TRUE(bufferHandle);
1171 const auto& info = buffer->info();
1172 const auto stride = buffer->stride();
1173 const ARect region{0, 0, buffer->info().width, buffer->info().height};
1174
1175 auto writeHandle = buffer->import();
1176 auto readHandle = buffer->import();
1177 ASSERT_TRUE(writeHandle && readHandle);
1178
1179 // lock buffer for writing
1180
1181 uint8_t* writeData;
1182 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1183 mapper()->v5.lock(*writeHandle, static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN),
1184 region, -1, (void**)&writeData));
1185
1186 uint8_t* readData;
1187 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1188 mapper()->v5.lock(*readHandle, static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN),
1189 region, -1, (void**)&readData));
1190
1191 fillRGBA8888(writeData, info.height, stride * 4, info.width * 4);
1192
1193 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.flushLockedBuffer(*writeHandle));
1194 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.rereadLockedBuffer(*readHandle));
1195
1196 ASSERT_NO_FATAL_FAILURE(
1197 verifyRGBA8888(*readHandle, readData, info.height, stride * 4, info.width * 4));
1198
1199 int releaseFence = -1;
1200
1201 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*readHandle, &releaseFence));
1202 if (releaseFence != -1) {
1203 close(releaseFence);
1204 releaseFence = -1;
1205 }
1206
1207 EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*writeHandle, &releaseFence));
1208 if (releaseFence != -1) {
1209 close(releaseFence);
1210 releaseFence = -1;
1211 }
1212}
1213
1214TEST_P(GraphicsMapperStableCTests, FlushLockedBufferBadBuffer) {
1215 // Amazingly this is enough to make the compiler happy even though flushLockedBuffer
1216 // is _Nonnull :shrug:
1217 buffer_handle_t badBuffer = nullptr;
1218 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.flushLockedBuffer(badBuffer));
1219}
1220
1221TEST_P(GraphicsMapperStableCTests, RereadLockedBufferBadBuffer) {
1222 buffer_handle_t badBuffer = nullptr;
1223 EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.rereadLockedBuffer(badBuffer));
1224}
1225
1226TEST_P(GraphicsMapperStableCTests, GetBufferId) {
1227 auto buffer = allocateGeneric();
1228 auto bufferHandle = buffer->import();
1229 auto bufferId = getStandardMetadata<StandardMetadataType::BUFFER_ID>(*bufferHandle);
1230 ASSERT_TRUE(bufferId.has_value());
1231
1232 auto buffer2 = allocateGeneric();
1233 auto bufferHandle2 = buffer2->import();
1234 auto bufferId2 = getStandardMetadata<StandardMetadataType::BUFFER_ID>(*bufferHandle2);
1235 ASSERT_TRUE(bufferId2.has_value());
1236
1237 EXPECT_NE(*bufferId, *bufferId2);
1238}
1239
1240TEST_P(GraphicsMapperStableCTests, GetName) {
1241 auto buffer = allocate({
1242 .name = {"Hello, World!"},
1243 .width = 64,
1244 .height = 64,
1245 .layerCount = 1,
1246 .format = PixelFormat::RGBA_8888,
1247 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1248 .reservedSize = 0,
1249 });
1250 auto bufferHandle = buffer->import();
1251 auto name = getStandardMetadata<StandardMetadataType::NAME>(*bufferHandle);
1252 ASSERT_TRUE(name.has_value());
1253 EXPECT_EQ(*name, "Hello, World!");
1254}
1255
1256TEST_P(GraphicsMapperStableCTests, GetWidthHeight) {
1257 auto buffer = allocate({
1258 .name = {"Hello, World!"},
1259 .width = 64,
1260 .height = 128,
1261 .layerCount = 1,
1262 .format = PixelFormat::RGBA_8888,
1263 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1264 .reservedSize = 0,
1265 });
1266 auto bufferHandle = buffer->import();
1267 auto value = getStandardMetadata<StandardMetadataType::WIDTH>(*bufferHandle);
1268 ASSERT_TRUE(value.has_value());
1269 EXPECT_EQ(*value, 64);
1270 value = getStandardMetadata<StandardMetadataType::HEIGHT>(*bufferHandle);
1271 ASSERT_TRUE(value.has_value());
1272 EXPECT_EQ(*value, 128);
1273}
1274
1275TEST_P(GraphicsMapperStableCTests, GetLayerCount) {
1276 auto buffer = allocateGeneric();
1277 auto bufferHandle = buffer->import();
1278 auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(*bufferHandle);
1279 ASSERT_TRUE(value.has_value());
1280 EXPECT_EQ(*value, buffer->info().layerCount);
1281}
1282
1283TEST_P(GraphicsMapperStableCTests, GetPixelFormatRequested) {
1284 auto buffer = allocateGeneric();
1285 auto bufferHandle = buffer->import();
1286 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(*bufferHandle);
1287 ASSERT_TRUE(value.has_value());
1288 EXPECT_EQ(*value, buffer->info().format);
1289}
1290
1291TEST_P(GraphicsMapperStableCTests, GetPixelFormatFourCC) {
1292 auto buffer = allocate({
1293 .name = {"Hello, World!"},
1294 .width = 64,
1295 .height = 128,
1296 .layerCount = 1,
1297 .format = PixelFormat::RGBA_8888,
1298 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1299 .reservedSize = 0,
1300 });
1301 {
1302 auto bufferHandle = buffer->import();
1303 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(*bufferHandle);
1304 ASSERT_TRUE(value.has_value());
1305 EXPECT_EQ(*value, DRM_FORMAT_ABGR8888);
1306 }
1307
1308 buffer = allocate({
1309 .name = {"yv12"},
1310 .width = 64,
1311 .height = 128,
1312 .layerCount = 1,
1313 .format = PixelFormat::YV12,
1314 .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
1315 .reservedSize = 0,
1316 });
1317 {
1318 auto bufferHandle = buffer->import();
1319 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(*bufferHandle);
1320 ASSERT_TRUE(value.has_value());
1321 EXPECT_EQ(*value, DRM_FORMAT_YVU420);
1322 }
1323}
1324
1325TEST_P(GraphicsMapperStableCTests, GetPixelFormatModifier) {
1326 auto buffer = allocateGeneric();
1327 auto bufferHandle = buffer->import();
1328 auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(*bufferHandle);
1329 ASSERT_TRUE(value.has_value());
1330 // Only the upper 8-bits are defined and is just the vendor ID, the lower 56 bits are
1331 // then vendor specific. So there's not anything useful to assert here beyond just that
1332 // we successfully queried a value
1333}
1334
1335TEST_P(GraphicsMapperStableCTests, GetUsage) {
1336 auto buffer = allocateGeneric();
1337 auto bufferHandle = buffer->import();
1338 auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
1339 ASSERT_TRUE(value.has_value());
1340 EXPECT_EQ(buffer->info().usage, *value);
1341}
1342
1343TEST_P(GraphicsMapperStableCTests, GetAllocationSize) {
1344 auto buffer = allocateGeneric();
1345 auto bufferHandle = buffer->import();
1346 auto value = getStandardMetadata<StandardMetadataType::ALLOCATION_SIZE>(*bufferHandle);
1347 ASSERT_TRUE(value.has_value());
1348 const auto estimatedSize = buffer->stride() * buffer->info().height * 4;
1349 // This buffer has CPU usage, so we expect at least stride * height * 4 since it should be
1350 // generally linear uncompressed.
1351 EXPECT_GE(*value, estimatedSize)
1352 << "Expected allocation size to be at least stride * height * 4bpp";
1353 // Might need refining, but hopefully this a generous-enough upper-bound?
1354 EXPECT_LT(*value, estimatedSize * 2)
1355 << "Expected allocation size to less than double stride * height * 4bpp";
1356}
1357
1358TEST_P(GraphicsMapperStableCTests, GetProtectedContent) {
1359 const BufferDescriptorInfo info{
1360 .name = {"prot8888"},
1361 .width = 64,
1362 .height = 64,
1363 .layerCount = 1,
1364 .format = PixelFormat::RGBA_8888,
1365 .usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY,
1366 .reservedSize = 0,
1367 };
1368 auto buffer = allocate(info);
1369 if (!buffer) {
1370 ASSERT_FALSE(isSupported(info))
1371 << "Allocation of trivial sized buffer failed, so isSupported() must be false";
1372 GTEST_SUCCEED() << "PROTECTED RGBA_8888 is unsupported";
1373 return;
1374 }
1375 auto bufferHandle = buffer->import();
1376 auto value = getStandardMetadata<StandardMetadataType::PROTECTED_CONTENT>(*bufferHandle);
1377 ASSERT_TRUE(value.has_value());
1378 EXPECT_EQ(*value, 1);
1379}
1380
1381TEST_P(GraphicsMapperStableCTests, GetCompression) {
1382 auto buffer = allocateGeneric();
1383 ASSERT_TRUE(buffer);
1384 auto bufferHandle = buffer->import();
1385 ASSERT_TRUE(bufferHandle);
1386 auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(*bufferHandle);
1387 ASSERT_TRUE(value.has_value());
1388 EXPECT_EQ(gralloc4::Compression_None.name, value->name);
1389 EXPECT_EQ(gralloc4::Compression_None.value, value->value);
1390}
1391
1392TEST_P(GraphicsMapperStableCTests, GetInterlaced) {
1393 auto buffer = allocateGeneric();
1394 ASSERT_TRUE(buffer);
1395 auto bufferHandle = buffer->import();
1396 ASSERT_TRUE(bufferHandle);
1397 auto value = getStandardMetadata<StandardMetadataType::INTERLACED>(*bufferHandle);
1398 ASSERT_TRUE(value.has_value());
1399 EXPECT_EQ(gralloc4::Interlaced_None.name, value->name);
1400 EXPECT_EQ(gralloc4::Interlaced_None.value, value->value);
1401}
1402
1403TEST_P(GraphicsMapperStableCTests, GetChromaSiting) {
1404 auto buffer = allocateGeneric();
1405 ASSERT_TRUE(buffer);
1406 auto bufferHandle = buffer->import();
1407 ASSERT_TRUE(bufferHandle);
1408 auto value = getStandardMetadata<StandardMetadataType::CHROMA_SITING>(*bufferHandle);
1409 ASSERT_TRUE(value.has_value());
1410 EXPECT_EQ(gralloc4::ChromaSiting_None.name, value->name);
1411 EXPECT_EQ(gralloc4::ChromaSiting_None.value, value->value);
1412}
1413
1414TEST_P(GraphicsMapperStableCTests, GetPlaneLayouts) {
1415 auto buffer = allocateGeneric();
1416 ASSERT_TRUE(buffer);
1417 auto bufferHandle = buffer->import();
1418 ASSERT_TRUE(bufferHandle);
1419 auto value = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*bufferHandle);
1420 ASSERT_TRUE(value.has_value());
1421 ASSERT_NO_FATAL_FAILURE(verifyRGBA8888PlaneLayouts(*value));
1422}
1423
1424TEST_P(GraphicsMapperStableCTests, GetCrop) {
1425 auto buffer = allocateGeneric();
1426 ASSERT_TRUE(buffer);
1427 auto bufferHandle = buffer->import();
1428 ASSERT_TRUE(bufferHandle);
1429 auto value = getStandardMetadata<StandardMetadataType::CROP>(*bufferHandle);
1430 ASSERT_TRUE(value.has_value());
1431 EXPECT_EQ(1, value->size());
1432 const Rect expected{0, 0, buffer->info().width, buffer->info().height};
1433 EXPECT_EQ(expected, value->at(0));
1434}
1435
1436TEST_P(GraphicsMapperStableCTests, GetSetDataspace) {
1437 auto buffer = allocateGeneric();
1438 ASSERT_TRUE(buffer);
1439 auto bufferHandle = buffer->import();
1440 ASSERT_TRUE(bufferHandle);
1441 auto value = getStandardMetadata<StandardMetadataType::DATASPACE>(*bufferHandle);
1442 ASSERT_TRUE(value.has_value());
1443 EXPECT_EQ(Dataspace::UNKNOWN, *value);
1444 EXPECT_EQ(AIMAPPER_ERROR_NONE, setStandardMetadata<StandardMetadataType::DATASPACE>(
1445 *bufferHandle, Dataspace::DISPLAY_P3));
1446 value = getStandardMetadata<StandardMetadataType::DATASPACE>(*bufferHandle);
1447 ASSERT_TRUE(value.has_value());
1448 EXPECT_EQ(Dataspace::DISPLAY_P3, *value);
1449}
1450
1451TEST_P(GraphicsMapperStableCTests, GetSetBlendMode) {
1452 auto buffer = allocateGeneric();
1453 ASSERT_TRUE(buffer);
1454 auto bufferHandle = buffer->import();
1455 ASSERT_TRUE(bufferHandle);
1456 auto value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(*bufferHandle);
1457 ASSERT_TRUE(value.has_value());
1458 EXPECT_EQ(BlendMode::INVALID, *value);
1459 EXPECT_EQ(AIMAPPER_ERROR_NONE, setStandardMetadata<StandardMetadataType::BLEND_MODE>(
1460 *bufferHandle, BlendMode::COVERAGE));
1461 value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(*bufferHandle);
1462 ASSERT_TRUE(value.has_value());
1463 EXPECT_EQ(BlendMode::COVERAGE, *value);
1464}
1465
1466TEST_P(GraphicsMapperStableCTests, GetSetSmpte2086) {
1467 auto buffer = allocateGeneric();
1468 ASSERT_TRUE(buffer);
1469 auto bufferHandle = buffer->import();
1470 ASSERT_TRUE(bufferHandle);
1471 auto value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
1472 ASSERT_TRUE(value.has_value());
1473 EXPECT_FALSE(value->has_value());
1474
1475 // TODO: Maybe use something resembling real values, but validation isn't supposed to happen
1476 // here anyway so :shrug:
1477 const Smpte2086 awesomeHdr{
1478 XyColor{1.f, 1.f}, XyColor{2.f, 2.f}, XyColor{3.f, 3.f},
1479 XyColor{400.f, 1000.f}, 100000.0f, 0.0001f,
1480 };
1481 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1482 setStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle, awesomeHdr));
1483 value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
1484 ASSERT_TRUE(value.has_value());
1485 ASSERT_TRUE(value->has_value());
1486 EXPECT_EQ(awesomeHdr, *value);
1487
1488 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1489 setStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle, std::nullopt));
1490 value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
1491 ASSERT_TRUE(value.has_value());
1492 EXPECT_FALSE(value->has_value());
1493}
1494
1495TEST_P(GraphicsMapperStableCTests, GetCta861_3) {
1496 auto buffer = allocateGeneric();
1497 ASSERT_TRUE(buffer);
1498 auto bufferHandle = buffer->import();
1499 ASSERT_TRUE(bufferHandle);
1500 auto value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
1501 ASSERT_TRUE(value.has_value());
1502 EXPECT_FALSE(value->has_value());
1503
1504 const Cta861_3 genericHlgish{1000.f, 140.f};
1505 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1506 setStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle, genericHlgish));
1507 value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
1508 ASSERT_TRUE(value.has_value());
1509 ASSERT_TRUE(value->has_value());
1510 EXPECT_EQ(genericHlgish, *value);
1511
1512 EXPECT_EQ(AIMAPPER_ERROR_NONE,
1513 setStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle, std::nullopt));
1514 value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
1515 ASSERT_TRUE(value.has_value());
1516 EXPECT_FALSE(value->has_value());
1517}
1518
1519TEST_P(GraphicsMapperStableCTests, GetSmpte2094_10) {
1520 auto buffer = allocateGeneric();
1521 ASSERT_TRUE(buffer);
1522 auto bufferHandle = buffer->import();
1523 ASSERT_TRUE(bufferHandle);
1524 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_10>(*bufferHandle);
1525 if (value.has_value()) {
1526 EXPECT_FALSE(value->has_value());
1527 }
1528}
1529
1530TEST_P(GraphicsMapperStableCTests, GetSmpte2094_40) {
1531 auto buffer = allocateGeneric();
1532 ASSERT_TRUE(buffer);
1533 auto bufferHandle = buffer->import();
1534 ASSERT_TRUE(bufferHandle);
1535 auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(*bufferHandle);
1536 ASSERT_TRUE(value.has_value());
1537 EXPECT_FALSE(value->has_value());
1538}
1539
1540std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> getIAllocatorsAtLeastVersion(
1541 int32_t minVersion) {
1542 auto instanceNames = getAidlHalInstanceNames(IAllocator::descriptor);
1543 std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> filteredInstances;
1544 filteredInstances.reserve(instanceNames.size());
1545 for (const auto& name : instanceNames) {
1546 auto allocator =
1547 IAllocator::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(name.c_str())));
1548 int32_t version = 0;
1549 if (allocator->getInterfaceVersion(&version).isOk()) {
1550 if (version >= minVersion) {
1551 filteredInstances.emplace_back(name, std::move(allocator));
1552 }
1553 }
1554 }
1555 return filteredInstances;
1556}
1557
1558GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperStableCTests);
1559INSTANTIATE_TEST_CASE_P(PerInstance, GraphicsMapperStableCTests,
1560 testing::ValuesIn(getIAllocatorsAtLeastVersion(2)),
1561 [](auto info) -> std::string {
1562 std::string name =
1563 std::to_string(info.index) + "/" + std::get<0>(info.param);
1564 return Sanitize(name);
1565 });