Home | History | Annotate | Download | only in dvr
      1 #ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
      2 #define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
      3 
      4 #include <hardware/gralloc.h>
      5 #include <pdx/channel_handle.h>
      6 #include <pdx/client.h>
      7 #include <pdx/file_handle.h>
      8 #include <pdx/status.h>
      9 
     10 #include <vector>
     11 
     12 #include <private/dvr/ion_buffer.h>
     13 
     14 #include "bufferhub_rpc.h"
     15 
     16 namespace android {
     17 namespace dvr {
     18 
     19 class BufferHubClient : public pdx::Client {
     20  public:
     21   BufferHubClient();
     22   explicit BufferHubClient(pdx::LocalChannelHandle channel_handle);
     23 
     24   bool IsValid() const;
     25   pdx::LocalChannelHandle TakeChannelHandle();
     26 
     27   using pdx::Client::Close;
     28   using pdx::Client::GetChannel;
     29   using pdx::Client::InvokeRemoteMethod;
     30   using pdx::Client::IsConnected;
     31   using pdx::Client::event_fd;
     32 };
     33 
     34 class BufferHubBuffer : public pdx::Client {
     35  public:
     36   using LocalHandle = pdx::LocalHandle;
     37   using LocalChannelHandle = pdx::LocalChannelHandle;
     38   template <typename T>
     39   using Status = pdx::Status<T>;
     40 
     41   // Create a new consumer channel that is attached to the producer. Returns
     42   // a file descriptor for the new channel or a negative error code.
     43   Status<LocalChannelHandle> CreateConsumer();
     44 
     45   // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
     46   int Poll(int timeout_ms);
     47 
     48   // Locks the area specified by (x, y, width, height) for a specific usage. If
     49   // the usage is software then |addr| will be updated to point to the address
     50   // of the buffer in virtual memory. The caller should only access/modify the
     51   // pixels in the specified area. anything else is undefined behavior.
     52   int Lock(int usage, int x, int y, int width, int height, void** addr);
     53 
     54   // Must be called after Lock() when the caller has finished changing the
     55   // buffer.
     56   int Unlock();
     57 
     58   // Gets a blob buffer that was created with BufferProducer::CreateBlob.
     59   // Locking and Unlocking is handled internally. There's no need to Unlock
     60   // after calling this method.
     61   int GetBlobReadWritePointer(size_t size, void** addr);
     62 
     63   // Gets a blob buffer that was created with BufferProducer::CreateBlob.
     64   // Locking and Unlocking is handled internally. There's no need to Unlock
     65   // after calling this method.
     66   int GetBlobReadOnlyPointer(size_t size, void** addr);
     67 
     68   // Returns a dup'd file descriptor for accessing the blob shared memory. The
     69   // caller takes ownership of the file descriptor and must close it or pass on
     70   // ownership. Some GPU API extensions can take file descriptors to bind shared
     71   // memory gralloc buffers to GPU buffer objects.
     72   LocalHandle GetBlobFd() const {
     73     // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
     74     // vendors and this is the wrong fd, late-latching and EDS will very clearly
     75     // stop working and we will need to correct this. The alternative is to use
     76     // a GL context in the pose service to allocate this buffer or to use the
     77     // ION API directly instead of gralloc.
     78     return LocalHandle(dup(native_handle()->data[0]));
     79   }
     80 
     81   // Get up to |max_fds_count| file descriptors for accessing the blob shared
     82   // memory. |fds_count| will contain the actual number of file descriptors.
     83   void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
     84 
     85   using Client::event_fd;
     86 
     87   Status<int> GetEventMask(int events) {
     88     if (auto* client_channel = GetChannel()) {
     89       return client_channel->GetEventMask(events);
     90     } else {
     91       return pdx::ErrorStatus(EINVAL);
     92     }
     93   }
     94 
     95   std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
     96     if (auto* client_channel = GetChannel()) {
     97       return client_channel->GetEventSources();
     98     } else {
     99       return {};
    100     }
    101   }
    102 
    103   native_handle_t* native_handle() const {
    104     return const_cast<native_handle_t*>(buffer_.handle());
    105   }
    106 
    107   IonBuffer* buffer() { return &buffer_; }
    108   const IonBuffer* buffer() const { return &buffer_; }
    109 
    110   int id() const { return id_; }
    111 
    112   // Returns the buffer buffer state.
    113   uint64_t buffer_state() { return buffer_state_->load(); };
    114 
    115   // A state mask which is unique to a buffer hub client among all its siblings
    116   // sharing the same concrete graphic buffer.
    117   uint64_t buffer_state_bit() const { return buffer_state_bit_; }
    118 
    119   // The following methods return settings of the first buffer. Currently,
    120   // it is only possible to create multi-buffer BufferHubBuffers with the same
    121   // settings.
    122   uint32_t width() const { return buffer_.width(); }
    123   uint32_t height() const { return buffer_.height(); }
    124   uint32_t stride() const { return buffer_.stride(); }
    125   uint32_t format() const { return buffer_.format(); }
    126   uint32_t usage() const { return buffer_.usage(); }
    127   uint32_t layer_count() const { return buffer_.layer_count(); }
    128 
    129   uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
    130   void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
    131 
    132  protected:
    133   explicit BufferHubBuffer(LocalChannelHandle channel);
    134   explicit BufferHubBuffer(const std::string& endpoint_path);
    135   virtual ~BufferHubBuffer();
    136 
    137   // Initialization helper.
    138   int ImportBuffer();
    139 
    140   // Check invalid metadata operation. Returns 0 if requested metadata is valid.
    141   int CheckMetadata(size_t user_metadata_size) const;
    142 
    143   // Send out the new fence by updating the shared fence (shared_release_fence
    144   // for producer and shared_acquire_fence for consumer). Note that during this
    145   // should only be used in LocalPost() or LocalRelease, and the shared fence
    146   // shouldn't be poll'ed by the other end.
    147   int UpdateSharedFence(const LocalHandle& new_fence,
    148                         const LocalHandle& shared_fence);
    149 
    150   // IonBuffer that is shared between bufferhubd, producer, and consumers.
    151   size_t metadata_buf_size_{0};
    152   size_t user_metadata_size_{0};
    153   BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
    154   void* user_metadata_ptr_{nullptr};
    155   std::atomic<uint64_t>* buffer_state_{nullptr};
    156   std::atomic<uint64_t>* fence_state_{nullptr};
    157 
    158   LocalHandle shared_acquire_fence_;
    159   LocalHandle shared_release_fence_;
    160 
    161   // A local fence fd that holds the ownership of the fence fd on Post (for
    162   // producer) and Release (for consumer).
    163   LocalHandle pending_fence_fd_;
    164 
    165  private:
    166   BufferHubBuffer(const BufferHubBuffer&) = delete;
    167   void operator=(const BufferHubBuffer&) = delete;
    168 
    169   // Global id for the buffer that is consistent across processes. It is meant
    170   // for logging and debugging purposes only and should not be used for lookup
    171   // or any other functional purpose as a security precaution.
    172   int id_;
    173   uint64_t buffer_state_bit_{0ULL};
    174   IonBuffer buffer_;
    175   IonBuffer metadata_buffer_;
    176 };
    177 
    178 // This represents a writable buffer. Calling Post notifies all clients and
    179 // makes the buffer read-only. Call Gain to acquire write access. A buffer
    180 // may have many consumers.
    181 //
    182 // The user of BufferProducer is responsible with making sure that the Post() is
    183 // done with the correct metadata type and size. The user is also responsible
    184 // for making sure that remote ends (BufferConsumers) are also using the correct
    185 // metadata when acquiring the buffer. The API guarantees that a Post() with a
    186 // metadata of wrong size will fail. However, it currently does not do any
    187 // type checking.
    188 // The API also assumes that metadata is a serializable type (plain old data).
    189 class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
    190  public:
    191   // Imports a bufferhub producer channel, assuming ownership of its handle.
    192   static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
    193   static std::unique_ptr<BufferProducer> Import(
    194       Status<LocalChannelHandle> status);
    195 
    196   // Asynchronously posts a buffer. The fence and metadata are passed to
    197   // consumer via shared fd and shared memory.
    198   int PostAsync(const DvrNativeBufferMetadata* meta,
    199                 const LocalHandle& ready_fence);
    200 
    201   // Post this buffer, passing |ready_fence| to the consumers. The bytes in
    202   // |meta| are passed unaltered to the consumers. The producer must not modify
    203   // the buffer until it is re-gained.
    204   // This returns zero or a negative unix error code.
    205   int Post(const LocalHandle& ready_fence, const void* meta,
    206            size_t user_metadata_size);
    207 
    208   template <typename Meta,
    209             typename = typename std::enable_if<std::is_void<Meta>::value>::type>
    210   int Post(const LocalHandle& ready_fence) {
    211     return Post(ready_fence, nullptr, 0);
    212   }
    213   template <typename Meta, typename = typename std::enable_if<
    214                                !std::is_void<Meta>::value>::type>
    215   int Post(const LocalHandle& ready_fence, const Meta& meta) {
    216     return Post(ready_fence, &meta, sizeof(meta));
    217   }
    218 
    219   // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
    220   // must be waited on before using the buffer. If it is not valid then the
    221   // buffer is free for immediate use. This call will only succeed if the buffer
    222   // is in the released state.
    223   // This returns zero or a negative unix error code.
    224   int Gain(LocalHandle* release_fence);
    225   int GainAsync();
    226 
    227   // Asynchronously marks a released buffer as gained. This method is similar to
    228   // the synchronous version above, except that it does not wait for BufferHub
    229   // to acknowledge success or failure. Because of the asynchronous nature of
    230   // the underlying message, no error is returned if this method is called when
    231   // the buffer is in an incorrect state. Returns zero if sending the message
    232   // succeeded, or a negative errno code if local error check fails.
    233   int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
    234 
    235   // Detaches a ProducerBuffer from an existing producer/consumer set. Can only
    236   // be called when a producer buffer has exclusive access to the buffer (i.e.
    237   // in the gain'ed state). On the successful return of the IPC call, a new
    238   // LocalChannelHandle representing a detached buffer will be returned and all
    239   // existing producer and consumer channels will be closed. Further IPCs
    240   // towards those channels will return error.
    241   Status<LocalChannelHandle> Detach();
    242 
    243  private:
    244   friend BASE;
    245 
    246   // Constructors are automatically exposed through BufferProducer::Create(...)
    247   // static template methods inherited from ClientBase, which take the same
    248   // arguments as the constructors.
    249 
    250   // Constructs a buffer with the given geometry and parameters.
    251   BufferProducer(uint32_t width, uint32_t height, uint32_t format,
    252                  uint64_t usage, size_t metadata_size = 0);
    253 
    254   // Constructs a blob (flat) buffer with the given usage flags.
    255   BufferProducer(uint64_t usage, size_t size);
    256 
    257   // Imports the given file handle to a producer channel, taking ownership.
    258   explicit BufferProducer(LocalChannelHandle channel);
    259 
    260   // Local state transition helpers.
    261   int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
    262   int LocalPost(const DvrNativeBufferMetadata* meta,
    263                 const LocalHandle& ready_fence);
    264 };
    265 
    266 // This is a connection to a producer buffer, which can be located in another
    267 // application. When that buffer is Post()ed, this fd will be signaled and
    268 // Acquire allows read access. The user is responsible for making sure that
    269 // Acquire is called with the correct metadata structure. The only guarantee the
    270 // API currently provides is that an Acquire() with metadata of the wrong size
    271 // will fail.
    272 class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
    273  public:
    274   // This call assumes ownership of |fd|.
    275   static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel);
    276   static std::unique_ptr<BufferConsumer> Import(
    277       Status<LocalChannelHandle> status);
    278 
    279   // Attempt to retrieve a post event from buffer hub. If successful,
    280   // |ready_fence| will be set to a fence to wait on until the buffer is ready.
    281   // This call will only succeed after the fd is signalled. This call may be
    282   // performed as an alternative to the Acquire() with metadata. In such cases
    283   // the metadata is not read.
    284   //
    285   // This returns zero or negative unix error code.
    286   int Acquire(LocalHandle* ready_fence);
    287 
    288   // Attempt to retrieve a post event from buffer hub. If successful,
    289   // |ready_fence| is set to a fence signaling that the contents of the buffer
    290   // are available. This call will only succeed if the buffer is in the posted
    291   // state.
    292   // Returns zero on success, or a negative errno code otherwise.
    293   int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
    294 
    295   // Attempt to retrieve a post event from buffer hub. If successful,
    296   // |ready_fence| is set to a fence to wait on until the buffer is ready. This
    297   // call will only succeed after the fd is signaled. This returns zero or a
    298   // negative unix error code.
    299   template <typename Meta>
    300   int Acquire(LocalHandle* ready_fence, Meta* meta) {
    301     return Acquire(ready_fence, meta, sizeof(*meta));
    302   }
    303 
    304   // Asynchronously acquires a bufer.
    305   int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
    306 
    307   // This should be called after a successful Acquire call. If the fence is
    308   // valid the fence determines the buffer usage, otherwise the buffer is
    309   // released immediately.
    310   // This returns zero or a negative unix error code.
    311   int Release(const LocalHandle& release_fence);
    312   int ReleaseAsync();
    313 
    314   // Asynchronously releases a buffer. Similar to the synchronous version above,
    315   // except that it does not wait for BufferHub to reply with success or error.
    316   // The fence and metadata are passed to consumer via shared fd and shared
    317   // memory.
    318   int ReleaseAsync(const DvrNativeBufferMetadata* meta,
    319                    const LocalHandle& release_fence);
    320 
    321   // May be called after or instead of Acquire to indicate that the consumer
    322   // does not need to access the buffer this cycle. This returns zero or a
    323   // negative unix error code.
    324   int Discard();
    325 
    326   // When set, this consumer is no longer notified when this buffer is
    327   // available. The system behaves as if Discard() is immediately called
    328   // whenever the buffer is posted. If ignore is set to true while a buffer is
    329   // pending, it will act as if Discard() was also called.
    330   // This returns zero or a negative unix error code.
    331   int SetIgnore(bool ignore);
    332 
    333  private:
    334   friend BASE;
    335 
    336   explicit BufferConsumer(LocalChannelHandle channel);
    337 
    338   // Local state transition helpers.
    339   int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
    340   int LocalRelease(const DvrNativeBufferMetadata* meta,
    341                    const LocalHandle& release_fence);
    342 };
    343 
    344 }  // namespace dvr
    345 }  // namespace android
    346 
    347 #endif  // ANDROID_DVR_BUFFER_HUB_CLIENT_H_
    348