xref: /aosp_15_r20/external/minigbm/cros_gralloc/mapper_stablec/Mapper.cpp (revision d95af8df99a05bcb8679a54dc3ab8e5cd312b38e)
1 /*
2  * Copyright 2022 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 #include <aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.h>
8 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
9 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
10 #include <aidl/android/hardware/graphics/common/StandardMetadataType.h>
11 #include <android-base/unique_fd.h>
12 #include <android/hardware/graphics/mapper/IMapper.h>
13 #include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
14 #include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
15 #include <cutils/native_handle.h>
16 #include <gralloctypes/Gralloc4.h>
17 
18 #include <memory>
19 
20 #include "cros_gralloc/cros_gralloc_driver.h"
21 #include "cros_gralloc/cros_gralloc_handle.h"
22 #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
23 
24 using namespace ::aidl::android::hardware::graphics::common;
25 using namespace ::android::hardware::graphics::mapper;
26 using ::aidl::android::hardware::graphics::allocator::BufferDescriptorInfo;
27 using ::android::base::unique_fd;
28 
29 #define REQUIRE_DRIVER()                                           \
30     if (!mDriver) {                                                \
31         ALOGE("Failed to %s. Driver is uninitialized.", __func__); \
32         return AIMAPPER_ERROR_NO_RESOURCES;                        \
33     }
34 
35 #define VALIDATE_BUFFER_HANDLE(bufferHandle)                    \
36     if (!(bufferHandle)) {                                      \
37         ALOGE("Failed to %s. Null buffer_handle_t.", __func__); \
38         return AIMAPPER_ERROR_BAD_BUFFER;                       \
39     }
40 
41 #define VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) \
42     REQUIRE_DRIVER()                                    \
43     VALIDATE_BUFFER_HANDLE(bufferHandle)
44 
45 static_assert(CROS_GRALLOC_BUFFER_METADATA_MAX_NAME_SIZE >=
46                       decltype(std::declval<BufferDescriptorInfo>().name){}.size(),
47               "Metadata name storage too small to fit a BufferDescriptorInfo::name");
48 
49 constexpr const char* STANDARD_METADATA_NAME =
50         "android.hardware.graphics.common.StandardMetadataType";
51 
isStandardMetadata(AIMapper_MetadataType metadataType)52 static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
53     return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
54 }
55 
56 class CrosGrallocMapperV5 final : public vendor::mapper::IMapperV5Impl {
57   private:
58     std::shared_ptr<cros_gralloc_driver> mDriver = cros_gralloc_driver::get_instance();
59 
60   public:
61     explicit CrosGrallocMapperV5() = default;
62     ~CrosGrallocMapperV5() override = default;
63 
64     AIMapper_Error importBuffer(const native_handle_t* _Nonnull handle,
65                                 buffer_handle_t _Nullable* _Nonnull outBufferHandle) override;
66 
67     AIMapper_Error freeBuffer(buffer_handle_t _Nonnull buffer) override;
68 
69     AIMapper_Error getTransportSize(buffer_handle_t _Nonnull buffer, uint32_t* _Nonnull outNumFds,
70                                     uint32_t* _Nonnull outNumInts) override;
71 
72     AIMapper_Error lock(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage, ARect accessRegion,
73                         int acquireFence, void* _Nullable* _Nonnull outData) override;
74 
75     AIMapper_Error unlock(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) override;
76 
77     AIMapper_Error flushLockedBuffer(buffer_handle_t _Nonnull buffer) override;
78 
79     AIMapper_Error rereadLockedBuffer(buffer_handle_t _Nonnull buffer) override;
80 
81     int32_t getMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType,
82                         void* _Nonnull outData, size_t outDataSize) override;
83 
84     int32_t getStandardMetadata(buffer_handle_t _Nonnull buffer, int64_t standardMetadataType,
85                                 void* _Nonnull outData, size_t outDataSize) override;
86 
87     AIMapper_Error setMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType,
88                                const void* _Nonnull metadata, size_t metadataSize) override;
89 
90     AIMapper_Error setStandardMetadata(buffer_handle_t _Nonnull buffer,
91                                        int64_t standardMetadataType, const void* _Nonnull metadata,
92                                        size_t metadataSize) override;
93 
94     AIMapper_Error listSupportedMetadataTypes(
95             const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
96             size_t* _Nonnull outNumberOfDescriptions) override;
97 
98     AIMapper_Error dumpBuffer(buffer_handle_t _Nonnull bufferHandle,
99                               AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
100                               void* _Null_unspecified context) override;
101 
102     AIMapper_Error dumpAllBuffers(AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
103                                   AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
104                                   void* _Null_unspecified context) override;
105 
106     AIMapper_Error getReservedRegion(buffer_handle_t _Nonnull buffer,
107                                      void* _Nullable* _Nonnull outReservedRegion,
108                                      uint64_t* _Nonnull outReservedSize) override;
109 
110   private:
111     template <typename F, StandardMetadataType TYPE>
112     int32_t getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide,
113                                 StandardMetadata<TYPE>);
114 
115     template <StandardMetadataType TYPE>
116     AIMapper_Error setStandardMetadata(cros_gralloc_buffer* crosBuffer,
117                                        typename StandardMetadata<TYPE>::value_type&& value);
118 
119     void dumpBuffer(
120             const cros_gralloc_buffer* crosBuffer,
121             std::function<void(AIMapper_MetadataType, const std::vector<uint8_t>&)> callback);
122 };
123 
importBuffer(const native_handle_t * _Nonnull bufferHandle,buffer_handle_t _Nullable * _Nonnull outBufferHandle)124 AIMapper_Error CrosGrallocMapperV5::importBuffer(
125         const native_handle_t* _Nonnull bufferHandle,
126         buffer_handle_t _Nullable* _Nonnull outBufferHandle) {
127     REQUIRE_DRIVER()
128 
129     if (!bufferHandle || bufferHandle->numFds == 0) {
130         ALOGE("Failed to importBuffer. Bad handle.");
131         return AIMAPPER_ERROR_BAD_BUFFER;
132     }
133 
134     native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle);
135     if (!importedBufferHandle) {
136         ALOGE("Failed to importBuffer. Handle clone failed: %s.", strerror(errno));
137         return AIMAPPER_ERROR_NO_RESOURCES;
138     }
139 
140     int ret = mDriver->retain(importedBufferHandle);
141     if (ret) {
142         native_handle_close(importedBufferHandle);
143         native_handle_delete(importedBufferHandle);
144         return AIMAPPER_ERROR_NO_RESOURCES;
145     }
146 
147     *outBufferHandle = importedBufferHandle;
148     return AIMAPPER_ERROR_NONE;
149 }
150 
freeBuffer(buffer_handle_t _Nonnull buffer)151 AIMapper_Error CrosGrallocMapperV5::freeBuffer(buffer_handle_t _Nonnull buffer) {
152     VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
153 
154     int ret = mDriver->release(buffer);
155     if (ret) {
156         return AIMAPPER_ERROR_BAD_BUFFER;
157     }
158 
159     native_handle_close(buffer);
160     native_handle_delete(const_cast<native_handle_t*>(buffer));
161     return AIMAPPER_ERROR_NONE;
162 }
163 
getTransportSize(buffer_handle_t _Nonnull bufferHandle,uint32_t * _Nonnull outNumFds,uint32_t * _Nonnull outNumInts)164 AIMapper_Error CrosGrallocMapperV5::getTransportSize(buffer_handle_t _Nonnull bufferHandle,
165                                                      uint32_t* _Nonnull outNumFds,
166                                                      uint32_t* _Nonnull outNumInts) {
167     VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
168 
169     // No local process data is currently stored on the native handle.
170     *outNumFds = bufferHandle->numFds;
171     *outNumInts = bufferHandle->numInts;
172     return AIMAPPER_ERROR_NONE;
173 }
174 
lock(buffer_handle_t _Nonnull bufferHandle,uint64_t cpuUsage,ARect region,int acquireFenceRawFd,void * _Nullable * _Nonnull outData)175 AIMapper_Error CrosGrallocMapperV5::lock(buffer_handle_t _Nonnull bufferHandle, uint64_t cpuUsage,
176                                          ARect region, int acquireFenceRawFd,
177                                          void* _Nullable* _Nonnull outData) {
178     // We take ownership of the FD in all cases, even for errors
179     unique_fd acquireFence(acquireFenceRawFd);
180     VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
181     if (cpuUsage == 0) {
182         ALOGE("Failed to lock. Bad cpu usage: %" PRIu64 ".", cpuUsage);
183         return AIMAPPER_ERROR_BAD_VALUE;
184     }
185 
186     uint32_t mapUsage = cros_gralloc_convert_map_usage(cpuUsage);
187 
188     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
189     if (crosHandle == nullptr) {
190         ALOGE("Failed to lock. Invalid handle.");
191         return AIMAPPER_ERROR_BAD_VALUE;
192     }
193 
194     struct rectangle rect;
195 
196     // An access region of all zeros means the entire buffer.
197     if (region.left == 0 && region.top == 0 && region.right == 0 && region.bottom == 0) {
198         rect = {0, 0, crosHandle->width, crosHandle->height};
199     } else {
200         if (region.left < 0 || region.top < 0 || region.right <= region.left ||
201             region.bottom <= region.top) {
202             ALOGE("Failed to lock. Invalid accessRegion: [%d, %d, %d, %d]", region.left, region.top,
203                   region.right, region.bottom);
204             return AIMAPPER_ERROR_BAD_VALUE;
205         }
206 
207         if (region.right > crosHandle->width) {
208             ALOGE("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).",
209                   region.right, crosHandle->width);
210             return AIMAPPER_ERROR_BAD_VALUE;
211         }
212 
213         if (region.bottom > crosHandle->height) {
214             ALOGE("Failed to lock. Invalid region: height greater than buffer height (%d vs "
215                   "%d).",
216                   region.bottom, crosHandle->height);
217             return AIMAPPER_ERROR_BAD_VALUE;
218         }
219 
220         rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top),
221                 static_cast<uint32_t>(region.right - region.left),
222                 static_cast<uint32_t>(region.bottom - region.top)};
223     }
224 
225     uint8_t* addr[DRV_MAX_PLANES];
226     int32_t status = mDriver->lock(bufferHandle, acquireFence.get(),
227                                    /*close_acquire_fence=*/false, &rect, mapUsage, addr);
228     if (status) {
229         return AIMAPPER_ERROR_BAD_VALUE;
230     }
231 
232     *outData = addr[0];
233     return AIMAPPER_ERROR_NONE;
234 }
235 
unlock(buffer_handle_t _Nonnull buffer,int * _Nonnull releaseFence)236 AIMapper_Error CrosGrallocMapperV5::unlock(buffer_handle_t _Nonnull buffer,
237                                            int* _Nonnull releaseFence) {
238     VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
239     int ret = mDriver->unlock(buffer, releaseFence);
240     if (ret) {
241         ALOGE("Failed to unlock.");
242         return AIMAPPER_ERROR_BAD_BUFFER;
243     }
244     return AIMAPPER_ERROR_NONE;
245 }
246 
flushLockedBuffer(buffer_handle_t _Nonnull buffer)247 AIMapper_Error CrosGrallocMapperV5::flushLockedBuffer(buffer_handle_t _Nonnull buffer) {
248     VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
249     int ret = mDriver->flush(buffer);
250     if (ret) {
251         ALOGE("Failed to flushLockedBuffer. Flush failed.");
252         return AIMAPPER_ERROR_BAD_BUFFER;
253     }
254     return AIMAPPER_ERROR_NONE;
255 }
256 
rereadLockedBuffer(buffer_handle_t _Nonnull buffer)257 AIMapper_Error CrosGrallocMapperV5::rereadLockedBuffer(buffer_handle_t _Nonnull buffer) {
258     VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
259     int ret = mDriver->invalidate(buffer);
260     if (ret) {
261         ALOGE("Failed to rereadLockedBuffer. Failed to invalidate.");
262         return AIMAPPER_ERROR_BAD_BUFFER;
263     }
264 
265     return AIMAPPER_ERROR_NONE;
266 }
267 
getMetadata(buffer_handle_t _Nonnull buffer,AIMapper_MetadataType metadataType,void * _Nonnull outData,size_t outDataSize)268 int32_t CrosGrallocMapperV5::getMetadata(buffer_handle_t _Nonnull buffer,
269                                          AIMapper_MetadataType metadataType, void* _Nonnull outData,
270                                          size_t outDataSize) {
271     // We don't have any vendor-specific metadata, so divert to getStandardMetadata after validating
272     // that this is a standard metadata request
273     if (isStandardMetadata(metadataType)) {
274         return getStandardMetadata(buffer, metadataType.value, outData, outDataSize);
275     }
276     return -AIMAPPER_ERROR_UNSUPPORTED;
277 }
278 
getStandardMetadata(buffer_handle_t _Nonnull bufferHandle,int64_t standardType,void * _Nonnull outData,size_t outDataSize)279 int32_t CrosGrallocMapperV5::getStandardMetadata(buffer_handle_t _Nonnull bufferHandle,
280                                                  int64_t standardType, void* _Nonnull outData,
281                                                  size_t outDataSize) {
282     // Can't use VALIDATE_DRIVER_AND_BUFFER_HANDLE because we need to negate the error
283     // for this call
284     if (!mDriver) {
285         ALOGE("Failed to %s. Driver is uninitialized.", __func__);
286         return -AIMAPPER_ERROR_NO_RESOURCES;
287     }
288     if (!(bufferHandle)) {
289         ALOGE("Failed to %s. Null buffer_handle_t.", __func__);
290         return -AIMAPPER_ERROR_BAD_BUFFER;
291     }
292 
293     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
294     if (!crosHandle) {
295         ALOGE("Failed to get. Invalid handle.");
296         return -AIMAPPER_ERROR_BAD_BUFFER;
297     }
298 
299     int32_t retValue = -AIMAPPER_ERROR_UNSUPPORTED;
300     mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
301         auto provider = [&]<StandardMetadataType T>(auto&& provide) -> int32_t {
302             return getStandardMetadata(crosBuffer, provide, StandardMetadata<T>{});
303         };
304         retValue = provideStandardMetadata(static_cast<StandardMetadataType>(standardType), outData,
305                                            outDataSize, provider);
306     });
307     return retValue;
308 }
309 
310 template <typename F, StandardMetadataType metadataType>
getStandardMetadata(const cros_gralloc_buffer * crosBuffer,F && provide,StandardMetadata<metadataType>)311 int32_t CrosGrallocMapperV5::getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide,
312                                                  StandardMetadata<metadataType>) {
313     if constexpr (metadataType == StandardMetadataType::BUFFER_ID) {
314         return provide(crosBuffer->get_id());
315     }
316     if constexpr (metadataType == StandardMetadataType::NAME) {
317         std::optional<std::string> name;
318         if (crosBuffer->get_name(&name)) {
319             return -AIMAPPER_ERROR_NO_RESOURCES;
320         } else {
321             return provide(*name);
322         }
323     }
324     if constexpr (metadataType == StandardMetadataType::WIDTH) {
325         return provide(crosBuffer->get_width());
326     }
327     if constexpr (metadataType == StandardMetadataType::STRIDE) {
328         return provide(crosBuffer->get_pixel_stride());
329     }
330     if constexpr (metadataType == StandardMetadataType::HEIGHT) {
331         return provide(crosBuffer->get_height());
332     }
333     if constexpr (metadataType == StandardMetadataType::LAYER_COUNT) {
334         return provide(1);
335     }
336     if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_REQUESTED) {
337         return provide(static_cast<PixelFormat>(crosBuffer->get_android_format()));
338     }
339     if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_FOURCC) {
340         return provide(drv_get_standard_fourcc(crosBuffer->get_format()));
341     }
342     if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_MODIFIER) {
343         return provide(crosBuffer->get_format_modifier());
344     }
345     if constexpr (metadataType == StandardMetadataType::USAGE) {
346         return provide(static_cast<BufferUsage>(crosBuffer->get_android_usage()));
347     }
348     if constexpr (metadataType == StandardMetadataType::ALLOCATION_SIZE) {
349         return provide(crosBuffer->get_total_size());
350     }
351     if constexpr (metadataType == StandardMetadataType::PROTECTED_CONTENT) {
352         uint64_t hasProtectedContent =
353                 crosBuffer->get_android_usage() & static_cast<int64_t>(BufferUsage::PROTECTED) ? 1
354                                                                                                : 0;
355         return provide(hasProtectedContent);
356     }
357     if constexpr (metadataType == StandardMetadataType::COMPRESSION) {
358         return provide(android::gralloc4::Compression_None);
359     }
360     if constexpr (metadataType == StandardMetadataType::INTERLACED) {
361         return provide(android::gralloc4::Interlaced_None);
362     }
363     if constexpr (metadataType == StandardMetadataType::CHROMA_SITING) {
364         return provide(android::gralloc4::ChromaSiting_None);
365     }
366     if constexpr (metadataType == StandardMetadataType::PLANE_LAYOUTS) {
367         std::vector<PlaneLayout> planeLayouts;
368         getPlaneLayouts(crosBuffer->get_format(), &planeLayouts);
369 
370         for (size_t plane = 0; plane < planeLayouts.size(); plane++) {
371             PlaneLayout& planeLayout = planeLayouts[plane];
372             planeLayout.offsetInBytes = crosBuffer->get_plane_offset(plane);
373             planeLayout.strideInBytes = crosBuffer->get_plane_stride(plane);
374             planeLayout.totalSizeInBytes = crosBuffer->get_plane_size(plane);
375             planeLayout.widthInSamples =
376                     crosBuffer->get_width() / planeLayout.horizontalSubsampling;
377             planeLayout.heightInSamples =
378                     crosBuffer->get_height() / planeLayout.verticalSubsampling;
379         }
380 
381         return provide(planeLayouts);
382     }
383     if constexpr (metadataType == StandardMetadataType::CROP) {
384         const uint32_t numPlanes = crosBuffer->get_num_planes();
385         const uint32_t w = crosBuffer->get_width();
386         const uint32_t h = crosBuffer->get_height();
387         std::vector<aidl::android::hardware::graphics::common::Rect> crops;
388         for (uint32_t plane = 0; plane < numPlanes; plane++) {
389             aidl::android::hardware::graphics::common::Rect crop;
390             crop.left = 0;
391             crop.top = 0;
392             crop.right = w;
393             crop.bottom = h;
394             crops.push_back(crop);
395         }
396 
397         return provide(crops);
398     }
399     if constexpr (metadataType == StandardMetadataType::DATASPACE) {
400         std::optional<Dataspace> dataspace;
401         if (crosBuffer->get_dataspace(&dataspace)) {
402             return -AIMAPPER_ERROR_NO_RESOURCES;
403         } else {
404             return provide(*dataspace);
405         }
406     }
407     if constexpr (metadataType == StandardMetadataType::BLEND_MODE) {
408         std::optional<BlendMode> blend;
409         if (crosBuffer->get_blend_mode(&blend)) {
410             return -AIMAPPER_ERROR_NO_RESOURCES;
411         } else {
412             return provide(*blend);
413         }
414     }
415     if constexpr (metadataType == StandardMetadataType::SMPTE2086) {
416         std::optional<Smpte2086> smpte;
417         if (crosBuffer->get_smpte2086(&smpte)) {
418             return -AIMAPPER_ERROR_NO_RESOURCES;
419         } else {
420             return smpte ? provide(*smpte) : 0;
421         }
422     }
423     if constexpr (metadataType == StandardMetadataType::CTA861_3) {
424         std::optional<Cta861_3> cta;
425         if (crosBuffer->get_cta861_3(&cta)) {
426             return -AIMAPPER_ERROR_NO_RESOURCES;
427         } else {
428             return cta ? provide(*cta) : 0;
429         }
430     }
431     return -AIMAPPER_ERROR_UNSUPPORTED;
432 }
433 
setMetadata(buffer_handle_t _Nonnull buffer,AIMapper_MetadataType metadataType,const void * _Nonnull metadata,size_t metadataSize)434 AIMapper_Error CrosGrallocMapperV5::setMetadata(buffer_handle_t _Nonnull buffer,
435                                                 AIMapper_MetadataType metadataType,
436                                                 const void* _Nonnull metadata,
437                                                 size_t metadataSize) {
438     // We don't have any vendor-specific metadata, so divert to setStandardMetadata after validating
439     // that this is a standard metadata request
440     if (isStandardMetadata(metadataType)) {
441         return setStandardMetadata(buffer, metadataType.value, metadata, metadataSize);
442     }
443     return AIMAPPER_ERROR_UNSUPPORTED;
444 }
445 
setStandardMetadata(buffer_handle_t _Nonnull bufferHandle,int64_t standardTypeRaw,const void * _Nonnull metadata,size_t metadataSize)446 AIMapper_Error CrosGrallocMapperV5::setStandardMetadata(buffer_handle_t _Nonnull bufferHandle,
447                                                         int64_t standardTypeRaw,
448                                                         const void* _Nonnull metadata,
449                                                         size_t metadataSize) {
450     VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
451 
452     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
453     if (!crosHandle) {
454         ALOGE("Failed to get. Invalid handle.");
455         return AIMAPPER_ERROR_BAD_BUFFER;
456     }
457 
458     auto standardType = static_cast<StandardMetadataType>(standardTypeRaw);
459 
460     switch (standardType) {
461         // Read-only values
462         case StandardMetadataType::BUFFER_ID:
463         case StandardMetadataType::NAME:
464         case StandardMetadataType::WIDTH:
465         case StandardMetadataType::HEIGHT:
466         case StandardMetadataType::LAYER_COUNT:
467         case StandardMetadataType::PIXEL_FORMAT_REQUESTED:
468         case StandardMetadataType::USAGE:
469             return AIMAPPER_ERROR_BAD_VALUE;
470 
471         // Supported to set
472         case StandardMetadataType::BLEND_MODE:
473         case StandardMetadataType::CTA861_3:
474         case StandardMetadataType::DATASPACE:
475         case StandardMetadataType::SMPTE2086:
476             break;
477 
478         // Everything else unsupported
479         default:
480             return AIMAPPER_ERROR_UNSUPPORTED;
481     }
482 
483     AIMapper_Error status = AIMAPPER_ERROR_UNSUPPORTED;
484     mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
485         auto applier = [&]<StandardMetadataType T>(auto&& value) -> AIMapper_Error {
486             return setStandardMetadata<T>(crosBuffer, std::forward<decltype(value)>(value));
487         };
488 
489         status = applyStandardMetadata(standardType, metadata, metadataSize, applier);
490     });
491     return status;
492 }
493 
494 template <StandardMetadataType TYPE>
setStandardMetadata(cros_gralloc_buffer * crosBuffer,typename StandardMetadata<TYPE>::value_type && value)495 AIMapper_Error CrosGrallocMapperV5::setStandardMetadata(
496         cros_gralloc_buffer* crosBuffer, typename StandardMetadata<TYPE>::value_type&& value) {
497     int ret = 0;
498     if constexpr (TYPE == StandardMetadataType::BLEND_MODE) {
499         ret = crosBuffer->set_blend_mode(value);
500     }
501     if constexpr (TYPE == StandardMetadataType::CTA861_3) {
502         ret = crosBuffer->set_cta861_3(value);
503     }
504     if constexpr (TYPE == StandardMetadataType::DATASPACE) {
505         ret = crosBuffer->set_dataspace(value);
506     }
507     if constexpr (TYPE == StandardMetadataType::SMPTE2086) {
508         ret = crosBuffer->set_smpte2086(value);
509     }
510 
511     if (ret) {
512         return AIMAPPER_ERROR_NO_RESOURCES;
513     }
514 
515     // Unsupported metadatas were already filtered before we reached this point
516     return AIMAPPER_ERROR_NONE;
517 }
518 
describeStandard(StandardMetadataType type,bool isGettable,bool isSettable)519 constexpr AIMapper_MetadataTypeDescription describeStandard(StandardMetadataType type,
520                                                             bool isGettable, bool isSettable) {
521     return {{STANDARD_METADATA_NAME, static_cast<int64_t>(type)},
522             nullptr,
523             isGettable,
524             isSettable,
525             {0}};
526 }
527 
listSupportedMetadataTypes(const AIMapper_MetadataTypeDescription * _Nullable * _Nonnull outDescriptionList,size_t * _Nonnull outNumberOfDescriptions)528 AIMapper_Error CrosGrallocMapperV5::listSupportedMetadataTypes(
529         const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
530         size_t* _Nonnull outNumberOfDescriptions) {
531     static constexpr std::array<AIMapper_MetadataTypeDescription, 22> sSupportedMetadaTypes{
532             describeStandard(StandardMetadataType::BUFFER_ID, true, false),
533             describeStandard(StandardMetadataType::NAME, true, false),
534             describeStandard(StandardMetadataType::WIDTH, true, false),
535             describeStandard(StandardMetadataType::HEIGHT, true, false),
536             describeStandard(StandardMetadataType::LAYER_COUNT, true, false),
537             describeStandard(StandardMetadataType::PIXEL_FORMAT_REQUESTED, true, false),
538             describeStandard(StandardMetadataType::PIXEL_FORMAT_FOURCC, true, false),
539             describeStandard(StandardMetadataType::PIXEL_FORMAT_MODIFIER, true, false),
540             describeStandard(StandardMetadataType::USAGE, true, false),
541             describeStandard(StandardMetadataType::ALLOCATION_SIZE, true, false),
542             describeStandard(StandardMetadataType::PROTECTED_CONTENT, true, false),
543             describeStandard(StandardMetadataType::COMPRESSION, true, false),
544             describeStandard(StandardMetadataType::INTERLACED, true, false),
545             describeStandard(StandardMetadataType::CHROMA_SITING, true, false),
546             describeStandard(StandardMetadataType::PLANE_LAYOUTS, true, false),
547             describeStandard(StandardMetadataType::CROP, true, false),
548             describeStandard(StandardMetadataType::DATASPACE, true, true),
549             describeStandard(StandardMetadataType::COMPRESSION, true, false),
550             describeStandard(StandardMetadataType::BLEND_MODE, true, true),
551             describeStandard(StandardMetadataType::SMPTE2086, true, true),
552             describeStandard(StandardMetadataType::CTA861_3, true, true),
553             describeStandard(StandardMetadataType::STRIDE, true, false),
554     };
555     *outDescriptionList = sSupportedMetadaTypes.data();
556     *outNumberOfDescriptions = sSupportedMetadaTypes.size();
557     return AIMAPPER_ERROR_NONE;
558 }
559 
dumpBuffer(const cros_gralloc_buffer * crosBuffer,std::function<void (AIMapper_MetadataType,const std::vector<uint8_t> &)> callback)560 void CrosGrallocMapperV5::dumpBuffer(
561         const cros_gralloc_buffer* crosBuffer,
562         std::function<void(AIMapper_MetadataType, const std::vector<uint8_t>&)> callback) {
563     // Temp buffer of ~10kb, should be large enough for any of the metadata we want to dump
564     std::vector<uint8_t> tempBuffer;
565     tempBuffer.resize(10000);
566     AIMapper_MetadataType metadataType;
567     metadataType.name = STANDARD_METADATA_NAME;
568 
569     // Take an instance of the empty StandardMetadat<T> class just to allow auto-deduction
570     // to happen as explicit template invocation on lambdas is ugly
571     auto dump = [&]<StandardMetadataType T>(StandardMetadata<T>) {
572         // Nested templated lambdas! Woo! But the cleanness of the result is worth it
573         // The outer lambda exists basically just to capture the StandardMetadataType that's
574         // being dumped, as the `provider` parameter of getStandardMetadata only knows
575         // the value_type that the enum maps to but not the enum value itself, which we need to
576         // construct the `AIMapper_MetadataType` to pass to the dump callback
577         auto dumpInner = [&](const typename StandardMetadata<T>::value_type& value) -> int32_t {
578             int32_t size =
579                     StandardMetadata<T>::value::encode(value, tempBuffer.data(), tempBuffer.size());
580             // The initial size should always be large enough, but just in case...
581             if (size > tempBuffer.size()) {
582                 tempBuffer.resize(size * 2);
583                 size = StandardMetadata<T>::value::encode(value, tempBuffer.data(),
584                                                           tempBuffer.size());
585             }
586             // If the first resize failed _somehow_, just give up. Also don't notify if any
587             // errors occurred during encoding.
588             if (size >= 0 && size <= tempBuffer.size()) {
589                 metadataType.value = static_cast<int64_t>(T);
590                 callback(metadataType, tempBuffer);
591             }
592             // We don't actually care about the return value in this case, but why not use the
593             // real value anyway
594             return size;
595         };
596         getStandardMetadata(crosBuffer, dumpInner, StandardMetadata<T>{});
597     };
598 
599     // So clean. So pretty.
600     dump(StandardMetadata<StandardMetadataType::BUFFER_ID>{});
601     dump(StandardMetadata<StandardMetadataType::NAME>{});
602     dump(StandardMetadata<StandardMetadataType::WIDTH>{});
603     dump(StandardMetadata<StandardMetadataType::HEIGHT>{});
604     dump(StandardMetadata<StandardMetadataType::LAYER_COUNT>{});
605     dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>{});
606     dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>{});
607     dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>{});
608     dump(StandardMetadata<StandardMetadataType::USAGE>{});
609     dump(StandardMetadata<StandardMetadataType::ALLOCATION_SIZE>{});
610     dump(StandardMetadata<StandardMetadataType::PROTECTED_CONTENT>{});
611     dump(StandardMetadata<StandardMetadataType::COMPRESSION>{});
612     dump(StandardMetadata<StandardMetadataType::INTERLACED>{});
613     dump(StandardMetadata<StandardMetadataType::CHROMA_SITING>{});
614     dump(StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>{});
615     dump(StandardMetadata<StandardMetadataType::DATASPACE>{});
616     dump(StandardMetadata<StandardMetadataType::BLEND_MODE>{});
617 }
618 
dumpBuffer(buffer_handle_t _Nonnull bufferHandle,AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,void * _Null_unspecified context)619 AIMapper_Error CrosGrallocMapperV5::dumpBuffer(
620         buffer_handle_t _Nonnull bufferHandle,
621         AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, void* _Null_unspecified context) {
622     VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle)
623     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
624     if (!crosHandle) {
625         ALOGE("Failed to get. Invalid handle.");
626         return AIMAPPER_ERROR_BAD_BUFFER;
627     }
628     auto callback = [&](AIMapper_MetadataType type, const std::vector<uint8_t>& buffer) {
629         dumpBufferCallback(context, type, buffer.data(), buffer.size());
630     };
631     mDriver->with_buffer(
632             crosHandle, [&](cros_gralloc_buffer* crosBuffer) { dumpBuffer(crosBuffer, callback); });
633     return AIMAPPER_ERROR_NONE;
634 }
635 
dumpAllBuffers(AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,void * _Null_unspecified context)636 AIMapper_Error CrosGrallocMapperV5::dumpAllBuffers(
637         AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
638         AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, void* _Null_unspecified context) {
639     REQUIRE_DRIVER()
640     auto callback = [&](AIMapper_MetadataType type, const std::vector<uint8_t>& buffer) {
641         dumpBufferCallback(context, type, buffer.data(), buffer.size());
642     };
643     mDriver->with_each_buffer([&](cros_gralloc_buffer* crosBuffer) {
644         beginDumpBufferCallback(context);
645         dumpBuffer(crosBuffer, callback);
646     });
647     return AIMAPPER_ERROR_NONE;
648 }
649 
getReservedRegion(buffer_handle_t _Nonnull buffer,void * _Nullable * _Nonnull outReservedRegion,uint64_t * _Nonnull outReservedSize)650 AIMapper_Error CrosGrallocMapperV5::getReservedRegion(buffer_handle_t _Nonnull buffer,
651                                                       void* _Nullable* _Nonnull outReservedRegion,
652                                                       uint64_t* _Nonnull outReservedSize) {
653     VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer)
654     cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(buffer);
655     if (!crosHandle) {
656         ALOGE("Failed to getReservedRegion. Invalid handle.");
657         return AIMAPPER_ERROR_BAD_BUFFER;
658     }
659 
660     void* reservedRegionAddr = nullptr;
661     uint64_t reservedRegionSize = 0;
662 
663     AIMapper_Error error = AIMAPPER_ERROR_NONE;
664     mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) {
665         int ret = crosBuffer->get_client_reserved_region(&reservedRegionAddr, &reservedRegionSize);
666         if (ret) {
667             reservedRegionAddr = nullptr;
668             reservedRegionSize = 0;
669             error = AIMAPPER_ERROR_NO_RESOURCES;
670         }
671     });
672 
673     if (error != AIMAPPER_ERROR_NONE) {
674         ALOGE("Failed to getReservedRegion. Failed to getReservedRegion.");
675         return AIMAPPER_ERROR_BAD_BUFFER;
676     }
677 
678     return AIMAPPER_ERROR_NONE;
679 }
680 
681 extern "C" uint32_t ANDROID_HAL_MAPPER_VERSION = AIMAPPER_VERSION_5;
682 
AIMapper_loadIMapper(AIMapper * _Nullable * _Nonnull outImplementation)683 extern "C" AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) {
684     static vendor::mapper::IMapperProvider<CrosGrallocMapperV5> provider;
685     return provider.load(outImplementation);
686 }