Home | History | Annotate | Download | only in bufferhubd
      1 #include "detached_buffer_channel.h"
      2 #include "producer_channel.h"
      3 
      4 using android::pdx::BorrowedHandle;
      5 using android::pdx::ErrorStatus;
      6 using android::pdx::Message;
      7 using android::pdx::RemoteChannelHandle;
      8 using android::pdx::Status;
      9 using android::pdx::rpc::DispatchRemoteMethod;
     10 
     11 namespace android {
     12 namespace dvr {
     13 
     14 DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service,
     15                                              int buffer_id, int channel_id,
     16                                              IonBuffer buffer,
     17                                              IonBuffer metadata_buffer,
     18                                              size_t user_metadata_size)
     19     : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
     20       buffer_(std::move(buffer)),
     21       metadata_buffer_(std::move(metadata_buffer)),
     22       user_metadata_size_(user_metadata_size) {
     23 }
     24 
     25 DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service,
     26                                              int buffer_id, uint32_t width,
     27                                              uint32_t height,
     28                                              uint32_t layer_count,
     29                                              uint32_t format, uint64_t usage,
     30                                              size_t user_metadata_size)
     31     : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType),
     32       user_metadata_size_(user_metadata_size) {
     33   // The size the of metadata buffer is used as the "width" parameter during
     34   // allocation. Thus it cannot overflow uint32_t.
     35   if (user_metadata_size_ >= (std::numeric_limits<uint32_t>::max() -
     36                               BufferHubDefs::kMetadataHeaderSize)) {
     37     ALOGE(
     38         "DetachedBufferChannel::DetachedBufferChannel: metadata size too big.");
     39     return;
     40   }
     41 
     42   if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
     43     ALOGE(
     44         "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
     45         "buffer: %s",
     46         strerror(-ret));
     47     return;
     48   }
     49 
     50   // Buffer metadata has two parts: 1) a fixed sized metadata header; and 2)
     51   // user requested metadata.
     52   const size_t size = BufferHubDefs::kMetadataHeaderSize + user_metadata_size_;
     53   if (int ret = metadata_buffer_.Alloc(size,
     54                                        /*height=*/1,
     55                                        /*layer_count=*/1,
     56                                        BufferHubDefs::kMetadataFormat,
     57                                        BufferHubDefs::kMetadataUsage)) {
     58     ALOGE(
     59         "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
     60         "metadata: %s",
     61         strerror(-ret));
     62     return;
     63   }
     64 }
     65 
     66 DetachedBufferChannel::~DetachedBufferChannel() {
     67   ALOGD_IF(TRACE,
     68            "DetachedBufferChannel::~DetachedBufferChannel: channel_id=%d "
     69            "buffer_id=%d.",
     70            channel_id(), buffer_id());
     71   Hangup();
     72 }
     73 
     74 BufferHubChannel::BufferInfo DetachedBufferChannel::GetBufferInfo() const {
     75   return BufferInfo(buffer_id(), /*consumer_count=*/0, buffer_.width(),
     76                     buffer_.height(), buffer_.layer_count(), buffer_.format(),
     77                     buffer_.usage(), /*pending_count=*/0, /*state=*/0,
     78                     /*signaled_mask=*/0, /*index=*/0);
     79 }
     80 
     81 void DetachedBufferChannel::HandleImpulse(Message& /*message*/) {
     82   ATRACE_NAME("DetachedBufferChannel::HandleImpulse");
     83 }
     84 
     85 bool DetachedBufferChannel::HandleMessage(Message& message) {
     86   ATRACE_NAME("DetachedBufferChannel::HandleMessage");
     87   switch (message.GetOp()) {
     88     case DetachedBufferRPC::Import::Opcode:
     89       DispatchRemoteMethod<DetachedBufferRPC::Import>(
     90           *this, &DetachedBufferChannel::OnImport, message);
     91       return true;
     92 
     93     case DetachedBufferRPC::Promote::Opcode:
     94       DispatchRemoteMethod<DetachedBufferRPC::Promote>(
     95           *this, &DetachedBufferChannel::OnPromote, message);
     96       return true;
     97 
     98     default:
     99       return false;
    100   }
    101 }
    102 
    103 Status<BufferDescription<BorrowedHandle>> DetachedBufferChannel::OnImport(
    104     Message& /*message*/) {
    105   ATRACE_NAME("DetachedBufferChannel::OnGetBuffer");
    106   ALOGD_IF(TRACE, "DetachedBufferChannel::OnGetBuffer: buffer=%d.",
    107            buffer_id());
    108 
    109   return BufferDescription<BorrowedHandle>{buffer_,
    110                                            metadata_buffer_,
    111                                            buffer_id(),
    112                                            /*buffer_state_bit=*/0,
    113                                            BorrowedHandle{},
    114                                            BorrowedHandle{}};
    115 }
    116 
    117 Status<RemoteChannelHandle> DetachedBufferChannel::OnPromote(
    118     Message& message) {
    119   ATRACE_NAME("DetachedBufferChannel::OnPromote");
    120   ALOGD_IF(TRACE, "DetachedBufferChannel::OnPromote: buffer_id=%d",
    121            buffer_id());
    122 
    123   // Note that the new ProducerChannel will have different channel_id, but
    124   // inherits the buffer_id from the DetachedBuffer.
    125   int channel_id;
    126   auto status = message.PushChannel(0, nullptr, &channel_id);
    127   if (!status) {
    128     ALOGE(
    129         "DetachedBufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
    130         status.GetErrorMessage().c_str());
    131     return ErrorStatus(ENOMEM);
    132   }
    133 
    134   std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
    135       service(), buffer_id(), channel_id, std::move(buffer_),
    136       std::move(metadata_buffer_), user_metadata_size_);
    137   if (!channel) {
    138     ALOGE(
    139         "DetachedBufferChannel::OnPromote: Failed to create ProducerChannel "
    140         "from a DetachedBufferChannel, buffer_id=%d.",
    141         buffer_id());
    142   }
    143 
    144   const auto channel_status =
    145       service()->SetChannel(channel_id, std::move(channel));
    146   if (!channel_status) {
    147     // Technically, this should never fail, as we just pushed the channel. Note
    148     // that LOG_FATAL will be stripped out in non-debug build.
    149     LOG_FATAL(
    150         "DetachedBufferChannel::OnPromote: Failed to set new producer buffer "
    151         "channel: %s.",
    152         channel_status.GetErrorMessage().c_str());
    153   }
    154 
    155   return status;
    156 }
    157 
    158 }  // namespace dvr
    159 }  // namespace android
    160