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

Commit 7957b72d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update BufferHubQueueProducer"

parents e900bb06 5afb7403
Loading
Loading
Loading
Loading
+53 −10
Original line number Diff line number Diff line
@@ -8,16 +8,6 @@
namespace android {
namespace dvr {

/* static */
sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
  auto config = ProducerQueueConfigBuilder()
                    .SetMetadata<DvrNativeBufferMetadata>()
                    .Build();
  producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
  return producer;
}

/* static */
sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
    const std::shared_ptr<ProducerQueue>& queue) {
@@ -33,6 +23,19 @@ sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
  return producer;
}

/* static */
sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
    ProducerQueueParcelable parcelable) {
  if (!parcelable.IsValid()) {
    ALOGE("BufferHubQueueProducer::Create: Invalid producer parcelable.");
    return nullptr;
  }

  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
  producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
  return producer;
}

status_t BufferHubQueueProducer::requestBuffer(int slot,
                                               sp<GraphicBuffer>* buf) {
  ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
@@ -475,6 +478,13 @@ status_t BufferHubQueueProducer::connect(
    return BAD_VALUE;
  }

  if (!queue_->is_connected()) {
    ALOGE(
        "BufferHubQueueProducer::connect: This BufferHubQueueProducer is not "
        "connected to bufferhud. Has it been taken out as a parcelable?");
    return BAD_VALUE;
  }

  switch (api) {
    case NATIVE_WINDOW_API_EGL:
    case NATIVE_WINDOW_API_CPU:
@@ -617,6 +627,39 @@ status_t BufferHubQueueProducer::getConsumerUsage(uint64_t* out_usage) const {
  return NO_ERROR;
}

status_t BufferHubQueueProducer::TakeAsParcelable(
    ProducerQueueParcelable* out_parcelable) {
  if (!out_parcelable || out_parcelable->IsValid())
    return BAD_VALUE;

  if (connected_api_ != kNoConnectedApi) {
    ALOGE(
        "BufferHubQueueProducer::TakeAsParcelable: BufferHubQueueProducer has "
        "connected client. Must disconnect first.");
    return BAD_VALUE;
  }

  if (!queue_->is_connected()) {
    ALOGE(
        "BufferHubQueueProducer::TakeAsParcelable: This BufferHubQueueProducer "
        "is not connected to bufferhud. Has it been taken out as a "
        "parcelable?");
    return BAD_VALUE;
  }

  auto status = queue_->TakeAsParcelable();
  if (!status) {
    ALOGE(
        "BufferHubQueueProducer::TakeAsParcelable: Failed to take out "
        "ProducuerQueueParcelable from the producer queue, error: %s.",
        status.GetErrorMessage().c_str());
    return BAD_VALUE;
  }

  *out_parcelable = status.take();
  return NO_ERROR;
}

status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
                                                uint32_t layer_count,
                                                PixelFormat format,
+2 −1
Original line number Diff line number Diff line
@@ -74,7 +74,8 @@ class BufferHubQueue : public pdx::Client {
    return available_buffers_.size() >= kMaxQueueCapacity;
  }

  explicit operator bool() const { return epoll_fd_.IsValid(); }
  // Returns whether the buffer queue is connected to bufferhubd.
  bool is_connected() const { return !!GetChannel(); }

  int GetBufferId(size_t slot) const {
    return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
+15 −4
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include <gui/IGraphicBufferProducer.h>
#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/buffer_hub_queue_parcelable.h>

namespace android {
namespace dvr {
@@ -17,14 +18,16 @@ class BufferHubQueueProducer : public BnGraphicBufferProducer {
  // that.
  static constexpr int kDefaultUndequeuedBuffers = 1;

  // Create a BufferHubQueueProducer instance by creating a new producer queue.
  static sp<BufferHubQueueProducer> Create();

  // Create a BufferHubQueueProducer instance by importing an existing prodcuer
  // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
  // queue.
  static sp<BufferHubQueueProducer> Create(
      const std::shared_ptr<ProducerQueue>& producer);

  // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
  // parcelable. Note that this call takes the ownership of the parcelable
  // object and is guaranteed to succeed if parcelable object is valid.
  static sp<BufferHubQueueProducer> Create(ProducerQueueParcelable parcelable);

  // See |IGraphicBufferProducer::requestBuffer|
  status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;

@@ -115,6 +118,14 @@ class BufferHubQueueProducer : public BnGraphicBufferProducer {
  // See |IGraphicBufferProducer::getConsumerUsage|
  status_t getConsumerUsage(uint64_t* out_usage) const override;

  // Takes out the current producer as a binder parcelable object. Note that the
  // producer must be disconnected to be exportable. After successful export,
  // the producer queue can no longer be connected again. Returns NO_ERROR when
  // takeout is successful and out_parcelable will hold the new parcelable
  // object. Also note that out_parcelable cannot be NULL and must points to an
  // invalid parcelable.
  status_t TakeAsParcelable(ProducerQueueParcelable* out_parcelable);

 private:
  using LocalHandle = pdx::LocalHandle;

+59 −1
Original line number Diff line number Diff line
@@ -3,12 +3,15 @@
#include <base/logging.h>
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
#include <pdx/default_transport/channel_parcelable.h>

#include <gtest/gtest.h>

namespace android {
namespace dvr {

using pdx::LocalHandle;

namespace {

// Default dimensions before setDefaultBufferSize is called by the consumer.
@@ -92,7 +95,13 @@ class BufferHubQueueProducerTest : public ::testing::Test {
    ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
             testInfo->name());

    mProducer = BufferHubQueueProducer::Create();
    auto config = ProducerQueueConfigBuilder()
                      .SetMetadata<DvrNativeBufferMetadata>()
                      .Build();
    auto queue = ProducerQueue::Create(config, UsagePolicy{});
    ASSERT_TRUE(queue != nullptr);

    mProducer = BufferHubQueueProducer::Create(std::move(queue));
    ASSERT_TRUE(mProducer != nullptr);
    mSurface = new Surface(mProducer, true);
    ASSERT_TRUE(mSurface != nullptr);
@@ -546,6 +555,55 @@ TEST_F(BufferHubQueueProducerTest, ConnectDisconnectReconnect) {
  EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
}

TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
  // Connected producer cannot be taken out as a parcelable.
  EXPECT_NO_FATAL_FAILURE(ConnectProducer());
  ProducerQueueParcelable producer_parcelable;
  EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);

  // Create a valid dummy producer parcelable.
  auto dummy_channel_parcelable =
      std::make_unique<pdx::default_transport::ChannelParcelable>(
          LocalHandle(0), LocalHandle(0), LocalHandle(0));
  EXPECT_TRUE(dummy_channel_parcelable->IsValid());
  ProducerQueueParcelable dummy_producer_parcelable(
      std::move(dummy_channel_parcelable));
  EXPECT_TRUE(dummy_producer_parcelable.IsValid());

  // Disconnect producer can be taken out, but only to an invalid parcelable.
  ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR);
  EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
  EXPECT_FALSE(producer_parcelable.IsValid());
  EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR);
  EXPECT_TRUE(producer_parcelable.IsValid());

  // Should still be able to query buffer dimension after disconnect.
  int32_t value = -1;
  EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
  EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);

  EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR);
  EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);

  EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR);
  EXPECT_EQ(value, kDefaultFormat);

  // But connect to API will fail.
  IGraphicBufferProducer::QueueBufferOutput output;
  EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
                               &output),
            BAD_VALUE);

  // Create a new producer from the parcelable and connect to kTestApi should
  // succeed.
  sp<BufferHubQueueProducer> new_producer =
      BufferHubQueueProducer::Create(std::move(producer_parcelable));
  ASSERT_TRUE(new_producer != nullptr);
  EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
                                  kTestControlledByApp, &output),
            NO_ERROR);
}

}  // namespace

}  // namespace dvr