Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7fe7b2b authored by Jiwen Cai's avatar Jiwen Cai Committed by android-build-merger
Browse files

Merge "Implement DetachedBuffer::Promote" into pi-dev

am: 79ab7215

Change-Id: I96c2a60a7cfbbbcabe575639f6e05f2ff2006645
parents 9eb96871 79ab7215
Loading
Loading
Loading
Loading
+90 −10
Original line number Diff line number Diff line
@@ -19,18 +19,18 @@
    return result;                            \
  })()

using android::sp;
using android::GraphicBuffer;
using android::sp;
using android::dvr::BufferConsumer;
using android::dvr::BufferHubDefs::kConsumerStateMask;
using android::dvr::BufferHubDefs::kMetadataHeaderSize;
using android::dvr::BufferHubDefs::kProducerStateBit;
using android::dvr::BufferProducer;
using android::dvr::DetachedBuffer;
using android::dvr::BufferHubDefs::IsBufferAcquired;
using android::dvr::BufferHubDefs::IsBufferGained;
using android::dvr::BufferHubDefs::IsBufferPosted;
using android::dvr::BufferHubDefs::IsBufferAcquired;
using android::dvr::BufferHubDefs::IsBufferReleased;
using android::dvr::BufferProducer;
using android::dvr::DetachedBuffer;
using android::dvr::BufferHubDefs::kConsumerStateMask;
using android::dvr::BufferHubDefs::kMetadataHeaderSize;
using android::dvr::BufferHubDefs::kProducerStateBit;
using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Status;
@@ -376,8 +376,8 @@ TEST_F(LibBufferHubTest, TestMaxConsumers) {
  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
  EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
  for (size_t i = 0; i < kMaxConsumerCount; i++) {
    EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
                               cs[i]->buffer_state_bit()));
    EXPECT_TRUE(
        IsBufferPosted(cs[i]->buffer_state(), cs[i]->buffer_state_bit()));
    EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
    EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
    EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
@@ -792,6 +792,7 @@ TEST_F(LibBufferHubTest, TestDetachBufferFromProducer) {
  // Detached buffer handle can be use to construct a new DetachedBuffer object.
  auto d = DetachedBuffer::Import(std::move(handle));
  EXPECT_FALSE(handle.valid());
  EXPECT_TRUE(d->IsConnected());
  EXPECT_TRUE(d->IsValid());

  ASSERT_TRUE(d->buffer() != nullptr);
@@ -805,6 +806,7 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBufferFails) {
                                   /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
                                   kUserMetadataSize);

  EXPECT_FALSE(b1->IsConnected());
  EXPECT_FALSE(b1->IsValid());
  EXPECT_TRUE(b1->buffer() == nullptr);

@@ -813,6 +815,7 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBufferFails) {
      kWidth, kHeight, kLayerCount, kFormat, kUsage,
      /*user_metadata_size=*/std::numeric_limits<size_t>::max());

  EXPECT_FALSE(b2->IsConnected());
  EXPECT_FALSE(b2->IsValid());
  EXPECT_TRUE(b2->buffer() == nullptr);

@@ -822,6 +825,7 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBufferFails) {
      /*user_metadata_size=*/std::numeric_limits<size_t>::max() -
          kMetadataHeaderSize);

  EXPECT_FALSE(b3->IsConnected());
  EXPECT_FALSE(b3->IsValid());
  EXPECT_TRUE(b3->buffer() == nullptr);
}
@@ -831,6 +835,7 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBuffer) {
                                   kUsage, kUserMetadataSize);
  int b1_id = b1->id();

  EXPECT_TRUE(b1->IsConnected());
  EXPECT_TRUE(b1->IsValid());
  ASSERT_TRUE(b1->buffer() != nullptr);
  EXPECT_NE(b1->id(), 0);
