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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
      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::LocalHandle;
     16 using android::pdx::LocalChannelHandle;
     17 using android::pdx::rpc::WrapBuffer;
     18 using android::pdx::Status;
     19 
     20 namespace android {
     21 namespace dvr {
     22 
     23 BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
     24     : Client{pdx::default_transport::ClientChannel::Create(
     25           std::move(channel_handle))},
     26       id_(-1) {}
     27 BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
     28     : Client{pdx::default_transport::ClientChannelFactory::Create(
     29           endpoint_path)},
     30       id_(-1) {}
     31 
     32 BufferHubBuffer::~BufferHubBuffer() {}
     33 
     34 Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
     35   Status<LocalChannelHandle> status =
     36       InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
     37   ALOGE_IF(!status,
     38            "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
     39            status.GetErrorMessage().c_str());
     40   return status;
     41 }
     42 
     43 int BufferHubBuffer::ImportBuffer() {
     44   ATRACE_NAME("BufferHubBuffer::ImportBuffer");
     45 
     46   Status<NativeBufferHandle<LocalHandle>> status =
     47       InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
     48   if (!status) {
     49     ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
     50           status.GetErrorMessage().c_str());
     51     return -status.error();
     52   } else if (status.get().id() < 0) {
     53     ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
     54     return -EIO;
     55   }
     56 
     57   auto buffer_handle = status.take();
     58 
     59   // Stash the buffer id to replace the value in id_.
     60   const int new_id = buffer_handle.id();
     61 
     62   // Import the buffer.
     63   IonBuffer ion_buffer;
     64   ALOGD_IF(
     65       TRACE, "BufferHubBuffer::ImportBuffer: id=%d FdCount=%zu IntCount=%zu",
     66       buffer_handle.id(), buffer_handle.FdCount(), buffer_handle.IntCount());
     67 
     68   const int ret = buffer_handle.Import(&ion_buffer);
     69   if (ret < 0)
     70     return ret;
     71 
     72   // If the import succeeds, replace the previous buffer and id.
     73   buffer_ = std::move(ion_buffer);
     74   id_ = new_id;
     75   return 0;
     76 }
     77 
     78 int BufferHubBuffer::Poll(int timeout_ms) {
     79   ATRACE_NAME("BufferHubBuffer::Poll");
     80   pollfd p = {event_fd(), POLLIN, 0};
     81   return poll(&p, 1, timeout_ms);
     82 }
     83 
     84 int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
     85                           void** address) {
     86   return buffer_.Lock(usage, x, y, width, height, address);
     87 }
     88 
     89 int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
     90 
     91 int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
     92   int width = static_cast<int>(size);
     93   int height = 1;
     94   int ret = Lock(usage(), 0, 0, width, height, addr);
     95   if (ret == 0)
     96     Unlock();
     97   return ret;
     98 }
     99 
    100 int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
    101   return GetBlobReadWritePointer(size, addr);
    102 }
    103 
    104 void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
    105                                  size_t max_fds_count) const {
    106   size_t numFds = static_cast<size_t>(native_handle()->numFds);
    107   *fds_count = std::min(max_fds_count, numFds);
    108   std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
    109 }
    110 
    111 BufferConsumer::BufferConsumer(LocalChannelHandle channel)
    112     : BASE(std::move(channel)) {
    113   const int ret = ImportBuffer();
    114   if (ret < 0) {
    115     ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
    116           strerror(-ret));
    117     Close(ret);
    118   }
    119 }
    120 
    121 std::unique_ptr<BufferConsumer> BufferConsumer::Import(
    122     LocalChannelHandle channel) {
    123   ATRACE_NAME("BufferConsumer::Import");
    124   ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
    125   return BufferConsumer::Create(std::move(channel));
    126 }
    127 
    128 std::unique_ptr<BufferConsumer> BufferConsumer::Import(
    129     Status<LocalChannelHandle> status) {
    130   return Import(status ? status.take()
    131                        : LocalChannelHandle{nullptr, -status.error()});
    132 }
    133 
    134 int BufferConsumer::Acquire(LocalHandle* ready_fence) {
    135   return Acquire(ready_fence, nullptr, 0);
    136 }
    137 
    138 int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
    139                             size_t meta_size_bytes) {
    140   ATRACE_NAME("BufferConsumer::Acquire");
    141   LocalFence fence;
    142   auto return_value =
    143       std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes));
    144   auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>(
    145       &return_value, meta_size_bytes);
    146   if (status && ready_fence)
    147     *ready_fence = fence.take();
    148   return status ? 0 : -status.error();
    149 }
    150 
    151 int BufferConsumer::Release(const LocalHandle& release_fence) {
    152   ATRACE_NAME("BufferConsumer::Release");
    153   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
    154       BorrowedFence(release_fence.Borrow())));
    155 }
    156 
    157 int BufferConsumer::ReleaseAsync() {
    158   ATRACE_NAME("BufferConsumer::ReleaseAsync");
    159   return ReturnStatusOrError(
    160       SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
    161 }
    162 
    163 int BufferConsumer::Discard() { return Release(LocalHandle()); }
    164 
    165 int BufferConsumer::SetIgnore(bool ignore) {
    166   return ReturnStatusOrError(
    167       InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
    168 }
    169 
    170 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
    171                                uint32_t usage, size_t metadata_size)
    172     : BufferProducer(width, height, format, usage, usage, metadata_size) {}
    173 
    174 BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
    175                                uint64_t producer_usage, uint64_t consumer_usage,
    176                                size_t metadata_size)
    177     : BASE(BufferHubRPC::kClientPath) {
    178   ATRACE_NAME("BufferProducer::BufferProducer");
    179   ALOGD_IF(TRACE,
    180            "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
    181            "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
    182            " metadata_size=%zu",
    183            event_fd(), width, height, format, producer_usage, consumer_usage,
    184            metadata_size);
    185 
    186   // (b/37881101) Deprecate producer/consumer usage
    187   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
    188       width, height, format, (producer_usage | consumer_usage), metadata_size);
    189   if (!status) {
    190     ALOGE(
    191         "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
    192         status.GetErrorMessage().c_str());
    193     Close(-status.error());
    194     return;
    195   }
    196 
    197   const int ret = ImportBuffer();
    198   if (ret < 0) {
    199     ALOGE(
    200         "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
    201         strerror(-ret));
    202     Close(ret);
    203   }
    204 }
    205 
    206 BufferProducer::BufferProducer(const std::string& name, int user_id,
    207                                int group_id, uint32_t width, uint32_t height,
    208                                uint32_t format, uint32_t usage,
    209                                size_t meta_size_bytes)
    210     : BufferProducer(name, user_id, group_id, width, height, format, usage,
    211                      usage, meta_size_bytes) {}
    212 
    213 BufferProducer::BufferProducer(const std::string& name, int user_id,
    214                                int group_id, uint32_t width, uint32_t height,
    215                                uint32_t format, uint64_t producer_usage,
    216                                uint64_t consumer_usage, size_t meta_size_bytes)
    217     : BASE(BufferHubRPC::kClientPath) {
    218   ATRACE_NAME("BufferProducer::BufferProducer");
    219   ALOGD_IF(TRACE,
    220            "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
    221            "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
    222            " consumer_usage=%" PRIx64 " meta_size_bytes=%zu",
    223            event_fd(), name.c_str(), user_id, group_id, width, height, format,
    224            producer_usage, consumer_usage, meta_size_bytes);
    225 
    226   // (b/37881101) Deprecate producer/consumer usage
    227   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
    228       name, user_id, group_id, width, height, format,
    229       (producer_usage | consumer_usage), meta_size_bytes);
    230   if (!status) {
    231     ALOGE(
    232         "BufferProducer::BufferProducer: Failed to create/get persistent "
    233         "buffer \"%s\": %s",
    234         name.c_str(), status.GetErrorMessage().c_str());
    235     Close(-status.error());
    236     return;
    237   }
    238 
    239   const int ret = ImportBuffer();
    240   if (ret < 0) {
    241     ALOGE(
    242         "BufferProducer::BufferProducer: Failed to import producer buffer "
    243         "\"%s\": %s",
    244         name.c_str(), strerror(-ret));
    245     Close(ret);
    246   }
    247 }
    248 
    249 BufferProducer::BufferProducer(uint32_t usage, size_t size)
    250     : BufferProducer(usage, usage, size) {}
    251 
    252 BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
    253                                size_t size)
    254     : BASE(BufferHubRPC::kClientPath) {
    255   ATRACE_NAME("BufferProducer::BufferProducer");
    256   ALOGD_IF(TRACE,
    257            "BufferProducer::BufferProducer: producer_usage=%" PRIx64
    258            " consumer_usage=%" PRIx64 " size=%zu",
    259            producer_usage, consumer_usage, size);
    260   const int width = static_cast<int>(size);
    261   const int height = 1;
    262   const int format = HAL_PIXEL_FORMAT_BLOB;
    263   const size_t meta_size_bytes = 0;
    264 
    265   // (b/37881101) Deprecate producer/consumer usage
    266   auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
    267       width, height, format, (producer_usage | consumer_usage),
    268       meta_size_bytes);
    269   if (!status) {
    270     ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
    271           status.GetErrorMessage().c_str());
    272     Close(-status.error());
    273     return;
    274   }
    275 
    276   const int ret = ImportBuffer();
    277   if (ret < 0) {
    278     ALOGE(
    279         "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
    280         strerror(-ret));
    281     Close(ret);
    282   }
    283 }
    284 
    285 BufferProducer::BufferProducer(const std::string& name, int user_id,
    286                                int group_id, uint32_t usage, size_t size)
    287     : BufferProducer(name, user_id, group_id, usage, usage, size) {}
    288 
    289 BufferProducer::BufferProducer(const std::string& name, int user_id,
    290                                int group_id, uint64_t producer_usage,
    291                                uint64_t consumer_usage, size_t size)
    292     : BASE(BufferHubRPC::kClientPath) {
    293   ATRACE_NAME("BufferProducer::BufferProducer");
    294   ALOGD_IF(TRACE,
    295            "BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
    296            "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
    297            name.c_str(), user_id, group_id, producer_usage, consumer_usage,
    298            size);
    299   const int width = static_cast<int>(size);
    300   const int height = 1;
    301   const int format = HAL_PIXEL_FORMAT_BLOB;
    302   const size_t meta_size_bytes = 0;
    303 
    304   // (b/37881101) Deprecate producer/consumer usage
    305   auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
    306       name, user_id, group_id, width, height, format,
    307       (producer_usage | consumer_usage), meta_size_bytes);
    308   if (!status) {
    309     ALOGE(
    310         "BufferProducer::BufferProducer: Failed to create persistent "
    311         "buffer \"%s\": %s",
    312         name.c_str(), status.GetErrorMessage().c_str());
    313     Close(-status.error());
    314     return;
    315   }
    316 
    317   const int ret = ImportBuffer();
    318   if (ret < 0) {
    319     ALOGE(
    320         "BufferProducer::BufferProducer: Failed to import producer buffer "
    321         "\"%s\": %s",
    322         name.c_str(), strerror(-ret));
    323     Close(ret);
    324   }
    325 }
    326 
    327 BufferProducer::BufferProducer(const std::string& name)
    328     : BASE(BufferHubRPC::kClientPath) {
    329   ATRACE_NAME("BufferProducer::BufferProducer");
    330   ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str());
    331 
    332   auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name);
    333   if (!status) {
    334     ALOGE(
    335         "BufferProducer::BufferProducer: Failed to get producer buffer by name "
    336         "\"%s\": %s",
    337         name.c_str(), status.GetErrorMessage().c_str());
    338     Close(-status.error());
    339     return;
    340   }
    341 
    342   const int ret = ImportBuffer();
    343   if (ret < 0) {
    344     ALOGE(
    345         "BufferProducer::BufferProducer: Failed to import producer buffer "
    346         "\"%s\": %s",
    347         name.c_str(), strerror(-ret));
    348     Close(ret);
    349   }
    350 }
    351 
    352 BufferProducer::BufferProducer(LocalChannelHandle channel)
    353     : BASE(std::move(channel)) {
    354   const int ret = ImportBuffer();
    355   if (ret < 0) {
    356     ALOGE(
    357         "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
    358         strerror(-ret));
    359     Close(ret);
    360   }
    361 }
    362 
    363 int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
    364                          size_t meta_size_bytes) {
    365   ATRACE_NAME("BufferProducer::Post");
    366   return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
    367       BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes)));
    368 }
    369 
    370 int BufferProducer::Gain(LocalHandle* release_fence) {
    371   ATRACE_NAME("BufferProducer::Gain");
    372   auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
    373   if (!status)
    374     return -status.error();
    375   if (release_fence)
    376     *release_fence = status.take().take();
    377   return 0;
    378 }
    379 
    380 int BufferProducer::GainAsync() {
    381   ATRACE_NAME("BufferProducer::GainAsync");
    382   return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
    383 }
    384 
    385 std::unique_ptr<BufferProducer> BufferProducer::Import(
    386     LocalChannelHandle channel) {
    387   ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
    388   return BufferProducer::Create(std::move(channel));
    389 }
    390 
    391 std::unique_ptr<BufferProducer> BufferProducer::Import(
    392     Status<LocalChannelHandle> status) {
    393   return Import(status ? status.take()
    394                        : LocalChannelHandle{nullptr, -status.error()});
    395 }
    396 
    397 int BufferProducer::MakePersistent(const std::string& name, int user_id,
    398                                    int group_id) {
    399   ATRACE_NAME("BufferProducer::MakePersistent");
    400   return ReturnStatusOrError(
    401       InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id,
    402                                                                group_id));
    403 }
    404 
    405 int BufferProducer::RemovePersistence() {
    406   ATRACE_NAME("BufferProducer::RemovePersistence");
    407   return ReturnStatusOrError(
    408       InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>());
    409 }
    410 
    411 }  // namespace dvr
    412 }  // namespace android
    413