1#include "acquired_buffer.h"
2
3#include <log/log.h>
4#include <sync/sync.h>
5
6using android::pdx::LocalHandle;
7
8namespace android {
9namespace dvr {
10
11AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
12                               LocalHandle acquire_fence)
13    : buffer_(buffer), acquire_fence_(std::move(acquire_fence)) {}
14
15AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
16                               int* error) {
17  LocalHandle fence;
18  const int ret = buffer->Acquire(&fence);
19
20  if (error)
21    *error = ret;
22
23  if (ret < 0) {
24    ALOGW("AcquiredBuffer::AcquiredBuffer: Failed to acquire buffer: %s",
25          strerror(-ret));
26    buffer_ = nullptr;
27    // Default construct sets acquire_fence_ to empty.
28  } else {
29    buffer_ = buffer;
30    acquire_fence_ = std::move(fence);
31  }
32}
33
34AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other)
35    : buffer_(std::move(other.buffer_)),
36      acquire_fence_(std::move(other.acquire_fence_)) {}
37
38AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
39
40AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
41  if (this != &other) {
42    Release(LocalHandle(kEmptyFence));
43
44    buffer_ = std::move(other.buffer_);
45    acquire_fence_ = std::move(other.acquire_fence_);
46  }
47  return *this;
48}
49
50bool AcquiredBuffer::IsAvailable() const {
51  if (IsEmpty())
52    return false;
53
54  // Only check the fence if the acquire fence is not empty.
55  if (acquire_fence_) {
56    const int ret = sync_wait(acquire_fence_.Get(), 0);
57    ALOGD_IF(TRACE || (ret < 0 && errno != ETIME),
58             "AcquiredBuffer::IsAvailable: acquire_fence_=%d sync_wait()=%d "
59             "errno=%d.",
60             acquire_fence_.Get(), ret, ret < 0 ? errno : 0);
61    if (ret == 0) {
62      // The fence is completed, so to avoid further calls to sync_wait we close
63      // it here.
64      acquire_fence_.Close();
65    }
66    return ret == 0;
67  } else {
68    return true;
69  }
70}
71
72LocalHandle AcquiredBuffer::ClaimAcquireFence() {
73  return std::move(acquire_fence_);
74}
75
76std::shared_ptr<BufferConsumer> AcquiredBuffer::ClaimBuffer() {
77  return std::move(buffer_);
78}
79
80int AcquiredBuffer::Release(LocalHandle release_fence) {
81  if (buffer_) {
82    // Close the release fence since we can't transfer it with an async release.
83    release_fence.Close();
84    const int ret = buffer_->ReleaseAsync();
85    if (ret < 0) {
86      ALOGE("AcquiredBuffer::Release: Failed to release buffer %d: %s",
87            buffer_->id(), strerror(-ret));
88      if (ret != -ESHUTDOWN)
89        return ret;
90    }
91
92    buffer_ = nullptr;
93    acquire_fence_.Close();
94  }
95
96  return 0;
97}
98
99}  // namespace dvr
100}  // namespace android
101