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