/* * Copyright (C) 2017 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. */ #define LOG_TAG "GrallocWrapper" #include "GrallocWrapper.h" #include <utils/Log.h> namespace android { GrallocWrapper::GrallocWrapper() { init(); } void GrallocWrapper::init() { mAllocator = allocator2::IAllocator::getService(); if (mAllocator == nullptr) { ALOGE("Failed to get allocator service"); } mMapper = mapper2::IMapper::getService(); if (mMapper == nullptr) { ALOGE("Failed to get mapper service"); } if (mMapper->isRemote()) { ALOGE("Mapper is not in passthrough mode"); } } GrallocWrapper::~GrallocWrapper() { for (auto bufferHandle : mClonedBuffers) { auto buffer = const_cast<native_handle_t*>(bufferHandle); native_handle_close(buffer); native_handle_delete(buffer); } mClonedBuffers.clear(); for (auto bufferHandle : mImportedBuffers) { auto buffer = const_cast<native_handle_t*>(bufferHandle); if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) { ALOGE("Failed to free buffer %p", buffer); } } mImportedBuffers.clear(); } sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const { return mAllocator; } std::string GrallocWrapper::dumpDebugInfo() { std::string debugInfo; mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); return debugInfo; } const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) { const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle()); if (bufferHandle) { mClonedBuffers.insert(bufferHandle); } return bufferHandle; } std::vector<const native_handle_t*> GrallocWrapper::allocate( const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) { std::vector<const native_handle_t*> bufferHandles; bufferHandles.reserve(count); mAllocator->allocate(descriptor, count, [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) { if (mapper2::Error::NONE != tmpError) { ALOGE("Failed to allocate buffers"); } if (count != tmpBuffers.size()) { ALOGE("Invalid buffer array"); } for (uint32_t i = 0; i < count; i++) { if (import) { bufferHandles.push_back(importBuffer(tmpBuffers[i])); } else { bufferHandles.push_back(cloneBuffer(tmpBuffers[i])); } } if (outStride) { *outStride = tmpStride; } }); return bufferHandles; } const native_handle_t* GrallocWrapper::allocate( const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import, uint32_t* outStride) { mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo); auto buffers = allocate(descriptor, 1, import, outStride); return buffers[0]; } sp<mapper2::IMapper> GrallocWrapper::getMapper() const { return mMapper; } mapper2::BufferDescriptor GrallocWrapper::createDescriptor( const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) { mapper2::BufferDescriptor descriptor; mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) { if (tmpError != mapper2::Error::NONE) { ALOGE("Failed to create descriptor"); } descriptor = tmpDescriptor; }); return descriptor; } const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) { const native_handle_t* bufferHandle = nullptr; mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) { if (tmpError != mapper2::Error::NONE) { ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle()); } bufferHandle = static_cast<const native_handle_t*>(tmpBuffer); }); if (bufferHandle) { mImportedBuffers.insert(bufferHandle); } return bufferHandle; } void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) { auto buffer = const_cast<native_handle_t*>(bufferHandle); if (mImportedBuffers.erase(bufferHandle)) { mapper2::Error error = mMapper->freeBuffer(buffer); if (error != mapper2::Error::NONE) { ALOGE("Failed to free %p", buffer); } } else { mClonedBuffers.erase(bufferHandle); native_handle_close(buffer); native_handle_delete(buffer); } } void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, const mapper2::IMapper::Rect& accessRegion, int acquireFence) { auto buffer = const_cast<native_handle_t*>(bufferHandle); NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0); hardware::hidl_handle acquireFenceHandle; if (acquireFence >= 0) { auto h = native_handle_init(acquireFenceStorage, 1, 0); h->data[0] = acquireFence; acquireFenceHandle = h; } void* data = nullptr; mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle, [&](const auto& tmpError, const auto& tmpData) { if (tmpError != mapper2::Error::NONE) { ALOGE("Failed to lock buffer %p", buffer); } data = tmpData; }); if (acquireFence >= 0) { close(acquireFence); } return data; } int GrallocWrapper::unlock(const native_handle_t* bufferHandle) { auto buffer = const_cast<native_handle_t*>(bufferHandle); int releaseFence = -1; mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) { if (tmpError != mapper2::Error::NONE) { ALOGE("Failed to unlock buffer %p", buffer); } auto fenceHandle = tmpReleaseFence.getNativeHandle(); if (fenceHandle) { if (fenceHandle->numInts != 0) { ALOGE("Invalid fence handle %p", fenceHandle); } if (fenceHandle->numFds == 1) { releaseFence = dup(fenceHandle->data[0]); if (releaseFence < 0) { ALOGE("Failed to dup fence fd"); } } else { if (fenceHandle->numFds != 0) { ALOGE("Invalid fence handle %p", fenceHandle); } } } }); return releaseFence; } } // namespace android