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