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