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