#include "include/dvr/dvr_display_manager.h"
#include <dvr/dvr_buffer.h>
#include <pdx/rpc/variant.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/display_manager_client.h>
#include "dvr_internal.h"
using android::AHardwareBuffer_convertToGrallocUsageBits;
using android::dvr::BufferConsumer;
using android::dvr::display::DisplayManagerClient;
using android::dvr::display::SurfaceAttributes;
using android::dvr::display::SurfaceAttribute;
using android::dvr::display::SurfaceState;
using android::dvr::CreateDvrReadBufferQueueFromConsumerQueue;
using android::pdx::rpc::EmptyVariant;
namespace {
// Extracts type and value from the attribute Variant and writes them into the
// respective fields of DvrSurfaceAttribute.
struct AttributeVisitor {
DvrSurfaceAttribute* attribute;
void operator()(int32_t value) {
attribute->value.int32_value = value;
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
}
void operator()(int64_t value) {
attribute->value.int64_value = value;
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT64;
}
void operator()(bool value) {
attribute->value.bool_value = value;
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
}
void operator()(float value) {
attribute->value.float_value = value;
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT;
}
void operator()(const std::array<float, 2>& value) {
std::copy(value.cbegin(), value.cend(), attribute->value.float2_value);
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2;
}
void operator()(const std::array<float, 3>& value) {
std::copy(value.cbegin(), value.cend(), attribute->value.float3_value);
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3;
}
void operator()(const std::array<float, 4>& value) {
std::copy(value.cbegin(), value.cend(), attribute->value.float4_value);
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4;
}
void operator()(const std::array<float, 8>& value) {
std::copy(value.cbegin(), value.cend(), attribute->value.float8_value);
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8;
}
void operator()(const std::array<float, 16>& value) {
std::copy(value.cbegin(), value.cend(), attribute->value.float16_value);
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16;
}
void operator()(EmptyVariant) {
attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
}
};
size_t ConvertSurfaceAttributes(const SurfaceAttributes& surface_attributes,
DvrSurfaceAttribute* attributes,
size_t max_count) {
size_t count = 0;
for (const auto& attribute : surface_attributes) {
if (count >= max_count)
break;
// Copy the key and extract the Variant value using a visitor.
attributes[count].key = attribute.first;
attribute.second.Visit(AttributeVisitor{&attributes[count]});
count++;
}
return count;
}
} // anonymous namespace
extern "C" {
struct DvrDisplayManager {
std::unique_ptr<DisplayManagerClient> client;
};
struct DvrSurfaceState {
std::vector<SurfaceState> state;
};
int dvrDisplayManagerCreate(DvrDisplayManager** client_out) {
if (!client_out)
return -EINVAL;
auto client = DisplayManagerClient::Create();
if (!client) {
ALOGE("dvrDisplayManagerCreate: Failed to create display manager client!");
return -EIO;
}
*client_out = new DvrDisplayManager{std::move(client)};
return 0;
}
void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
const char* name, size_t size,
uint64_t usage, DvrBuffer** buffer_out) {
if (!client || !name || !buffer_out)
return -EINVAL;
uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
auto buffer_status =
client->client->SetupNamedBuffer(name, size, gralloc_usage);
if (!buffer_status) {
ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
buffer_status.GetErrorMessage().c_str());
return -buffer_status.error();
}
*buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
return 0;
}
int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
if (!client)
return -EINVAL;
return client->client->event_fd();
}
int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
int in_events, int* out_events) {
if (!client || !out_events)
return -EINVAL;
auto status = client->client->GetEventMask(in_events);
if (!status)
return -status.error();
*out_events = status.get();
return 0;
}
int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
DvrSurfaceState* state) {
if (!client || !state)
return -EINVAL;
auto status = client->client->GetSurfaceState();
if (!status)
return -status.error();
state->state = status.take();
return 0;
}
int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
int surface_id, int queue_id,
DvrReadBufferQueue** queue_out) {
if (!client || !queue_out)
return -EINVAL;
auto status = client->client->GetSurfaceQueue(surface_id, queue_id);
if (!status) {
ALOGE("dvrDisplayManagerGetReadBufferQueue: Failed to get queue: %s",
status.GetErrorMessage().c_str());
return -status.error();
}
*queue_out = CreateDvrReadBufferQueueFromConsumerQueue(status.take());
return 0;
}
int dvrSurfaceStateCreate(DvrSurfaceState** surface_state_out) {
if (!surface_state_out)
return -EINVAL;
*surface_state_out = new DvrSurfaceState{};
return 0;
}
void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state) {
delete surface_state;
}
int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
size_t* count_out) {
if (!surface_state)
return -EINVAL;
*count_out = surface_state->state.size();
return 0;
}
int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
size_t surface_index,
DvrSurfaceUpdateFlags* flags_out) {
if (!surface_state || surface_index >= surface_state->state.size())
return -EINVAL;
*flags_out = surface_state->state[surface_index].update_flags;
return 0;
}
int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
size_t surface_index, int* surface_id_out) {
if (!surface_state || surface_index >= surface_state->state.size())
return -EINVAL;
*surface_id_out = surface_state->state[surface_index].surface_id;
return 0;
}
int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
size_t surface_index, int* process_id_out) {
if (!surface_state || surface_index >= surface_state->state.size())
return -EINVAL;
*process_id_out = surface_state->state[surface_index].process_id;
return 0;
}
int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
size_t surface_index, size_t* count_out) {
if (!surface_state || surface_index >= surface_state->state.size())
return -EINVAL;
*count_out = surface_state->state[surface_index].queue_ids.size();
return 0;
}
ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
size_t surface_index, int* queue_ids,
size_t max_count) {
if (!surface_state || surface_index >= surface_state->state.size())
return -EINVAL;
size_t i;
const auto& state = surface_state->state[surface_index];
for (i = 0; i < std::min(max_count, state.queue_ids.size()); i++) {
queue_ids[i] = state.queue_ids[i];
}
return i;
}
int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
size_t surface_index, int* z_order_out) {
if (!surface_state || surface_index >= surface_state->state.size() ||
!z_order_out) {
return -EINVAL;
}
*z_order_out = surface_state->state[surface_index].GetZOrder();
return 0;
}
int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
size_t surface_index, bool* visible_out) {
if (!surface_state || surface_index >= surface_state->state.size() ||
!visible_out) {
return -EINVAL;
}
*visible_out = surface_state->state[surface_index].GetVisible();
return 0;
}
int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
size_t surface_index, size_t* count_out) {
if (!surface_state || surface_index >= surface_state->state.size() ||
!count_out) {
return -EINVAL;
}
*count_out = surface_state->state[surface_index].surface_attributes.size();
return 0;
}
ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
size_t surface_index,
DvrSurfaceAttribute* attributes,
size_t max_count) {
if (!surface_state || surface_index >= surface_state->state.size() ||
!attributes) {
return -EINVAL;
}
return ConvertSurfaceAttributes(
surface_state->state[surface_index].surface_attributes, attributes,
max_count);
}
} // extern "C"