You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
8.1 KiB
262 lines
8.1 KiB
#include "include/private/dvr/display_client.h"
|
|
|
|
#include <cutils/native_handle.h>
|
|
#include <log/log.h>
|
|
#include <pdx/default_transport/client_channel.h>
|
|
#include <pdx/default_transport/client_channel_factory.h>
|
|
#include <pdx/status.h>
|
|
|
|
#include <mutex>
|
|
|
|
#include <private/dvr/display_protocol.h>
|
|
|
|
using android::pdx::ErrorStatus;
|
|
using android::pdx::LocalHandle;
|
|
using android::pdx::LocalChannelHandle;
|
|
using android::pdx::Status;
|
|
using android::pdx::Transaction;
|
|
using android::pdx::rpc::IfAnyOf;
|
|
|
|
namespace android {
|
|
namespace dvr {
|
|
namespace display {
|
|
|
|
Surface::Surface(LocalChannelHandle channel_handle, int* error)
|
|
: BASE{pdx::default_transport::ClientChannel::Create(
|
|
std::move(channel_handle))} {
|
|
auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
|
|
if (!status) {
|
|
ALOGE("Surface::Surface: Failed to get surface info: %s",
|
|
status.GetErrorMessage().c_str());
|
|
Close(status.error());
|
|
if (error)
|
|
*error = status.error();
|
|
}
|
|
|
|
surface_id_ = status.get().surface_id;
|
|
z_order_ = status.get().z_order;
|
|
visible_ = status.get().visible;
|
|
}
|
|
|
|
Surface::Surface(const SurfaceAttributes& attributes, int* error)
|
|
: BASE{pdx::default_transport::ClientChannelFactory::Create(
|
|
DisplayProtocol::kClientPath),
|
|
kInfiniteTimeout} {
|
|
auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
|
|
if (!status) {
|
|
ALOGE("Surface::Surface: Failed to create display surface: %s",
|
|
status.GetErrorMessage().c_str());
|
|
Close(status.error());
|
|
if (error)
|
|
*error = status.error();
|
|
}
|
|
|
|
surface_id_ = status.get().surface_id;
|
|
z_order_ = status.get().z_order;
|
|
visible_ = status.get().visible;
|
|
}
|
|
|
|
Status<void> Surface::SetVisible(bool visible) {
|
|
return SetAttributes(
|
|
{{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
|
|
}
|
|
|
|
Status<void> Surface::SetZOrder(int z_order) {
|
|
return SetAttributes(
|
|
{{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
|
|
}
|
|
|
|
Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
|
|
auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
|
|
if (!status) {
|
|
ALOGE(
|
|
"Surface::SetAttributes: Failed to set display surface "
|
|
"attributes: %s",
|
|
status.GetErrorMessage().c_str());
|
|
return status.error_status();
|
|
}
|
|
|
|
// Set the local cached copies of the attributes we care about from the full
|
|
// set of attributes sent to the display service.
|
|
for (const auto& attribute : attributes) {
|
|
const auto& key = attribute.first;
|
|
const auto* variant = &attribute.second;
|
|
bool invalid_value = false;
|
|
switch (key) {
|
|
case SurfaceAttribute::Visible:
|
|
invalid_value =
|
|
!IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
|
|
break;
|
|
case SurfaceAttribute::ZOrder:
|
|
invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
|
|
break;
|
|
}
|
|
|
|
if (invalid_value) {
|
|
ALOGW(
|
|
"Surface::SetAttributes: Failed to set display surface "
|
|
"attribute %d because of incompatible type: %d",
|
|
key, variant->index());
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
|
|
uint32_t width, uint32_t height, uint32_t format, size_t metadata_size) {
|
|
ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
|
|
auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(
|
|
ProducerQueueConfigBuilder()
|
|
.SetDefaultWidth(width)
|
|
.SetDefaultHeight(height)
|
|
.SetDefaultFormat(format)
|
|
.SetMetadataSize(metadata_size)
|
|
.Build());
|
|
if (!status) {
|
|
ALOGE("Surface::CreateQueue: Failed to create queue: %s",
|
|
status.GetErrorMessage().c_str());
|
|
return status.error_status();
|
|
}
|
|
|
|
auto producer_queue = ProducerQueue::Import(status.take());
|
|
if (!producer_queue) {
|
|
ALOGE("Surface::CreateQueue: Failed to import producer queue!");
|
|
return ErrorStatus(ENOMEM);
|
|
}
|
|
|
|
return {std::move(producer_queue)};
|
|
}
|
|
|
|
Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
|
|
uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
|
|
uint64_t usage, size_t capacity, size_t metadata_size) {
|
|
ALOGD_IF(TRACE,
|
|
"Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
|
|
"usage=%" PRIx64 " capacity=%zu",
|
|
width, height, layer_count, format, usage, capacity);
|
|
auto status = CreateQueue(width, height, format, metadata_size);
|
|
if (!status)
|
|
return status.error_status();
|
|
|
|
auto producer_queue = status.take();
|
|
|
|
ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
|
|
auto allocate_status = producer_queue->AllocateBuffers(
|
|
width, height, layer_count, format, usage, capacity);
|
|
if (!allocate_status) {
|
|
ALOGE("Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
|
|
producer_queue->id(), allocate_status.GetErrorMessage().c_str());
|
|
return allocate_status.error_status();
|
|
}
|
|
|
|
return {std::move(producer_queue)};
|
|
}
|
|
|
|
DisplayClient::DisplayClient(int* error)
|
|
: BASE(pdx::default_transport::ClientChannelFactory::Create(
|
|
DisplayProtocol::kClientPath),
|
|
kInfiniteTimeout) {
|
|
if (error)
|
|
*error = Client::error();
|
|
}
|
|
|
|
Status<Metrics> DisplayClient::GetDisplayMetrics() {
|
|
return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
|
|
}
|
|
|
|
Status<std::string> DisplayClient::GetConfigurationData(
|
|
ConfigFileType config_type) {
|
|
auto status =
|
|
InvokeRemoteMethod<DisplayProtocol::GetConfigurationData>(config_type);
|
|
if (!status && status.error() != ENOENT) {
|
|
ALOGE(
|
|
"DisplayClient::GetConfigurationData: Unable to get"
|
|
"configuration data. Error: %s",
|
|
status.GetErrorMessage().c_str());
|
|
}
|
|
return status;
|
|
}
|
|
|
|
Status<uint8_t> DisplayClient::GetDisplayIdentificationPort() {
|
|
return InvokeRemoteMethod<DisplayProtocol::GetDisplayIdentificationPort>();
|
|
}
|
|
|
|
Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
|
|
const SurfaceAttributes& attributes) {
|
|
int error;
|
|
if (auto client = Surface::Create(attributes, &error))
|
|
return {std::move(client)};
|
|
else
|
|
return ErrorStatus(error);
|
|
}
|
|
|
|
pdx::Status<std::unique_ptr<IonBuffer>> DisplayClient::SetupGlobalBuffer(
|
|
DvrGlobalBufferKey key, size_t size, uint64_t usage) {
|
|
auto status =
|
|
InvokeRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(key, size, usage);
|
|
if (!status) {
|
|
ALOGE(
|
|
"DisplayClient::SetupGlobalBuffer: Failed to create the global buffer "
|
|
"%s",
|
|
status.GetErrorMessage().c_str());
|
|
return status.error_status();
|
|
}
|
|
|
|
auto ion_buffer = std::make_unique<IonBuffer>();
|
|
auto native_buffer_handle = status.take();
|
|
const int ret = native_buffer_handle.Import(ion_buffer.get());
|
|
if (ret < 0) {
|
|
ALOGE(
|
|
"DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
|
|
"key=%d; error=%s",
|
|
key, strerror(-ret));
|
|
return ErrorStatus(-ret);
|
|
}
|
|
|
|
return {std::move(ion_buffer)};
|
|
}
|
|
|
|
pdx::Status<void> DisplayClient::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
|
|
auto status = InvokeRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(key);
|
|
if (!status) {
|
|
ALOGE("DisplayClient::DeleteGlobalBuffer Failed: %s",
|
|
status.GetErrorMessage().c_str());
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
Status<std::unique_ptr<IonBuffer>> DisplayClient::GetGlobalBuffer(
|
|
DvrGlobalBufferKey key) {
|
|
auto status = InvokeRemoteMethod<DisplayProtocol::GetGlobalBuffer>(key);
|
|
if (!status) {
|
|
ALOGE(
|
|
"DisplayClient::GetGlobalBuffer: Failed to get named buffer: key=%d; "
|
|
"error=%s",
|
|
key, status.GetErrorMessage().c_str());
|
|
return status.error_status();
|
|
}
|
|
|
|
auto ion_buffer = std::make_unique<IonBuffer>();
|
|
auto native_buffer_handle = status.take();
|
|
const int ret = native_buffer_handle.Import(ion_buffer.get());
|
|
if (ret < 0) {
|
|
ALOGE(
|
|
"DisplayClient::GetGlobalBuffer: Failed to import global buffer: "
|
|
"key=%d; error=%s",
|
|
key, strerror(-ret));
|
|
return ErrorStatus(-ret);
|
|
}
|
|
|
|
return {std::move(ion_buffer)};
|
|
}
|
|
|
|
Status<bool> DisplayClient::IsVrAppRunning() {
|
|
return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
|
|
}
|
|
|
|
} // namespace display
|
|
} // namespace dvr
|
|
} // namespace android
|