1 #include "acquired_buffer.h"
2 
3 #include <log/log.h>
4 #include <sync/sync.h>
5 
6 using android::pdx::LocalHandle;
7 
8 namespace android {
9 namespace dvr {
10 
AcquiredBuffer(const std::shared_ptr<ConsumerBuffer> & buffer,LocalHandle acquire_fence,std::size_t slot)11 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
12                                LocalHandle acquire_fence, std::size_t slot)
13     : buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {}
14 
AcquiredBuffer(const std::shared_ptr<ConsumerBuffer> & buffer,int * error)15 AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& 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 
AcquiredBuffer(AcquiredBuffer && other)34 AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) noexcept {
35   *this = std::move(other);
36 }
37 
~AcquiredBuffer()38 AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
39 
operator =(AcquiredBuffer && other)40 AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) noexcept {
41   if (this != &other) {
42     Release();
43 
44     using std::swap;
45     swap(buffer_, other.buffer_);
46     swap(acquire_fence_, other.acquire_fence_);
47     swap(slot_, other.slot_);
48   }
49   return *this;
50 }
51 
IsAvailable() const52 bool AcquiredBuffer::IsAvailable() const {
53   if (IsEmpty())
54     return false;
55 
56   // Only check the fence if the acquire fence is not empty.
57   if (acquire_fence_) {
58     const int ret = sync_wait(acquire_fence_.Get(), 0);
59     ALOGD_IF(TRACE || (ret < 0 && errno != ETIME),
60              "AcquiredBuffer::IsAvailable: buffer_id=%d acquire_fence=%d "
61              "sync_wait()=%d errno=%d.",
62              buffer_->id(), acquire_fence_.Get(), ret, ret < 0 ? errno : 0);
63     if (ret == 0) {
64       // The fence is completed, so to avoid further calls to sync_wait we close
65       // it here.
66       acquire_fence_.Close();
67     }
68     return ret == 0;
69   } else {
70     return true;
71   }
72 }
73 
ClaimAcquireFence()74 LocalHandle AcquiredBuffer::ClaimAcquireFence() {
75   return std::move(acquire_fence_);
76 }
77 
ClaimBuffer()78 std::shared_ptr<ConsumerBuffer> AcquiredBuffer::ClaimBuffer() {
79   return std::move(buffer_);
80 }
81 
Release(LocalHandle release_fence)82 int AcquiredBuffer::Release(LocalHandle release_fence) {
83   ALOGD_IF(TRACE, "AcquiredBuffer::Release: buffer_id=%d release_fence=%d",
84            buffer_ ? buffer_->id() : -1, release_fence.Get());
85   if (buffer_) {
86     const int ret = buffer_->ReleaseAsync();
87     if (ret < 0) {
88       ALOGE("AcquiredBuffer::Release: Failed to release buffer %d: %s",
89             buffer_->id(), strerror(-ret));
90       if (ret != -ESHUTDOWN)
91         return ret;
92     }
93 
94     buffer_ = nullptr;
95   }
96 
97   acquire_fence_.Close();
98   slot_ = 0;
99   return 0;
100 }
101 
102 }  // namespace dvr
103 }  // namespace android
104