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
17namespace android {
18namespace dvr {
19
20class ConsumerQueue;
21
22// |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are
23// automatically re-requeued when released by the remote side.
24class 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
265class 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
350class 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