blob: 4e8c36b5535a15a98dd3a1f39e29ec3f793d38fe [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.
41 uint64_t buffer_state = buffer_state_->load();
42 if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
43 ALOGE("ConsumerBuffer::LocalAcquire: not posted, id=%d state=%" PRIx64
44 " buffer_state_bit=%" PRIx64 ".",
45 id(), buffer_state, buffer_state_bit());
46 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
60 uint64_t fence_state = fence_state_->load();
61 // If there is an acquire fence from producer, we need to return it.
62 if (fence_state & BufferHubDefs::kProducerStateBit) {
63 *out_fence = shared_acquire_fence_.Duplicate();
64 }
65
66 // Set the consumer bit unique to this consumer.
67 BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
68 return 0;
69}
70
71int ConsumerBuffer::Acquire(LocalHandle* ready_fence) {
72 return Acquire(ready_fence, nullptr, 0);
73}
74
75int ConsumerBuffer::Acquire(LocalHandle* ready_fence, void* meta,
76 size_t user_metadata_size) {
77 ATRACE_NAME("ConsumerBuffer::Acquire");
78
79 if (const int error = CheckMetadata(user_metadata_size))
80 return error;
81
82 DvrNativeBufferMetadata canonical_meta;
83 if (const int error = LocalAcquire(&canonical_meta, ready_fence))
84 return error;
85
86 if (meta && user_metadata_size) {
87 void* metadata_src =
88 reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
89 if (metadata_src) {
90 memcpy(meta, metadata_src, user_metadata_size);
91 } else {
92 ALOGW("ConsumerBuffer::Acquire: no user-defined metadata.");
93 }
94 }
95
96 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
97 if (!status)
98 return -status.error();
99 return 0;
100}
101
102int ConsumerBuffer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
103 LocalHandle* out_fence) {
104 ATRACE_NAME("ConsumerBuffer::AcquireAsync");
105
106 if (const int error = LocalAcquire(out_meta, out_fence))
107 return error;
108
109 auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
110 if (!status)
111 return -status.error();
112 return 0;
113}
114
115int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta,
116 const LocalHandle& release_fence) {
117 if (const int error = CheckMetadata(meta->user_metadata_size))
118 return error;
119
120 // Check invalid state transition.
121 uint64_t buffer_state = buffer_state_->load();
122 if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
123 ALOGE("ConsumerBuffer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
124 id(), buffer_state);
125 return -EBUSY;
126 }
127
128 // On release, only the user requested metadata is copied back into the shared
129 // memory for metadata. Since there are multiple consumers, it doesn't make
130 // sense to send the canonical metadata back to the producer. However, one of
131 // the consumer can still choose to write up to user_metadata_size bytes of
132 // data into user_metadata_ptr.
133 if (meta->user_metadata_ptr && meta->user_metadata_size) {
134 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
135 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
136 }
137
138 // Send out the release fence through the shared epoll fd. Note that during
139 // releasing the producer is not expected to be polling on the fence.
140 if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
141 return error;
142
143 // For release operation, the client don't need to change the state as it's
144 // bufferhubd's job to flip the produer bit once all consumers are released.
145 return 0;
146}
147
148int ConsumerBuffer::Release(const LocalHandle& release_fence) {
149 ATRACE_NAME("ConsumerBuffer::Release");
150
151 DvrNativeBufferMetadata meta;
152 if (const int error = LocalRelease(&meta, release_fence))
153 return error;
154
155 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
156 BorrowedFence(release_fence.Borrow())));
157}
158
159int ConsumerBuffer::ReleaseAsync() {
160 DvrNativeBufferMetadata meta;
161 return ReleaseAsync(&meta, LocalHandle());
162}
163
164int ConsumerBuffer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
165 const LocalHandle& release_fence) {
166 ATRACE_NAME("ConsumerBuffer::ReleaseAsync");
167
168 if (const int error = LocalRelease(meta, release_fence))
169 return error;
170
171 return ReturnStatusOrError(
172 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
173}
174
175int ConsumerBuffer::Discard() { return Release(LocalHandle()); }
176
177int ConsumerBuffer::SetIgnore(bool ignore) {
178 return ReturnStatusOrError(
179 InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
180}
181
182} // namespace dvr
183} // namespace android