| #include "include/private/dvr/display_client.h" |
| |
| #include <cutils/log.h> |
| #include <cutils/native_handle.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_rpc.h> |
| #include <private/dvr/late_latch.h> |
| #include <private/dvr/native_buffer.h> |
| |
| 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 { |
| |
| SurfaceClient::SurfaceClient(LocalChannelHandle channel_handle, |
| SurfaceType type) |
| : Client{pdx::default_transport::ClientChannel::Create( |
| std::move(channel_handle))}, |
| type_(type) {} |
| |
| SurfaceClient::SurfaceClient(const std::string& endpoint_path, SurfaceType type) |
| : Client{pdx::default_transport::ClientChannelFactory::Create( |
| endpoint_path), |
| kInfiniteTimeout}, |
| type_(type) {} |
| |
| int SurfaceClient::GetMetadataBufferFd(LocalHandle* out_fd) { |
| auto buffer_producer = GetMetadataBuffer(); |
| if (!buffer_producer) |
| return -ENOMEM; |
| |
| *out_fd = buffer_producer->GetBlobFd(); |
| return 0; |
| } |
| |
| std::shared_ptr<BufferProducer> SurfaceClient::GetMetadataBuffer() { |
| if (!metadata_buffer_) { |
| auto status = InvokeRemoteMethod<DisplayRPC::GetMetadataBuffer>(); |
| if (!status) { |
| ALOGE( |
| "SurfaceClient::AllocateMetadataBuffer: Failed to allocate buffer: " |
| "%s", |
| status.GetErrorMessage().c_str()); |
| return nullptr; |
| } |
| |
| metadata_buffer_ = BufferProducer::Import(status.take()); |
| } |
| |
| return metadata_buffer_; |
| } |
| |
| DisplaySurfaceClient::DisplaySurfaceClient(int width, int height, int format, |
| int usage, int flags) |
| : BASE(DisplayRPC::kClientPath, SurfaceTypeEnum::Normal), |
| width_(width), |
| height_(height), |
| format_(format), |
| usage_(usage), |
| flags_(flags), |
| z_order_(0), |
| visible_(true), |
| exclude_from_blur_(false), |
| blur_behind_(true), |
| mapped_metadata_buffer_(nullptr) { |
| auto status = InvokeRemoteMethod<DisplayRPC::CreateSurface>( |
| width, height, format, usage, flags); |
| if (!status) { |
| ALOGE( |
| "DisplaySurfaceClient::DisplaySurfaceClient: Failed to create display " |
| "surface: %s", |
| status.GetErrorMessage().c_str()); |
| Close(status.error()); |
| } |
| } |
| |
| void DisplaySurfaceClient::SetVisible(bool visible) { |
| SetAttributes({{DisplaySurfaceAttributeEnum::Visible, |
| DisplaySurfaceAttributeValue{visible}}}); |
| } |
| |
| void DisplaySurfaceClient::SetZOrder(int z_order) { |
| SetAttributes({{DisplaySurfaceAttributeEnum::ZOrder, |
| DisplaySurfaceAttributeValue{z_order}}}); |
| } |
| |
| void DisplaySurfaceClient::SetExcludeFromBlur(bool exclude_from_blur) { |
| SetAttributes({{DisplaySurfaceAttributeEnum::ExcludeFromBlur, |
| DisplaySurfaceAttributeValue{exclude_from_blur}}}); |
| } |
| |
| void DisplaySurfaceClient::SetBlurBehind(bool blur_behind) { |
| SetAttributes({{DisplaySurfaceAttributeEnum::BlurBehind, |
| DisplaySurfaceAttributeValue{blur_behind}}}); |
| } |
| |
| void DisplaySurfaceClient::SetAttributes( |
| const DisplaySurfaceAttributes& attributes) { |
| Status<int> status = |
| InvokeRemoteMethod<DisplayRPC::SetAttributes>(attributes); |
| if (!status) { |
| ALOGE( |
| "DisplaySurfaceClient::SetAttributes: Failed to set display surface " |
| "attributes: %s", |
| status.GetErrorMessage().c_str()); |
| return; |
| } |
| |
| // 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 DisplaySurfaceAttributeEnum::Visible: |
| invalid_value = |
| !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_); |
| break; |
| case DisplaySurfaceAttributeEnum::ZOrder: |
| invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_); |
| break; |
| case DisplaySurfaceAttributeEnum::ExcludeFromBlur: |
| invalid_value = |
| !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &exclude_from_blur_); |
| break; |
| case DisplaySurfaceAttributeEnum::BlurBehind: |
| invalid_value = |
| !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &blur_behind_); |
| break; |
| } |
| |
| if (invalid_value) { |
| ALOGW( |
| "DisplaySurfaceClient::SetAttributes: Failed to set display " |
| "surface attribute '%s' because of incompatible type: %d", |
| DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index()); |
| } |
| } |
| } |
| |
| std::shared_ptr<BufferProducer> DisplaySurfaceClient::AllocateBuffer( |
| uint32_t* buffer_index) { |
| auto status = InvokeRemoteMethod<DisplayRPC::AllocateBuffer>(); |
| if (!status) { |
| ALOGE("DisplaySurfaceClient::AllocateBuffer: Failed to allocate buffer: %s", |
| status.GetErrorMessage().c_str()); |
| return nullptr; |
| } |
| |
| if (buffer_index) |
| *buffer_index = status.get().first; |
| return BufferProducer::Import(status.take().second); |
| } |
| |
| volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() { |
| if (!mapped_metadata_buffer_) { |
| if (auto buffer_producer = GetMetadataBuffer()) { |
| void* addr = nullptr; |
| const int ret = buffer_producer->GetBlobReadWritePointer( |
| sizeof(DisplaySurfaceMetadata), &addr); |
| if (ret < 0) { |
| ALOGE( |
| "DisplaySurfaceClient::GetMetadataBufferPtr: Failed to map surface " |
| "metadata: %s", |
| strerror(-ret)); |
| return nullptr; |
| } |
| mapped_metadata_buffer_ = static_cast<DisplaySurfaceMetadata*>(addr); |
| } |
| } |
| |
| return mapped_metadata_buffer_; |
| } |
| |
| LocalChannelHandle DisplaySurfaceClient::CreateVideoMeshSurface() { |
| auto status = InvokeRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(); |
| if (!status) { |
| ALOGE( |
| "DisplaySurfaceClient::CreateVideoMeshSurface: Failed to create " |
| "video mesh surface: %s", |
| status.GetErrorMessage().c_str()); |
| } |
| return status.take(); |
| } |
| |
| DisplayClient::DisplayClient(int* error) |
| : BASE(pdx::default_transport::ClientChannelFactory::Create( |
| DisplayRPC::kClientPath), |
| kInfiniteTimeout) { |
| if (error) |
| *error = Client::error(); |
| } |
| |
| int DisplayClient::GetDisplayMetrics(SystemDisplayMetrics* metrics) { |
| auto status = InvokeRemoteMethod<DisplayRPC::GetMetrics>(); |
| if (!status) { |
| ALOGE("DisplayClient::GetDisplayMetrics: Failed to get metrics: %s", |
| status.GetErrorMessage().c_str()); |
| return -status.error(); |
| } |
| |
| *metrics = status.get(); |
| return 0; |
| } |
| |
| pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) { |
| auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params); |
| if (!status) { |
| ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s", |
| status.GetErrorMessage().c_str()); |
| } |
| return status; |
| } |
| |
| int DisplayClient::GetLastFrameEdsTransform(LateLatchOutput* ll_out) { |
| auto status = InvokeRemoteMethod<DisplayRPC::GetEdsCapture>(); |
| if (!status) { |
| ALOGE( |
| "DisplayClient::GetLastFrameLateLatch: Failed to get most recent late" |
| " latch: %s", |
| status.GetErrorMessage().c_str()); |
| return -status.error(); |
| } |
| |
| if (status.get().size() != sizeof(LateLatchOutput)) { |
| ALOGE( |
| "DisplayClient::GetLastFrameLateLatch: Error expected to receive %zu " |
| "bytes but received %zu", |
| sizeof(LateLatchOutput), status.get().size()); |
| return -EIO; |
| } |
| |
| *ll_out = *reinterpret_cast<const LateLatchOutput*>(status.get().data()); |
| return 0; |
| } |
| |
| int DisplayClient::EnterVrMode() { |
| auto status = InvokeRemoteMethod<DisplayRPC::EnterVrMode>(); |
| if (!status) { |
| ALOGE( |
| "DisplayClient::EnterVrMode: Failed to set display service to Vr mode"); |
| return -status.error(); |
| } |
| |
| return 0; |
| } |
| |
| int DisplayClient::ExitVrMode() { |
| auto status = InvokeRemoteMethod<DisplayRPC::ExitVrMode>(); |
| if (!status) { |
| ALOGE( |
| "DisplayClient::ExitVrMode: Failed to revert display service from Vr " |
| "mode"); |
| return -status.error(); |
| } |
| |
| return 0; |
| } |
| |
| std::unique_ptr<DisplaySurfaceClient> DisplayClient::CreateDisplaySurface( |
| int width, int height, int format, int usage, int flags) { |
| return DisplaySurfaceClient::Create(width, height, format, usage, flags); |
| } |
| |
| } // namespace dvr |
| } // namespace android |