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

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

Merge "Move detached buffer off IonBuffer"

parents cbb3b63a 9004b8c9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -920,6 +920,7 @@ TEST_F(LibBufferHubTest, TestDuplicateDetachedBuffer) {
                                   kUsage, kUserMetadataSize);
  int b1_id = b1->id();
  EXPECT_TRUE(b1->IsValid());
  EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);

  auto status_or_handle = b1->Duplicate();
  EXPECT_TRUE(status_or_handle);
@@ -935,6 +936,9 @@ TEST_F(LibBufferHubTest, TestDuplicateDetachedBuffer) {
  std::unique_ptr<DetachedBuffer> b2 = DetachedBuffer::Import(std::move(h2));
  EXPECT_FALSE(h2.valid());
  ASSERT_TRUE(b2 != nullptr);
  EXPECT_TRUE(b2->IsValid());
  EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);

  int b2_id = b2->id();

  // These two buffer instances are based on the same physical buffer under the
+3 −0
Original line number Diff line number Diff line
@@ -74,6 +74,9 @@ BufferHubMetadata BufferHubMetadata::Import(pdx::LocalHandle ashmem_handle) {
  size_t metadata_size = ashmem_get_size_region(ashmem_handle.Get());
  size_t user_metadata_size = metadata_size - kMetadataHeaderSize;

  // Note that here the buffer state is mapped from shared memory as an atomic
  // object. The std::atomic's constructor will not be called so that the
  // original value stored in the memory region can be preserved.
  auto metadata_header = static_cast<MetadataHeader*>(
      mmap(nullptr, metadata_size, kAshmemProt, MAP_SHARED, ashmem_handle.Get(),
           /*offset=*/0));
+35 −45
Original line number Diff line number Diff line
@@ -16,8 +16,16 @@ using android::pdx::default_transport::ClientChannelFactory;
namespace android {
namespace dvr {

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(BufferHubRPC::kClientPath)) {}
    : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}

BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
    : Client(ClientChannel::Create(std::move(channel_handle))) {}
@@ -80,71 +88,53 @@ int DetachedBuffer::ImportGraphicBuffer() {
    return -status.error();
  }

  BufferDescription<LocalHandle> buffer_desc = status.take();
  if (buffer_desc.id() < 0) {
  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_desc.id();
  const int buffer_id = buffer_traits.id();

  // Import the buffer.
  IonBuffer ion_buffer;
  ALOGD_IF(TRACE, "DetachedBuffer::DetachedBuffer: id=%d.", buffer_id);
  // Import the metadata.
  metadata_ = BufferHubMetadata::Import(buffer_traits.take_metadata_handle());

  if (const int ret = buffer_desc.ImportBuffer(&ion_buffer)) {
    ALOGE("Failed to import GraphicBuffer, error=%d", ret);
    return ret;
  if (!metadata_.IsValid()) {
    ALOGE("DetachedBuffer::ImportGraphicBuffer: invalid metadata.");
    return -ENOMEM;
  }

  // Import the metadata.
  IonBuffer metadata_buffer;
  if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
    ALOGE("Failed to import metadata buffer, error=%d", ret);
    return ret;
  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 = metadata_buffer.width();

  size_t metadata_buf_size = buffer_traits.metadata_size();
  if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
    ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: %zu",
    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_ = std::move(ion_buffer);
  metadata_buffer_ = std::move(metadata_buffer);
  user_metadata_size_ = metadata_buf_size - BufferHubDefs::kMetadataHeaderSize;

  void* metadata_ptr = nullptr;
  if (const int ret =
          metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
                                /*y=*/0, metadata_buf_size,
                                /*height=*/1, &metadata_ptr)) {
    ALOGE("DetachedBuffer::ImportGraphicBuffer: Failed to lock metadata.");
    return ret;
  }
  buffer_state_bit_ = buffer_traits.buffer_state_bit();

  // TODO(b/112012161) Set up shared fences.

  // Note that here the buffer state is mapped from shared memory as an atomic
  // object. The std::atomic's constructor will not be called so that the
  // original value stored in the memory region can be preserved.
  metadata_header_ = static_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
  if (user_metadata_size_) {
    user_metadata_ptr_ = static_cast<void*>(metadata_header_ + 1);
  } else {
    user_metadata_ptr_ = nullptr;
  }

  id_ = buffer_desc.id();
  buffer_state_bit_ = buffer_desc.buffer_state_bit();

  ALOGD_IF(TRACE,
           "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
           ".",
           id(), metadata_header_->buffer_state.load());
           id(),
           metadata_.metadata_header()->buffer_state.load(
               std::memory_order_acquire));
  return 0;
}

@@ -166,7 +156,7 @@ Status<LocalChannelHandle> DetachedBuffer::Promote() {
      client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
  if (status_or_handle.ok()) {
    // Invalidate the buffer.
    buffer_ = {};
    buffer_handle_ = {};
  } else {
    ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
          status_or_handle.GetErrorMessage().c_str());
+135 −1
Original line number Diff line number Diff line
@@ -3,6 +3,11 @@

#include <dvr/dvr_api.h>
#include <hardware/gralloc.h>
#include <pdx/channel_handle.h>
#include <pdx/file_handle.h>
#include <pdx/rpc/remote_method.h>
#include <pdx/rpc/serializable.h>
#include <private/dvr/native_handle_wrapper.h>

#include <atomic>

@@ -82,8 +87,137 @@ static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader);

}  // namespace BufferHubDefs

