diff options
Diffstat (limited to 'libs/ui/BufferHubBuffer.cpp')
-rw-r--r-- | libs/ui/BufferHubBuffer.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp new file mode 100644 index 0000000000..9293711d0e --- /dev/null +++ b/libs/ui/BufferHubBuffer.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// We would eliminate the clang warnings introduced by libdpx. +// TODO(b/112338294): Remove those once BufferHub moved to use Binder +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wdouble-promotion" +#pragma clang diagnostic ignored "-Wgnu-case-range" +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" +#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override" +#pragma clang diagnostic ignored "-Wnested-anon-types" +#pragma clang diagnostic ignored "-Wpacked" +#pragma clang diagnostic ignored "-Wshadow" +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wundefined-func-template" +#pragma clang diagnostic ignored "-Wunused-template" +#pragma clang diagnostic ignored "-Wweak-vtables" +#include <pdx/default_transport/client_channel.h> +#include <pdx/default_transport/client_channel_factory.h> +#include <pdx/file_handle.h> +#include <private/dvr/bufferhub_rpc.h> +#pragma clang diagnostic pop + +#include <ui/BufferHubBuffer.h> +#include <ui/DetachedBufferHandle.h> + +#include <poll.h> + +using android::dvr::BufferHubMetadata; +using android::dvr::BufferTraits; +using android::dvr::DetachedBufferRPC; +using android::dvr::NativeHandleWrapper; +using android::pdx::LocalChannelHandle; +using android::pdx::LocalHandle; +using android::pdx::Status; +using android::pdx::default_transport::ClientChannel; +using android::pdx::default_transport::ClientChannelFactory; + +namespace android { + +namespace { + +// TODO(b/112338294): Remove this string literal after refactoring BufferHub +// to use Binder. +static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client"; + +} // namespace + +BufferHubClient::BufferHubClient() + : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {} + +BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle) + : Client(ClientChannel::Create(std::move(channel_handle))) {} + +BufferHubClient::~BufferHubClient() {} + +bool BufferHubClient::IsValid() const { + return IsConnected() && GetChannelHandle().valid(); +} + +LocalChannelHandle BufferHubClient::TakeChannelHandle() { + if (IsConnected()) { + return std::move(GetChannelHandle()); + } else { + return {}; + } +} + +DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height, + uint32_t layer_count, uint32_t format, + uint64_t usage, size_t user_metadata_size) { + ATRACE_NAME("DetachedBuffer::DetachedBuffer"); + ALOGD("DetachedBuffer::DetachedBuffer: width=%u height=%u layer_count=%u, format=%u " + "usage=%" PRIx64 " user_metadata_size=%zu", + width, height, layer_count, format, usage, user_metadata_size); + + auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Create>( + width, height, layer_count, format, usage, user_metadata_size); + if (!status) { + ALOGE( + "DetachedBuffer::DetachedBuffer: Failed to create detached buffer: %s", + status.GetErrorMessage().c_str()); + client_.Close(-status.error()); + } + + const int ret = ImportGraphicBuffer(); + if (ret < 0) { + ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s", + strerror(-ret)); + client_.Close(ret); + } +} + +DetachedBuffer::DetachedBuffer(LocalChannelHandle channel_handle) + : client_(std::move(channel_handle)) { + const int ret = ImportGraphicBuffer(); + if (ret < 0) { + ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s", + strerror(-ret)); + client_.Close(ret); + } +} + +int DetachedBuffer::ImportGraphicBuffer() { + ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer"); + + auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>(); + if (!status) { + ALOGE("DetachedBuffer::DetachedBuffer: Failed to import GraphicBuffer: %s", + status.GetErrorMessage().c_str()); + return -status.error(); + } + + BufferTraits<LocalHandle> buffer_traits = status.take(); + if (buffer_traits.id() < 0) { + ALOGE("DetachedBuffer::DetachedBuffer: Received an invalid id!"); + return -EIO; + } + + // Stash the buffer id to replace the value in id_. + const int buffer_id = buffer_traits.id(); + + // Import the metadata. + metadata_ = BufferHubMetadata::Import(buffer_traits.take_metadata_handle()); + + if (!metadata_.IsValid()) { + ALOGE("DetachedBuffer::ImportGraphicBuffer: invalid metadata."); + return -ENOMEM; + } + + if (metadata_.metadata_size() != buffer_traits.metadata_size()) { + ALOGE( + "DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: " + "%zu, expected: %" PRIu64 ".", + metadata_.metadata_size(), buffer_traits.metadata_size()); + return -ENOMEM; + } + + size_t metadata_buf_size = static_cast<size_t>(buffer_traits.metadata_size()); + if (metadata_buf_size < dvr::BufferHubDefs::kMetadataHeaderSize) { + ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata too small: %zu", + metadata_buf_size); + return -EINVAL; + } + + // Import the buffer: We only need to hold on the native_handle_t here so that + // GraphicBuffer instance can be created in future. + buffer_handle_ = buffer_traits.take_buffer_handle(); + + // If all imports succeed, replace the previous buffer and id. + id_ = buffer_id; + buffer_state_bit_ = buffer_traits.buffer_state_bit(); + + // TODO(b/112012161) Set up shared fences. + ALOGD("DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64 ".", id(), + metadata_.metadata_header()->buffer_state.load(std::memory_order_acquire)); + return 0; +} + +int DetachedBuffer::Poll(int timeout_ms) { + ATRACE_NAME("DetachedBuffer::Poll"); + pollfd p = {client_.event_fd(), POLLIN, 0}; + return poll(&p, 1, timeout_ms); +} + +Status<LocalChannelHandle> DetachedBuffer::Promote() { + // TODO(b/112338294) remove after migrate producer buffer to binder + ALOGW("DetachedBuffer::Promote: not supported operation during migration"); + return {}; + + ATRACE_NAME("DetachedBuffer::Promote"); + ALOGD("DetachedBuffer::Promote: id=%d.", id_); + + auto status_or_handle = + client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>(); + if (status_or_handle.ok()) { + // Invalidate the buffer. + buffer_handle_ = {}; + } else { + ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_, + status_or_handle.GetErrorMessage().c_str()); + } + return status_or_handle; +} + +Status<LocalChannelHandle> DetachedBuffer::Duplicate() { + ATRACE_NAME("DetachedBuffer::Duplicate"); + ALOGD("DetachedBuffer::Duplicate: id=%d.", id_); + + auto status_or_handle = + client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>(); + + if (!status_or_handle.ok()) { + ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.", + id_, status_or_handle.GetErrorMessage().c_str()); + } + return status_or_handle; +} + +} // namespace android |