• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #undef LOG_TAG
18 #define LOG_TAG "VtsHalGraphicsMapperStableC_TargetTest"
19 
20 #include <aidl/Vintf.h>
21 #include <aidl/android/hardware/graphics/allocator/AllocationError.h>
22 #include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
23 #include <aidl/android/hardware/graphics/allocator/IAllocator.h>
24 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
25 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
26 #include <aidlcommonsupport/NativeHandle.h>
27 #include <android/binder_enums.h>
28 #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 
46 using namespace aidl::android::hardware::graphics::allocator;
47 using namespace aidl::android::hardware::graphics::common;
48 using namespace android;
49 using namespace android::hardware;
50 using namespace ::android::hardware::graphics::mapper;
51 
52 typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper* _Nullable* _Nonnull outImplementation);
53 
operator |(BufferUsage lhs,BufferUsage rhs)54 inline 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 
operator |=(BufferUsage & lhs,BufferUsage rhs)59 inline BufferUsage& operator|=(BufferUsage& lhs, BufferUsage rhs) {
60     lhs = lhs | rhs;
61     return lhs;
62 }
63 
64 struct YCbCr {
65     android_ycbcr yCbCr;
66     int64_t horizontalSubSampling;
67     int64_t verticalSubSampling;
68 };
69 
70 constexpr const char* STANDARD_METADATA_NAME =
71         "android.hardware.graphics.common.StandardMetadataType";
72 
isStandardMetadata(AIMapper_MetadataType metadataType)73 static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
74     return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
75 }
76 
toString(const std::vector<StandardMetadataType> types)77 static 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 
88 class BufferHandle {
89     AIMapper* mIMapper;
90     buffer_handle_t mHandle = nullptr;
91 
92   public:
BufferHandle(AIMapper * mapper,native_handle_t * rawHandle)93     explicit BufferHandle(AIMapper* mapper, native_handle_t* rawHandle) : mIMapper(mapper) {
94         EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.importBuffer(rawHandle, &mHandle));
95     }
96 
BufferHandle(BufferHandle && other)97     explicit BufferHandle(BufferHandle&& other) { *this = std::move(other); }
98 
operator =(BufferHandle && other)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 
~BufferHandle()107     ~BufferHandle() { reset(); }
108 
operator bool() const109     constexpr explicit operator bool() const noexcept { return mHandle != nullptr; }
110 
operator *() const111     buffer_handle_t operator*() const noexcept { return mHandle; }
112 
reset()113     void reset() {
114         if (mHandle != nullptr) {
115             EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.freeBuffer(mHandle));
116             mHandle = nullptr;
117         }
118     }
119 };
120 
121 class 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 
BufferAllocation(AIMapper * mapper,native_handle_t * handle,uint32_t stride,const BufferDescriptorInfo & info)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 
~BufferAllocation()135     ~BufferAllocation() {
136         if (mRawHandle == nullptr) return;
137 
138         native_handle_close(mRawHandle);
139         native_handle_delete(mRawHandle);
140     }
141 
stride() const142     uint32_t stride() const { return mStride; }
info() const143     const BufferDescriptorInfo& info() const { return mInfo; }
144 
import()145     BufferHandle import() { return BufferHandle{mIMapper, mRawHandle}; }
146 
rawHandle() const147     const native_handle_t* rawHandle() const { return mRawHandle; }
148 };
149 
150 class 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     int32_t* mIMapperHALVersion = nullptr;
158 
159   protected:
Initialize(std::shared_ptr<IAllocator> allocator)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);
175         mIMapperHALVersion = (int32_t*)dlsym(so, "ANDROID_HAL_MAPPER_VERSION");
176     }
177 
178   public:
getIMapperLoader() const179     AIMapper_loadIMapperFn getIMapperLoader() const { return mIMapperLoader; }
getHalVersion() const180     int32_t* getHalVersion() const { return mIMapperHALVersion; }
181 
allocate(const BufferDescriptorInfo & descriptorInfo)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 
allocateGeneric()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 
isSupported(const BufferDescriptorInfo & descriptorInfo)212     bool isSupported(const BufferDescriptorInfo& descriptorInfo) {
213         bool ret = false;
214         EXPECT_TRUE(mAllocator->isSupported(descriptorInfo, &ret).isOk());
215         return ret;
216     }
217 
mapper() const218     AIMapper* mapper() const { return mIMapper; }
219 
220     template <StandardMetadataType T>
getStandardMetadata(buffer_handle_t bufferHandle)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         }
240         if (sizeRequired < 0 || sizeRequired > buffer.size()) {
241             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>
setStandardMetadata(buffer_handle_t bufferHandle,const typename StandardMetadata<T>::value_type & value)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 
verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout> & planeLayouts)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 
fillRGBA8888(uint8_t * data,uint32_t height,size_t strideInBytes,size_t widthInBytes)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 
verifyRGBA8888(const buffer_handle_t bufferHandle,const uint8_t * data,uint32_t height,size_t strideInBytes,size_t widthInBytes)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 
traverseYCbCrData(const android_ycbcr & yCbCr,int32_t width,int32_t height,int64_t hSubsampling,int64_t vSubsampling,std::function<void (uint8_t *,uint8_t)> traverseFuncion)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 
fillYCbCrData(const android_ycbcr & yCbCr,int32_t width,int32_t height,int64_t hSubsampling,int64_t vSubsampling)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 
verifyYCbCrData(const android_ycbcr & yCbCr,int32_t width,int32_t height,int64_t hSubsampling,int64_t vSubsampling)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 
bitsToBytes(int64_t bits)382     constexpr uint64_t bitsToBytes(int64_t bits) { return bits / 8; }
bytesToBits(int64_t bytes)383     constexpr uint64_t bytesToBits(int64_t bytes) { return bytes * 8; }
384 
getAndroidYCbCr(buffer_handle_t bufferHandle,uint8_t * data,android_ycbcr * outYCbCr,int64_t * hSubsampling,int64_t * vSubsampling)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 
getAndroidYCbCr_P010(const native_handle_t * bufferHandle,uint8_t * data)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 
554 class GraphicsMapperStableCTests
555     : public GraphicsTestsBase,
556       public ::testing::TestWithParam<std::tuple<std::string, std::shared_ptr<IAllocator>>> {
557   public:
SetUp()558     void SetUp() override { Initialize(std::get<1>(GetParam())); }
559 
TearDown()560     void TearDown() override {}
561 };
562 
TEST_P(GraphicsMapperStableCTests,VersionChecks)563 TEST_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 
TEST_P(GraphicsMapperStableCTests,AllV5CallbacksDefined)572 TEST_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 
TEST_P(GraphicsMapperStableCTests,DualLoadIsIdentical)591 TEST_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 
TEST_P(GraphicsMapperStableCTests,CanAllocate)612 TEST_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 
TEST_P(GraphicsMapperStableCTests,ImportFreeBuffer)626 TEST_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  */
TEST_P(GraphicsMapperStableCTests,ImportFreeBufferSingleton)651 TEST_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  */
TEST_P(GraphicsMapperStableCTests,ImportBufferNegative)676 TEST_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  */
TEST_P(GraphicsMapperStableCTests,FreeBufferNegative)691 TEST_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  */
TEST_P(GraphicsMapperStableCTests,LockUnlockBasic)709 TEST_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  */
TEST_P(GraphicsMapperStableCTests,Lock_YCRCB_420_SP)754 TEST_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 
TEST_P(GraphicsMapperStableCTests,YV12SubsampleMetadata)813 TEST_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 
TEST_P(GraphicsMapperStableCTests,Lock_YV12)872 TEST_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 
TEST_P(GraphicsMapperStableCTests,Lock_YCBCR_420_888)926 TEST_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 
TEST_P(GraphicsMapperStableCTests,Lock_RAW10)975 TEST_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 
TEST_P(GraphicsMapperStableCTests,Lock_RAW12)1025 TEST_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 
TEST_P(GraphicsMapperStableCTests,Lock_YCBCR_P010)1075 TEST_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 
TEST_P(GraphicsMapperStableCTests,LockBadAccessRegion)1122 TEST_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 
TEST_P(GraphicsMapperStableCTests,UnlockNegative)1135 TEST_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 
TEST_P(GraphicsMapperStableCTests,UnlockNotImported)1151 TEST_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 
TEST_P(GraphicsMapperStableCTests,UnlockNotLocked)1159 TEST_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 
TEST_P(GraphicsMapperStableCTests,LockUnlockNested)1169 TEST_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 
TEST_P(GraphicsMapperStableCTests,FlushRereadBasic)1197 TEST_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 
TEST_P(GraphicsMapperStableCTests,FlushLockedBufferBadBuffer)1245 TEST_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 
TEST_P(GraphicsMapperStableCTests,RereadLockedBufferBadBuffer)1252 TEST_P(GraphicsMapperStableCTests, RereadLockedBufferBadBuffer) {
1253     buffer_handle_t badBuffer = nullptr;
1254     EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.rereadLockedBuffer(badBuffer));
1255 }
1256 
TEST_P(GraphicsMapperStableCTests,GetBufferId)1257 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetName)1271 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetWidthHeight)1287 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetLayerCount)1306 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetPixelFormatRequested)1314 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetPixelFormatFourCC)1322 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetPixelFormatModifier)1356 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetUsage)1366 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetAllocationSize)1374 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetProtectedContent)1389 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetCompression)1412 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetInterlaced)1423 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetChromaSiting)1434 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetPlaneLayouts)1445 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetCrop)1455 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetSetDataspace)1467 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetSetBlendMode)1482 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetSetSmpte2086)1497 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetCta861_3)1526 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetSmpte2094_10)1550 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetSmpte2094_40)1561 TEST_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);
1567     if (value.has_value()) {
1568         EXPECT_FALSE(value->has_value());
1569     }
1570 }
1571 
TEST_P(GraphicsMapperStableCTests,GetStride)1572 TEST_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 
TEST_P(GraphicsMapperStableCTests,SupportsRequiredGettersSetters)1582 TEST_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,
1612             StandardMetadataType::STRIDE,
1613     };
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  */
TEST_P(GraphicsMapperStableCTests,CheckRequiredSettersIfHasGetters)1652 TEST_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 
TEST_P(GraphicsMapperStableCTests,ListSupportedWorks)1681 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetMetadataBadValue)1726 TEST_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 
TEST_P(GraphicsMapperStableCTests,GetUnsupportedMetadata)1743 TEST_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);
1759 }
1760 
getIAllocatorsAtLeastVersion(int32_t minVersion)1761 std::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 
1779 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperStableCTests);
1780 INSTANTIATE_TEST_CASE_P(PerInstance, GraphicsMapperStableCTests,
1781                         testing::ValuesIn(getIAllocatorsAtLeastVersion(2)),
__anon9cc5ed4b0502(auto info) 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                         });