@@ -843,6 +848,7 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBuffer) {
  ASSERT_TRUE(g1 != nullptr);
  EXPECT_TRUE(g1->isDetachedBuffer());

  EXPECT_FALSE(b1->IsConnected());
  EXPECT_FALSE(b1->IsValid());
  EXPECT_TRUE(b1->buffer() == nullptr);

@@ -856,6 +862,7 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBuffer) {

  auto b2 = DetachedBuffer::Import(std::move(h1->handle()));
  ASSERT_FALSE(h1->isValid());
  EXPECT_TRUE(b2->IsConnected());
  EXPECT_TRUE(b2->IsValid());

  ASSERT_TRUE(b2->buffer() != nullptr);
@@ -865,3 +872,76 @@ TEST_F(LibBufferHubTest, TestCreateDetachedBuffer) {
  EXPECT_EQ(b2->id(), b1_id);
  EXPECT_FALSE(b2->buffer()->isDetachedBuffer());
}

TEST_F(LibBufferHubTest, TestPromoteDetachedBuffer) {
  auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
                                   kUsage, kUserMetadataSize);
  int b1_id = b1->id();
  EXPECT_TRUE(b1->IsValid());

  auto status_or_handle = b1->Promote();
  EXPECT_TRUE(status_or_handle);

  // The detached buffer should have hangup.
  EXPECT_GT(RETRY_EINTR(b1->Poll(kPollTimeoutMs)), 0);
  auto status_or_int = b1->GetEventMask(POLLHUP);
  EXPECT_TRUE(status_or_int.ok());
  EXPECT_EQ(status_or_int.get(), POLLHUP);

  // The buffer client is still considered as connected but invalid.
  EXPECT_TRUE(b1->IsConnected());
  EXPECT_FALSE(b1->IsValid());

  // Gets the channel handle for the producer.
  LocalChannelHandle h1 = status_or_handle.take();
  EXPECT_TRUE(h1.valid());

  std::unique_ptr<BufferProducer> p1 = BufferProducer::Import(std::move(h1));
  EXPECT_FALSE(h1.valid());
  ASSERT_TRUE(p1 != nullptr);
  int p1_id = p1->id();

  // A newly promoted ProducerBuffer should inherit the same buffer id.
  EXPECT_EQ(b1_id, p1_id);
  EXPECT_TRUE(IsBufferGained(p1->buffer_state()));
}

