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