blob: df30bf7dafda75504208f8f36957aa8eb3b522d8 [file] [log] [blame]
/*
* Copyright (C) 2018 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 "goog_gralloc_wrapper"
#include "goog_gralloc_wrapper.h"
#include <utils/Log.h>
namespace android {
namespace camera_sensor_listener {
using ::android::hardware::hidl_handle;
using ::android::hardware::graphics::allocator::V3_0::IAllocator;
using ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
using ::android::hardware::graphics::mapper::V3_0::Error;
using ::android::hardware::graphics::mapper::V3_0::IMapper;
GoogGrallocWrapper::GoogGrallocWrapper() {
allocator_ = IAllocator::getService();
if (allocator_ == nullptr) {
ALOGE("%s %d Failed to get allocator service", __func__, __LINE__);
}
mapper_ = IMapper::getService();
if (mapper_ == nullptr) {
ALOGE("%s %d Failed to get mapper service", __func__, __LINE__);
}
if (mapper_->isRemote()) {
ALOGE("%s %d Mapper is not in passthrough mode", __func__, __LINE__);
}
}
GoogGrallocWrapper::~GoogGrallocWrapper() {
for (auto buffer_handle : cloned_buffers_) {
auto buffer = const_cast<native_handle_t*>(buffer_handle);
native_handle_close(buffer);
native_handle_delete(buffer);
}
cloned_buffers_.clear();
for (auto buffer_handle : imported_buffers_) {
auto buffer = const_cast<native_handle_t*>(buffer_handle);
if (mapper_->freeBuffer(buffer) != Error::NONE) {
ALOGE("%s %d Failed to free buffer %p", __func__, __LINE__, buffer);
}
}
imported_buffers_.clear();
}
sp<IAllocator> GoogGrallocWrapper::GetAllocator() const {
return allocator_;
}
std::string GoogGrallocWrapper::DumpDebugInfo() const {
std::string debug_info;
allocator_->dumpDebugInfo([&debug_info](const auto& tmp_debug_info) {
debug_info = tmp_debug_info.c_str();
});
return debug_info;
}
const native_handle_t* GoogGrallocWrapper::CloneBuffer(
const hidl_handle& raw_handle) {
const native_handle_t* buffer_handle =
native_handle_clone(raw_handle.getNativeHandle());
if (buffer_handle) {
cloned_buffers_.insert(buffer_handle);
}
return buffer_handle;
}
// When import is false, this simply calls IAllocator::allocate. When import
// is true, the returned buffers are also imported into the mapper.
// Either case, the returned buffers must be freed with freeBuffer.
std::vector<const native_handle_t*> GoogGrallocWrapper::Allocate(
const BufferDescriptor& descriptor, uint32_t count, bool import,
uint32_t* out_stride) {
std::vector<const native_handle_t*> buffer_handles;
buffer_handles.reserve(count);
allocator_->allocate(
descriptor, count,
[&](const auto& tmp_error, const auto& tmp_stride,
const auto& tmp_buffers) {
if (tmp_error != Error::NONE) {
ALOGE("%s %d Failed to allocate buffers", __func__, __LINE__);
}
if (count != tmp_buffers.size()) {
ALOGE("%s %d Invalid buffer array", __func__, __LINE__);
}
for (uint32_t i = 0; i < count; i++) {
if (import) {
buffer_handles.push_back(ImportBuffer(tmp_buffers[i]));
} else {
buffer_handles.push_back(CloneBuffer(tmp_buffers[i]));
}
}
if (out_stride) {
*out_stride = tmp_stride;
}
});
return buffer_handles;
}
const native_handle_t* GoogGrallocWrapper::AllocateOneBuffer(
const IMapper::BufferDescriptorInfo& descriptor_info, bool import,
uint32_t* out_stride) {
BufferDescriptor descriptor = CreateDescriptor(descriptor_info);
auto buffers = Allocate(descriptor, 1, import, out_stride);
return buffers[0];
}
sp<IMapper> GoogGrallocWrapper::GetMapper() const {
return mapper_;
}
BufferDescriptor GoogGrallocWrapper::CreateDescriptor(
const IMapper::BufferDescriptorInfo& descriptor_info) {
BufferDescriptor descriptor;
mapper_->createDescriptor(
descriptor_info,
[&descriptor](const auto& tmp_error, const auto& tmp_descriptor) {
if (tmp_error != Error::NONE) {
ALOGE("Failed to create descriptor");
}
descriptor = tmp_descriptor;
});
return descriptor;
}
const native_handle_t* GoogGrallocWrapper::ImportBuffer(
const hidl_handle& raw_handle) {
const native_handle_t* buffer_handle = nullptr;
mapper_->importBuffer(
raw_handle, [&buffer_handle, &raw_handle](const auto& tmp_error,
const auto& tmp_buffer) {
if (tmp_error != Error::NONE) {
ALOGE("%s %d Failed to import buffer %p", __func__, __LINE__,
raw_handle.getNativeHandle());
}
buffer_handle = static_cast<const native_handle_t*>(tmp_buffer);
});
if (buffer_handle) {
imported_buffers_.insert(buffer_handle);
}
return buffer_handle;
}
void GoogGrallocWrapper::FreeBuffer(const native_handle_t* buffer_handle) {
auto buffer = const_cast<native_handle_t*>(buffer_handle);
if (imported_buffers_.erase(buffer_handle)) {
Error error = mapper_->freeBuffer(buffer);
if (error != Error::NONE) {
ALOGE("%s %d Failed to free %p", __func__, __LINE__, buffer);
}
} else {
cloned_buffers_.erase(buffer_handle);
native_handle_close(buffer);
native_handle_delete(buffer);
}
}
// We use fd instead of ::android::hardware::hidl_handle in these functions to
// pass fences in and out of the mapper. The ownership of the fd is always
// transferred with each of these functions.
void* GoogGrallocWrapper::Lock(const native_handle_t* buffer_handle,
uint64_t cpu_usage,
const IMapper::Rect& access_region,
int acquire_fence) {
auto buffer = const_cast<native_handle_t*>(buffer_handle);
NATIVE_HANDLE_DECLARE_STORAGE(acquire_fence_storage, 1, 0);
hidl_handle acquire_fence_handle;
if (acquire_fence >= 0) {
auto h = native_handle_init(acquire_fence_storage, 1, 0);
h->data[0] = acquire_fence;
acquire_fence_handle = h;
}
void* data = nullptr;
mapper_->lock(buffer, cpu_usage, access_region, acquire_fence_handle,
[&buffer, &data](const auto& tmp_error, const auto& tmp_data,
const auto& /*bytesPerPixel*/,
const auto& /*bytesPerStride*/) {
if (tmp_error != Error::NONE) {
ALOGE("Failed to lock buffer %p", buffer);
} else {
data = tmp_data;
}
});
if (acquire_fence >= 0) {
close(acquire_fence);
}
return data;
}
int GoogGrallocWrapper::Unlock(const native_handle_t* buffer_handle) {
auto buffer = const_cast<native_handle_t*>(buffer_handle);
int release_fence = -1;
mapper_->unlock(buffer,
[&buffer, &release_fence](const auto& tmp_error,
const auto& tmp_release_fence) {
if (tmp_error != Error::NONE) {
ALOGE("Failed to unlock buffer %p", buffer);
}
auto fence_handle = tmp_release_fence.getNativeHandle();
if (fence_handle) {
if (fence_handle->numInts != 0) {
ALOGE("Invalid fence handle %p", fence_handle);
}
if (fence_handle->numFds == 1) {
release_fence = dup(fence_handle->data[0]);
if (release_fence < 0) {
ALOGE("Failed to dup fence fd");
}
} else {
if (fence_handle->numFds != 0) {
ALOGE("Invalid fence handle %p", fence_handle);
}
}
}
});
return release_fence;
}
} // namespace camera_sensor_listener
} // namespace android