Home | History | Annotate | Download | only in libbufferhub
      1 #include <private/dvr/buffer_hub_client.h>
      2 
      3 #include <log/log.h>
      4 #include <poll.h>
      5 #include <sys/epoll.h>
      6 #include <utils/Trace.h>
      7 
      8 #include <mutex>
      9 
     10 #include <pdx/default_transport/client_channel.h>
     11 #include <pdx/default_transport/client_channel_factory.h>
     12 
     13 #include "include/private/dvr/bufferhub_rpc.h"
     14 
     15 using android::pdx::LocalChannelHandle;
     16 using android::pdx::LocalHandle;
     17 using android::pdx::Status;
     18 using android::pdx::default_transport::ClientChannel;
     19 using android::pdx::default_transport::ClientChannelFactory;
     20 
     21 namespace android {
     22 namespace dvr {
     23 
     24 BufferHubClient::BufferHubClient()
     25     : Client(ClientChannelFactory::Create(BufferHubRPC::kClientPath)) {}
     26 
     27 BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
     28     : Client(ClientChannel::Create(std::move(channel_handle))) {}
     29 
     30 bool BufferHubClient::IsValid() const {
     31   return IsConnected() && GetChannelHandle().valid();
     32 }
     33 
     34 LocalChannelHandle BufferHubClient::TakeChannelHandle() {
     35   if (IsConnected()) {
     36     return std::move(GetChannelHandle());
     37   } else {
     38     return {};
     39   }
     40 }
     41 
     42 BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
     43     : Client{pdx::default_transport::ClientChannel::Create(
     44           std::move(channel_handle))},
     45       id_(-1) {}
     46 BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
     47     : Client{pdx::default_transport::ClientChannelFactory::Create(
     48           endpoint_path)},
     49       id_(-1) {}
     50 
     51 BufferHubBuffer::~BufferHubBuffer() {
     52   if (metadata_header_ != nullptr) {
     53     metadata_buffer_.Unlock();
     54   }
     55 }
     56 
     57 Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
     58   Status<LocalChannelHandle> status =
     59       InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
     60   ALOGE_IF(!status,
     61            "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
     62            status.GetErrorMessage().c_str());
     63   return status;
     64 }
     65 
     66 int BufferHubBuffer::ImportBuffer() {
     67   ATRACE_NAME("BufferHubBuffer::ImportBuffer");
     68 
     69   Status<BufferDescription<LocalHandle>> status =
     70       InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
     71   if (!status) {
     72     ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
     73           status.GetErrorMessage().c_str());
     74     return -status.error();
     75   } else if (status.get().id() < 0) {
     76     ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
     77     return -EIO;
     78   }
     79 
     80   auto buffer_desc = status.take();
     81 
     82   // Stash the buffer id to replace the value in id_.
     83   const int new_id = buffer_desc.id();
     84 
     85   // Import the buffer.
     86   IonBuffer ion_buffer;
     87   ALOGD_IF(TRACE, "BufferHubBuffer::ImportBuffer: id=%d.", buffer_desc.id());
     88 
     89   if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
     90     return ret;
     91 
     92   // Import the metadata.
     93   IonBuffer metadata_buffer;
     94   if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
     95     ALOGE("Failed to import metadata buffer, error=%d", ret);
     96     return ret;
     97   }
     98   size_t metadata_buf_size = metadata_buffer.width();
     99   if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
    100     ALOGE("BufferHubBuffer::ImportBuffer: metadata buffer too small: %zu",
    101           metadata_buf_size);
    102     return -ENOMEM;
    103   }
    104 
    105   // If all imports succee, replace the previous buffer and id.
    106   buffer_ = std::move(ion_buffer);
    107   metadata_buffer_ = std::move(metadata_buffer);
    108   metadata_buf_size_ = metadata_buf_size;
    109   user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
    110 
    111   void* metadata_ptr = nullptr;
    112   if (const int ret =
    113           metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
    114                                 /*y=*/0, metadata_buf_size_,
    115                                 /*height=*/1, &metadata_ptr)) {
    116     ALOGE("BufferHubBuffer::ImportBuffer: Failed to lock metadata.");
    117     return ret;
    118   }
    119 
    120   // Set up shared fences.
    121   shared_acquire_fence_ = buffer_desc.take_acquire_fence();
    122   shared_release_fence_ = buffer_desc.take_release_fence();
    123   if (!shared_acquire_fence_ || !shared_release_fence_) {
    124     ALOGE("BufferHubBuffer::ImportBuffer: Failed to import shared fences.");
    125     return -EIO;
    126   }
    127 
    128   metadata_header_ =
    129       reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
    130   if (user_metadata_size_) {
    131     user_metadata_ptr_ =
    132         reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
    133                                 BufferHubDefs::kMetadataHeaderSize);
    134   } else {
    135     user_metadata_ptr_ = nullptr;
    136   }
    137 
    138   id_ = new_id;
    139   buffer_state_bit_ = buffer_desc.buffer_state_bit();
    140 
    141   // Note that here the buffer state is mapped from shared memory as an atomic
    142   // object. The std::atomic's constructor will not be called so that the
    143   // original value stored in the memory region will be preserved.
    144   buffer_state_ = &metadata_header_->buffer_state;
    145   ALOGD_IF(TRACE,
    146            "BufferHubBuffer::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
    147            id(), buffer_state_->load());
    148   fence_state_ = &metadata_header_->fence_state;
    149   ALOGD_IF(TRACE,
    150            "BufferHubBuffer::ImportBuffer: id=%d, fence_state=%" PRIx64 ".",
    151            id(), fence_state_->load());
    152 
    153   return 0;
    154 }
    155 
    156 inline int BufferHubBuffer::CheckMetadata(size_t user_metadata_size) const {
    157   if (user_metadata_size && !user_metadata_ptr_) {
    158     ALOGE("BufferHubBuffer::CheckMetadata: doesn't support custom metadata.");
    159     return -EINVAL;
    160   }
    161   if (user_metadata_size > user_metadata_size_) {
    162     ALOGE("BufferHubBuffer::CheckMetadata: too big: %zu, maximum: %zu.",
    163           user_metadata_size, user_metadata_size_);
    164     return -E2BIG;
    165   }
    166   return 0;
    167 }
    168 
    169 int BufferHubBuffer::UpdateSharedFence(const LocalHandle& new_fence,
    170                                        const LocalHandle& shared_fence) {
    171   if (pending_fence_fd_.Get() != new_fence.Get()) {
    172     // First, replace the old fd if there was already one. Skipping if the new
    173     // one is the same as the old.
    174     if (pending_fence_fd_.IsValid()) {
    175       const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
    176                                 pending_fence_fd_.Get(), nullptr);
    177       ALOGW_IF(ret,
    178                "BufferHubBuffer::UpdateSharedFence: failed to remove old fence "
    179                "fd from epoll set, error: %s.",
    180                strerror(errno));
    181     }
    182 
    183     if (new_fence.IsValid()) {
    184       // If ready fence is valid, we put that into the epoll set.
    185       epoll_event event;
    186       event.events = EPOLLIN;
    187       event.data.u64 = buffer_state_bit();
    188       pending_fence_fd_ = new_fence.Duplicate();
    189       if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
    190                     &event) < 0) {
    191         const int error = errno;
    192         ALOGE(
    193             "BufferHubBuffer::UpdateSharedFence: failed to add new fence fd "
    194             "into epoll set, error: %s.",
    195             strerror(error));
    196         return -error;
    197       }
    198       // Set bit in fence state to indicate that there is a fence from this
    199       // producer or consumer.
    200       fence_state_->fetch_or(buffer_state_bit());
    201     } else {
    202       // Unset bit in fence state to indicate that there is no fence, so that
    203       // when consumer to acquire or producer to acquire, it knows no need to
    204       // check fence for this buffer.
    205       fence_state_->fetch_and(~buffer_state_bit());
    206     }
    207   }
    208 
    209   return 0;
    210 }
    211 
    212 int BufferHubBuffer::Poll(int timeout_ms) {
    213   ATRACE_NAME("BufferHubBuffer::Poll");
    214   pollfd p = {event_fd(), POLLIN, 0};
    215   return poll(&p, 1, timeout_ms);
    216 }
    217 
    218 int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
    219                           void** address) {
    220   return buffer_.Lock(usage, x, y, width, height, address);
    221 }
    222 
    223 int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
    224 
    225 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
    226   int width = static_cast<int>(size);
    227   int height = 1;
    228   int ret = Lock(usage(), 0, 0, width, height, addr);
    229   if (ret == 0)
    230     Unlock();
    231   return ret;
    232 }
    233 
    234 int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
    235   return GetBlobReadWritePointer(size, addr);
    236 }
    237 
    238 void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
    239                                  size_t max_fds_count) const {
    240   size_t numFds = static_cast<size_t>(native_handle()->numFds);
    241   *fds_count = std::min(max_fds_count, numFds);
    242   std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
    243 }
    244 
    245 BufferConsumer::BufferConsumer(LocalChannelHandle channel)
    246     : BASE(std::move(channel)) {
    247   const int ret = ImportBuffer();
    248   if (ret < 0) {
    249     ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
    250           strerror(-ret));
    251     Close(ret);
    252   }
    253 }
    254 
    255 std::unique_ptr<BufferConsumer> BufferConsumer::Import(
    256     LocalChannelHandle channel) {
    257   ATRACE_NAME("BufferConsumer::Import");
    258   ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
    259   return BufferConsumer::Create(std::move(channel));
    260 }
    261 
    262 std::unique_ptr<BufferConsumer> BufferConsumer::Import(
    263     Status<LocalChannelHandle> status) {
    264   return Import(status ? status.take()
    265                        : LocalChannelHandle{nullptr, -status.error()});
    266 }
    267 
    268 int BufferConsumer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
    269                                  LocalHandle* out_fence) {
    270   if (!out_meta)
    271     return -EINVAL;
    272 
    273   // Only check producer bit and this consumer buffer's particular consumer bit.
    274   // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
    275   // is not set.
    276   uint64_t buffer_state = buffer_state_->load();
    277   if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
    278     ALOGE("BufferConsumer::LocalAcquire: not posted, id=%d state=%" PRIx64
    279           " buffer_state_bit=%" PRIx64 ".",
    280           id(), buffer_state, buffer_state_bit());
    281     return -EBUSY;
    282   }
    283 
    284   // Copy the canonical metadata.
    285   void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
    286   memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
    287   // Fill in the user_metadata_ptr in address space of the local process.
    288   if (out_meta->user_metadata_size) {
    289     out_meta->user_metadata_ptr =
    290         reinterpret_cast<uint64_t>(user_metadata_ptr_);
    291   } else {
    292     out_meta->user_metadata_ptr = 0;
    293   }
    294 
    295   uint64_t fence_state = fence_state_->load();
    296   // If there is an acquire fence from producer, we need to return it.
    297   if (fence_state & BufferHubDefs::kProducerStateBit) {
    298     *out_fence = shared_acquire_fence_.Duplicate();
    299   }
    300 
    301   // Set the consumer bit unique to this consumer.
    302   BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
    303   return 0;
    304 }
    305 
    306 int BufferConsumer::Acquire(LocalHandle* ready_fence) {
    307   return Acquire(ready_fence, nullptr, 0);
    308 }
    309 
    310 int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
    311                             size_t user_metadata_size) {
    312   ATRACE_NAME("BufferConsumer::Acquire");
    313 
    314   if (const int error = CheckMetadata(user_metadata_size))
    315     return error;
    316 
    317   DvrNativeBufferMetadata canonical_meta;
    318   if (const int error = LocalAcquire(&canonical_meta, ready_fence))
    319     return error;
    320 
    321   if (meta && user_metadata_size) {
    322     void* metadata_src =
    323         reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
    324     if (metadata_src) {
    325       memcpy(meta, metadata_src, user_metadata_size);
    326     } else {
    327       ALOGW("BufferConsumer::Acquire: no user-defined metadata.");
    328     }
    329   }
    330 
    331   auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
    332   if (!status)
    333     return -status.error();
    334   return 0;
    335 }
    336 
    337 int BufferConsumer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
    338                                  LocalHandle* out_fence) {
    339   ATRACE_NAME("BufferConsumer::AcquireAsync");
    340 
    341   if (const int error = LocalAcquire(out_meta, out_fence))
    342     return error;
    343 
    344   auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
    345   if (!status)
    346     return -status.error();
    347   return 0;
    348 }
    349 
    350 int BufferConsumer::LocalRelease(const DvrNativeBufferMetadata* meta,
    351                                  const LocalHandle& release_fence) {
    352   if (const int error = CheckMetadata(meta->user_metadata_size))
    353     return error;
    354 
    355   // Check invalid state transition.
    356   uint64_t buffer_state = buffer_state_->load();
    357   if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
    358     ALOGE("BufferConsumer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
    359           id(), buffer_state);
    360     return -EBUSY;
    361   }
    362 
    363   // On release, only the user requested metadata is copied back into the shared
    364   // memory for metadata. Since there are multiple consumers, it doesn't make
    365   // sense to send the canonical metadata back to the producer. However, one of
    366   // the consumer can still choose to write up to user_metadata_size bytes of
    367   // data into user_metadata_ptr.
    368   if (meta->user_metadata_ptr && meta->user_metadata_size) {
    369     void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
    370     memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
    371   }
    372 
    373   // Send out the release fence through the shared epoll fd. Note that during
    374   // releasing the producer is not expected to be polling on the fence.
    375   if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
    376     return error;
    377 
    378   // For release operation, the client don't need to change the state as it's
    379   // bufferhubd's job to flip the produer bit once all consumers are released.
    380   return 0;
    381 }
    382 
    383 int BufferConsumer::Release(const LocalHandle& release_fence) {
    384   ATRACE_NAME("BufferConsumer::Release");
    385 
    386   DvrNativeBufferMetadata meta;
    387   if (const int error = LocalRelease(&meta, release_fence))
    388     return error;
    389 
    390   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
    391       BorrowedFence(release_fence.Borrow())));
    392 }
    393 
    394 int BufferConsumer::ReleaseAsync() {
    395   DvrNativeBufferMetadata meta;
    396   return ReleaseAsync(&meta, LocalHandle());
    397 }
    398 
    399 int BufferConsumer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
    400                                  const LocalHandle& release_fence) {
    401   ATRACE_NAME("BufferConsumer::ReleaseAsync");
    402 
    403   if (const int error = LocalRelease(meta, release_fence))
    404     return error;
    405 
    406   return ReturnStatusOrError(
    407       SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
    408 }
    409 
    410 int BufferConsumer::Discard() { return Release(LocalHandle()); }
    411 
    412 int BufferConsumer::SetIgnore(bool ignore) {
    413   return ReturnStatusOrError(
    414       InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
    415 }
    416 
    417 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
    418                                uint64_t usage, size_t user_metadata_size)
    419     : BASE(BufferHubRPC::kClientPath) {
    420   ATRACE_NAME("BufferProducer::BufferProducer");
    421   ALOGD_IF(TRACE,
    422            "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
    423            "usage=%" PRIx64 " user_metadata_size=%zu",
    424            event_fd(), width, height, format, usage, user_metadata_size);
    425 
    426   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
    427       width, height, format, usage, user_metadata_size);
    428   if (!status) {
    429     ALOGE(
    430         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
    431         status.GetErrorMessage().c_str());
    432     Close(-status.error());
    433     return;
    434   }
    435 
    436   const int ret = ImportBuffer();
    437   if (ret < 0) {
    438     ALOGE(
    439         "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
    440         strerror(-ret));
    441     Close(ret);
    442   }
    443 }
    444 
    445 BufferProducer::BufferProducer(uint64_t usage, size_t size)
    446     : BASE(BufferHubRPC::kClientPath) {
    447   ATRACE_NAME("BufferProducer::BufferProducer");
    448   ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%" PRIx64 " size=%zu",
    449            usage, size);
    450   const int width = static_cast<int>(size);
    451   const int height = 1;
    452   const int format = HAL_PIXEL_FORMAT_BLOB;
    453   const size_t user_metadata_size = 0;
    454 
    455   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
    456       width, height, format, usage, user_metadata_size);
    457   if (!status) {
    458     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
    459           status.GetErrorMessage().c_str());
    460     Close(-status.error());
    461     return;
    462   }
    463 
    464   const int ret = ImportBuffer();
    465   if (ret < 0) {
    466     ALOGE(
    467         "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
    468         strerror(-ret));
    469     Close(ret);
    470   }
    471 }
    472 
    473 BufferProducer::BufferProducer(LocalChannelHandle channel)
    474     : BASE(std::move(channel)) {
    475   const int ret = ImportBuffer();
    476   if (ret < 0) {
    477     ALOGE(
    478         "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
    479         strerror(-ret));
    480     Close(ret);
    481   }
    482 }
    483 
    484 int BufferProducer::LocalPost(const DvrNativeBufferMetadata* meta,
    485                               const LocalHandle& ready_fence) {
    486   if (const int error = CheckMetadata(meta->user_metadata_size))
    487     return error;
    488 
    489   // Check invalid state transition.
    490   uint64_t buffer_state = buffer_state_->load();
    491   if (!BufferHubDefs::IsBufferGained(buffer_state)) {
    492     ALOGE("BufferProducer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
    493           id(), buffer_state);
    494     return -EBUSY;
    495   }
    496 
    497   // Copy the canonical metadata.
    498   void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
    499   memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
    500   // Copy extra user requested metadata.
    501   if (meta->user_metadata_ptr && meta->user_metadata_size) {
    502     void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
    503     memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
    504   }
    505 
    506   // Send out the acquire fence through the shared epoll fd. Note that during
    507   // posting no consumer is not expected to be polling on the fence.
    508   if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
    509     return error;
    510 
    511   // Set the producer bit atomically to transit into posted state.
    512   BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
    513                                    BufferHubDefs::kProducerStateBit);
    514   return 0;
    515 }
    516 
    517 int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
    518                          size_t user_metadata_size) {
    519   ATRACE_NAME("BufferProducer::Post");
    520 
    521   // Populate cononical metadata for posting.
    522   DvrNativeBufferMetadata canonical_meta;
    523   canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
    524   canonical_meta.user_metadata_size = user_metadata_size;
    525 
    526   if (const int error = LocalPost(&canonical_meta, ready_fence))
    527     return error;
    528 
    529   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
    530       BorrowedFence(ready_fence.Borrow())));
    531 }
    532 
    533 int BufferProducer::PostAsync(const DvrNativeBufferMetadata* meta,
    534                               const LocalHandle& ready_fence) {
    535   ATRACE_NAME("BufferProducer::PostAsync");
    536 
    537   if (const int error = LocalPost(meta, ready_fence))
    538     return error;
    539 
    540   return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
    541 }
    542 
    543 int BufferProducer::LocalGain(DvrNativeBufferMetadata* out_meta,
    544                               LocalHandle* out_fence) {
    545   uint64_t buffer_state = buffer_state_->load();
    546   ALOGD_IF(TRACE, "BufferProducer::LocalGain: buffer=%d, state=%" PRIx64 ".",
    547            id(), buffer_state);
    548 
    549   if (!out_meta)
    550     return -EINVAL;
    551 
    552   if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
    553     if (BufferHubDefs::IsBufferGained(buffer_state)) {
    554       // We don't want to log error when gaining a newly allocated
    555       // buffer.
    556       ALOGI("BufferProducer::LocalGain: already gained id=%d.", id());
    557       return -EALREADY;
    558     }
    559     ALOGE("BufferProducer::LocalGain: not released id=%d state=%" PRIx64 ".",
    560           id(), buffer_state);
    561     return -EBUSY;
    562   }
    563 
    564   // Canonical metadata is undefined on Gain. Except for user_metadata and
    565   // release_fence_mask. Fill in the user_metadata_ptr in address space of the
    566   // local process.
    567   if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
    568     out_meta->user_metadata_size =
    569         metadata_header_->metadata.user_metadata_size;
    570     out_meta->user_metadata_ptr =
    571         reinterpret_cast<uint64_t>(user_metadata_ptr_);
    572   } else {
    573     out_meta->user_metadata_size = 0;
    574     out_meta->user_metadata_ptr = 0;
    575   }
    576 
    577   uint64_t fence_state = fence_state_->load();
    578   // If there is an release fence from consumer, we need to return it.
    579   if (fence_state & BufferHubDefs::kConsumerStateMask) {
    580     *out_fence = shared_release_fence_.Duplicate();
    581     out_meta->release_fence_mask =
    582         fence_state & BufferHubDefs::kConsumerStateMask;
    583   }
    584 
    585   // Clear out all bits and the buffer is now back to gained state.
    586   buffer_state_->store(0ULL);
    587   return 0;
    588 }
    589 
    590 int BufferProducer::Gain(LocalHandle* release_fence) {
    591   ATRACE_NAME("BufferProducer::Gain");
    592 
    593   DvrNativeBufferMetadata meta;
    594   if (const int error = LocalGain(&meta, release_fence))
    595     return error;
    596 
    597   auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
    598   if (!status)
    599     return -status.error();
    600   return 0;
    601 }
    602 
    603 int BufferProducer::GainAsync(DvrNativeBufferMetadata* out_meta,
    604                               LocalHandle* release_fence) {
    605   ATRACE_NAME("BufferProducer::GainAsync");
    606 
    607   if (const int error = LocalGain(out_meta, release_fence))
    608     return error;
    609 
    610   return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
    611 }
    612 
    613 int BufferProducer::GainAsync() {
    614   DvrNativeBufferMetadata meta;
    615   LocalHandle fence;
    616   return GainAsync(&meta, &fence);
    617 }
    618 
    619 std::unique_ptr<BufferProducer> BufferProducer::Import(
    620     LocalChannelHandle channel) {
    621   ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
    622   return BufferProducer::Create(std::move(channel));
    623 }
    624 
    625 std::unique_ptr<BufferProducer> BufferProducer::Import(
    626     Status<LocalChannelHandle> status) {
    627   return Import(status ? status.take()
    628                        : LocalChannelHandle{nullptr, -status.error()});
    629 }
    630 
    631 Status<LocalChannelHandle> BufferProducer::Detach() {
    632   uint64_t buffer_state = buffer_state_->load();
    633   if (!BufferHubDefs::IsBufferGained(buffer_state)) {
    634     // Can only detach a BufferProducer when it's in gained state.
    635     ALOGW("BufferProducer::Detach: The buffer (id=%d, state=0x%" PRIx64
    636           ") is not in gained state.",
    637           id(), buffer_state);
    638     return {};
    639   }
    640 
    641   Status<LocalChannelHandle> status =
    642       InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
    643   ALOGE_IF(!status,
    644            "BufferProducer::Detach: Failed to detach buffer (id=%d): %s.", id(),
    645            status.GetErrorMessage().c_str());
    646   return status;
    647 }
    648 
    649 }  // namespace dvr
    650 }  // namespace android
    651