Home | History | Annotate | Download | only in dvr
      1 #ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
      2 #define ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
      3 
      4 #include <gui/BufferQueueDefs.h>
      5 
      6 #include <pdx/client.h>
      7 #include <pdx/status.h>
      8 #include <private/dvr/buffer_hub_client.h>
      9 #include <private/dvr/bufferhub_rpc.h>
     10 #include <private/dvr/epoll_file_descriptor.h>
     11 #include <private/dvr/ring_buffer.h>
     12 
     13 #include <memory>
     14 #include <queue>
     15 #include <vector>
     16 
     17 namespace android {
     18 namespace dvr {
     19 
     20 class ConsumerQueue;
     21 
     22 // |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are
     23 // automatically re-requeued when released by the remote side.
     24 class BufferHubQueue : public pdx::Client {
     25  public:
     26   using BufferAvailableCallback = std::function<void()>;
     27   using BufferRemovedCallback =
     28       std::function<void(const std::shared_ptr<BufferHubBuffer>&)>;
     29 
     30   virtual ~BufferHubQueue() {}
     31 
     32   // Creates a new consumer queue that is attached to the producer. Returns
     33   // a new consumer queue client or nullptr on failure.
     34   std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
     35 
     36   // Creates a new consumer queue that is attached to the producer. This queue
     37   // sets each of its imported consumer buffers to the ignored state to avoid
     38   // participation in lifecycle events.
     39   std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
     40 
     41   // Returns whether the buffer queue is in async mode.
     42   bool is_async() const { return is_async_; }
     43 
     44   // Returns the default buffer width of this buffer queue.
     45   uint32_t default_width() const { return default_width_; }
     46 
     47   // Returns the default buffer height of this buffer queue.
     48   uint32_t default_height() const { return default_height_; }
     49 
     50   // Returns the default buffer format of this buffer queue.
     51   uint32_t default_format() const { return default_format_; }
     52 
     53   // Creates a new consumer in handle form for immediate transport over RPC.
     54   pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
     55       bool silent = false);
     56 
     57   // Returns the number of buffers avaiable for dequeue.
     58   size_t count() const { return available_buffers_.size(); }
     59 
     60   // Returns the total number of buffers that the queue is tracking.
     61   size_t capacity() const { return capacity_; }
     62 
     63   // Returns the size of metadata structure associated with this queue.
     64   size_t metadata_size() const { return user_metadata_size_; }
     65 
     66   // Returns whether the buffer queue is full.
     67   bool is_full() const {
     68     return available_buffers_.size() >= kMaxQueueCapacity;
     69   }
     70 
     71   explicit operator bool() const { return epoll_fd_.IsValid(); }
     72 
     73   int GetBufferId(size_t slot) const {
     74     return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
     75                                                       : -1;
     76   }
     77 
     78   std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
     79     return buffers_[slot];
     80   }
     81 
     82   pdx::Status<int> GetEventMask(int events) {
     83     if (auto* client_channel = GetChannel()) {
     84       return client_channel->GetEventMask(events);
     85     } else {
     86       return pdx::ErrorStatus(EINVAL);
     87     }
     88   }
     89 
     90   // Returns an fd that signals pending queue events using
     91   // EPOLLIN/POLLIN/readible. Either HandleQueueEvents or WaitForBuffers may be
     92   // called to handle pending queue events.
     93   int queue_fd() const { return epoll_fd_.Get(); }
     94 
     95   // Handles any pending events, returning available buffers to the queue and
     96   // reaping disconnected buffers. Returns true if successful, false if an error
     97   // occurred.
     98   bool HandleQueueEvents() { return WaitForBuffers(0); }
     99 
    100   // Set buffer event callbacks, which are std::function wrappers. The caller is
    101   // responsible for ensuring the validity of these callbacks' callable targets.
    102   void SetBufferAvailableCallback(BufferAvailableCallback callback);
    103   void SetBufferRemovedCallback(BufferRemovedCallback callback);
    104 
    105   // The queue tracks at most this many buffers.
    106   static constexpr size_t kMaxQueueCapacity =
    107       android::BufferQueueDefs::NUM_BUFFER_SLOTS;
    108 
    109   static constexpr int kNoTimeOut = -1;
    110 
    111   int id() const { return id_; }
    112   bool hung_up() const { return hung_up_; }
    113 
    114  protected:
    115   BufferHubQueue(pdx::LocalChannelHandle channel);
    116   BufferHubQueue(const std::string& endpoint_path);
    117 
    118   // Imports the queue parameters by querying BufferHub for the parameters for
    119   // this channel.
    120   pdx::Status<void> ImportQueue();
    121 
    122   // Sets up the queue with the given parameters.
    123   void SetupQueue(const QueueInfo& queue_info);
    124 
    125   // Register a buffer for management by the queue. Used by subclasses to add a
    126   // buffer to internal bookkeeping.
    127   pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
    128                               size_t slot);
    129 
    130   // Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only
    131   // to deregister a buffer for epoll and internal bookkeeping.
    132   virtual pdx::Status<void> RemoveBuffer(size_t slot);
    133 
    134   // Free all buffers that belongs to this queue. Can only be called from
    135   // producer side.
    136   virtual pdx::Status<void> FreeAllBuffers();
    137 
    138   // Dequeue a buffer from the free queue, blocking until one is available. The
    139   // timeout argument specifies the number of milliseconds that |Dequeue()| will
    140   // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
    141   // while specifying a timeout equal to zero cause Dequeue() to return
    142   // immediately, even if no buffers are available.
    143   pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
    144                                                         size_t* slot);
    145 
    146   // Waits for buffers to become available and adds them to the available queue.
    147   bool WaitForBuffers(int timeout);
    148 
    149   pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd,
    150                                       int poll_events);
    151   pdx::Status<void> HandleQueueEvent(int poll_events);
    152 
    153   // Entry in the ring buffer of available buffers that stores related
    154   // per-buffer data.
    155   struct Entry {
    156     Entry() : slot(0) {}
    157     Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot,
    158           uint64_t index)
    159         : buffer(buffer), slot(slot), index(index) {}
    160     Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
    161           std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
    162           size_t slot)
    163         : buffer(buffer),
    164           metadata(std::move(metadata)),
    165           fence(std::move(fence)),
    166           slot(slot) {}
    167     Entry(Entry&&) = default;
    168     Entry& operator=(Entry&&) = default;
    169 
    170     std::shared_ptr<BufferHubBuffer> buffer;
    171     std::unique_ptr<uint8_t[]> metadata;
    172     pdx::LocalHandle fence;
    173     size_t slot;
    174     uint64_t index;
    175   };
    176 
    177   struct EntryComparator {
    178     bool operator()(const Entry& lhs, const Entry& rhs) {
    179       return lhs.index > rhs.index;
    180     }
    181   };
    182 
    183   // Enqueues a buffer to the available list (Gained for producer or Acquireed
    184   // for consumer).
    185   pdx::Status<void> Enqueue(Entry entry);
    186 
    187   // Called when a buffer is allocated remotely.
    188   virtual pdx::Status<void> OnBufferAllocated() { return {}; }
    189 
    190   // Size of the metadata that buffers in this queue cary.
    191   size_t user_metadata_size_{0};
    192 
    193  private:
    194   void Initialize();
    195 
    196   // Special epoll data field indicating that the epoll event refers to the
    197   // queue.
    198   static constexpr int64_t kEpollQueueEventIndex = -1;
    199 
    200   static constexpr size_t kMaxEvents = 128;
    201 
    202   // The u64 data field of an epoll event is interpreted as int64_t:
    203   // When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific
    204   // element of |buffers_| as a direct index;
    205   static bool is_buffer_event_index(int64_t index) {
    206     return index >= 0 &&
    207            index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity);
    208   }
    209 
    210   // When |index| == kEpollQueueEventIndex it refers to the queue itself.
    211   static bool is_queue_event_index(int64_t index) {
    212     return index == BufferHubQueue::kEpollQueueEventIndex;
    213   }
    214 
    215   // Whether the buffer queue is operating in Async mode.
    216   // From GVR's perspective of view, this means a buffer can be acquired
    217   // asynchronously by the compositor.
    218   // From Android Surface's perspective of view, this is equivalent to
    219   // IGraphicBufferProducer's async mode. When in async mode, a producer
    220   // will never block even if consumer is running slow.
    221   bool is_async_{false};
    222 
    223   // Default buffer width that is set during ProducerQueue's creation.
    224   size_t default_width_{1};
    225 
    226   // Default buffer height that is set during ProducerQueue's creation.
    227   size_t default_height_{1};
    228 
    229   // Default buffer format that is set during ProducerQueue's creation.
    230   int32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
    231 
    232   // Tracks the buffers belonging to this queue. Buffers are stored according to
    233   // "slot" in this vector. Each slot is a logical id of the buffer within this
    234   // queue regardless of its queue position or presence in the ring buffer.
    235   std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
    236 
    237   // Buffers and related data that are available for dequeue.
    238   // RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
    239   std::priority_queue<Entry, std::vector<Entry>, EntryComparator>
    240       available_buffers_;
    241 
    242   // Keeps track with how many buffers have been added into the queue.
    243   size_t capacity_{0};
    244 
    245   // Epoll fd used to manage buffer events.
    246   EpollFileDescriptor epoll_fd_;
    247 
    248   // Flag indicating that the other side hung up. For ProducerQueues this
    249   // triggers when BufferHub dies or explicitly closes the queue channel. For
    250   // ConsumerQueues this can either mean the same or that the ProducerQueue on
    251   // the other end hung up.
    252   bool hung_up_{false};
    253 
    254   // Global id for the queue that is consistent across processes.
    255   int id_{-1};
    256 
    257   // Buffer event callbacks
    258   BufferAvailableCallback on_buffer_available_;
    259   BufferRemovedCallback on_buffer_removed_;
    260 
    261   BufferHubQueue(const BufferHubQueue&) = delete;
    262   void operator=(BufferHubQueue&) = delete;
    263 };
    264 
    265 class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
    266  public:
    267   // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
    268   // in |usage_clear_mask| will be automatically masked off. Note that
    269   // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but
    270   // |usage_set_mask| takes precedence over |usage_clear_mask|. All buffer
    271   // allocation through this producer queue shall not have any of the usage bits
    272   // in |usage_deny_set_mask| set. Allocation calls violating this will be
    273   // rejected. All buffer allocation through this producer queue must have all
    274   // the usage bits in |usage_deny_clear_mask| set. Allocation calls violating
    275   // this will be rejected. Note that |usage_deny_set_mask| and
    276   // |usage_deny_clear_mask| shall not conflict with each other. Such
    277   // configuration will be treated as invalid input on creation.
    278   static std::unique_ptr<ProducerQueue> Create(
    279       const ProducerQueueConfig& config, const UsagePolicy& usage) {
    280     return BASE::Create(config, usage);
    281   }
    282 
    283   // Import a ProducerQueue from a channel handle.
    284   static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) {
    285     return BASE::Create(std::move(handle));
    286   }
    287 
    288   // Get a buffer producer. Note that the method doesn't check whether the
    289   // buffer slot has a valid buffer that has been allocated already. When no
    290   // buffer has been imported before it returns nullptr; otherwise it returns
    291   // a shared pointer to a BufferProducer.
    292   std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
    293     return std::static_pointer_cast<BufferProducer>(
    294         BufferHubQueue::GetBuffer(slot));
    295   }
    296 
    297   // Batch allocate buffers. Once allocated, producer buffers are automatically
    298   // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED
    299   // state). Upon success, returns a list of slots for each buffer allocated.
    300   pdx::Status<std::vector<size_t>> AllocateBuffers(
    301       uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
    302       uint64_t usage, size_t buffer_count);
    303 
    304   // Allocate producer buffer to populate the queue. Once allocated, a producer
    305   // buffer is automatically enqueue'd into the ProducerQueue and available to
    306   // use (i.e. in GAINED state). Upon success, returns the slot number for the
    307   // buffer allocated.
    308   pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height,
    309                                      uint32_t layer_count, uint32_t format,
    310                                      uint64_t usage);
    311 
    312   // Add a producer buffer to populate the queue. Once added, a producer buffer
    313   // is available to use (i.e. in GAINED state).
    314   pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
    315                               size_t slot);
    316 
    317   // Remove producer buffer from the queue.
    318   pdx::Status<void> RemoveBuffer(size_t slot) override;
    319 
    320   // Free all buffers on this producer queue.
    321   pdx::Status<void> FreeAllBuffers() override {
    322     return BufferHubQueue::FreeAllBuffers();
    323   }
    324 
    325   // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
    326   // and caller should call Post() once it's done writing to release the buffer
    327   // to the consumer side.
    328   pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
    329       int timeout, size_t* slot, pdx::LocalHandle* release_fence);
    330   pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
    331       int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
    332       pdx::LocalHandle* release_fence);
    333 
    334   // Enqueues a producer buffer in the queue.
    335   pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
    336                             size_t slot, uint64_t index) {
    337     return BufferHubQueue::Enqueue({buffer, slot, index});
    338   }
    339 
    340  private:
    341   friend BASE;
    342 
    343   // Constructors are automatically exposed through ProducerQueue::Create(...)
    344   // static template methods inherited from ClientBase, which take the same
    345   // arguments as the constructors.
    346   explicit ProducerQueue(pdx::LocalChannelHandle handle);
    347   ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
    348 };
    349 
    350 class ConsumerQueue : public BufferHubQueue {
    351  public:
    352   // Get a buffer consumer. Note that the method doesn't check whether the
    353   // buffer slot has a valid buffer that has been imported already. When no
    354   // buffer has been imported before it returns nullptr; otherwise returns a
    355   // shared pointer to a BufferConsumer.
    356   std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
    357     return std::static_pointer_cast<BufferConsumer>(
    358         BufferHubQueue::GetBuffer(slot));
    359   }
    360 
    361   // Import a ConsumerQueue from a channel handle. |ignore_on_import| controls
    362   // whether or not buffers are set to be ignored when imported. This may be
    363   // used to avoid participation in the buffer lifecycle by a consumer queue
    364   // that is only used to spawn other consumer queues, such as in an
    365   // intermediate service.
    366   static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle) {
    367     return std::unique_ptr<ConsumerQueue>(
    368         new ConsumerQueue(std::move(handle)));
    369   }
    370 
    371   // Import newly created buffers from the service side.
    372   // Returns number of buffers successfully imported or an error.
    373   pdx::Status<size_t> ImportBuffers();
    374 
    375   // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
    376   // mode, and caller should call Releasse() once it's done writing to release
    377   // the buffer to the producer side. |meta| is passed along from BufferHub,
    378   // The user of BufferProducer is responsible with making sure that the
    379   // Dequeue() is done with the corect metadata type and size with those used
    380   // when the buffer is orignally created.
    381   template <typename Meta>
    382   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
    383       int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
    384     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
    385   }
    386   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
    387       int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
    388     return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
    389   }
    390 
    391   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
    392       int timeout, size_t* slot, void* meta, size_t user_metadata_size,
    393       pdx::LocalHandle* acquire_fence);
    394   pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
    395       int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
    396       pdx::LocalHandle* acquire_fence);
    397 
    398  private:
    399   friend BufferHubQueue;
    400 
    401   ConsumerQueue(pdx::LocalChannelHandle handle);
    402 
    403   // Add a consumer buffer to populate the queue. Once added, a consumer buffer
    404   // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
    405   // will catch the |Post| and |Acquire| the buffer to make it available for
    406   // consumer.
    407   pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
    408                               size_t slot);
    409 
    410   pdx::Status<void> OnBufferAllocated() override;
    411 };
    412 
    413 }  // namespace dvr
    414 }  // namespace android
    415 
    416 #endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
    417