blob: 2b01b800589136add9618e6b5049a0ce284a5545 [file] [log] [blame]
#include "GrallocAllocator.h"
#include <aidl/android/hardware/graphics/allocator/AllocationError.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <android/binder_ibinder.h>
#include <android/binder_status.h>
#include <cutils/android_filesystem_config.h>
#include <hidl/HidlSupport.h>
#include "hidl_common/Allocator.h"
namespace pixel::allocator {
namespace AidlAllocator = aidl::android::hardware::graphics::allocator;
namespace HidlAllocator = android::hardware::graphics::allocator::V4_0;
using android::hardware::hidl_handle;
using android::hardware::hidl_vec;
using HidlError = android::hardware::graphics::mapper::V4_0::Error;
unsigned long callingPid() {
return static_cast<unsigned long>(AIBinder_getCallingPid());
}
unsigned long callingUid() {
return static_cast<unsigned long>(AIBinder_getCallingUid());
}
GrallocAllocator::GrallocAllocator() {}
GrallocAllocator::~GrallocAllocator() {}
ndk::ScopedAStatus GrallocAllocator::allocate(const std::vector<uint8_t>& descriptor, int32_t count,
AidlAllocator::AllocationResult* result) {
MALI_GRALLOC_LOGV("Allocation request from process: %lu", callingPid());
buffer_descriptor_t bufferDescriptor;
if (!arm::mapper::common::grallocDecodeBufferDescriptor(hidl_vec(descriptor),
bufferDescriptor)) {
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::BAD_DESCRIPTOR));
}
// TODO(layog@): This dependency between AIDL and HIDL backends is not good.
// Ideally common::allocate should return the result and it should be encoded
// by this interface into HIDL or AIDL.
HidlError error = HidlError::NONE;
auto hidl_cb = [&](HidlError _error, int _stride, hidl_vec<hidl_handle> _buffers) {
if (_error != HidlError::NONE) {
error = _error;
return;
}
const uint32_t size = _buffers.size();
result->stride = _stride;
result->buffers.resize(size);
for (uint32_t i = 0; i < size; i++) {
// Dup here is necessary. After this callback returns common::allocate
// will free the buffer which will destroy the older fd.
result->buffers[i] = android::dupToAidl(static_cast<const native_handle*>(_buffers[i]));
}
};
arm::allocator::common::allocate(bufferDescriptor, count, hidl_cb);
switch (error) {
case HidlError::NONE:
break;
case HidlError::BAD_DESCRIPTOR:
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::BAD_DESCRIPTOR));
case HidlError::NO_RESOURCES:
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::NO_RESOURCES));
case HidlError::UNSUPPORTED:
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::UNSUPPORTED));
default:
return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_ERROR);
}
return ndk::ScopedAStatus::ok();
}
buffer_descriptor_t decodeBufferDescriptorInfo(
const AidlAllocator::BufferDescriptorInfo& descriptor) {
buffer_descriptor_t bufferDescriptor;
bufferDescriptor.width = descriptor.width;
bufferDescriptor.height = descriptor.height;
bufferDescriptor.layer_count = descriptor.layerCount;
bufferDescriptor.hal_format = static_cast<uint64_t>(descriptor.format);
bufferDescriptor.producer_usage = static_cast<uint64_t>(descriptor.usage);
bufferDescriptor.consumer_usage = bufferDescriptor.producer_usage;
bufferDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
bufferDescriptor.signature = sizeof(buffer_descriptor_t);
bufferDescriptor.reserved_size = descriptor.reservedSize;
const char *str = (const char*) descriptor.name.data();
bufferDescriptor.name = std::string(str);
return bufferDescriptor;
}
ndk::ScopedAStatus GrallocAllocator::allocate2(
const AidlAllocator::BufferDescriptorInfo& descriptor, int32_t count,
AidlAllocator::AllocationResult* result) {
MALI_GRALLOC_LOGV("Allocation request from process: %lu", callingPid());
buffer_descriptor_t bufferDescriptor = decodeBufferDescriptorInfo(descriptor);
HidlError error = HidlError::NONE;
auto hidl_cb = [&](HidlError _error, int _stride, hidl_vec<hidl_handle> _buffers) {
if (_error != HidlError::NONE) {
error = _error;
return;
}
const uint32_t size = _buffers.size();
result->stride = _stride;
result->buffers.resize(size);
for (uint32_t i = 0; i < size; i++) {
// Dup here is necessary. After this callback returns common::allocate
// will free the buffer which will destroy the older fd.
result->buffers[i] = android::dupToAidl(static_cast<const native_handle*>(_buffers[i]));
}
};
arm::allocator::common::allocate(bufferDescriptor, count, hidl_cb);
switch (error) {
case HidlError::NONE:
break;
case HidlError::BAD_DESCRIPTOR:
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::BAD_DESCRIPTOR));
case HidlError::NO_RESOURCES:
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::NO_RESOURCES));
case HidlError::UNSUPPORTED:
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::UNSUPPORTED));
default:
return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_ERROR);
}
return ndk::ScopedAStatus::ok();
}
// TODO(b/315883761): isSupported should return false for unknown-to-HAL usage
ndk::ScopedAStatus GrallocAllocator::isSupported(
const AidlAllocator::BufferDescriptorInfo& descriptor, bool* result) {
buffer_descriptor_t bufferDescriptor = decodeBufferDescriptorInfo(descriptor);
int isBufferDescriptorSupported = arm::allocator::common::isSupported(&bufferDescriptor);
*result = (isBufferDescriptorSupported == 0);
if (isBufferDescriptorSupported) {
MALI_GRALLOC_LOGV("Allocation for the given description will not succeed. error %d",
isBufferDescriptorSupported);
return ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(AidlAllocator::AllocationError::UNSUPPORTED));
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus GrallocAllocator::getIMapperLibrarySuffix(std::string* result) {
*result = "";
return ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_ERROR);
}
binder_status_t GrallocAllocator::dump(int fd, const char** /* args */, uint32_t numArgs) {
if (callingUid() != AID_ROOT) {
const std::string permission_denied = "Permission Denied\n";
write(fd, permission_denied.c_str(), permission_denied.size());
return STATUS_PERMISSION_DENIED;
}
if (numArgs != 0) {
const std::string argument_error = "No argument expected\n";
write(fd, argument_error.c_str(), argument_error.size());
return STATUS_BAD_VALUE;
}
const std::string dump_info = arm::allocator::common::dump();
write(fd, dump_info.c_str(), dump_info.size());
return STATUS_OK;
}
} // namespace pixel::allocator