blob: 8e630ec72503848409bc02d3ff677530305f032d [file] [log] [blame]
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -07001#include <private/dvr/consumer_buffer.h>
2
3using android::pdx::LocalChannelHandle;
4using android::pdx::LocalHandle;
5using android::pdx::Status;
6
7namespace android {
8namespace dvr {
9
10ConsumerBuffer::ConsumerBuffer(LocalChannelHandle channel)
11 : BASE(std::move(channel)) {
12 const int ret = ImportBuffer();
13 if (ret < 0) {
14 ALOGE("ConsumerBuffer::ConsumerBuffer: Failed to import buffer: %s",
15 strerror(-ret));
16 Close(ret);
17 }
18}
19
20std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import(
21 LocalChannelHandle channel) {
22 ATRACE_NAME("ConsumerBuffer::Import");
23 ALOGD_IF(TRACE, "ConsumerBuffer::Import: channel=%d", channel.value());
24 return ConsumerBuffer::Create(std::move(channel));
25}
26
27std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import(
28 Status<LocalChannelHandle> status) {
29 return Import(status ? status.take()
30 : LocalChannelHandle{nullptr, -status.error()});
31}
32
33int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
34 LocalHandle* out_fence) {
35 if (!out_meta)
36 return -EINVAL;
37
38 // Only check producer bit and this consumer buffer's particular consumer bit.
39 // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
40 // is not set.
Tianyu Jiange2cdec92018-10-30 17:40:58 -070041 uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Tianyu Jiang7e204b72018-10-26 15:39:18 -070042 if (!BufferHubDefs::IsBufferPosted(buffer_state, client_state_mask())) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -070043 ALOGE("ConsumerBuffer::LocalAcquire: not posted, id=%d state=%" PRIx64
Tianyu Jiang7e204b72018-10-26 15:39:18 -070044 " client_state_mask=%" PRIx64 ".",
45 id(), buffer_state, client_state_mask());
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -070046 return -EBUSY;
47 }
48
49 // Copy the canonical metadata.
50 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
51 memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
52 // Fill in the user_metadata_ptr in address space of the local process.
53 if (out_meta->user_metadata_size) {
54 out_meta->user_metadata_ptr =
55 reinterpret_cast<uint64_t>(user_metadata_ptr_);
56 } else {
57 out_meta->user_metadata_ptr = 0;
58 }
59
Tianyu Jiange2cdec92018-10-30 17:40:58 -070060 uint64_t fence_state = fence_state_->load(std::memory_order_acquire);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -070061 // If there is an acquire fence from producer, we need to return it.
Tianyu Jiang63dd7c32018-10-30 18:35:06 -070062 // The producer state bit mask is kFirstClientBitMask for now.
63 if (fence_state & BufferHubDefs::kFirstClientBitMask) {
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -070064 *out_fence = shared_acquire_fence_.Duplicate();
65 }
66
67 // Set the consumer bit unique to this consumer.
Tianyu Jiang7e204b72018-10-26 15:39:18 -070068 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, client_state_mask());
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -070069 return 0;
70}
71
72int ConsumerBuffer::Acquire(LocalHandle* ready_fence) {
73 return Acquire(ready_fence, nullptr, 0);
74}
75
76int ConsumerBuffer::Acquire(LocalHandle* ready_fence, void* meta,
77 size_t user_metadata_size) {
78 ATRACE_NAME("ConsumerBuffer::Acquire");
79
80 if (const int error = CheckMetadata(user_metadata_size))
81 return error;
82
83 DvrNativeBufferMetadata canonical_meta;
84 if (const int error = LocalAcquire(&canonical_meta, ready_fence))
85 return error;
86
87 if (meta && user_metadata_size) {
88 void* metadata_src =
89 reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
90 if (metadata_src) {
91 memcpy(meta, metadata_src, user_metadata_size);
92 } else {
93 ALOGW("ConsumerBuffer::Acquire: no user-defined metadata.");
94 }
95 }
96
97 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
98 if (!status)
99 return -status.error();
100 return 0;
101}
102
103int ConsumerBuffer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
104 LocalHandle* out_fence) {
105 ATRACE_NAME("ConsumerBuffer::AcquireAsync");
106
107 if (const int error = LocalAcquire(out_meta, out_fence))
108 return error;
109
110 auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
111 if (!status)
112 return -status.error();
113 return 0;
114}
115
116int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta,
117 const LocalHandle& release_fence) {
118 if (const int error = CheckMetadata(meta->user_metadata_size))
119 return error;
120
121 // Check invalid state transition.
Tianyu Jiange2cdec92018-10-30 17:40:58 -0700122 uint64_t buffer_state = buffer_state_->load(std::memory_order_acquire);
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700123 if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
124 ALOGE("ConsumerBuffer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
125 id(), buffer_state);
126 return -EBUSY;
127 }
128
129 // On release, only the user requested metadata is copied back into the shared
130 // memory for metadata. Since there are multiple consumers, it doesn't make
131 // sense to send the canonical metadata back to the producer. However, one of
132 // the consumer can still choose to write up to user_metadata_size bytes of
133 // data into user_metadata_ptr.
134 if (meta->user_metadata_ptr && meta->user_metadata_size) {
135 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
136 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
137 }
138
139 // Send out the release fence through the shared epoll fd. Note that during
140 // releasing the producer is not expected to be polling on the fence.
141 if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
142 return error;
143
144 // For release operation, the client don't need to change the state as it's
145 // bufferhubd's job to flip the produer bit once all consumers are released.
146 return 0;
147}
148
149int ConsumerBuffer::Release(const LocalHandle& release_fence) {
150 ATRACE_NAME("ConsumerBuffer::Release");
151
152 DvrNativeBufferMetadata meta;
153 if (const int error = LocalRelease(&meta, release_fence))
154 return error;
155
156 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
157 BorrowedFence(release_fence.Borrow())));
158}
159
160int ConsumerBuffer::ReleaseAsync() {
161 DvrNativeBufferMetadata meta;
162 return ReleaseAsync(&meta, LocalHandle());
163}
164
165int ConsumerBuffer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
166 const LocalHandle& release_fence) {
167 ATRACE_NAME("ConsumerBuffer::ReleaseAsync");
168
169 if (const int error = LocalRelease(meta, release_fence))
170 return error;
171
172 return ReturnStatusOrError(
173 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
174}
175
176int ConsumerBuffer::Discard() { return Release(LocalHandle()); }
177
Jiwen 'Steve' Caic6fcf2f2018-09-27 23:34:45 -0700178} // namespace dvr
179} // namespace android