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