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
16namespace android {
17namespace dvr {
18
19class 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).
175class 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.
297class 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