1 #ifndef ANDROID_DVR_BUFFERHUB_RPC_H_
2 #define ANDROID_DVR_BUFFERHUB_RPC_H_
3 
4 #include <cutils/native_handle.h>
5 #include <sys/types.h>
6 #include <ui/BufferQueueDefs.h>
7 
8 #include <dvr/dvr_api.h>
9 #include <pdx/channel_handle.h>
10 #include <pdx/file_handle.h>
11 #include <pdx/rpc/remote_method.h>
12 #include <pdx/rpc/serializable.h>
13 #include <private/dvr/ion_buffer.h>
14 
15 namespace android {
16 namespace dvr {
17 
18 namespace BufferHubDefs {
19 
20 static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB;
21 static constexpr uint32_t kMetadataUsage =
22     GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
23 
24 // Single producuer multiple (up to 63) consumers ownership signal.
25 // 64-bit atomic unsigned int.
26 //
27 // MSB           LSB
28 //  |             |
29 //  v             v
30 // [P|C62|...|C1|C0]
31 // Gain'ed state:     [0|..|0|0] -> Exclusively Writable.
32 // Post'ed state:     [1|..|0|0]
33 // Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits
34 // Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits
35 static constexpr uint64_t kProducerStateBit = 1ULL << 63;
36 static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1;
37 
ModifyBufferState(std::atomic<uint64_t> * buffer_state,uint64_t clear_mask,uint64_t set_mask)38 static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state,
39                                      uint64_t clear_mask, uint64_t set_mask) {
40   uint64_t old_state;
41   uint64_t new_state;
42   do {
43     old_state = buffer_state->load();
44     new_state = (old_state & ~clear_mask) | set_mask;
45   } while (!buffer_state->compare_exchange_weak(old_state, new_state));
46 }
47 
IsBufferGained(uint64_t state)48 static inline bool IsBufferGained(uint64_t state) { return state == 0; }
49 
50 static inline bool IsBufferPosted(uint64_t state,
51                                   uint64_t consumer_bit = kConsumerStateMask) {
52   return (state & kProducerStateBit) && !(state & consumer_bit);
53 }
54 
IsBufferAcquired(uint64_t state)55 static inline bool IsBufferAcquired(uint64_t state) {
56   return (state & kProducerStateBit) && (state & kConsumerStateMask);
57 }
58 
IsBufferReleased(uint64_t state)59 static inline bool IsBufferReleased(uint64_t state) {
60   return !(state & kProducerStateBit) && (state & kConsumerStateMask);
61 }
62 
63 struct __attribute__((packed, aligned(8))) MetadataHeader {
64   // Internal data format, which can be updated as long as the size, padding and
65   // field alignment of the struct is consistent within the same ABI. As this
66   // part is subject for future updates, it's not stable cross Android version,
67   // so don't have it visible from outside of the Android platform (include Apps
68   // and vendor HAL).
69   std::atomic<uint64_t> buffer_state;
70   std::atomic<uint64_t> fence_state;
71   uint64_t queue_index;
72 
73   // Public data format, which should be updated with caution. See more details
74   // in dvr_api.h
75   DvrNativeBufferMetadata metadata;
76 };
77 
78 static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size");
79 static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader);
80 
81 }  // namespace BufferHubDefs
82 
83 template <typename FileHandleType>
84 class NativeBufferHandle {
85  public:
NativeBufferHandle()86   NativeBufferHandle() { Clear(); }
NativeBufferHandle(const IonBuffer & buffer,int id)87   NativeBufferHandle(const IonBuffer& buffer, int id)
88       : id_(id),
89         stride_(buffer.stride()),
90         width_(buffer.width()),
91         height_(buffer.height()),
92         layer_count_(buffer.layer_count()),
93         format_(buffer.format()),
94         usage_(buffer.usage()) {
95     // Populate the fd and int vectors: native_handle->data[] is an array of fds
96     // followed by an array of opaque ints.
97     const int fd_count = buffer.handle()->numFds;
98     const int int_count = buffer.handle()->numInts;
99     for (int i = 0; i < fd_count; i++) {
100       fds_.emplace_back(FileHandleType::AsDuplicate(buffer.handle()->data[i]));
101     }
102     for (int i = 0; i < int_count; i++) {
103       opaque_ints_.push_back(buffer.handle()->data[fd_count + i]);
104     }
105   }
106   NativeBufferHandle(NativeBufferHandle&& other) = default;
107   NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
108 
109   // Imports the native handle into the given IonBuffer instance.
Import(IonBuffer * buffer)110   int Import(IonBuffer* buffer) {
111     // This is annoying, but we need to convert the vector of FileHandles into a
112     // vector of ints for the Import API.
113     std::vector<int> fd_ints;
114     for (const auto& fd : fds_)
115       fd_ints.push_back(fd.Get());
116 
117     const int ret =
118         buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
119                        opaque_ints_.size(), width_, height_, layer_count_,
120                        stride_, format_, usage_);
121     if (ret < 0)
122       return ret;
123 
124     // Import succeeded, release the file handles which are now owned by the
125     // IonBuffer and clear members.
126     for (auto& fd : fds_)
127       fd.Release();
128     opaque_ints_.clear();
129     Clear();
130 
131     return 0;
132   }
133 
id()134   int id() const { return id_; }
IntCount()135   size_t IntCount() const { return opaque_ints_.size(); }
FdCount()136   size_t FdCount() const { return fds_.size(); }
137 
138  private:
139   int id_;
140   uint32_t stride_;
141   uint32_t width_;
142   uint32_t height_;
143   uint32_t layer_count_;
144   uint32_t format_;
145   uint64_t usage_;
146   std::vector<int> opaque_ints_;
147   std::vector<FileHandleType> fds_;
148 
Clear()149   void Clear() {
150     id_ = -1;
151     stride_ = width_ = height_ = format_ = usage_ = 0;
152   }
153 
154   PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
155                            width_, height_, layer_count_, format_, usage_,
156                            opaque_ints_, fds_);
157 
158   NativeBufferHandle(const NativeBufferHandle&) = delete;
159   void operator=(const NativeBufferHandle&) = delete;
160 };
161 
162 template <typename FileHandleType>
163 class BufferDescription {
164  public:
165   BufferDescription() = default;
BufferDescription(const IonBuffer & buffer,const IonBuffer & metadata,int id,uint64_t buffer_state_bit,const FileHandleType & acquire_fence_fd,const FileHandleType & release_fence_fd)166   BufferDescription(const IonBuffer& buffer, const IonBuffer& metadata, int id,
167                     uint64_t buffer_state_bit,
168                     const FileHandleType& acquire_fence_fd,
169                     const FileHandleType& release_fence_fd)
170       : id_(id),
171         buffer_state_bit_(buffer_state_bit),
172         buffer_(buffer, id),
173         metadata_(metadata, id),
174         acquire_fence_fd_(acquire_fence_fd.Borrow()),
175         release_fence_fd_(release_fence_fd.Borrow()) {}
176 
177   BufferDescription(BufferDescription&& other) = default;
178   BufferDescription& operator=(BufferDescription&& other) = default;
179 
180   // ID of the buffer client. All BufferHubBuffer clients derived from the same
181   // buffer in bufferhubd share the same buffer id.
id()182   int id() const { return id_; }
183   // State mask of the buffer client. Each BufferHubBuffer client backed by the
184   // same buffer channel has uniqued state bit among its siblings. For a
185   // producer buffer the bit must be kProducerStateBit; for a consumer the bit
186   // must be one of the kConsumerStateMask.
buffer_state_bit()187   uint64_t buffer_state_bit() const { return buffer_state_bit_; }
take_acquire_fence()188   FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); }
take_release_fence()189   FileHandleType take_release_fence() { return std::move(release_fence_fd_); }
190 
ImportBuffer(IonBuffer * buffer)191   int ImportBuffer(IonBuffer* buffer) { return buffer_.Import(buffer); }
ImportMetadata(IonBuffer * metadata)192   int ImportMetadata(IonBuffer* metadata) { return metadata_.Import(metadata); }
193 
194  private:
195   int id_{-1};
196   uint64_t buffer_state_bit_{0};
197   // Two IonBuffers: one for the graphic buffer and one for metadata.
198   NativeBufferHandle<FileHandleType> buffer_;
199   NativeBufferHandle<FileHandleType> metadata_;
200 
201   // Pamameters for shared fences.
202   FileHandleType acquire_fence_fd_;
203   FileHandleType release_fence_fd_;
204 
205   PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_,
206                            buffer_state_bit_, buffer_, metadata_,
207                            acquire_fence_fd_, release_fence_fd_);
208 
209   BufferDescription(const BufferDescription&) = delete;
210   void operator=(const BufferDescription&) = delete;
211 };
212 
213 using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
214 using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
215 
216 template <typename FileHandleType>
217 class FenceHandle {
218  public:
219   FenceHandle() = default;
FenceHandle(int fence)220   explicit FenceHandle(int fence) : fence_{fence} {}
FenceHandle(FileHandleType && fence)221   explicit FenceHandle(FileHandleType&& fence) : fence_{std::move(fence)} {}
222   FenceHandle(FenceHandle&&) = default;
223   FenceHandle& operator=(FenceHandle&&) = default;
224 
225   explicit operator bool() const { return fence_.IsValid(); }
226 
get()227   const FileHandleType& get() const { fence_; }
take()228   FileHandleType&& take() { return std::move(fence_); }
229 
get_fd()230   int get_fd() const { return fence_.Get(); }
close()231   void close() { fence_.Close(); }
232 
borrow()233   FenceHandle<pdx::BorrowedHandle> borrow() const {
234     return FenceHandle<pdx::BorrowedHandle>(fence_.Borrow());
235   }
236 
237  private:
238   FileHandleType fence_;
239 
240   PDX_SERIALIZABLE_MEMBERS(FenceHandle<FileHandleType>, fence_);
241 
242   FenceHandle(const FenceHandle&) = delete;
243   void operator=(const FenceHandle&) = delete;
244 };
245 
246 using LocalFence = FenceHandle<pdx::LocalHandle>;
247 using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;
248 
249 struct ProducerQueueConfig {
250   // Whether the buffer queue is operating in Async mode.
251   // From GVR's perspective of view, this means a buffer can be acquired
252   // asynchronously by the compositor.
253   // From Android Surface's perspective of view, this is equivalent to
254   // IGraphicBufferProducer's async mode. When in async mode, a producer
255   // will never block even if consumer is running slow.
256   bool is_async;
257 
258   // Default buffer width that is set during ProducerQueue's creation.
259   uint32_t default_width;
260 
261   // Default buffer height that is set during ProducerQueue's creation.
262   uint32_t default_height;
263 
264   // Default buffer format that is set during ProducerQueue's creation.
265   uint32_t default_format;
266 
267   // Size of the meta data associated with all the buffers allocated from the
268   // queue.
269   size_t user_metadata_size;
270 
271  private:
272   PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width,
273                            default_height, default_format, user_metadata_size);
274 };
275 
276 class ProducerQueueConfigBuilder {
277  public:
278   // Build a ProducerQueueConfig object.
Build()279   ProducerQueueConfig Build() {
280     return {is_async_, default_width_, default_height_, default_format_,
281             user_metadata_size_};
282   }
283 
SetIsAsync(bool is_async)284   ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
285     is_async_ = is_async;
286     return *this;
287   }
288 
SetDefaultWidth(uint32_t width)289   ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) {
290     default_width_ = width;
291     return *this;
292   }
293 
SetDefaultHeight(uint32_t height)294   ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) {
295     default_height_ = height;
296     return *this;
297   }
298 
SetDefaultFormat(uint32_t format)299   ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) {
300     default_format_ = format;
301     return *this;
302   }
303 
304   template <typename Meta>
SetMetadata()305   ProducerQueueConfigBuilder& SetMetadata() {
306     user_metadata_size_ = sizeof(Meta);
307     return *this;
308   }
309 
SetMetadataSize(size_t user_metadata_size)310   ProducerQueueConfigBuilder& SetMetadataSize(size_t user_metadata_size) {
311     user_metadata_size_ = user_metadata_size;
312     return *this;
313   }
314 
315  private:
316   bool is_async_{false};
317   uint32_t default_width_{1};
318   uint32_t default_height_{1};
319   uint32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
320   size_t user_metadata_size_{0};
321 };
322 
323 // Explicit specializations of ProducerQueueConfigBuilder::Build for void
324 // metadata type.
325 template <>
326 inline ProducerQueueConfigBuilder&
327 ProducerQueueConfigBuilder::SetMetadata<void>() {
328   user_metadata_size_ = 0;
329   return *this;
330 }
331 
332 struct QueueInfo {
333   ProducerQueueConfig producer_config;
334   int id;
335 
336  private:
337   PDX_SERIALIZABLE_MEMBERS(QueueInfo, producer_config, id);
338 };
339 
340 struct UsagePolicy {
341   uint64_t usage_set_mask{0};
342   uint64_t usage_clear_mask{0};
343   uint64_t usage_deny_set_mask{0};
344   uint64_t usage_deny_clear_mask{0};
345 
346  private:
347   PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask,
348                            usage_deny_set_mask, usage_deny_clear_mask);
349 };
350 
351 // BufferHub Service RPC interface. Defines the endpoints, op codes, and method
352 // type signatures supported by bufferhubd.
353 struct BufferHubRPC {
354   // Service path.
355   static constexpr char kClientPath[] = "system/buffer_hub/client";
356 
357   // |BufferHubQueue| will keep track of at most this value of buffers.
358   // Attempts at runtime to increase the number of buffers past this
359   // will fail. Note that the value is in sync with |android::BufferQueue|, so
360   // that slot id can be shared between |android::dvr::BufferHubQueueProducer|
361   // and |android::BufferQueueProducer| which both implements the same
362   // interface: |android::IGraphicBufferProducer|.
363   static constexpr size_t kMaxQueueCapacity =
364       android::BufferQueueDefs::NUM_BUFFER_SLOTS;
365 
366   // Op codes.
367   enum {
368     kOpCreateBuffer = 0,
369     kOpGetBuffer,
370     kOpNewConsumer,
371     kOpProducerPost,
372     kOpProducerGain,
373     kOpConsumerAcquire,
374     kOpConsumerRelease,
375     kOpConsumerSetIgnore,
376     kOpProducerBufferDetach,
377     kOpConsumerBufferDetach,
378     kOpDetachedBufferCreate,
379     kOpDetachedBufferPromote,
380     kOpCreateProducerQueue,
381     kOpCreateConsumerQueue,
382     kOpGetQueueInfo,
383     kOpProducerQueueAllocateBuffers,
384     kOpProducerQueueRemoveBuffer,
385     kOpConsumerQueueImportBuffers,
386     // TODO(b/77153033): Separate all those RPC operations into subclasses.
387     kOpDetachedBufferBase = 1000,
388   };
389 
390   // Aliases.
391   using LocalChannelHandle = pdx::LocalChannelHandle;
392   using LocalHandle = pdx::LocalHandle;
393   using Void = pdx::rpc::Void;
394 
395   // Methods.
396   PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
397                     void(uint32_t width, uint32_t height, uint32_t format,
398                          uint64_t usage, size_t user_metadata_size));
399   PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
400                     BufferDescription<LocalHandle>(Void));
401   PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
402   PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
403                     void(LocalFence acquire_fence));
404   PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
405   PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire, LocalFence(Void));
406   PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
407                     void(LocalFence release_fence));
408   PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
409   PDX_REMOTE_METHOD(ProducerBufferDetach, kOpProducerBufferDetach,
410                     LocalChannelHandle(Void));
411 
412   // Detaches a ConsumerBuffer from an existing producer/consumer set. Can only
413   // be called when the consumer is the only consumer and it has exclusive
414   // access to the buffer (i.e. in the acquired'ed state). On the successful
415   // return of the IPC call, a new DetachedBufferChannel handle will be returned
416   // and all existing producer and consumer channels will be closed. Further
417   // IPCs towards those channels will return error.
418   PDX_REMOTE_METHOD(ConsumerBufferDetach, kOpConsumerBufferDetach,
419                     LocalChannelHandle(Void));
420 
421   // Buffer Queue Methods.
422   PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
423                     QueueInfo(const ProducerQueueConfig& producer_config,
424                               const UsagePolicy& usage_policy));
425   PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
426                     LocalChannelHandle(bool silent_queue));
427   PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
428   PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
429                     kOpProducerQueueAllocateBuffers,
430                     std::vector<std::pair<LocalChannelHandle, size_t>>(
431                         uint32_t width, uint32_t height, uint32_t layer_count,
432                         uint32_t format, uint64_t usage, size_t buffer_count));
433   PDX_REMOTE_METHOD(ProducerQueueRemoveBuffer, kOpProducerQueueRemoveBuffer,
434                     void(size_t slot));
435   PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
436                     std::vector<std::pair<LocalChannelHandle, size_t>>(Void));
437 };
438 
439 struct DetachedBufferRPC final : public BufferHubRPC {
440  private:
441   enum {
442     kOpCreate = kOpDetachedBufferBase,
443     kOpImport,
444     kOpPromote,
445   };
446 
447  public:
448   PDX_REMOTE_METHOD(Create, kOpCreate,
449                     void(uint32_t width, uint32_t height, uint32_t layer_count,
450                          uint32_t format, uint64_t usage,
451                          size_t user_metadata_size));
452   PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void));
453   PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void));
454 
455   PDX_REMOTE_API(API, Create, Promote);
456 };
457 
458 }  // namespace dvr
459 }  // namespace android
460 
461 #endif  // ANDROID_DVR_BUFFERHUB_RPC_H_
462