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

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

Merge "Make BufferHubQueue binder parcelable"

parents 972fa30f a88e3ee3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ staticLibraries = [

sharedLibraries = [
    "libbase",
    "libbinder",
    "libcutils",
    "libhardware",
    "liblog",
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

sourceFiles = [
    "buffer_hub_queue_client.cpp",
    "buffer_hub_queue_parcelable.cpp",
    "buffer_hub_queue_producer.cpp",
]

+41 −0
Original line number Diff line number Diff line
@@ -137,6 +137,28 @@ Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle(
  return status;
}

pdx::Status<ConsumerQueueParcelable>
BufferHubQueue::CreateConsumerQueueParcelable(bool silent) {
  auto status = CreateConsumerQueueHandle(silent);
  if (!status)
    return status.error_status();

  // A temporary consumer queue client to pull its channel parcelable.
  auto consumer_queue =
      std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
  ConsumerQueueParcelable queue_parcelable(
      consumer_queue->GetChannel()->TakeChannelParcelable());

  if (!queue_parcelable.IsValid()) {
    ALOGE(
        "BufferHubQueue::CreateConsumerQueueParcelable: Failed to create "
        "consumer queue parcelable.");
    return ErrorStatus(EINVAL);
  }

  return {std::move(queue_parcelable)};
}

bool BufferHubQueue::WaitForBuffers(int timeout) {
  ATRACE_NAME("BufferHubQueue::WaitForBuffers");
  std::array<epoll_event, kMaxEvents> events;
@@ -555,6 +577,25 @@ pdx::Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
  return {std::move(buffer)};
}

pdx::Status<ProducerQueueParcelable> ProducerQueue::TakeAsParcelable() {
  if (capacity() != 0) {
    ALOGE(
        "ProducerQueue::TakeAsParcelable: producer queue can only be taken out"
        " as a parcelable when empty. Current queue capacity: %zu",
        capacity());
    return ErrorStatus(EINVAL);
  }

  std::unique_ptr<pdx::ClientChannel> channel = TakeChannel();
  ProducerQueueParcelable queue_parcelable(channel->TakeChannelParcelable());

  // Here the queue parcelable is returned and holds the underlying system
  // resources backing the queue; while the original client channel of this
  // producer queue is destroyed in place so that this client can no longer
  // provide producer operations.
  return {std::move(queue_parcelable)};
}

ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
    : BufferHubQueue(std::move(handle)) {
  auto status = ImportQueue();
+82 −0
Original line number Diff line number Diff line
#include "include/private/dvr/buffer_hub_queue_parcelable.h"

#include <binder/Parcel.h>
#include <pdx/default_transport/channel_parcelable.h>

namespace android {
namespace dvr {

template <BufferHubQueueParcelableMagic Magic>
bool BufferHubQueueParcelable<Magic>::IsValid() const {
  return !!channel_parcelable_ && channel_parcelable_->IsValid();
}

template <BufferHubQueueParcelableMagic Magic>
pdx::LocalChannelHandle BufferHubQueueParcelable<Magic>::TakeChannelHandle() {
  if (!IsValid()) {
    ALOGE(
        "BufferHubQueueParcelable::TakeChannelHandle: Invalid channel parcel.");
    return {};  // Returns an empty channel handle.
  }

  // Take channel handle out of the parcelable and reset the parcelable.
  pdx::LocalChannelHandle handle = channel_parcelable_->TakeChannelHandle();
  // Now channel_parcelable_ should already be invalid, but reset it to release
  // the invalid parcelable object from unique_ptr.
  channel_parcelable_ = nullptr;
  return handle;
}

template <BufferHubQueueParcelableMagic Magic>
status_t BufferHubQueueParcelable<Magic>::writeToParcel(Parcel* parcel) const {
  if (!IsValid()) {
    ALOGE("BufferHubQueueParcelable::writeToParcel: Invalid channel.");
    return -EINVAL;
  }

  status_t res = parcel->writeUint32(Magic);
  if (res != NO_ERROR) {
    ALOGE("BufferHubQueueParcelable::writeToParcel: Cannot write magic.");
    return res;
  }

  return channel_parcelable_->writeToParcel(parcel);
}

template <BufferHubQueueParcelableMagic Magic>
status_t BufferHubQueueParcelable<Magic>::readFromParcel(const Parcel* parcel) {
  if (IsValid()) {
    ALOGE(
        "BufferHubQueueParcelable::readFromParcel: This parcelable object has "
        "been initialized already.");
    return -EINVAL;
  }

  uint32_t out_magic = 0;
  status_t res = NO_ERROR;

  res = parcel->readUint32(&out_magic);
  if (res != NO_ERROR)
    return res;

  if (out_magic != Magic) {
    ALOGE(
        "BufferHubQueueParcelable::readFromParcel: Unexpected magic: 0x%x, "
        "epxected: 0x%x",
        out_magic, Magic);
    return -EINVAL;
  }

  // (Re)Alocate channel parcelable object.
  channel_parcelable_ =
      std::make_unique<pdx::default_transport::ChannelParcelable>();
  return channel_parcelable_->readFromParcel(parcel);
}

template class BufferHubQueueParcelable<
    BufferHubQueueParcelableMagic::Producer>;
template class BufferHubQueueParcelable<
    BufferHubQueueParcelableMagic::Consumer>;

}  // namespace dvr
}  // namespace android
+11 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include <pdx/client.h>
#include <pdx/status.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/buffer_hub_queue_parcelable.h>
#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/epoll_file_descriptor.h>
#include <private/dvr/ring_buffer.h>
@@ -54,6 +55,11 @@ class BufferHubQueue : public pdx::Client {
  pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
      bool silent = false);

  // Creates a new consumer in parcelable form for immediate transport over
  // Binder.
  pdx::Status<ConsumerQueueParcelable> CreateConsumerQueueParcelable(
      bool silent = false);

  // Returns the number of buffers avaiable for dequeue.
  size_t count() const { return available_buffers_.size(); }

@@ -337,6 +343,11 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
    return BufferHubQueue::Enqueue({buffer, slot, index});
  }

  // Takes out the current producer queue as a binder parcelable object. Note
  // that the queue must be empty to be exportable. After successful export, the
  // producer queue client should no longer be used.
  pdx::Status<ProducerQueueParcelable> TakeAsParcelable();

 private:
  friend BASE;

Loading