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