Implement DetachedBuffer::Promote
1/ This enables a BufferHub-backed DetachedBuffer to be promoted into
the ProducerBuffer.
2/ Add DetachedBuffer::IsConnected in addition to
DetachedBuffer::IsValid.
3/ Cleaned up some using pdx:: namespace statements.
Bug: 69982239
Bug: 69981968
Bug: 70046255
Test: buffer_hub-test
Change-Id: I6ee99507b190d142647455532cdce0c2c780b2b0
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 72bf6f2..e57c8ed 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -266,6 +266,14 @@
SetChannel(channel->channel_id(), nullptr);
return {};
+ case DetachedBufferRPC::Promote::Opcode:
+ // In addition to the message handler in the DetachedBufferChannel's
+ // HandleMessage method, we also need to invalid the channel. Note that
+ // this has to be done after HandleMessage returns to make sure the IPC
+ // request has went back to the client first.
+ SetChannel(channel->channel_id(), nullptr);
+ return {};
+
default:
return DefaultHandleMessage(message);
}
diff --git a/services/vr/bufferhubd/detached_buffer_channel.cpp b/services/vr/bufferhubd/detached_buffer_channel.cpp
index 4f4160a..a5cf68d 100644
--- a/services/vr/bufferhubd/detached_buffer_channel.cpp
+++ b/services/vr/bufferhubd/detached_buffer_channel.cpp
@@ -1,4 +1,5 @@
#include "detached_buffer_channel.h"
+#include "producer_channel.h"
using android::pdx::BorrowedHandle;
using android::pdx::ErrorStatus;
@@ -62,6 +63,14 @@
}
}
+DetachedBufferChannel::~DetachedBufferChannel() {
+ ALOGD_IF(TRACE,
+ "DetachedBufferChannel::~DetachedBufferChannel: channel_id=%d "
+ "buffer_id=%d.",
+ channel_id(), buffer_id());
+ Hangup();
+}
+
BufferHubChannel::BufferInfo DetachedBufferChannel::GetBufferInfo() const {
return BufferInfo(buffer_id(), /*consumer_count=*/0, buffer_.width(),
buffer_.height(), buffer_.layer_count(), buffer_.format(),
@@ -106,13 +115,44 @@
}
Status<RemoteChannelHandle> DetachedBufferChannel::OnPromote(
- Message& /*message*/) {
+ Message& message) {
ATRACE_NAME("DetachedBufferChannel::OnPromote");
ALOGD_IF(TRACE, "DetachedBufferChannel::OnPromote: buffer_id=%d",
buffer_id());
- // TODO(b/69982239): Implement the logic to promote a detached buffer.
- return ErrorStatus(ENOSYS);
+ // Note that the new ProducerChannel will have different channel_id, but
+ // inherits the buffer_id from the DetachedBuffer.
+ int channel_id;
+ auto status = message.PushChannel(0, nullptr, &channel_id);
+ if (!status) {
+ ALOGE(
+ "DetachedBufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
+ status.GetErrorMessage().c_str());
+ return ErrorStatus(ENOMEM);
+ }
+
+ std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
+ service(), buffer_id(), channel_id, std::move(buffer_),
+ std::move(metadata_buffer_), user_metadata_size_);
+ if (!channel) {
+ ALOGE(
+ "DetachedBufferChannel::OnPromote: Failed to create ProducerChannel "
+ "from a DetachedBufferChannel, buffer_id=%d.",
+ buffer_id());
+ }
+
+ const auto channel_status =
+ service()->SetChannel(channel_id, std::move(channel));
+ if (!channel_status) {
+ // Technically, this should never fail, as we just pushed the channel. Note
+ // that LOG_FATAL will be stripped out in non-debug build.
+ LOG_FATAL(
+ "DetachedBufferChannel::OnPromote: Failed to set new producer buffer "
+ "channel: %s.",
+ channel_status.GetErrorMessage().c_str());
+ }
+
+ return status;
}
} // namespace dvr
diff --git a/services/vr/bufferhubd/detached_buffer_channel.h b/services/vr/bufferhubd/detached_buffer_channel.h
index 079ba72..8b6dab8 100644
--- a/services/vr/bufferhubd/detached_buffer_channel.h
+++ b/services/vr/bufferhubd/detached_buffer_channel.h
@@ -11,6 +11,8 @@
class DetachedBufferChannel : public BufferHubChannel {
public:
+ ~DetachedBufferChannel() override;
+
template <typename... Args>
static std::unique_ptr<DetachedBufferChannel> Create(Args&&... args) {
auto buffer = std::unique_ptr<DetachedBufferChannel>(
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index a753168..b6977aa 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -35,6 +35,30 @@
} // namespace
+ProducerChannel::ProducerChannel(BufferHubService* service, int buffer_id,
+ int channel_id, IonBuffer buffer,
+ IonBuffer metadata_buffer,
+ size_t user_metadata_size, int* error)
+ : BufferHubChannel(service, buffer_id, channel_id, kProducerType),
+ buffer_(std::move(buffer)),
+ metadata_buffer_(std::move(metadata_buffer)),
+ user_metadata_size_(user_metadata_size),
+ metadata_buf_size_(BufferHubDefs::kMetadataHeaderSize +
+ user_metadata_size) {
+ if (!buffer_.IsValid()) {
+ ALOGE("ProducerChannel::ProducerChannel: Invalid buffer.");
+ *error = -EINVAL;
+ return;
+ }
+ if (!metadata_buffer_.IsValid()) {
+ ALOGE("ProducerChannel::ProducerChannel: Invalid metadata buffer.");
+ *error = -EINVAL;
+ return;
+ }
+
+ *error = InitializeBuffer();
+}
+
ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
uint32_t width, uint32_t height,
uint32_t layer_count, uint32_t format,
@@ -63,13 +87,16 @@
return;
}
+ *error = InitializeBuffer();
+}
+
+int ProducerChannel::InitializeBuffer() {
void* metadata_ptr = nullptr;
if (int ret = metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
/*y=*/0, metadata_buf_size_,
/*height=*/1, &metadata_ptr)) {
ALOGE("ProducerChannel::ProducerChannel: Failed to lock metadata.");
- *error = -ret;
- return;
+ return ret;
}
metadata_header_ =
reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
@@ -85,15 +112,13 @@
release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
if (!acquire_fence_fd_ || !release_fence_fd_) {
ALOGE("ProducerChannel::ProducerChannel: Failed to create shared fences.");
- *error = -EIO;
- return;
+ return -EIO;
}
dummy_fence_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
if (!dummy_fence_fd_) {
ALOGE("ProducerChannel::ProducerChannel: Failed to create dummy fences.");
- *error = -EIO;
- return;
+ return EIO;
}
epoll_event event;
@@ -105,12 +130,25 @@
"ProducerChannel::ProducerChannel: Failed to modify the shared "
"release fence to include the dummy fence: %s",
strerror(errno));
- *error = -EIO;
- return;
+ return -EIO;
}
// Success.
- *error = 0;
+ return 0;
+}
+
+std::unique_ptr<ProducerChannel> ProducerChannel::Create(
+ BufferHubService* service, int buffer_id, int channel_id, IonBuffer buffer,
+ IonBuffer metadata_buffer, size_t user_metadata_size) {
+ int error = 0;
+ std::unique_ptr<ProducerChannel> producer(new ProducerChannel(
+ service, buffer_id, channel_id, std::move(buffer),
+ std::move(metadata_buffer), user_metadata_size, &error));
+
+ if (error < 0)
+ return nullptr;
+ else
+ return producer;
}
Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index de9ff31..67fdf15 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -30,6 +30,12 @@
template <typename T>
using BufferWrapper = pdx::rpc::BufferWrapper<T>;
+ static std::unique_ptr<ProducerChannel> Create(BufferHubService* service,
+ int buffer_id, int channel_id,
+ IonBuffer buffer,
+ IonBuffer metadata_buffer,
+ size_t user_metadata_size);
+
static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
BufferHubService* service, int channel_id, uint32_t width,
uint32_t height, uint32_t layer_count, uint32_t format, uint64_t usage,
@@ -92,10 +98,14 @@
pdx::LocalHandle release_fence_fd_;
pdx::LocalHandle dummy_fence_fd_;
+ ProducerChannel(BufferHubService* service, int buffer_id, int channel_id,
+ IonBuffer buffer, IonBuffer metadata_buffer,
+ size_t user_metadata_size, int* error);
ProducerChannel(BufferHubService* service, int channel, uint32_t width,
uint32_t height, uint32_t layer_count, uint32_t format,
uint64_t usage, size_t user_metadata_size, int* error);
+ int InitializeBuffer();
pdx::Status<BufferDescription<BorrowedHandle>> OnGetBuffer(Message& message);
pdx::Status<void> OnProducerPost(Message& message, LocalFence acquire_fence);
pdx::Status<LocalFence> OnProducerGain(Message& message);