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