blob: 1a7c2d38262126c1b817ab6404c8cae780aa3438 [file] [log] [blame]
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -08001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070017#include <dvr/dvr_api.h>
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -080018#include <gui/BufferHubProducer.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -080019#include <inttypes.h>
20#include <log/log.h>
Mathias Agopian6a3c05b2017-04-27 20:06:55 -070021#include <system/window.h>
Jiwen 'Steve' Cai8f51ec62018-08-07 21:50:51 -070022#include <ui/BufferHubBuffer.h>
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -070023#include <ui/DetachedBufferHandle.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -080024
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080025namespace android {
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080026
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -080027using namespace dvr;
28
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070029/* static */
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -080030sp<BufferHubProducer> BufferHubProducer::Create(const std::shared_ptr<ProducerQueue>& queue) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080031 sp<BufferHubProducer> producer = new BufferHubProducer;
32 producer->queue_ = queue;
33 return producer;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -070034}
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080035
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080036/* static */
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -080037sp<BufferHubProducer> BufferHubProducer::Create(ProducerQueueParcelable parcelable) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080038 if (!parcelable.IsValid()) {
39 ALOGE("BufferHubProducer::Create: Invalid producer parcelable.");
40 return nullptr;
41 }
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080042
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080043 sp<BufferHubProducer> producer = new BufferHubProducer;
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -080044 producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080045 return producer;
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -080046}
47
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -080048status_t BufferHubProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080049 ALOGV("requestBuffer: slot=%d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080050
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080051 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080052
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080053 if (connected_api_ == kNoConnectedApi) {
54 ALOGE("requestBuffer: BufferHubProducer has no connected producer");
55 return NO_INIT;
56 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070057
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080058 if (slot < 0 || slot >= max_buffer_count_) {
59 ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
60 return BAD_VALUE;
61 } else if (!buffers_[slot].mBufferState.isDequeued()) {
62 ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)", slot,
63 buffers_[slot].mBufferState.string());
64 return BAD_VALUE;
65 } else if (buffers_[slot].mGraphicBuffer != nullptr) {
66 ALOGE("requestBuffer: slot %d is not empty.", slot);
67 return BAD_VALUE;
68 } else if (buffers_[slot].mBufferProducer == nullptr) {
69 ALOGE("requestBuffer: slot %d is not dequeued.", slot);
70 return BAD_VALUE;
71 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080072
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080073 const auto& buffer_producer = buffers_[slot].mBufferProducer;
74 sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070075
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080076 buffers_[slot].mGraphicBuffer = graphic_buffer;
77 buffers_[slot].mRequestBufferCalled = true;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070078
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080079 *buf = graphic_buffer;
80 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080081}
82
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080083status_t BufferHubProducer::setMaxDequeuedBufferCount(int max_dequeued_buffers) {
84 ALOGV("setMaxDequeuedBufferCount: max_dequeued_buffers=%d", max_dequeued_buffers);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080085
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080086 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080087
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080088 if (max_dequeued_buffers <= 0 ||
89 max_dequeued_buffers >
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -080090 int(BufferHubQueue::kMaxQueueCapacity - kDefaultUndequeuedBuffers)) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080091 ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]", max_dequeued_buffers,
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -080092 BufferHubQueue::kMaxQueueCapacity);
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080093 return BAD_VALUE;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070094 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -070095
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -080096 // The new dequeued_buffers count should not be violated by the number
97 // of currently dequeued buffers.
98 int dequeued_count = 0;
99 for (const auto& buf : buffers_) {
100 if (buf.mBufferState.isDequeued()) {
101 dequeued_count++;
102 }
103 }
104 if (dequeued_count > max_dequeued_buffers) {
105 ALOGE("setMaxDequeuedBufferCount: the requested dequeued_buffers"
106 "count (%d) exceeds the current dequeued buffer count (%d)",
107 max_dequeued_buffers, dequeued_count);
108 return BAD_VALUE;
109 }
110
111 max_dequeued_buffer_count_ = max_dequeued_buffers;
112 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800113}
114
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800115status_t BufferHubProducer::setAsyncMode(bool async) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800116 if (async) {
117 // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
118 // automatically and behaves differently from IGraphicBufferConsumer. Thus,
119 // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
120 // to prevent dequeueBuffer from being blocking) technically does not apply
121 // here.
122 //
123 // In Daydream, non-blocking producer side dequeue is guaranteed by careful
124 // buffer consumer implementations. In another word, BufferHubQueue based
125 // dequeueBuffer should never block whether setAsyncMode(true) is set or
126 // not.
127 //
128 // See: IGraphicBufferProducer::setAsyncMode and
129 // BufferQueueProducer::setAsyncMode for more about original implementation.
130 ALOGW("BufferHubProducer::setAsyncMode: BufferHubQueue should always be "
131 "asynchronous. This call makes no effact.");
132 return NO_ERROR;
133 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700134 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800135}
136
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800137status_t BufferHubProducer::dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
138 uint32_t height, PixelFormat format, uint64_t usage,
139 uint64_t* /*outBufferAge*/,
140 FrameEventHistoryDelta* /* out_timestamps */) {
Jiwen 'Steve' Caie7cf62a2018-04-30 22:56:08 -0700141 ALOGV("dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width, height, format, usage);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800142
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800143 status_t ret;
144 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800145
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800146 if (connected_api_ == kNoConnectedApi) {
147 ALOGE("dequeueBuffer: BufferQueue has no connected producer");
148 return NO_INIT;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800149 }
150
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800151 const uint32_t kLayerCount = 1;
152 if (int32_t(queue_->capacity()) < max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
153 // Lazy allocation. When the capacity of |queue_| has not reached
154 // |max_dequeued_buffer_count_|, allocate new buffer.
155 // TODO(jwcai) To save memory, the really reasonable thing to do is to go
156 // over existing slots and find first existing one to dequeue.
157 ret = AllocateBuffer(width, height, kLayerCount, format, usage);
158 if (ret < 0) return ret;
159 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800160
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800161 size_t slot = 0;
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -0800162 std::shared_ptr<BufferProducer> buffer_producer;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800163
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -0800164 for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800165 LocalHandle fence;
166 auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
167 if (!buffer_status) return NO_MEMORY;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800168
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800169 buffer_producer = buffer_status.take();
170 if (!buffer_producer) return NO_MEMORY;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800171
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800172 if (width == buffer_producer->width() && height == buffer_producer->height() &&
173 uint32_t(format) == buffer_producer->format()) {
174 // The producer queue returns a buffer producer matches the request.
175 break;
176 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800177
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800178 // Needs reallocation.
179 // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
180 ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
181 "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
182 "re-allocattion.",
183 width, height, format, slot, buffer_producer->width(), buffer_producer->height(),
184 buffer_producer->format());
185 // Mark the slot as reallocating, so that later we can set
186 // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
187 buffers_[slot].mIsReallocating = true;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800188
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800189 // Remove the old buffer once the allocation before allocating its
190 // replacement.
191 RemoveBuffer(slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800192
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800193 // Allocate a new producer buffer with new buffer configs. Note that if
194 // there are already multiple buffers in the queue, the next one returned
195 // from |queue_->Dequeue| may not be the new buffer we just reallocated.
196 // Retry up to BufferHubQueue::kMaxQueueCapacity times.
197 ret = AllocateBuffer(width, height, kLayerCount, format, usage);
198 if (ret < 0) return ret;
199 }
200
201 // With the BufferHub backed solution. Buffer slot returned from
202 // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
203 // It's either in free state (if the buffer has never been used before) or
204 // in queued state (if the buffer has been dequeued and queued back to
205 // BufferHubQueue).
206 LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
207 !buffers_[slot].mBufferState.isQueued()),
208 "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot,
209 buffers_[slot].mBufferState.string());
210
211 buffers_[slot].mBufferState.freeQueued();
212 buffers_[slot].mBufferState.dequeue();
Jiwen 'Steve' Caie7cf62a2018-04-30 22:56:08 -0700213 ALOGV("dequeueBuffer: slot=%zu", slot);
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800214
215 // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
216 // just need to exopose that through |BufferHubQueue| once we need fence.
217 *out_fence = Fence::NO_FENCE;
218 *out_slot = int(slot);
219 ret = NO_ERROR;
220
221 if (buffers_[slot].mIsReallocating) {
222 ret |= BUFFER_NEEDS_REALLOCATION;
223 buffers_[slot].mIsReallocating = false;
224 }
225
226 return ret;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800227}
228
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700229status_t BufferHubProducer::detachBuffer(int slot) {
230 ALOGV("detachBuffer: slot=%d", slot);
231 std::unique_lock<std::mutex> lock(mutex_);
232
233 return DetachBufferLocked(static_cast<size_t>(slot));
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800234}
235
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700236status_t BufferHubProducer::DetachBufferLocked(size_t slot) {
237 if (connected_api_ == kNoConnectedApi) {
238 ALOGE("detachBuffer: BufferHubProducer is not connected.");
239 return NO_INIT;
240 }
241
242 if (slot >= static_cast<size_t>(max_buffer_count_)) {
243 ALOGE("detachBuffer: slot index %zu out of range [0, %d)", slot, max_buffer_count_);
244 return BAD_VALUE;
245 } else if (!buffers_[slot].mBufferState.isDequeued()) {
246 ALOGE("detachBuffer: slot %zu is not owned by the producer (state = %s)", slot,
247 buffers_[slot].mBufferState.string());
248 return BAD_VALUE;
249 } else if (!buffers_[slot].mRequestBufferCalled) {
250 ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot);
251 return BAD_VALUE;
252 }
253 std::shared_ptr<BufferProducer> buffer_producer = queue_->GetBuffer(slot);
254 if (buffer_producer == nullptr || buffer_producer->buffer() == nullptr) {
255 ALOGE("detachBuffer: Invalid BufferProducer at slot %zu.", slot);
256 return BAD_VALUE;
257 }
258 sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
259 if (graphic_buffer == nullptr) {
260 ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot);
261 return BAD_VALUE;
262 }
263
264 // Remove the BufferProducer from the ProducerQueue.
265 status_t error = RemoveBuffer(slot);
266 if (error != NO_ERROR) {
267 ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error);
268 return error;
269 }
270
271 // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject
272 // the handle into the GraphicBuffer object at the requested slot.
273 auto status_or_handle = buffer_producer->Detach();
274 if (!status_or_handle.ok()) {
275 ALOGE("detachBuffer: Failed to detach from a BufferProducer at slot %zu, error=%d.", slot,
276 status_or_handle.error());
277 return BAD_VALUE;
278 }
279 std::unique_ptr<DetachedBufferHandle> handle =
280 DetachedBufferHandle::Create(status_or_handle.take());
281 if (!handle->isValid()) {
282 ALOGE("detachBuffer: Failed to create a DetachedBufferHandle at slot %zu.", slot);
283 return BAD_VALUE;
284 }
285
286 return graphic_buffer->setDetachedBufferHandle(std::move(handle));
287}
288
289status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) {
290 ALOGV("detachNextBuffer.");
291
292 if (out_buffer == nullptr || out_fence == nullptr) {
293 ALOGE("detachNextBuffer: Invalid parameter: out_buffer=%p, out_fence=%p", out_buffer,
294 out_fence);
295 return BAD_VALUE;
296 }
297
298 std::unique_lock<std::mutex> lock(mutex_);
299
300 if (connected_api_ == kNoConnectedApi) {
301 ALOGE("detachNextBuffer: BufferHubProducer is not connected.");
302 return NO_INIT;
303 }
304
305 // detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer, and detachBuffer in
306 // sequence, except for two things:
307 //
308 // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the
309 // function just returns whatever BufferProducer is available from the ProducerQueue and no
310 // buffer allocation or re-allocation will happen.
311 // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return
312 // an error instead.
313 size_t slot = 0;
314 LocalHandle fence;
315
316 // First, dequeue a BufferProducer from the ProducerQueue with no timeout. Report error
317 // immediately if ProducerQueue::Dequeue() fails.
318 auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence);
319 if (!status_or_buffer.ok()) {
320 ALOGE("detachNextBuffer: Failed to dequeue buffer, error=%d.", status_or_buffer.error());
321 return NO_MEMORY;
322 }
323
324 std::shared_ptr<BufferProducer> buffer_producer = status_or_buffer.take();
325 if (buffer_producer == nullptr) {
326 ALOGE("detachNextBuffer: Dequeued buffer is null.");
327 return NO_MEMORY;
328 }
329
330 // With the BufferHub backed solution, slot returned from |queue_->Dequeue| is guaranteed to
331 // be available for producer's use. It's either in free state (if the buffer has never been used
332 // before) or in queued state (if the buffer has been dequeued and queued back to
333 // BufferHubQueue).
334 if (!buffers_[slot].mBufferState.isFree() && !buffers_[slot].mBufferState.isQueued()) {
335 ALOGE("detachNextBuffer: slot %zu is not free or queued, actual state: %s.", slot,
336 buffers_[slot].mBufferState.string());
337 return BAD_VALUE;
338 }
339 if (buffers_[slot].mBufferProducer == nullptr) {
340 ALOGE("detachNextBuffer: BufferProducer at slot %zu is null.", slot);
341 return BAD_VALUE;
342 }
343 if (buffers_[slot].mBufferProducer->id() != buffer_producer->id()) {
344 ALOGE("detachNextBuffer: BufferProducer at slot %zu has mismatched id, actual: "
345 "%d, expected: %d.",
346 slot, buffers_[slot].mBufferProducer->id(), buffer_producer->id());
347 return BAD_VALUE;
348 }
349
350 ALOGV("detachNextBuffer: slot=%zu", slot);
351 buffers_[slot].mBufferState.freeQueued();
352 buffers_[slot].mBufferState.dequeue();
353
354 // Second, request the buffer.
355 sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
356 buffers_[slot].mGraphicBuffer = buffer_producer->buffer()->buffer();
357
358 // Finally, detach the buffer and then return.
359 status_t error = DetachBufferLocked(slot);
360 if (error == NO_ERROR) {
361 *out_fence = new Fence(fence.Release());
362 *out_buffer = graphic_buffer;
363 }
364 return error;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800365}
366
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700367status_t BufferHubProducer::attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) {
368 // In the BufferHub design, all buffers are allocated and owned by the BufferHub. Thus only
369 // GraphicBuffers that are originated from BufferHub can be attached to a BufferHubProducer.
370 ALOGV("queueBuffer: buffer=%p", buffer.get());
371
372 if (out_slot == nullptr) {
373 ALOGE("attachBuffer: out_slot cannot be NULL.");
374 return BAD_VALUE;
375 }
376 if (buffer == nullptr || !buffer->isDetachedBuffer()) {
377 ALOGE("attachBuffer: invalid GraphicBuffer.");
378 return BAD_VALUE;
379 }
380
381 std::unique_lock<std::mutex> lock(mutex_);
382
383 if (connected_api_ == kNoConnectedApi) {
384 ALOGE("attachBuffer: BufferQueue has no connected producer");
385 return NO_INIT;
386 }
387
388 // Before attaching the buffer, caller is supposed to call
389 // IGraphicBufferProducer::setGenerationNumber to inform the
390 // BufferHubProducer the next generation number.
391 if (buffer->getGenerationNumber() != generation_number_) {
392 ALOGE("attachBuffer: Mismatched generation number, buffer: %u, queue: %u.",
393 buffer->getGenerationNumber(), generation_number_);
394 return BAD_VALUE;
395 }
396
397 // Creates a BufferProducer from the GraphicBuffer.
398 std::unique_ptr<DetachedBufferHandle> detached_handle = buffer->takeDetachedBufferHandle();
399 if (detached_handle == nullptr) {
400 ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL.");
401 return BAD_VALUE;
402 }
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700403 std::shared_ptr<BufferProducer> buffer_producer =
Tianyub61df912018-10-16 14:55:39 -0700404 BufferProducer::Import(std::move(detached_handle->handle()));
Jiwen 'Steve' Cai57ae3ee2018-05-03 17:51:52 -0700405 if (buffer_producer == nullptr) {
406 ALOGE("attachBuffer: Failed to import BufferProducer.");
407 return BAD_VALUE;
408 }
409
410 // Adds the BufferProducer into the Queue.
411 auto status_or_slot = queue_->InsertBuffer(buffer_producer);
412 if (!status_or_slot.ok()) {
413 ALOGE("attachBuffer: Failed to insert buffer, error=%d.", status_or_slot.error());
414 return BAD_VALUE;
415 }
416
417 size_t slot = status_or_slot.get();
418 ALOGV("attachBuffer: returning slot %zu.", slot);
419 if (slot >= static_cast<size_t>(max_buffer_count_)) {
420 ALOGE("attachBuffer: Invalid slot: %zu.", slot);
421 return BAD_VALUE;
422 }
423
424 // The just attached buffer should be in dequeued state according to IGraphicBufferProducer
425 // interface. In BufferHub's language the buffer should be in Gained state.
426 buffers_[slot].mGraphicBuffer = buffer;
427 buffers_[slot].mBufferState.attachProducer();
428 buffers_[slot].mEglFence = EGL_NO_SYNC_KHR;
429 buffers_[slot].mFence = Fence::NO_FENCE;
430 buffers_[slot].mRequestBufferCalled = true;
431 buffers_[slot].mAcquireCalled = false;
432 buffers_[slot].mNeedsReallocation = false;
433
434 *out_slot = static_cast<int>(slot);
435 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800436}
437
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800438status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
439 QueueBufferOutput* output) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800440 ALOGV("queueBuffer: slot %d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800441
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800442 if (output == nullptr) {
443 return BAD_VALUE;
444 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700445
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800446 int64_t timestamp;
447 bool is_auto_timestamp;
448 android_dataspace dataspace;
449 Rect crop(Rect::EMPTY_RECT);
450 int scaling_mode;
451 uint32_t transform;
452 sp<Fence> fence;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800453
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800454 input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop, &scaling_mode, &transform,
455 &fence);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800456
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800457 // Check input scaling mode is valid.
458 switch (scaling_mode) {
459 case NATIVE_WINDOW_SCALING_MODE_FREEZE:
460 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
461 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
462 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
463 break;
464 default:
465 ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
466 return BAD_VALUE;
467 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700468
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800469 // Check input fence is valid.
470 if (fence == nullptr) {
471 ALOGE("queueBuffer: fence is NULL");
472 return BAD_VALUE;
473 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800474
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800475 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800476
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800477 if (connected_api_ == kNoConnectedApi) {
478 ALOGE("queueBuffer: BufferQueue has no connected producer");
479 return NO_INIT;
480 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700481
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800482 if (slot < 0 || slot >= max_buffer_count_) {
483 ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
484 return BAD_VALUE;
485 } else if (!buffers_[slot].mBufferState.isDequeued()) {
486 ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)", slot,
487 buffers_[slot].mBufferState.string());
488 return BAD_VALUE;
489 } else if ((!buffers_[slot].mRequestBufferCalled || buffers_[slot].mGraphicBuffer == nullptr)) {
490 ALOGE("queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
491 "mGraphicBuffer=%p)",
492 slot, buffers_[slot].mRequestBufferCalled, buffers_[slot].mGraphicBuffer.get());
493 return BAD_VALUE;
494 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800495
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800496 // Post the buffer producer with timestamp in the metadata.
497 const auto& buffer_producer = buffers_[slot].mBufferProducer;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700498
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800499 // Check input crop is not out of boundary of current buffer.
500 Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
501 Rect cropped_rect(Rect::EMPTY_RECT);
502 crop.intersect(buffer_rect, &cropped_rect);
503 if (cropped_rect != crop) {
504 ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
505 return BAD_VALUE;
506 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700507
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800508 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800509
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800510 DvrNativeBufferMetadata meta_data;
511 meta_data.timestamp = timestamp;
512 meta_data.is_auto_timestamp = int32_t(is_auto_timestamp);
513 meta_data.dataspace = int32_t(dataspace);
514 meta_data.crop_left = crop.left;
515 meta_data.crop_top = crop.top;
516 meta_data.crop_right = crop.right;
517 meta_data.crop_bottom = crop.bottom;
518 meta_data.scaling_mode = int32_t(scaling_mode);
519 meta_data.transform = int32_t(transform);
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700520
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800521 buffer_producer->PostAsync(&meta_data, fence_fd);
522 buffers_[slot].mBufferState.queue();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800523
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800524 output->width = buffer_producer->width();
525 output->height = buffer_producer->height();
526 output->transformHint = 0; // default value, we don't use it yet.
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700527
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800528 // |numPendingBuffers| counts of the number of buffers that has been enqueued
529 // by the producer but not yet acquired by the consumer. Due to the nature
530 // of BufferHubQueue design, this is hard to trace from the producer's client
531 // side, but it's safe to assume it's zero.
532 output->numPendingBuffers = 0;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700533
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800534 // Note that we are not setting nextFrameNumber here as it seems to be only
535 // used by surface flinger. See more at b/22802885, ag/791760.
536 output->nextFrameNumber = 0;
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700537
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800538 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800539}
540
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800541status_t BufferHubProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800542 ALOGV(__FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800543
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800544 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800545
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800546 if (connected_api_ == kNoConnectedApi) {
547 ALOGE("cancelBuffer: BufferQueue has no connected producer");
548 return NO_INIT;
549 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700550
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800551 if (slot < 0 || slot >= max_buffer_count_) {
552 ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
553 return BAD_VALUE;
554 } else if (!buffers_[slot].mBufferState.isDequeued()) {
555 ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)", slot,
556 buffers_[slot].mBufferState.string());
557 return BAD_VALUE;
558 } else if (fence == nullptr) {
559 ALOGE("cancelBuffer: fence is NULL");
560 return BAD_VALUE;
561 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800562
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800563 auto buffer_producer = buffers_[slot].mBufferProducer;
564 queue_->Enqueue(buffer_producer, size_t(slot), 0ULL);
565 buffers_[slot].mBufferState.cancel();
566 buffers_[slot].mFence = fence;
567 ALOGV("cancelBuffer: slot %d", slot);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800568
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800569 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800570}
571
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800572status_t BufferHubProducer::query(int what, int* out_value) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800573 ALOGV(__FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800574
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800575 std::unique_lock<std::mutex> lock(mutex_);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800576
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800577 if (out_value == nullptr) {
578 ALOGE("query: out_value was NULL");
579 return BAD_VALUE;
580 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800581
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800582 int value = 0;
583 switch (what) {
584 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
585 // TODO(b/36187402) This should be the maximum number of buffers that this
586 // producer queue's consumer can acquire. Set to be at least one. Need to
587 // find a way to set from the consumer side.
588 value = kDefaultUndequeuedBuffers;
589 break;
590 case NATIVE_WINDOW_BUFFER_AGE:
591 value = 0;
592 break;
593 case NATIVE_WINDOW_WIDTH:
594 value = int32_t(queue_->default_width());
595 break;
596 case NATIVE_WINDOW_HEIGHT:
597 value = int32_t(queue_->default_height());
598 break;
599 case NATIVE_WINDOW_FORMAT:
600 value = int32_t(queue_->default_format());
601 break;
602 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
603 // BufferHubQueue is always operating in async mode, thus semantically
604 // consumer can never be running behind. See BufferQueueCore.cpp core
605 // for more information about the original meaning of this flag.
606 value = 0;
607 break;
608 case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
609 // TODO(jwcai) This is currently not implement as we don't need
610 // IGraphicBufferConsumer parity.
611 value = 0;
612 break;
613 case NATIVE_WINDOW_DEFAULT_DATASPACE:
614 // TODO(jwcai) Return the default value android::BufferQueue is using as
615 // there is no way dvr::ConsumerQueue can set it.
616 value = 0; // HAL_DATASPACE_UNKNOWN
617 break;
618 case NATIVE_WINDOW_STICKY_TRANSFORM:
619 // TODO(jwcai) Return the default value android::BufferQueue is using as
620 // there is no way dvr::ConsumerQueue can set it.
621 value = 0;
622 break;
623 case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
624 // In Daydream's implementation, the consumer end (i.e. VR Compostior)
625 // knows how to handle protected buffers.
626 value = 1;
627 break;
628 default:
629 return BAD_VALUE;
630 }
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800631
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800632 ALOGV("query: key=%d, v=%d", what, value);
633 *out_value = value;
634 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800635}
636
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800637status_t BufferHubProducer::connect(const sp<IProducerListener>& /* listener */, int api,
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800638 bool /* producer_controlled_by_app */,
639 QueueBufferOutput* output) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800640 // Consumer interaction are actually handled by buffer hub, and we need
641 // to maintain consumer operations here. We only need to perform basic input
642 // parameter checks here.
643 ALOGV(__FUNCTION__);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700644
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800645 if (output == nullptr) {
646 return BAD_VALUE;
647 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700648
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800649 std::unique_lock<std::mutex> lock(mutex_);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700650
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800651 if (connected_api_ != kNoConnectedApi) {
652 return BAD_VALUE;
653 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700654
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800655 if (!queue_->is_connected()) {
656 ALOGE("BufferHubProducer::connect: This BufferHubProducer is not "
657 "connected to bufferhud. Has it been taken out as a parcelable?");
658 return BAD_VALUE;
659 }
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800660
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800661 switch (api) {
662 case NATIVE_WINDOW_API_EGL:
663 case NATIVE_WINDOW_API_CPU:
664 case NATIVE_WINDOW_API_MEDIA:
665 case NATIVE_WINDOW_API_CAMERA:
666 connected_api_ = api;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700667
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800668 output->width = queue_->default_width();
669 output->height = queue_->default_height();
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700670
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800671 // default values, we don't use them yet.
672 output->transformHint = 0;
673 output->numPendingBuffers = 0;
674 output->nextFrameNumber = 0;
675 output->bufferReplaced = false;
Jiwen 'Steve' Caicb4751c2017-04-14 17:56:55 -0700676
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800677 break;
678 default:
679 ALOGE("BufferHubProducer::connect: unknow API %d", api);
680 return BAD_VALUE;
681 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700682
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800683 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800684}
685
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800686status_t BufferHubProducer::disconnect(int api, DisconnectMode /*mode*/) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800687 // Consumer interaction are actually handled by buffer hub, and we need
688 // to maintain consumer operations here. We only need to perform basic input
689 // parameter checks here.
690 ALOGV(__FUNCTION__);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700691
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800692 std::unique_lock<std::mutex> lock(mutex_);
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700693
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800694 if (kNoConnectedApi == connected_api_) {
695 return NO_INIT;
696 } else if (api != connected_api_) {
697 return BAD_VALUE;
698 }
Jiwen 'Steve' Cai1601bcf2017-03-24 14:03:06 -0700699
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800700 FreeAllBuffers();
701 connected_api_ = kNoConnectedApi;
702 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800703}
704
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800705status_t BufferHubProducer::setSidebandStream(const sp<NativeHandle>& stream) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800706 if (stream != nullptr) {
707 // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
708 // metadata.
709 ALOGE("SidebandStream is not currently supported.");
710 return INVALID_OPERATION;
711 }
712 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800713}
714
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800715void BufferHubProducer::allocateBuffers(uint32_t /* width */, uint32_t /* height */,
716 PixelFormat /* format */, uint64_t /* usage */) {
717 // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
718 // of buffers permitted by the current BufferQueue configuration (aka
719 // |max_buffer_count_|).
720 ALOGE("BufferHubProducer::allocateBuffers not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800721}
722
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800723status_t BufferHubProducer::allowAllocation(bool /* allow */) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800724 ALOGE("BufferHubProducer::allowAllocation not implemented.");
725 return INVALID_OPERATION;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800726}
727
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800728status_t BufferHubProducer::setGenerationNumber(uint32_t generation_number) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800729 ALOGV(__FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800730
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800731 std::unique_lock<std::mutex> lock(mutex_);
732 generation_number_ = generation_number;
733 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800734}
735
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800736String8 BufferHubProducer::getConsumerName() const {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800737 // BufferHub based implementation could have one to many producer/consumer
738 // relationship, thus |getConsumerName| from the producer side does not
739 // make any sense.
740 ALOGE("BufferHubProducer::getConsumerName not supported.");
741 return String8("BufferHubQueue::DummyConsumer");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800742}
743
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800744status_t BufferHubProducer::setSharedBufferMode(bool shared_buffer_mode) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800745 if (shared_buffer_mode) {
746 ALOGE("BufferHubProducer::setSharedBufferMode(true) is not supported.");
747 // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
748 return INVALID_OPERATION;
749 }
750 // Setting to default should just work as a no-op.
751 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800752}
753
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800754status_t BufferHubProducer::setAutoRefresh(bool auto_refresh) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800755 if (auto_refresh) {
756 ALOGE("BufferHubProducer::setAutoRefresh(true) is not supported.");
757 return INVALID_OPERATION;
758 }
759 // Setting to default should just work as a no-op.
760 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800761}
762
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800763status_t BufferHubProducer::setDequeueTimeout(nsecs_t timeout) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800764 ALOGV(__FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800765
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800766 std::unique_lock<std::mutex> lock(mutex_);
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -0800767 dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800768 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800769}
770
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800771status_t BufferHubProducer::getLastQueuedBuffer(sp<GraphicBuffer>* /* out_buffer */,
772 sp<Fence>* /* out_fence */,
773 float /*out_transform_matrix*/[16]) {
774 ALOGE("BufferHubProducer::getLastQueuedBuffer not implemented.");
775 return INVALID_OPERATION;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800776}
777
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800778void BufferHubProducer::getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {
779 ALOGE("BufferHubProducer::getFrameTimestamps not implemented.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800780}
781
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800782status_t BufferHubProducer::getUniqueId(uint64_t* out_id) const {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800783 ALOGV(__FUNCTION__);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800784
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800785 *out_id = unique_id_;
786 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800787}
788
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800789status_t BufferHubProducer::getConsumerUsage(uint64_t* out_usage) const {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800790 ALOGV(__FUNCTION__);
Chia-I Wue2786ea2017-08-07 10:36:08 -0700791
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800792 // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS
793 *out_usage = 0;
794 return NO_ERROR;
Chia-I Wue2786ea2017-08-07 10:36:08 -0700795}
796
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -0800797status_t BufferHubProducer::TakeAsParcelable(ProducerQueueParcelable* out_parcelable) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800798 if (!out_parcelable || out_parcelable->IsValid()) return BAD_VALUE;
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800799
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800800 if (connected_api_ != kNoConnectedApi) {
801 ALOGE("BufferHubProducer::TakeAsParcelable: BufferHubProducer has "
802 "connected client. Must disconnect first.");
803 return BAD_VALUE;
804 }
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800805
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800806 if (!queue_->is_connected()) {
807 ALOGE("BufferHubProducer::TakeAsParcelable: This BufferHubProducer "
808 "is not connected to bufferhud. Has it been taken out as a "
809 "parcelable?");
810 return BAD_VALUE;
811 }
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800812
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800813 auto status = queue_->TakeAsParcelable();
814 if (!status) {
815 ALOGE("BufferHubProducer::TakeAsParcelable: Failed to take out "
816 "ProducuerQueueParcelable from the producer queue, error: %s.",
817 status.GetErrorMessage().c_str());
818 return BAD_VALUE;
819 }
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800820
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800821 *out_parcelable = status.take();
822 return NO_ERROR;
Jiwen 'Steve' Cai5afb7402017-11-09 18:50:32 -0800823}
824
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800825status_t BufferHubProducer::AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800826 PixelFormat format, uint64_t usage) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800827 auto status = queue_->AllocateBuffer(width, height, layer_count, uint32_t(format), usage);
828 if (!status) {
829 ALOGE("BufferHubProducer::AllocateBuffer: Failed to allocate buffer: %s",
830 status.GetErrorMessage().c_str());
831 return NO_MEMORY;
832 }
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700833
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800834 size_t slot = status.get();
835 auto buffer_producer = queue_->GetBuffer(slot);
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700836
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800837 LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, "Failed to get buffer producer at slot: %zu",
838 slot);
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700839
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800840 buffers_[slot].mBufferProducer = buffer_producer;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700841
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800842 return NO_ERROR;
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700843}
844
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800845status_t BufferHubProducer::RemoveBuffer(size_t slot) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800846 auto status = queue_->RemoveBuffer(slot);
847 if (!status) {
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700848 ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer at slot: %zu, error: %s.",
849 slot, status.GetErrorMessage().c_str());
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800850 return INVALID_OPERATION;
851 }
Jiwen 'Steve' Caid6cb17f2017-05-08 16:15:35 -0700852
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800853 // Reset in memory objects related the the buffer.
854 buffers_[slot].mBufferProducer = nullptr;
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800855 buffers_[slot].mBufferState.detachProducer();
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700856 buffers_[slot].mFence = Fence::NO_FENCE;
857 buffers_[slot].mGraphicBuffer = nullptr;
858 buffers_[slot].mRequestBufferCalled = false;
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800859 return NO_ERROR;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800860}
861
Jiwen 'Steve' Cai0f950842018-01-16 17:05:54 -0800862status_t BufferHubProducer::FreeAllBuffers() {
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -0800863 for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800864 // Reset in memory objects related the the buffer.
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800865 buffers_[slot].mBufferProducer = nullptr;
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700866 buffers_[slot].mBufferState.reset();
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800867 buffers_[slot].mFence = Fence::NO_FENCE;
Jiwen 'Steve' Cai42875352018-04-30 17:55:11 -0700868 buffers_[slot].mGraphicBuffer = nullptr;
869 buffers_[slot].mRequestBufferCalled = false;
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800870 }
Jiwen 'Steve' Cai005f45d2017-08-04 17:34:37 -0700871
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800872 auto status = queue_->FreeAllBuffers();
873 if (!status) {
874 ALOGE("BufferHubProducer::FreeAllBuffers: Failed to free all buffers on "
875 "the queue: %s",
876 status.GetErrorMessage().c_str());
877 }
Jiwen 'Steve' Cai005f45d2017-08-04 17:34:37 -0700878
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800879 if (queue_->capacity() != 0 || queue_->count() != 0) {
880 LOG_ALWAYS_FATAL("BufferHubProducer::FreeAllBuffers: Not all buffers are freed.");
881 }
Jiwen 'Steve' Cai005f45d2017-08-04 17:34:37 -0700882
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800883 return NO_ERROR;
Jiwen 'Steve' Cai005f45d2017-08-04 17:34:37 -0700884}
885
Jiwen 'Steve' Caic90a77f2018-01-14 15:42:29 -0800886status_t BufferHubProducer::exportToParcel(Parcel* parcel) {
887 status_t res = TakeAsParcelable(&pending_producer_parcelable_);
888 if (res != NO_ERROR) return res;
889
890 if (!pending_producer_parcelable_.IsValid()) {
891 ALOGE("BufferHubProducer::exportToParcel: Invalid parcelable object.");
892 return BAD_VALUE;
893 }
894
895 res = parcel->writeUint32(USE_BUFFER_HUB);
896 if (res != NO_ERROR) {
897 ALOGE("BufferHubProducer::exportToParcel: Cannot write magic, res=%d.", res);
898 return res;
899 }
900
901 return pending_producer_parcelable_.writeToParcel(parcel);
902}
903
904IBinder* BufferHubProducer::onAsBinder() {
905 ALOGE("BufferHubProducer::onAsBinder: BufferHubProducer should never be used as an Binder "
906 "object.");
907 return nullptr;
908}
909
Jiwen 'Steve' Cai9a6ddf72018-01-18 14:37:24 -0800910} // namespace android