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