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