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

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

Merge "Implement BufferHubProducer::attachBuffer"

parents 6ed8bd22 57ae3eea
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ cc_library_shared {
        "android.hardware.graphics.common@1.1",
        "libsync",
        "libbinder",
        "libbufferhub",
        "libbufferhubqueue",  // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
        "libpdx_default_transport",
        "libcutils",
@@ -149,6 +150,7 @@ cc_library_shared {
                "BufferHubProducer.cpp",
            ],
            exclude_shared_libs: [
                "libbufferhub",
                "libbufferhubqueue",
                "libpdx_default_transport",
            ],
+81 −7
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <gui/BufferHubProducer.h>
#include <inttypes.h>
#include <log/log.h>
#include <private/dvr/detached_buffer.h>
#include <system/window.h>
#include <ui/DetachedBufferHandle.h>

@@ -363,13 +364,86 @@ status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<F
    return error;
}

status_t BufferHubProducer::attachBuffer(int* /* out_slot */,
                                         const sp<GraphicBuffer>& /* buffer */) {
    // With this BufferHub backed implementation, we assume (for now) all buffers
    // are allocated and owned by the BufferHub. Thus the attempt of transfering
    // ownership of a buffer to the buffer queue is intentionally unsupported.
    LOG_ALWAYS_FATAL("BufferHubProducer::attachBuffer not supported.");
    return INVALID_OPERATION;
status_t BufferHubProducer::attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) {
    // In the BufferHub design, all buffers are allocated and owned by the BufferHub. Thus only
    // GraphicBuffers that are originated from BufferHub can be attached to a BufferHubProducer.
    ALOGV("queueBuffer: buffer=%p", buffer.get());

    if (out_slot == nullptr) {
        ALOGE("attachBuffer: out_slot cannot be NULL.");
        return BAD_VALUE;
    }
    if (buffer == nullptr || !buffer->isDetachedBuffer()) {
        ALOGE("attachBuffer: invalid GraphicBuffer.");
        return BAD_VALUE;
    }

    std::unique_lock<std::mutex> lock(mutex_);

    if (connected_api_ == kNoConnectedApi) {
        ALOGE("attachBuffer: BufferQueue has no connected producer");
        return NO_INIT;
    }

    // Before attaching the buffer, caller is supposed to call
    // IGraphicBufferProducer::setGenerationNumber to inform the
    // BufferHubProducer the next generation number.
    if (buffer->getGenerationNumber() != generation_number_) {
        ALOGE("attachBuffer: Mismatched generation number, buffer: %u, queue: %u.",
              buffer->getGenerationNumber(), generation_number_);
        return BAD_VALUE;
    }

    // Creates a BufferProducer from the GraphicBuffer.
    std::unique_ptr<DetachedBufferHandle> detached_handle = buffer->takeDetachedBufferHandle();
    if (detached_handle == nullptr) {
        ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL.");
        return BAD_VALUE;
    }
    auto detached_buffer = DetachedBuffer::Import(std::move(detached_handle->handle()));
    if (detached_buffer == nullptr) {
        ALOGE("attachBuffer: DetachedBuffer cannot be NULL.");
        return BAD_VALUE;
    }
    auto status_or_handle = detached_buffer->Promote();
    if (!status_or_handle.ok()) {
        ALOGE("attachBuffer: Failed to promote a DetachedBuffer into a BufferProducer, error=%d.",
              status_or_handle.error());
        return BAD_VALUE;
    }
    std::shared_ptr<BufferProducer> buffer_producer =
            BufferProducer::Import(status_or_handle.take());
    if (buffer_producer == nullptr) {
        ALOGE("attachBuffer: Failed to import BufferProducer.");
        return BAD_VALUE;
    }

    // Adds the BufferProducer into the Queue.
    auto status_or_slot = queue_->InsertBuffer(buffer_producer);
    if (!status_or_slot.ok()) {
        ALOGE("attachBuffer: Failed to insert buffer, error=%d.", status_or_slot.error());
        return BAD_VALUE;
    }

    size_t slot = status_or_slot.get();
    ALOGV("attachBuffer: returning slot %zu.", slot);
    if (slot >= static_cast<size_t>(max_buffer_count_)) {
        ALOGE("attachBuffer: Invalid slot: %zu.", slot);
        return BAD_VALUE;
    }

    // The just attached buffer should be in dequeued state according to IGraphicBufferProducer
    // interface. In BufferHub's language the buffer should be in Gained state.
    buffers_[slot].mGraphicBuffer = buffer;
    buffers_[slot].mBufferState.attachProducer();
    buffers_[slot].mEglFence = EGL_NO_SYNC_KHR;
    buffers_[slot].mFence = Fence::NO_FENCE;
    buffers_[slot].mRequestBufferCalled = true;
    buffers_[slot].mAcquireCalled = false;
    buffers_[slot].mNeedsReallocation = false;

    *out_slot = static_cast<int>(slot);
    return NO_ERROR;
}