TEST_F(LibBufferHubTest, TestDetachThenPromote) {
  std::unique_ptr<BufferProducer> p1 = BufferProducer::Create(
      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
  ASSERT_TRUE(p1.get() != nullptr);
  int p1_id = p1->id();

  // Detached the producer.
  auto status_or_handle = p1->Detach();
  EXPECT_TRUE(status_or_handle.ok());
  LocalChannelHandle h1 = status_or_handle.take();
  EXPECT_TRUE(h1.valid());

  // Detached buffer handle can be use to construct a new DetachedBuffer object.
  auto b1 = DetachedBuffer::Import(std::move(h1));
  EXPECT_FALSE(h1.valid());
  EXPECT_TRUE(b1->IsValid());
  int b1_id = b1->id();
  EXPECT_EQ(b1_id, p1_id);

  // Promote the detached buffer.
  status_or_handle = b1->Promote();
  // The buffer client is still considered as connected but invalid.
  EXPECT_TRUE(b1->IsConnected());
  EXPECT_FALSE(b1->IsValid());
  EXPECT_TRUE(status_or_handle.ok());

  // Gets the channel handle for the producer.
  LocalChannelHandle h2 = status_or_handle.take();
  EXPECT_TRUE(h2.valid());

  std::unique_ptr<BufferProducer> p2 = BufferProducer::Import(std::move(h2));
  EXPECT_FALSE(h2.valid());
  ASSERT_TRUE(p2 != nullptr);
  int p2_id = p2->id();

  // A newly promoted ProducerBuffer should inherit the same buffer id.
  EXPECT_EQ(b1_id, p2_id);
  EXPECT_TRUE(IsBufferGained(p2->buffer_state()));
}
+24 −3
Original line number Diff line number Diff line
@@ -3,7 +3,11 @@
#include <pdx/file_handle.h>
#include <ui/DetachedBufferHandle.h>

#include <poll.h>

using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Status;

namespace android {
namespace dvr {
@@ -78,9 +82,26 @@ int DetachedBuffer::ImportGraphicBuffer() {
  return 0;
}

std::unique_ptr<BufferProducer> DetachedBuffer::Promote() {
  ALOGE("DetachedBuffer::Promote: Not implemented.");
  return nullptr;
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() {
  ATRACE_NAME("DetachedBuffer::Promote");
  ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);

  auto status_or_handle =
      client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
  if (status_or_handle.ok()) {
    // Invalidate the buffer.
    buffer_ = {};
  } else {
    ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
          status_or_handle.GetErrorMessage().c_str());
  }
  return status_or_handle;
}

sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() {
+4 −4
Original line number Diff line number Diff line
@@ -18,17 +18,17 @@ namespace dvr {

class BufferHubClient : public pdx::Client {
 public:
  using LocalChannelHandle = pdx::LocalChannelHandle;

  BufferHubClient();
  explicit BufferHubClient(LocalChannelHandle channel_handle);
  explicit BufferHubClient(pdx::LocalChannelHandle channel_handle);

  bool IsValid() const;
  LocalChannelHandle TakeChannelHandle();
  pdx::LocalChannelHandle TakeChannelHandle();

  using pdx::Client::Close;
  using pdx::Client::GetChannel;
  using pdx::Client::InvokeRemoteMethod;
  using pdx::Client::IsConnected;
  using pdx::Client::event_fd;
};

class BufferHubBuffer : public pdx::Client {
+23 −6
Original line number Diff line number Diff line
@@ -8,8 +8,6 @@ namespace dvr {

class DetachedBuffer {
 public:
  using LocalChannelHandle = pdx::LocalChannelHandle;

  // Allocates a standalone DetachedBuffer not associated with any producer
  // consumer set.
  static std::unique_ptr<DetachedBuffer> Create(uint32_t width, uint32_t height,
@@ -22,7 +20,7 @@ class DetachedBuffer {

  // Imports the given channel handle to a DetachedBuffer, taking ownership.
  static std::unique_ptr<DetachedBuffer> Import(
      LocalChannelHandle channel_handle) {
      pdx::LocalChannelHandle channel_handle) {
    return std::unique_ptr<DetachedBuffer>(
        new DetachedBuffer(std::move(channel_handle)));
  }
@@ -33,12 +31,31 @@ class DetachedBuffer {
  const sp<GraphicBuffer>& buffer() const { return buffer_.buffer(); }

  int id() const { return id_; }
  bool IsValid() const { return client_.IsValid(); }

  // Returns true if the buffer holds an open PDX channels towards bufferhubd.
  bool IsConnected() const { return client_.IsValid(); }

  // Returns true if the buffer holds an valid gralloc buffer handle that's
  // availble for the client to read from and/or write into.
  bool IsValid() const { return buffer_.IsValid(); }

  // Returns the event mask for all the events that are pending on this buffer
  // (see sys/poll.h for all possible bits).
  pdx::Status<int> GetEventMask(int events) {
    if (auto* channel = client_.GetChannel()) {
      return channel->GetEventMask(events);
    } else {
      return pdx::ErrorStatus(EINVAL);
    }
  }

  // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
  int Poll(int timeout_ms);

  // Promotes a DetachedBuffer to become a ProducerBuffer. Once promoted the
  // DetachedBuffer channel will be closed automatically on successful IPC
  // return. Further IPCs towards this channel will return error.
  std::unique_ptr<BufferProducer> Promote();
  pdx::Status<pdx::LocalChannelHandle> Promote();

  // Takes the underlying graphic buffer out of this DetachedBuffer. This call
  // immediately invalidates this DetachedBuffer object and transfers the
@@ -49,7 +66,7 @@ class DetachedBuffer {
  DetachedBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
                 uint32_t format, uint64_t usage, size_t user_metadata_size);

  DetachedBuffer(LocalChannelHandle channel_handle);
  DetachedBuffer(pdx::LocalChannelHandle channel_handle);

  int ImportGraphicBuffer();

+8 −0
Original line number Diff line number Diff line
@@ -266,6 +266,14 @@ pdx::Status<void> BufferHubService::HandleMessage(Message& message) {
      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);
  }
Loading