blob: 38d5377b870ab9deb715a55457e49a27359d3c3b [file] [log] [blame]
/*
* Copyright (C) 2020 ARM Limited. All rights reserved.
*
* Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <inttypes.h>
#include <sync/sync.h>
#include "RegisteredHandlePool.h"
#include "Mapper.h"
#include "BufferDescriptor.h"
#include "mali_gralloc_log.h"
#include "core/mali_gralloc_bufferallocation.h"
#include "core/mali_gralloc_bufferdescriptor.h"
#include "core/mali_gralloc_bufferaccess.h"
#include "core/mali_gralloc_reference.h"
#include "core/format_info.h"
#include "allocator/mali_gralloc_ion.h"
#include "mali_gralloc_buffer.h"
#include "mali_gralloc_log.h"
#include "MapperMetadata.h"
#include "SharedMetadata.h"
/* GraphicBufferMapper is expected to be valid (and leaked) during process
* termination. IMapper, and in turn, gRegisteredHandles must be valid as
* well. Create the registered handle pool on the heap, and let
* it leak for simplicity.
*
* However, there is no way to make sure gralloc0/gralloc1 are valid. Any use
* of static/global object in gralloc0/gralloc1 that may have been destructed
* is potentially broken.
*/
RegisteredHandlePool* gRegisteredHandles = new RegisteredHandlePool;
namespace arm {
namespace mapper {
namespace common {
/*
* Translates the register buffer API into existing gralloc implementation
*
* @param bufferHandle [in] Private handle for the buffer to be imported
*
* @return Error::BAD_BUFFER for an invalid buffer
* Error::NO_RESOURCES when unable to import the given buffer
* Error::NONE on successful import
*/
static Error registerBuffer(buffer_handle_t bufferHandle)
{
if (private_handle_t::validate(bufferHandle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
return Error::BAD_BUFFER;
}
if (mali_gralloc_reference_retain(bufferHandle) < 0)
{
return Error::NO_RESOURCES;
}
return Error::NONE;
}
/*
* Translates the unregister buffer API into existing gralloc implementation
*
* @param bufferHandle [in] Private handle for the buffer to be released
*
* @return Error::BAD_BUFFER for an invalid buffer / buffers which can't be released
* Error::NONE on successful release of the buffer
*/
static Error unregisterBuffer(buffer_handle_t bufferHandle)
{
if (private_handle_t::validate(bufferHandle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
return Error::BAD_BUFFER;
}
const int status = mali_gralloc_reference_release(bufferHandle);
if (status != 0)
{
MALI_GRALLOC_LOGE("Unable to release buffer:%p", bufferHandle);
return Error::BAD_BUFFER;
}
return Error::NONE;
}
/*
* Retrieves the file descriptor referring to a sync fence object
*
* @param fenceHandle [in] HIDL fence handle
* @param outFenceFd [out] Fence file descriptor. '-1' indicates no fence
*
* @return false, for an invalid HIDL fence handle
* true, otherwise
*/
static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd)
{
auto const handle = fenceHandle.getNativeHandle();
if (handle && handle->numFds > 1)
{
MALI_GRALLOC_LOGE("Invalid fence handle with %d fds", handle->numFds);
return false;
}
*outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
return true;
}
/*
* Populates the HIDL fence handle for the given fence object
*
* @param fenceFd [in] Fence file descriptor
* @param handleStorage [in] HIDL handle storage for fence
*
* @return HIDL fence handle
*/
static hidl_handle getFenceHandle(int fenceFd, char* handleStorage)
{
native_handle_t* handle = nullptr;
if (fenceFd >= 0)
{
handle = native_handle_init(handleStorage, 1, 0);
handle->data[0] = fenceFd;
}
return hidl_handle(handle);
}
/*
* Locks the given buffer for the specified CPU usage.
*
* @param bufferHandle [in] Buffer to lock.
* @param cpuUsage [in] Specifies one or more CPU usage flags to request
* @param accessRegion [in] Portion of the buffer that the client intends to access.
* @param fenceFd [in] Fence file descriptor
* @param outData [out] CPU accessible buffer address
*
* @return Error::BAD_BUFFER for an invalid buffer
* Error::NO_RESOURCES when unable to duplicate fence
* Error::BAD_VALUE when locking fails
* Error::NONE on successful buffer lock
*/
static Error lockBuffer(buffer_handle_t bufferHandle,
uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
void** outData)
{
/* dup fenceFd as it is going to be owned by gralloc. Note that it is
* gralloc's responsibility to close it, even on locking errors.
*/
if (fenceFd >= 0)
{
fenceFd = dup(fenceFd);
if (fenceFd < 0)
{
MALI_GRALLOC_LOGE("Error encountered while duplicating fence file descriptor");
return Error::NO_RESOURCES;
}
}
if (private_handle_t::validate(bufferHandle) < 0)
{
if (fenceFd >= 0)
{
close(fenceFd);
}
MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
return Error::BAD_BUFFER;
}
if (mali_gralloc_reference_validate(bufferHandle) < 0)
{
if (fenceFd >= 0)
{
close(fenceFd);
}
MALI_GRALLOC_LOGE("Buffer: %p is not imported", bufferHandle);
return Error::BAD_VALUE;
}
auto private_handle = private_handle_t::dynamicCast(bufferHandle);
if (private_handle->cpu_write != 0 && (cpuUsage & BufferUsage::CPU_WRITE_MASK))
{
if (fenceFd >= 0)
{
close(fenceFd);
}
#if 0
MALI_GRALLOC_LOGW("Attempt to call lock*() for writing on an already locked buffer (%p)", bufferHandle);
#endif
/* TODO: handle simulatneous locks differently. May be keep a global lock count per buffer? */
}
else if (fenceFd >= 0)
{
sync_wait(fenceFd, -1);
close(fenceFd);
}
void* data = nullptr;
if (mali_gralloc_lock(bufferHandle, cpuUsage, accessRegion.left, accessRegion.top, accessRegion.width,
accessRegion.height, &data) < 0)
{
return Error::BAD_VALUE;
}
*outData = data;
return Error::NONE;
}
/*
* Unlocks a buffer to indicate all CPU accesses to the buffer have completed
*
* @param bufferHandle [in] Buffer to lock.
* @param outFenceFd [out] Fence file descriptor
*
* @return Error::BAD_BUFFER for an invalid buffer
* Error::BAD_VALUE when unlocking failed
* Error::NONE on successful buffer unlock
*/
static Error unlockBuffer(buffer_handle_t bufferHandle,
int* outFenceFd)
{
if (private_handle_t::validate(bufferHandle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
return Error::BAD_BUFFER;
}
auto private_handle = private_handle_t::dynamicCast(bufferHandle);
const int result = mali_gralloc_unlock(bufferHandle);
if (result)
{
MALI_GRALLOC_LOGE("Unlocking failed with error: %d", result);
return Error::BAD_VALUE;
}
*outFenceFd = -1;
return Error::NONE;
}
void importBuffer(const hidl_handle& rawHandle, IMapper::importBuffer_cb hidl_cb)
{
if (!rawHandle.getNativeHandle())
{
MALI_GRALLOC_LOGE("Invalid buffer handle to import");
hidl_cb(Error::BAD_BUFFER, nullptr);
return;
}
native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
if (!bufferHandle)
{
MALI_GRALLOC_LOGE("Failed to clone buffer handle");
hidl_cb(Error::NO_RESOURCES, nullptr);
return;
}
const Error error = registerBuffer(bufferHandle);
if (error != Error::NONE)
{
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
hidl_cb(error, nullptr);
return;
}
auto *private_handle = static_cast<private_handle_t *>(bufferHandle);
if (gRegisteredHandles->add(bufferHandle) == false)
{
/* The newly cloned handle is already registered. This can only happen
* when a handle previously registered was native_handle_delete'd instead
* of freeBuffer'd.
*/
MALI_GRALLOC_LOGE("Handle %p has already been imported; potential fd leaking",
bufferHandle);
unregisterBuffer(bufferHandle);
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
hidl_cb(Error::NO_RESOURCES, nullptr);
return;
}
hidl_cb(Error::NONE, bufferHandle);
}
Error freeBuffer(void* buffer)
{
native_handle_t * const bufferHandle = gRegisteredHandles->remove(buffer);
if (!bufferHandle)
{
MALI_GRALLOC_LOGE("Invalid buffer handle %p to freeBuffer", buffer);
return Error::BAD_BUFFER;
}
const Error status = unregisterBuffer(bufferHandle);
if (status != Error::NONE)
{
return status;
}
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
return Error::NONE;
}
void lock(void* buffer, uint64_t cpuUsage, const IMapper::Rect& accessRegion,
const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb)
{
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle || private_handle_t::validate(bufferHandle) < 0)
{
MALI_GRALLOC_LOGE("Buffer to lock: %p is not valid", buffer);
hidl_cb(Error::BAD_BUFFER, nullptr);
return;
}
int fenceFd;
if (!getFenceFd(acquireFence, &fenceFd))
{
hidl_cb(Error::BAD_VALUE, nullptr);
return;
}
void* data = nullptr;
const Error error = lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
hidl_cb(error, data);
}
void unlock(void* buffer, IMapper::unlock_cb hidl_cb)
{
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle)
{
MALI_GRALLOC_LOGE("Buffer to unlock: %p has not been registered with Gralloc", buffer);
hidl_cb(Error::BAD_BUFFER, nullptr);
return;
}
int fenceFd;
const Error error = unlockBuffer(bufferHandle, &fenceFd);
if (error == Error::NONE)
{
NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
if (fenceFd >= 0)
{
close(fenceFd);
}
}
else
{
hidl_cb(error, nullptr);
}
}
Error validateBufferSize(void* buffer,
const IMapper::BufferDescriptorInfo& descriptorInfo,
uint32_t in_stride)
{
/* The buffer must have been allocated by Gralloc */
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle)
{
MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
return Error::BAD_BUFFER;
}
if (private_handle_t::validate(bufferHandle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
return Error::BAD_BUFFER;
}
buffer_descriptor_t grallocDescriptor;
grallocDescriptor.width = descriptorInfo.width;
grallocDescriptor.height = descriptorInfo.height;
grallocDescriptor.layer_count = descriptorInfo.layerCount;
grallocDescriptor.hal_format = static_cast<uint64_t>(descriptorInfo.format);
grallocDescriptor.producer_usage = static_cast<uint64_t>(descriptorInfo.usage);
grallocDescriptor.consumer_usage = grallocDescriptor.producer_usage;
grallocDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
/* Derive the buffer size for the given descriptor */
const int result = mali_gralloc_derive_format_and_size(&grallocDescriptor);
if (result)
{
MALI_GRALLOC_LOGV("Unable to derive format and size for the given descriptor information. error: %d", result);
return Error::BAD_VALUE;
}
/* Validate the buffer parameters against descriptor info */
private_handle_t *gralloc_buffer = (private_handle_t *)bufferHandle;
/* The buffer size must be greater than (or equal to) what would have been allocated with descriptor */
for (int i = 0; i < gralloc_buffer->fd_count; i++)
{
if (gralloc_buffer->alloc_sizes[i] < grallocDescriptor.alloc_sizes[i])
{
MALI_GRALLOC_LOGW("Buf size mismatch. fd_idx(%d) Buffer size = %" PRIu64 ", Descriptor (derived) size = %" PRIu64,
i, gralloc_buffer->alloc_sizes[i], grallocDescriptor.alloc_sizes[i]);
return Error::BAD_VALUE;
}
}
if (in_stride != 0 && (uint32_t)gralloc_buffer->stride != in_stride)
{
MALI_GRALLOC_LOGE("Stride mismatch. Expected stride = %d, Buffer stride = %d",
in_stride, gralloc_buffer->stride);
return Error::BAD_VALUE;
}
if (gralloc_buffer->alloc_format != grallocDescriptor.alloc_format)
{
MALI_GRALLOC_LOGE("Buffer alloc format: (%s, 0x%" PRIx64") does not match descriptor (derived) alloc format: (%s 0x%"
PRIx64 ")", format_name(gralloc_buffer->alloc_format), gralloc_buffer->alloc_format,
format_name(grallocDescriptor.alloc_format), grallocDescriptor.alloc_format);
return Error::BAD_VALUE;
}
const int format_idx = get_format_index(gralloc_buffer->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
if (format_idx == -1)
{
MALI_GRALLOC_LOGE("Invalid format to validate buffer descriptor");
return Error::BAD_VALUE;
}
else
{
for (int i = 0; i < formats[format_idx].npln; i++)
{
if (gralloc_buffer->plane_info[i].byte_stride != grallocDescriptor.plane_info[i].byte_stride)
{
MALI_GRALLOC_LOGE("Buffer byte stride 0x%x mismatch with desc byte stride 0x%x in plane %d ",
gralloc_buffer->plane_info[i].byte_stride, grallocDescriptor.plane_info[i].byte_stride, i);
return Error::BAD_VALUE;
}
if (gralloc_buffer->plane_info[i].alloc_width != grallocDescriptor.plane_info[i].alloc_width)
{
MALI_GRALLOC_LOGE("Buffer alloc width 0x%x mismatch with desc alloc width 0x%x in plane %d ",
gralloc_buffer->plane_info[i].alloc_width, grallocDescriptor.plane_info[i].alloc_width, i);
return Error::BAD_VALUE;
}
if (gralloc_buffer->plane_info[i].alloc_height != grallocDescriptor.plane_info[i].alloc_height)
{
MALI_GRALLOC_LOGE("Buffer alloc height 0x%x mismatch with desc alloc height 0x%x in plane %d ",
gralloc_buffer->plane_info[i].alloc_height, grallocDescriptor.plane_info[i].alloc_height, i);
return Error::BAD_VALUE;
}
}
}
if ((uint32_t)gralloc_buffer->width != grallocDescriptor.width)
{
MALI_GRALLOC_LOGE("Width mismatch. Buffer width = %u, Descriptor width = %u",
gralloc_buffer->width, grallocDescriptor.width);
return Error::BAD_VALUE;
}
if ((uint32_t)gralloc_buffer->height != grallocDescriptor.height)
{
MALI_GRALLOC_LOGE("Height mismatch. Buffer height = %u, Descriptor height = %u",
gralloc_buffer->height, grallocDescriptor.height);
return Error::BAD_VALUE;
}
if (gralloc_buffer->layer_count != grallocDescriptor.layer_count)
{
MALI_GRALLOC_LOGE("Layer Count mismatch. Buffer layer_count = %u, Descriptor layer_count width = %u",
gralloc_buffer->layer_count, grallocDescriptor.layer_count);
return Error::BAD_VALUE;
}
return Error::NONE;
}
void getTransportSize(void* buffer, IMapper::getTransportSize_cb hidl_cb)
{
/* The buffer must have been allocated by Gralloc */
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle)
{
MALI_GRALLOC_LOGE("Buffer %p is not registered with Gralloc", bufferHandle);
hidl_cb(Error::BAD_BUFFER, -1, -1);
return;
}
if (private_handle_t::validate(bufferHandle) < 0)
{
MALI_GRALLOC_LOGE("Buffer %p is corrupted", buffer);
hidl_cb(Error::BAD_BUFFER, -1, -1);
return;
}
hidl_cb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts);
}
void isSupported(const IMapper::BufferDescriptorInfo& description, IMapper::isSupported_cb hidl_cb)
{
buffer_descriptor_t grallocDescriptor;
grallocDescriptor.width = description.width;
grallocDescriptor.height = description.height;
grallocDescriptor.layer_count = description.layerCount;
grallocDescriptor.hal_format = static_cast<uint64_t>(description.format);
grallocDescriptor.producer_usage = static_cast<uint64_t>(description.usage);
grallocDescriptor.consumer_usage = grallocDescriptor.producer_usage;
grallocDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
/* Check if it is possible to allocate a buffer for the given description */
const int result = mali_gralloc_derive_format_and_size(&grallocDescriptor);
if (result != 0)
{
MALI_GRALLOC_LOGV("Allocation for the given description will not succeed. error: %d", result);
hidl_cb(Error::NONE, false);
}
else
{
hidl_cb(Error::NONE, true);
}
}
void flushLockedBuffer(void *buffer, IMapper::flushLockedBuffer_cb hidl_cb)
{
buffer_handle_t handle = gRegisteredHandles->get(buffer);
if (private_handle_t::validate(handle) < 0)
{
MALI_GRALLOC_LOGE("Bandle: %p is corrupted", handle);
hidl_cb(Error::BAD_BUFFER, hidl_handle{});
return;
}
auto private_handle = static_cast<const private_handle_t *>(handle);
if (!private_handle->cpu_write && !private_handle->cpu_read)
{
MALI_GRALLOC_LOGE("Attempt to call flushLockedBuffer() on an unlocked buffer (%p)", handle);
hidl_cb(Error::BAD_BUFFER, hidl_handle{});
return;
}
mali_gralloc_ion_sync_end(private_handle, false, true);
hidl_cb(Error::NONE, hidl_handle{});
}
Error rereadLockedBuffer(void *buffer)
{
buffer_handle_t handle = gRegisteredHandles->get(buffer);
if (private_handle_t::validate(handle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is corrupted", handle);
return Error::BAD_BUFFER;
}
auto private_handle = static_cast<const private_handle_t *>(handle);
if (!private_handle->cpu_write && !private_handle->cpu_read)
{
MALI_GRALLOC_LOGE("Attempt to call rereadLockedBuffer() on an unlocked buffer (%p)", handle);
return Error::BAD_BUFFER;
}
mali_gralloc_ion_sync_start(private_handle, true, false);
return Error::NONE;
}
void get(void *buffer, const IMapper::MetadataType &metadataType, IMapper::get_cb hidl_cb)
{
/* The buffer must have been allocated by Gralloc */
const private_handle_t *handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
if (handle == nullptr)
{
MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
hidl_cb(Error::BAD_BUFFER, hidl_vec<uint8_t>());
return;
}
if (mali_gralloc_reference_validate((buffer_handle_t)handle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is not imported", handle);
hidl_cb(Error::BAD_VALUE, hidl_vec<uint8_t>());
return;
}
get_metadata(handle, metadataType, hidl_cb);
}
Error set(void *buffer, const IMapper::MetadataType &metadataType, const hidl_vec<uint8_t> &metadata)
{
/* The buffer must have been allocated by Gralloc */
const private_handle_t *handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
if (handle == nullptr)
{
MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
return Error::BAD_BUFFER;
}
if (mali_gralloc_reference_validate((buffer_handle_t)handle) < 0)
{
MALI_GRALLOC_LOGE("Buffer: %p is not imported", handle);
return Error::BAD_VALUE;
}
return set_metadata(handle, metadataType, metadata);
}
void listSupportedMetadataTypes(IMapper::listSupportedMetadataTypes_cb hidl_cb)
{
/* Returns a vector of {metadata type, description, isGettable, isSettable}
* Only non-standardMetadataTypes require a description.
*/
hidl_vec<IMapper::MetadataTypeDescription> descriptions = {
{ android::gralloc4::MetadataType_BufferId, "", true, false },
{ android::gralloc4::MetadataType_Name, "", true, false },
{ android::gralloc4::MetadataType_Width, "", true, false },
{ android::gralloc4::MetadataType_Height, "", true, false },
{ android::gralloc4::MetadataType_LayerCount, "", true, false },
{ android::gralloc4::MetadataType_PixelFormatRequested, "", true, false },
{ android::gralloc4::MetadataType_PixelFormatFourCC, "", true, false },
{ android::gralloc4::MetadataType_PixelFormatModifier, "", true, false },
{ android::gralloc4::MetadataType_Usage, "", true, false },
{ android::gralloc4::MetadataType_AllocationSize, "", true, false },
{ android::gralloc4::MetadataType_ProtectedContent, "", true, false },
{ android::gralloc4::MetadataType_Compression, "", true, false },
{ android::gralloc4::MetadataType_Interlaced, "", true, false },
{ android::gralloc4::MetadataType_ChromaSiting, "", true, false },
{ android::gralloc4::MetadataType_PlaneLayouts, "", true, false },
{ android::gralloc4::MetadataType_Dataspace, "", true, true },
{ android::gralloc4::MetadataType_BlendMode, "", true, true },
{ android::gralloc4::MetadataType_Smpte2086, "", true, true },
{ android::gralloc4::MetadataType_Cta861_3, "", true, true },
{ android::gralloc4::MetadataType_Smpte2094_40, "", true, true },
{ android::gralloc4::MetadataType_Crop, "", true, true },
/* Arm vendor metadata */
{ ArmMetadataType_PLANE_FDS,
"Vector of file descriptors of each plane", true, false },
};
hidl_cb(Error::NONE, descriptions);
return;
}
static hidl_vec<IMapper::MetadataDump> dumpBufferHelper(const private_handle_t* handle)
{
hidl_vec<IMapper::MetadataType> standardMetadataTypes = {
android::gralloc4::MetadataType_BufferId,
android::gralloc4::MetadataType_Name,
android::gralloc4::MetadataType_Width,
android::gralloc4::MetadataType_Height,
android::gralloc4::MetadataType_LayerCount,
android::gralloc4::MetadataType_PixelFormatRequested,
android::gralloc4::MetadataType_PixelFormatFourCC,
android::gralloc4::MetadataType_PixelFormatModifier,
android::gralloc4::MetadataType_Usage,
android::gralloc4::MetadataType_AllocationSize,
android::gralloc4::MetadataType_ProtectedContent,
android::gralloc4::MetadataType_Compression,
android::gralloc4::MetadataType_Interlaced,
android::gralloc4::MetadataType_ChromaSiting,
android::gralloc4::MetadataType_PlaneLayouts,
android::gralloc4::MetadataType_Dataspace,
android::gralloc4::MetadataType_BlendMode,
android::gralloc4::MetadataType_Smpte2086,
android::gralloc4::MetadataType_Cta861_3,
android::gralloc4::MetadataType_Smpte2094_40,
android::gralloc4::MetadataType_Crop,
};
std::vector<IMapper::MetadataDump> metadataDumps;
for (const auto& metadataType: standardMetadataTypes)
{
get_metadata(handle, metadataType, [&metadataDumps, &metadataType](Error error, hidl_vec<uint8_t> metadata) {
switch(error)
{
case Error::NONE:
metadataDumps.push_back({metadataType, metadata});
break;
case Error::UNSUPPORTED:
default:
return;
}
});
}
return hidl_vec<IMapper::MetadataDump>(metadataDumps);
}
void dumpBuffer(void *buffer, IMapper::dumpBuffer_cb hidl_cb)
{
IMapper::BufferDump bufferDump{};
auto handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
if (handle == nullptr)
{
MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
hidl_cb(Error::BAD_BUFFER, bufferDump);
return;
}
bufferDump.metadataDump = dumpBufferHelper(handle);
hidl_cb(Error::NONE, bufferDump);
}
void dumpBuffers(IMapper::dumpBuffers_cb hidl_cb)
{
std::vector<IMapper::BufferDump> bufferDumps;
gRegisteredHandles->for_each([&bufferDumps](buffer_handle_t buffer) {
IMapper::BufferDump bufferDump { dumpBufferHelper(static_cast<const private_handle_t *>(buffer)) };
bufferDumps.push_back(bufferDump);
});
hidl_cb(Error::NONE, hidl_vec<IMapper::BufferDump>(bufferDumps));
}
void getReservedRegion(void *buffer, IMapper::getReservedRegion_cb hidl_cb)
{
auto handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
if (handle == nullptr)
{
MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
hidl_cb(Error::BAD_BUFFER, 0, 0);
return;
}
else if (handle->reserved_region_size == 0)
{
MALI_GRALLOC_LOGE("Buffer: %p has no reserved region", buffer);
hidl_cb(Error::BAD_BUFFER, 0, 0);
return;
}
auto metadata_addr_oe = mali_gralloc_reference_get_metadata_addr(handle);
if (!metadata_addr_oe.has_value()) {
hidl_cb(Error::BAD_BUFFER, 0, 0);
}
void *reserved_region = static_cast<std::byte *>(metadata_addr_oe.value())
+ mapper::common::shared_metadata_size();
hidl_cb(Error::NONE, reserved_region, handle->reserved_region_size);
}
} // namespace common
} // namespace mapper
} // namespace arm