blob: 0d81d5cc45f550b0924d416c8cc0d7a6c6a35ed1 [file] [log] [blame]
/*
* Copyright 2022 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Allocator.h"
#include <aidl/android/hardware/graphics/allocator/AllocationError.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
#include <gralloctypes/Gralloc4.h>
#include <log/log.h>
#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h"
using aidl::android::hardware::common::NativeHandle;
using BufferDescriptorInfo =
android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo;
namespace aidl::android::hardware::graphics::allocator::impl {
namespace {
inline ndk::ScopedAStatus ToBinderStatus(AllocationError error) {
return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(error));
}
} // namespace
bool Allocator::init() {
mDriver = cros_gralloc_driver::get_instance();
return mDriver != nullptr;
}
// TODO(natsu): deduplicate with CrosGralloc4Allocator after the T release.
ndk::ScopedAStatus Allocator::initializeMetadata(
cros_gralloc_handle_t crosHandle,
const struct cros_gralloc_buffer_descriptor& crosDescriptor) {
if (!mDriver) {
ALOGE("Failed to initializeMetadata. Driver is uninitialized.\n");
return ToBinderStatus(AllocationError::NO_RESOURCES);
}
if (!crosHandle) {
ALOGE("Failed to initializeMetadata. Invalid handle.\n");
return ToBinderStatus(AllocationError::NO_RESOURCES);
}
void* addr;
uint64_t size;
int ret = mDriver->get_reserved_region(crosHandle, &addr, &size);
if (ret) {
ALOGE("Failed to getReservedRegion.\n");
return ToBinderStatus(AllocationError::NO_RESOURCES);
}
CrosGralloc4Metadata* crosMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr);
snprintf(crosMetadata->name, CROS_GRALLOC4_METADATA_MAX_NAME_SIZE, "%s",
crosDescriptor.name.c_str());
crosMetadata->dataspace = common::Dataspace::UNKNOWN;
crosMetadata->blendMode = common::BlendMode::INVALID;
return ndk::ScopedAStatus::ok();
}
void Allocator::releaseBufferAndHandle(native_handle_t* handle) {
mDriver->release(handle);
native_handle_close(handle);
native_handle_delete(handle);
}
ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& descriptor, int32_t count,
allocator::AllocationResult* outResult) {
if (!mDriver) {
ALOGE("Failed to allocate. Driver is uninitialized.\n");
return ToBinderStatus(AllocationError::NO_RESOURCES);
}
BufferDescriptorInfo description;
int ret = ::android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description);
if (ret) {
ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret);
return ToBinderStatus(AllocationError::BAD_DESCRIPTOR);
}
std::vector<native_handle_t*> handles;
handles.resize(count, nullptr);
for (int32_t i = 0; i < count; i++) {
ndk::ScopedAStatus status = allocate(description, &outResult->stride, &handles[i]);
if (!status.isOk()) {
for (int32_t j = 0; j < i; j++) {
releaseBufferAndHandle(handles[j]);
}
return status;
}
}
outResult->buffers.resize(count);
for (int32_t i = 0; i < count; i++) {
auto handle = handles[i];
outResult->buffers[i] = ::android::dupToAidl(handle);
releaseBufferAndHandle(handle);
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfo& descriptor, int32_t* outStride,
native_handle_t** outHandle) {
if (!mDriver) {
ALOGE("Failed to allocate. Driver is uninitialized.\n");
return ToBinderStatus(AllocationError::NO_RESOURCES);
}
struct cros_gralloc_buffer_descriptor crosDescriptor;
if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
return ToBinderStatus(AllocationError::UNSUPPORTED);
}
crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata);
if (!mDriver->is_supported(&crosDescriptor)) {
const std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format);
const std::string pixelFormatString = getPixelFormatString(descriptor.format);
const std::string usageString = getUsageString(descriptor.usage);
ALOGE("Failed to allocate. Unsupported combination: pixel format:%s, drm format:%s, "
"usage:%s\n",
pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str());
return ToBinderStatus(AllocationError::UNSUPPORTED);
}
native_handle_t* handle;
int ret = mDriver->allocate(&crosDescriptor, &handle);
if (ret) {
return ToBinderStatus(AllocationError::NO_RESOURCES);
}
cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle);
auto status = initializeMetadata(crosHandle, crosDescriptor);
if (!status.isOk()) {
ALOGE("Failed to allocate. Failed to initialize gralloc buffer metadata.");
releaseBufferAndHandle(handle);
return status;
}
*outStride = static_cast<int32_t>(crosHandle->pixel_stride);
*outHandle = handle;
return ndk::ScopedAStatus::ok();
}
::ndk::SpAIBinder Allocator::createBinder() {
auto binder = BnAllocator::createBinder();
AIBinder_setInheritRt(binder.get(), true);
return binder;
}
} // namespace aidl::android::hardware::graphics::allocator::impl