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