| /* |
| * Copyright (C) 2018-2019 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 <log/log.h> |
| #include <sync/sync.h> |
| #include <mutex> |
| #include <unordered_set> |
| #include <system/window.h> |
| |
| #include "GrallocMapper.h" |
| #include "GrallocBufferDescriptor.h" |
| #include "mali_gralloc_bufferallocation.h" |
| #include "mali_gralloc_bufferdescriptor.h" |
| #include "mali_gralloc_bufferaccess.h" |
| #include "mali_gralloc_reference.h" |
| #include "mali_gralloc_ion.h" |
| #include "mali_gralloc_buffer.h" |
| |
| namespace android { |
| namespace hardware { |
| namespace graphics { |
| namespace mapper { |
| namespace HIDL_IMAPPER_NAMESPACE { |
| namespace implementation { |
| |
| /* Default definitions for IMapper 2.x interface */ |
| using V2_0::Error; |
| using V2_0::BufferDescriptor; |
| |
| namespace { |
| |
| /* An unordered set to internally store / retrieve imported buffer handles */ |
| class RegisteredHandlePool |
| { |
| public: |
| /* Stores the buffer handle in the internal list */ |
| bool add(buffer_handle_t bufferHandle) |
| { |
| std::lock_guard<std::mutex> lock(mutex); |
| return bufPool.insert(bufferHandle).second; |
| } |
| |
| /* Retrieves and removes the buffer handle from internal list */ |
| native_handle_t* remove(void* buffer) |
| { |
| auto bufferHandle = static_cast<native_handle_t*>(buffer); |
| |
| std::lock_guard<std::mutex> lock(mutex); |
| return bufPool.erase(bufferHandle) == 1 ? bufferHandle : nullptr; |
| } |
| |
| /* Retrieves the buffer handle from internal list */ |
| buffer_handle_t get(const void* buffer) |
| { |
| auto bufferHandle = static_cast<buffer_handle_t>(buffer); |
| |
| std::lock_guard<std::mutex> lock(mutex); |
| return bufPool.count(bufferHandle) == 1 ? bufferHandle : nullptr; |
| } |
| |
| private: |
| std::mutex mutex; |
| std::unordered_set<buffer_handle_t> bufPool; |
| }; |
| |
| /* 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; |
| |
| } /* anonymous namespace */ |
| |
| /** |
| * IMapper constructor. All the state information required for the Gralloc |
| * private module is populated in its default constructor. Gralloc 2.0 specific |
| * state information can be populated here. |
| * |
| * @return None |
| */ |
| GrallocMapper::GrallocMapper() |
| { |
| } |
| |
| /* |
| * IMapper destructor. All the resources aquired for Gralloc private module |
| * (in the IMapper context) are released |
| * |
| * @return None |
| */ |
| GrallocMapper::~GrallocMapper() |
| { |
| mali_gralloc_ion_close(); |
| } |
| |
| /* |
| * Validates incoming IMapper descriptor attributes |
| * |
| * @param descriptor_attr [in] Specifies the attributes of the descriptor. |
| * |
| * @return false, for invalid buffer attributes |
| * true, otherwise |
| * Note: Latest IMapper version encapsulates all previous versions, hence all |
| * incoming descriptor information is mapped to the latest IMapper for validation |
| */ |
| bool GrallocMapper::validateDescriptorInfo(void *descriptor_attr) const |
| { |
| BufferDescriptorInfo * const descriptorInfo = (BufferDescriptorInfo *)descriptor_attr; |
| |
| using android::hardware::graphics::common::HIDL_COMMON_NAMESPACE::BufferUsage; |
| using android::hardware::graphics::common::HIDL_COMMON_NAMESPACE::PixelFormat; |
| |
| const uint64_t validUsageBits = |
| #if HIDL_MAPPER_VERSION_SCALED >= 210 |
| BufferUsage::GPU_CUBE_MAP | |
| BufferUsage::GPU_MIPMAP_COMPLETE | |
| #endif |
| BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | |
| BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET | |
| BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET | |
| BufferUsage::CAMERA_INPUT | BufferUsage::CAMERA_OUTPUT | |
| BufferUsage::PROTECTED | |
| BufferUsage::COMPOSER_CURSOR | |
| BufferUsage::VIDEO_ENCODER | |
| BufferUsage::RENDERSCRIPT | |
| BufferUsage::VIDEO_DECODER | |
| BufferUsage::SENSOR_DIRECT_DATA | |
| BufferUsage::GPU_DATA_BUFFER | |
| BufferUsage::VENDOR_MASK; |
| |
| if (!descriptorInfo->width || !descriptorInfo->height || |
| !descriptorInfo->layerCount) |
| { |
| AERR("Invalid buffer descriptor (2.x mapper) attributes, width = %d height = %d layerCount = %d ", |
| descriptorInfo->width, descriptorInfo->height, descriptorInfo->layerCount); |
| return false; |
| } |
| |
| if (descriptorInfo->format == static_cast<PixelFormat>(0)) |
| { |
| return false; |
| } |
| |
| if (descriptorInfo->usage & ~validUsageBits) |
| { |
| /* It is possible that application uses private usage bits. */ |
| ALOGW("Buffer descriptor with invalid usage bits 0x%" PRIx64, |
| descriptorInfo->usage & ~validUsageBits); |
| } |
| |
| return true; |
| } |
| |
| /* |
| * Creates a buffer descriptor from incoming descriptor attributes |
| * |
| * @param descriptorInfo [in] Specifies the (2.0 IMapper) attributes of |
| * the descriptor. |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error: NONE upon success. Otherwise, |
| * BAD_VALUE when any of the specified attributes are invalid |
| * descriptor: Newly created buffer descriptor. |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::createDescriptor( |
| const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo, |
| createDescriptor_cb hidl_cb) |
| { |
| if (validateDescriptorInfo((void *)&descriptorInfo)) |
| { |
| hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo)); |
| } |
| else |
| { |
| AERR("Invalid attributes to create descriptor for Mapper 2.0"); |
| hidl_cb(Error::BAD_VALUE, BufferDescriptor()); |
| } |
| |
| return Void(); |
| } |
| |
| /* |
| * Imports a raw buffer handle to create an imported buffer handle for use with |
| * the rest of the mapper or with other in-process libraries. |
| * |
| * @param rawHandle [in] Raw buffer handle to import. |
| * @param hidl_cb [in] HIDL Callback function to export output information |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error : NONE upon success. Otherwise, |
| * BAD_BUFFER for an invalid buffer |
| * NO_RESOURCES when the raw handle cannot be imported |
| * BAD_VALUE when any of the specified attributes are invalid |
| * buffer : Imported buffer handle |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle, |
| importBuffer_cb hidl_cb) |
| { |
| if (!rawHandle.getNativeHandle()) |
| { |
| AERR("Invalid buffer handle to import"); |
| hidl_cb(Error::BAD_BUFFER, nullptr); |
| return Void(); |
| } |
| |
| native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle()); |
| if (!bufferHandle) |
| { |
| AERR("Failed to clone buffer handle"); |
| hidl_cb(Error::NO_RESOURCES, nullptr); |
| return Void(); |
| } |
| |
| const Error error = registerBuffer(bufferHandle); |
| if (error != Error::NONE) |
| { |
| native_handle_close(bufferHandle); |
| native_handle_delete(bufferHandle); |
| |
| hidl_cb(error, nullptr); |
| return Void(); |
| } |
| |
| 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. |
| */ |
| AERR("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 Void(); |
| } |
| |
| hidl_cb(Error::NONE, bufferHandle); |
| return Void(); |
| } |
| |
| /* |
| * Frees a buffer handle and releases all the resources associated with it |
| * |
| * @param buffer [in] Imported buffer to free |
| * |
| * @return Error::BAD_BUFFER for an invalid buffer / when failed to free the buffer |
| * Error::NONE on successful free |
| */ |
| Return<Error> GrallocMapper::freeBuffer(void* buffer) |
| { |
| native_handle_t * const bufferHandle = gRegisteredHandles->remove(buffer); |
| if (!bufferHandle) |
| { |
| AERR("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; |
| } |
| |
| /* |
| * 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 |
| */ |
| bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle, |
| int* outFenceFd) const |
| { |
| auto const handle = fenceHandle.getNativeHandle(); |
| if (handle && handle->numFds > 1) |
| { |
| AERR("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 |
| */ |
| hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) const |
| { |
| 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 buffer [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 acquireFence [in] Handle for aquire fence object |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error: NONE upon success. Otherwise, |
| * BAD_BUFFER for an invalid buffer |
| * BAD_VALUE for an invalid input parameters |
| * data: CPU-accessible pointer to the buffer data |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage, |
| const IMapper::Rect& accessRegion, |
| const hidl_handle& acquireFence, |
| lock_cb hidl_cb) |
| { |
| buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer); |
| if (!bufferHandle) |
| { |
| AERR("Buffer to lock: %p has not been registered with Gralloc", buffer); |
| hidl_cb(Error::BAD_BUFFER, nullptr); |
| return Void(); |
| } |
| |
| int fenceFd; |
| if (!getFenceFd(acquireFence, &fenceFd)) |
| { |
| hidl_cb(Error::BAD_VALUE, nullptr); |
| return Void(); |
| } |
| |
| void* data = nullptr; |
| const Error error = lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data); |
| hidl_cb(error, data); |
| return Void(); |
| } |
| |
| /* |
| * Locks the given buffer for the specified CPU usage and exports cpu accessible |
| * data in YCbCr structure. |
| * |
| * @param buffer [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 acquireFence [in] Handle for aquire fence object |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error: NONE upon success. Otherwise, |
| * BAD_BUFFER for an invalid buffer |
| * BAD_VALUE for an invalid input parameters |
| * layout: Data layout of the buffer |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage, |
| const IMapper::Rect& accessRegion, |
| const hidl_handle& acquireFence, |
| lockYCbCr_cb hidl_cb) |
| { |
| YCbCrLayout layout = {}; |
| |
| buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer); |
| if (!bufferHandle) |
| { |
| AERR("Buffer to lock(YCbCr): %p has not been registered with Gralloc", buffer); |
| hidl_cb(Error::BAD_BUFFER, layout); |
| return Void(); |
| } |
| |
| int fenceFd; |
| if (!getFenceFd(acquireFence, &fenceFd)) |
| { |
| hidl_cb(Error::BAD_VALUE, layout); |
| return Void(); |
| } |
| |
| const Error error = lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout); |
| hidl_cb(error, layout); |
| return Void(); |
| } |
| |
| /* |
| * Unlocks a buffer to indicate all CPU accesses to the buffer have completed |
| * |
| * @param buffer [in] Buffer to lock. |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error: NONE upon success. Otherwise, |
| * BAD_BUFFER for an invalid buffer |
| * releaseFence: Referrs to a sync fence object |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) |
| { |
| buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer); |
| if (!bufferHandle) |
| { |
| AERR("Buffer to unlock: %p has not been registered with Gralloc", buffer); |
| hidl_cb(Error::BAD_BUFFER, nullptr); |
| return Void(); |
| } |
| |
| 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); |
| } |
| |
| return Void(); |
| } |
| |
| /* |
| * 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 |
| */ |
| Error GrallocMapper::registerBuffer(buffer_handle_t bufferHandle) const |
| { |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer: %p is corrupted", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| if (mali_gralloc_reference_retain(&privateModule, 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 |
| */ |
| Error GrallocMapper::unregisterBuffer(buffer_handle_t bufferHandle) const |
| { |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer: %p is corrupted", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| const int status = mali_gralloc_reference_release(&privateModule, bufferHandle, true); |
| if (status != 0) |
| { |
| AERR("Unable to release buffer:%p", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| return Error::NONE; |
| } |
| |
| /* |
| * 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 |
| */ |
| Error GrallocMapper::lockBuffer(buffer_handle_t bufferHandle, |
| uint64_t cpuUsage, |
| const IMapper::Rect& accessRegion, int fenceFd, |
| void** outData) const |
| { |
| /* 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) |
| { |
| AERR("Error encountered while duplicating fence file descriptor"); |
| return Error::NO_RESOURCES; |
| } |
| } |
| |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer: %p is corrupted", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| void* data = nullptr; |
| if (mali_gralloc_lock_async(&privateModule, bufferHandle, cpuUsage, |
| accessRegion.left, accessRegion.top, |
| accessRegion.width, accessRegion.height, |
| &data, fenceFd) < 0) |
| { |
| return Error::BAD_VALUE; |
| } |
| |
| *outData = data; |
| return Error::NONE; |
| } |
| |
| /* |
| * Locks the given buffer for the specified CPU usage and exports cpu accessible |
| * data in YCbCr structure. |
| * |
| * @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 outLayout [out] Describes CPU accessible information in YCbCr format |
| * |
| * @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 |
| */ |
| Error GrallocMapper::lockBuffer(buffer_handle_t bufferHandle, |
| uint64_t cpuUsage, |
| const IMapper::Rect& accessRegion, int fenceFd, |
| YCbCrLayout* outLayout) const |
| { |
| int result; |
| android_ycbcr ycbcr = {}; |
| |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer: %p is corrupted", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| if (fenceFd >= 0) |
| { |
| fenceFd = dup(fenceFd); |
| if (fenceFd < 0) |
| { |
| AERR("Error encountered while duplicating fence file descriptor"); |
| return Error::NO_RESOURCES; |
| } |
| } |
| |
| result = mali_gralloc_lock_ycbcr_async(&privateModule, bufferHandle, cpuUsage, |
| accessRegion.left, accessRegion.top, |
| accessRegion.width, accessRegion.height, |
| &ycbcr, fenceFd); |
| if (result) |
| { |
| AERR("Locking(YCbCr) failed with error: %d", result); |
| return Error::BAD_VALUE; |
| } |
| |
| outLayout->y = ycbcr.y; |
| outLayout->cb = ycbcr.cb; |
| outLayout->cr = ycbcr.cr; |
| outLayout->yStride = ycbcr.ystride; |
| outLayout->cStride = ycbcr.cstride; |
| outLayout->chromaStep = ycbcr.chroma_step; |
| |
| 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 |
| */ |
| Error GrallocMapper::unlockBuffer(buffer_handle_t bufferHandle, |
| int* outFenceFd) const |
| { |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer: %p is corrupted", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| int fenceFd = -1; |
| const int result = mali_gralloc_unlock_async(&privateModule, bufferHandle, &fenceFd); |
| if (result) |
| { |
| AERR("Unlocking failed with error: %d", result); |
| return Error::BAD_VALUE; |
| } |
| |
| *outFenceFd = fenceFd; |
| |
| return Error::NONE; |
| } |
| |
| #if HIDL_MAPPER_VERSION_SCALED >= 210 |
| |
| /* |
| * Validates the buffer against specified descriptor attributes |
| * |
| * @param buffer [in] Buffer which needs to be validated. |
| * @param descriptorInfo [in] Required attributes of the buffer |
| * @param in_stride [in] Buffer stride returned by IAllocator::allocate |
| * |
| * @return Error::NONE upon success. Otherwise, |
| * Error::BAD_BUFFER upon bad buffer input |
| * Error::BAD_VALUE when any of the specified attributes are invalid |
| */ |
| Return<Error> GrallocMapper::validateBufferSize(void* buffer, |
| const V2_1::IMapper::BufferDescriptorInfo& descriptorInfo, |
| uint32_t in_stride) |
| { |
| /* The buffer must have been allocated by Gralloc */ |
| buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer); |
| if (!bufferHandle) |
| { |
| AERR("Buffer: %p has not been registered with Gralloc", buffer); |
| return Error::BAD_BUFFER; |
| } |
| |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer: %p is corrupted", bufferHandle); |
| return Error::BAD_BUFFER; |
| } |
| |
| /* All Gralloc allocated buffers must be conform to local descriptor validation */ |
| if (!validateDescriptorInfo((void *)&descriptorInfo)) |
| { |
| AERR("Invalid descriptor attributes for validating buffer size"); |
| return Error::BAD_VALUE; |
| } |
| |
| 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(&privateModule, |
| &grallocDescriptor); |
| if (result) |
| { |
| AERR("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 */ |
| if ((size_t)gralloc_buffer->size < grallocDescriptor.size) |
| { |
| ALOGW("Buf size mismatch. Buffer size = %u, Descriptor (derived) size = %zu", |
| gralloc_buffer->size, grallocDescriptor.size); |
| return Error::BAD_VALUE; |
| } |
| |
| if ((uint32_t)gralloc_buffer->stride != in_stride) |
| { |
| AERR("Stride mismatch. Expected stride = %d, Buffer stride = %d", |
| in_stride, gralloc_buffer->stride); |
| return Error::BAD_VALUE; |
| } |
| |
| if (gralloc_buffer->internal_format != grallocDescriptor.internal_format) |
| { |
| AERR("Buffer format :0x%" PRIx64" does not match descriptor (derived) format :0x%" |
| PRIx64, gralloc_buffer->internal_format, grallocDescriptor.internal_format); |
| return Error::BAD_VALUE; |
| } |
| |
| if ((uint32_t)gralloc_buffer->width != grallocDescriptor.width) |
| { |
| AERR("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) |
| { |
| AERR("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) |
| { |
| AERR("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; |
| } |
| |
| /* |
| * Get the transport size of a buffer |
| * |
| * @param buffer [in] Buffer for computing transport size |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error: NONE upon success. Otherwise, |
| * BAD_BUFFER for an invalid buffer |
| * numFds: Number of file descriptors needed for transport |
| * numInts: Number of integers needed for transport |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::getTransportSize(void* buffer, getTransportSize_cb hidl_cb) |
| { |
| /* The buffer must have been allocated by Gralloc */ |
| buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer); |
| if (!bufferHandle) |
| { |
| AERR("Buffer %p is not registered with Gralloc", bufferHandle); |
| hidl_cb(Error::BAD_BUFFER, -1, -1); |
| return Void(); |
| } |
| |
| if (private_handle_t::validate(bufferHandle) < 0) |
| { |
| AERR("Buffer %p is corrupted", buffer); |
| hidl_cb(Error::BAD_BUFFER, -1, -1); |
| return Void(); |
| } |
| |
| hidl_cb(Error::NONE, GRALLOC_ARM_NUM_FDS, NUM_INTS_IN_PRIVATE_HANDLE); |
| |
| return Void(); |
| } |
| |
| /* |
| * Creates a buffer descriptor from incoming descriptor attributes |
| * |
| * @param descriptorInfo [in] Specifies the (2.1 IMapper) attributes of |
| * the descriptor. |
| * @param hidl_cb [in] HIDL callback function generating - |
| * error: NONE upon success. Otherwise, |
| * BAD_VALUE when any of the specified attributes are invalid |
| * descriptor: Newly created buffer descriptor. |
| * |
| * @return Void |
| */ |
| Return<void> GrallocMapper::createDescriptor_2_1(const V2_1::IMapper::BufferDescriptorInfo& descriptorInfo, |
| createDescriptor_2_1_cb hidl_cb) |
| { |
| if (validateDescriptorInfo((void *)&descriptorInfo)) |
| { |
| hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo)); |
| } |
| else |
| { |
| AERR("Invalid (IMapper 2.1) attributes to create descriptor"); |
| hidl_cb(Error::BAD_VALUE, V2_0::BufferDescriptor()); |
| } |
| |
| return Void(); |
| } |
| #endif /* HIDL_MAPPER_VERSION_SCALED >= 210 */ |
| |
| IMapper* HIDL_FETCH_IMapper(const char* /* name */) |
| { |
| ALOGV("Arm Module IMapper %d.%d , pid = %d ppid = %d ", GRALLOC_VERSION_MAJOR, |
| (HIDL_MAPPER_VERSION_SCALED - (GRALLOC_VERSION_MAJOR * 100)) / 10, getpid(), getppid()); |
| |
| return new GrallocMapper(); |
| } |
| |
| } // namespace implementation |
| } // namespace HIDL_IMAPPER_NAMESPACE |
| } // namespace mapper |
| } // namespace graphics |
| } // namespace hardware |
| } // namespace android |