#include "include/private/dvr/display_client.h" #include #include #include #include #include #include #include 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(); 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(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 Surface::SetVisible(bool visible) { return SetAttributes( {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}}); } Status Surface::SetZOrder(int z_order) { return SetAttributes( {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}}); } Status Surface::SetAttributes(const SurfaceAttributes& attributes) { auto status = InvokeRemoteMethod(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::Get(variant, &visible_); break; case SurfaceAttribute::ZOrder: invalid_value = !IfAnyOf::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> 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( 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> 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 DisplayClient::GetDisplayMetrics() { return InvokeRemoteMethod(); } Status DisplayClient::GetConfigurationData( ConfigFileType config_type) { auto status = InvokeRemoteMethod(config_type); if (!status && status.error() != ENOENT) { ALOGE( "DisplayClient::GetConfigurationData: Unable to get" "configuration data. Error: %s", status.GetErrorMessage().c_str()); } return status; } Status> DisplayClient::CreateSurface( const SurfaceAttributes& attributes) { int error; if (auto client = Surface::Create(attributes, &error)) return {std::move(client)}; else return ErrorStatus(error); } pdx::Status> DisplayClient::SetupGlobalBuffer( DvrGlobalBufferKey key, size_t size, uint64_t usage) { auto status = InvokeRemoteMethod(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(); 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 DisplayClient::DeleteGlobalBuffer(DvrGlobalBufferKey key) { auto status = InvokeRemoteMethod(key); if (!status) { ALOGE("DisplayClient::DeleteGlobalBuffer Failed: %s", status.GetErrorMessage().c_str()); } return status; } Status> DisplayClient::GetGlobalBuffer( DvrGlobalBufferKey key) { auto status = InvokeRemoteMethod(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(); 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 DisplayClient::IsVrAppRunning() { return InvokeRemoteMethod(); } } // namespace display } // namespace dvr } // namespace android