Home | History | Annotate | Download | only in libbufferhub
      1 #include <private/dvr/detached_buffer.h>
      2 
      3 #include <pdx/file_handle.h>
      4 #include <ui/DetachedBufferHandle.h>
      5 
      6 #include <poll.h>
      7 
      8 using android::pdx::LocalChannelHandle;
      9 using android::pdx::LocalHandle;
     10 using android::pdx::Status;
     11 
     12 namespace android {
     13 namespace dvr {
     14 
     15 DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height,
     16                                uint32_t layer_count, uint32_t format,
     17                                uint64_t usage, size_t user_metadata_size) {
     18   ATRACE_NAME("DetachedBuffer::DetachedBuffer");
     19   ALOGD_IF(TRACE,
     20            "DetachedBuffer::DetachedBuffer: width=%u height=%u layer_count=%u, "
     21            "format=%u usage=%" PRIx64 " user_metadata_size=%zu",
     22            width, height, layer_count, format, usage, user_metadata_size);
     23 
     24   auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Create>(
     25       width, height, layer_count, format, usage, user_metadata_size);
     26   if (!status) {
     27     ALOGE(
     28         "DetachedBuffer::DetachedBuffer: Failed to create detached buffer: %s",
     29         status.GetErrorMessage().c_str());
     30     client_.Close(-status.error());
     31   }
     32 
     33   const int ret = ImportGraphicBuffer();
     34   if (ret < 0) {
     35     ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
     36           strerror(-ret));
     37     client_.Close(ret);
     38   }
     39 }
     40 
     41 DetachedBuffer::DetachedBuffer(LocalChannelHandle channel_handle)
     42     : client_(std::move(channel_handle)) {
     43   const int ret = ImportGraphicBuffer();
     44   if (ret < 0) {
     45     ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
     46           strerror(-ret));
     47     client_.Close(ret);
     48   }
     49 }
     50 
     51 int DetachedBuffer::ImportGraphicBuffer() {
     52   ATRACE_NAME("DetachedBuffer::DetachedBuffer");
     53 
     54   auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
     55   if (!status) {
     56     ALOGE("DetachedBuffer::DetachedBuffer: Failed to import GraphicBuffer: %s",
     57           status.GetErrorMessage().c_str());
     58     return -status.error();
     59   }
     60 
     61   BufferDescription<LocalHandle> buffer_desc = status.take();
     62   if (buffer_desc.id() < 0) {
     63     ALOGE("DetachedBuffer::DetachedBuffer: Received an invalid id!");
     64     return -EIO;
     65   }
     66 
     67   // Stash the buffer id to replace the value in id_.
     68   const int buffer_id = buffer_desc.id();
     69 
     70   // Import the buffer.
     71   IonBuffer ion_buffer;
     72   ALOGD_IF(TRACE, "DetachedBuffer::DetachedBuffer: id=%d.", buffer_id);
     73 
     74   if (const int ret = buffer_desc.ImportBuffer(&ion_buffer)) {
     75     ALOGE("Failed to import GraphicBuffer, error=%d", ret);
     76     return ret;
     77   }
     78 
     79   // If all imports succeed, replace the previous buffer and id.
     80   id_ = buffer_id;
     81   buffer_ = std::move(ion_buffer);
     82   return 0;
     83 }
     84 
     85 int DetachedBuffer::Poll(int timeout_ms) {
     86   ATRACE_NAME("DetachedBuffer::Poll");
     87   pollfd p = {client_.event_fd(), POLLIN, 0};
     88   return poll(&p, 1, timeout_ms);
     89 }
     90 
     91 Status<LocalChannelHandle> DetachedBuffer::Promote() {
     92   ATRACE_NAME("DetachedBuffer::Promote");
     93   ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);
     94 
     95   auto status_or_handle =
     96       client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
     97   if (status_or_handle.ok()) {
     98     // Invalidate the buffer.
     99     buffer_ = {};
    100   } else {
    101     ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
    102           status_or_handle.GetErrorMessage().c_str());
    103   }
    104   return status_or_handle;
    105 }
    106 
    107 sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() {
    108   if (!client_.IsValid() || !buffer_.buffer()) {
    109     ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer.");
    110     return nullptr;
    111   }
    112 
    113   // Technically this should never happen.
    114   LOG_FATAL_IF(
    115       buffer_.buffer()->isDetachedBuffer(),
    116       "DetachedBuffer::TakeGraphicBuffer: GraphicBuffer is already detached.");
    117 
    118   sp<GraphicBuffer> buffer = std::move(buffer_.buffer());
    119   buffer->setDetachedBufferHandle(
    120       DetachedBufferHandle::Create(client_.TakeChannelHandle()));
    121   return buffer;
    122 }
    123 
    124 }  // namespace dvr
    125 }  // namespace android
    126