status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
+24 −3
Original line number Diff line number Diff line
@@ -787,10 +787,31 @@ TEST_P(IGraphicBufferProducerTest,

    ASSERT_OK(mProducer->disconnect(TEST_API));

    if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
        // TODO(b/69981968): Implement BufferHubProducer::attachBuffer
    ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
}

TEST_P(IGraphicBufferProducerTest, DetachThenAttach_Succeeds) {
    int slot = -1;
    sp<Fence> fence;
    sp<GraphicBuffer> buffer;

    setupDequeueRequestBuffer(&slot, &fence, &buffer);
    ASSERT_TRUE(buffer != nullptr);

    ASSERT_OK(mProducer->detachBuffer(slot));
    EXPECT_OK(buffer->initCheck());

    if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
        // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have
        // isDetachedBuffer() set. Note that this only applies to BufferHub.
        EXPECT_TRUE(buffer->isDetachedBuffer());
    } else {
        EXPECT_FALSE(buffer->isDetachedBuffer());
    }

    EXPECT_OK(mProducer->attachBuffer(&slot, buffer));
    EXPECT_FALSE(buffer->isDetachedBuffer());
    EXPECT_OK(buffer->initCheck());
}

#if USE_BUFFER_HUB_AS_BUFFER_QUEUE
+5 −2
Original line number Diff line number Diff line
@@ -42,11 +42,13 @@ LocalChannelHandle BufferHubClient::TakeChannelHandle() {
BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
    : Client{pdx::default_transport::ClientChannel::Create(
          std::move(channel_handle))},
      id_(-1) {}
      id_(-1),
      cid_(-1) {}
BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
    : Client{pdx::default_transport::ClientChannelFactory::Create(
          endpoint_path)},
      id_(-1) {}
      id_(-1),
      cid_(-1) {}

BufferHubBuffer::~BufferHubBuffer() {
  if (metadata_header_ != nullptr) {
@@ -136,6 +138,7 @@ int BufferHubBuffer::ImportBuffer() {
  }

  id_ = new_id;
  cid_ = buffer_desc.buffer_cid();
  buffer_state_bit_ = buffer_desc.buffer_state_bit();

  // Note that here the buffer state is mapped from shared memory as an atomic
+7 −0
Original line number Diff line number Diff line
@@ -107,8 +107,14 @@ class BufferHubBuffer : public pdx::Client {
  IonBuffer* buffer() { return &buffer_; }
  const IonBuffer* buffer() const { return &buffer_; }

  // Gets ID of the buffer client. All BufferHubBuffer clients derived from the
  // same buffer in bufferhubd share the same buffer id.
  int id() const { return id_; }

  // Gets the channel id of the buffer client. Each BufferHubBuffer client has
  // its system unique channel id.
  int cid() const { return cid_; }

  // Returns the buffer buffer state.
  uint64_t buffer_state() { return buffer_state_->load(); };

@@ -170,6 +176,7 @@ class BufferHubBuffer : public pdx::Client {
  // for logging and debugging purposes only and should not be used for lookup
  // or any other functional purpose as a security precaution.
  int id_;
  int cid_;
  uint64_t buffer_state_bit_{0ULL};
  IonBuffer buffer_;
  IonBuffer metadata_buffer_;
Loading