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