Home | History | Annotate | Download | only in dvr
      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 
     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 
     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 
     55 static inline bool IsBufferAcquired(uint64_t state) {
     56   return (state & kProducerStateBit) && (state & kConsumerStateMask);
     57 }
     58 
     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:
     86   NativeBufferHandle() { Clear(); }
     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.
    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 
    134   int id() const { return id_; }
    135   size_t IntCount() const { return opaque_ints_.size(); }
    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 
    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;
    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.
    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.
    187   uint64_t buffer_state_bit() const { return buffer_state_bit_; }
    188   FileHandleType take_acquire_fence() { return std::move(acquire_fence_fd_); }
    189   FileHandleType take_release_fence() { return std::move(release_fence_fd_); }
    190 
    191   int ImportBuffer(IonBuffer* buffer) { return buffer_.Import(buffer); }
    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;
    220   explicit FenceHandle(int fence) : fence_{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 
    227   const FileHandleType& get() const { fence_; }
    228   FileHandleType&& take() { return std::move(fence_); }
    229 
    230   int get_fd() const { return fence_.Get(); }
    231   void close() { fence_.Close(); }
    232 
    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.
    279   ProducerQueueConfig Build() {
    280     return {is_async_, default_width_, default_height_, default_format_,
    281             user_metadata_size_};
    282   }
    283 
    284   ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
    285     is_async_ = is_async;
    286     return *this;
    287   }
    288 
    289   ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) {
    290     default_width_ = width;
    291     return *this;
    292   }
    293 
    294   ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) {
    295     default_height_ = height;
    296     return *this;
    297   }
    298 
    299   ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) {
    300     default_format_ = format;
    301     return *this;
    302   }
    303 
    304   template <typename Meta>
    305   ProducerQueueConfigBuilder& SetMetadata() {
    306     user_metadata_size_ = sizeof(Meta);
    307     return *this;
    308   }
    309 
    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