template <typename FileHandleType>
class BufferTraits {
 public:
  BufferTraits() = default;
  BufferTraits(const native_handle_t* buffer_handle,
               const FileHandleType& metadata_handle, int id,
               uint64_t buffer_state_bit, uint64_t metadata_size,
               uint32_t width, uint32_t height, uint32_t layer_count,
               uint32_t format, uint64_t usage, uint32_t stride,
               const FileHandleType& acquire_fence_fd,
               const FileHandleType& release_fence_fd)
      : id_(id),
        buffer_state_bit_(buffer_state_bit),
        metadata_size_(metadata_size),
        width_(width),
        height_(height),
        layer_count_(layer_count),
        format_(format),
        usage_(usage),
        stride_(stride),
        buffer_handle_(buffer_handle),
        metadata_handle_(metadata_handle.Borrow()),
        acquire_fence_fd_(acquire_fence_fd.Borrow()),
        release_fence_fd_(release_fence_fd.Borrow()) {}

  BufferTraits(BufferTraits&& other) = default;
  BufferTraits& operator=(BufferTraits&& other) = default;

  // 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_; }

  // State mask of the buffer client. Each BufferHubBuffer client backed by the
  // same buffer channel has uniqued state bit among its siblings. For a
  // producer buffer the bit must be kProducerStateBit; for a consumer the bit
  // must be one of the kConsumerStateMask.
  uint64_t buffer_state_bit() const { return buffer_state_bit_; }
  uint64_t metadata_size() const { return metadata_size_; }

  uint32_t width() { return width_; }
  uint32_t height() { return height_; }
  uint32_t layer_count() { return layer_count_; }
  uint32_t format() { return format_; }
  uint64_t usage() { return usage_; }
  uint32_t stride() { return stride_; }

  const NativeHandleWrapper<FileHandleType>& buffer_handle() const {
    return buffer_handle_;
  }

  NativeHandleWrapper<FileHandleType> take_buffer_handle() {
    return std::move(buffer_handle_);
  }
  FileHandleType take_metadata_handle() { return std::move(metadata_handle_); }
  FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); }
  FileHandleType take_release_fence() { return std::move(release_fence_fd_); }

 private:
  // BufferHub specific traits.
  int id_ = -1;
  uint64_t buffer_state_bit_;
  uint64_t metadata_size_;

  // Traits for a GraphicBuffer.
  uint32_t width_;
  uint32_t height_;
  uint32_t layer_count_;
  uint32_t format_;
  uint64_t usage_;
  uint32_t stride_;

  // Native handle for the graphic buffer.
  NativeHandleWrapper<FileHandleType> buffer_handle_;

  // File handle of an ashmem that holds buffer metadata.
  FileHandleType metadata_handle_;

  // Pamameters for shared fences.
  FileHandleType acquire_fence_fd_;
  FileHandleType release_fence_fd_;

  PDX_SERIALIZABLE_MEMBERS(BufferTraits<FileHandleType>, id_, buffer_state_bit_,
                           metadata_size_, stride_, width_, height_,
                           layer_count_, format_, usage_, buffer_handle_,
                           metadata_handle_, acquire_fence_fd_,
                           release_fence_fd_);

  BufferTraits(const BufferTraits&) = delete;
  void operator=(const BufferTraits&) = delete;
};

struct DetachedBufferRPC {
 private:
  enum {
    kOpDetachedBufferBase = 1000,

    // Allocates a standalone DetachedBuffer not associated with any producer
    // consumer set.
    kOpCreate,

    // Imports the given channel handle to a DetachedBuffer, taking ownership.
    kOpImport,

    // 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.
    kOpPromote,

    // Creates a DetachedBuffer client from an existing one. The new client will
    // share the same underlying gralloc buffer and ashmem region for metadata.
    kOpDuplicate,
  };

  // Aliases.
  using LocalChannelHandle = pdx::LocalChannelHandle;
  using LocalHandle = pdx::LocalHandle;
  using Void = pdx::rpc::Void;

 public:
  PDX_REMOTE_METHOD(Create, kOpCreate,
                    void(uint32_t width, uint32_t height, uint32_t layer_count,
                         uint32_t format, uint64_t usage,
                         size_t user_metadata_size));
  PDX_REMOTE_METHOD(Import, kOpImport, BufferTraits<LocalHandle>(Void));
  PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void));
  PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void));

  PDX_REMOTE_API(API, Create, Import, Promote, Duplicate);
};

}  // namespace dvr
}  // namespace android


#endif  // ANDROID_DVR_BUFFER_HUB_DEFS_H_
+0 −24
Original line number Diff line number Diff line
@@ -316,8 +316,6 @@ struct BufferHubRPC {
    kOpConsumerRelease,
    kOpProducerBufferDetach,
    kOpConsumerBufferDetach,
    kOpDetachedBufferCreate,
    kOpDetachedBufferPromote,
    kOpCreateProducerQueue,
    kOpCreateConsumerQueue,
    kOpGetQueueInfo,
@@ -326,7 +324,6 @@ struct BufferHubRPC {
    kOpProducerQueueRemoveBuffer,
    kOpConsumerQueueImportBuffers,
    // TODO(b/77153033): Separate all those RPC operations into subclasses.
    kOpDetachedBufferBase = 1000,
  };

  // Aliases.
@@ -379,27 +376,6 @@ struct BufferHubRPC {
                    std::vector<std::pair<LocalChannelHandle, size_t>>(Void));
};

struct DetachedBufferRPC final : public BufferHubRPC {
 private:
  enum {
    kOpCreate = kOpDetachedBufferBase,
    kOpImport,
    kOpPromote,
    kOpDuplicate,
  };

 public:
  PDX_REMOTE_METHOD(Create, kOpCreate,
                    void(uint32_t width, uint32_t height, uint32_t layer_count,
                         uint32_t format, uint64_t usage,
                         size_t user_metadata_size));
  PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void));
  PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void));
  PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void));

  PDX_REMOTE_API(API, Create, Import, Promote, Duplicate);
};

}  // namespace dvr
}  // namespace android

Loading