Home | History | Annotate | Download | only in gui
      1 /*
      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 
     17 #include <dvr/dvr_api.h>
     18 #include <gui/BufferHubProducer.h>
     19 #include <inttypes.h>
     20 #include <log/log.h>
     21 #include <system/window.h>
     22 #include <ui/BufferHubBuffer.h>
     23 
     24 namespace android {
     25 
     26 using namespace dvr;
     27 
     28 /* static */
     29 sp<BufferHubProducer> BufferHubProducer::Create(const std::shared_ptr<ProducerQueue>& queue) {
     30     sp<BufferHubProducer> producer = new BufferHubProducer;
     31     producer->queue_ = queue;
     32     return producer;
     33 }
     34 
     35 /* static */
     36 sp<BufferHubProducer> BufferHubProducer::Create(ProducerQueueParcelable parcelable) {
     37     if (!parcelable.IsValid()) {
     38         ALOGE("BufferHubProducer::Create: Invalid producer parcelable.");
     39         return nullptr;
     40     }
     41 
     42     sp<BufferHubProducer> producer = new BufferHubProducer;
     43     producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
     44     return producer;
     45 }
     46 
     47 status_t BufferHubProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
     48     ALOGV("requestBuffer: slot=%d", slot);
     49 
     50     std::unique_lock<std::mutex> lock(mutex_);
     51 
     52     if (connected_api_ == kNoConnectedApi) {
     53         ALOGE("requestBuffer: BufferHubProducer has no connected producer");
     54         return NO_INIT;
     55     }
     56 
     57     if (slot < 0 || slot >= max_buffer_count_) {
     58         ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
     59         return BAD_VALUE;
     60     } else if (!buffers_[slot].mBufferState.isDequeued()) {
     61         ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)", slot,
     62               buffers_[slot].mBufferState.string());
     63         return BAD_VALUE;
     64     } else if (buffers_[slot].mGraphicBuffer != nullptr) {
     65         ALOGE("requestBuffer: slot %d is not empty.", slot);
     66         return BAD_VALUE;
     67     } else if (buffers_[slot].mProducerBuffer == nullptr) {
     68         ALOGE("requestBuffer: slot %d is not dequeued.", slot);
     69         return BAD_VALUE;
     70     }
     71 
     72     const auto& producer_buffer = buffers_[slot].mProducerBuffer;
     73     sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
     74 
     75     buffers_[slot].mGraphicBuffer = graphic_buffer;
     76     buffers_[slot].mRequestBufferCalled = true;
     77 
     78     *buf = graphic_buffer;
     79     return NO_ERROR;
     80 }
     81 
     82 status_t BufferHubProducer::setMaxDequeuedBufferCount(int max_dequeued_buffers) {
     83     ALOGV("setMaxDequeuedBufferCount: max_dequeued_buffers=%d", max_dequeued_buffers);
     84 
     85     std::unique_lock<std::mutex> lock(mutex_);
     86 
     87     if (max_dequeued_buffers <= 0 ||
     88         max_dequeued_buffers >
     89                 int(BufferHubQueue::kMaxQueueCapacity - kDefaultUndequeuedBuffers)) {
     90         ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]", max_dequeued_buffers,
     91               BufferHubQueue::kMaxQueueCapacity);
     92         return BAD_VALUE;
     93     }
     94 
     95     // The new dequeued_buffers count should not be violated by the number
     96     // of currently dequeued buffers.
     97     int dequeued_count = 0;
     98     for (const auto& buf : buffers_) {
     99         if (buf.mBufferState.isDequeued()) {
    100             dequeued_count++;
    101         }
    102     }
    103     if (dequeued_count > max_dequeued_buffers) {
    104         ALOGE("setMaxDequeuedBufferCount: the requested dequeued_buffers"
    105               "count (%d) exceeds the current dequeued buffer count (%d)",
    106               max_dequeued_buffers, dequeued_count);
    107         return BAD_VALUE;
    108     }
    109 
    110     max_dequeued_buffer_count_ = max_dequeued_buffers;
    111     return NO_ERROR;
    112 }
    113 
    114 status_t BufferHubProducer::setAsyncMode(bool async) {
    115     if (async) {
    116         // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
    117         // automatically and behaves differently from IGraphicBufferConsumer. Thus,
    118         // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
    119         // to prevent dequeueBuffer from being blocking) technically does not apply
    120         // here.
    121         //
    122         // In Daydream, non-blocking producer side dequeue is guaranteed by careful
    123         // buffer consumer implementations. In another word, BufferHubQueue based
    124         // dequeueBuffer should never block whether setAsyncMode(true) is set or
    125         // not.
    126         //
    127         // See: IGraphicBufferProducer::setAsyncMode and
    128         // BufferQueueProducer::setAsyncMode for more about original implementation.
    129         ALOGW("BufferHubProducer::setAsyncMode: BufferHubQueue should always be "
    130               "asynchronous. This call makes no effact.");
    131         return NO_ERROR;
    132     }
    133     return NO_ERROR;
    134 }
    135 
    136 status_t BufferHubProducer::dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
    137                                           uint32_t height, PixelFormat format, uint64_t usage,
    138                                           uint64_t* /*outBufferAge*/,
    139                                           FrameEventHistoryDelta* /* out_timestamps */) {
    140     ALOGV("dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width, height, format, usage);
    141 
    142     status_t ret;
    143     std::unique_lock<std::mutex> lock(mutex_);
    144 
    145     if (connected_api_ == kNoConnectedApi) {
    146         ALOGE("dequeueBuffer: BufferQueue has no connected producer");
    147         return NO_INIT;
    148     }
    149 
    150     const uint32_t kLayerCount = 1;
    151     if (int32_t(queue_->capacity()) < max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
    152         // Lazy allocation. When the capacity of |queue_| has not reached
    153         // |max_dequeued_buffer_count_|, allocate new buffer.
    154         // TODO(jwcai) To save memory, the really reasonable thing to do is to go
    155         // over existing slots and find first existing one to dequeue.
    156         ret = AllocateBuffer(width, height, kLayerCount, format, usage);
    157         if (ret < 0) return ret;
    158     }
    159 
    160     size_t slot = 0;
    161     std::shared_ptr<ProducerBuffer> producer_buffer;
    162 
    163     for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
    164         LocalHandle fence;
    165         auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
    166         if (!buffer_status) return NO_MEMORY;
    167 
    168         producer_buffer = buffer_status.take();
    169         if (!producer_buffer) return NO_MEMORY;
    170 
    171         if (width == producer_buffer->width() && height == producer_buffer->height() &&
    172             uint32_t(format) == producer_buffer->format()) {
    173             // The producer queue returns a producer buffer matches the request.
    174             break;
    175         }
    176 
    177         // Needs reallocation.
    178         // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
    179         ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
    180               "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
    181               "re-allocattion.",
    182               width, height, format, slot, producer_buffer->width(), producer_buffer->height(),
    183               producer_buffer->format());
    184         // Mark the slot as reallocating, so that later we can set
    185         // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
    186         buffers_[slot].mIsReallocating = true;
    187 
    188         // Remove the old buffer once the allocation before allocating its
    189         // replacement.
    190         RemoveBuffer(slot);
    191 
    192         // Allocate a new producer buffer with new buffer configs. Note that if
    193         // there are already multiple buffers in the queue, the next one returned
    194         // from |queue_->Dequeue| may not be the new buffer we just reallocated.
    195         // Retry up to BufferHubQueue::kMaxQueueCapacity times.
    196         ret = AllocateBuffer(width, height, kLayerCount, format, usage);
    197         if (ret < 0) return ret;
    198     }
    199 
    200     // With the BufferHub backed solution. Buffer slot returned from
    201     // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
    202     // It's either in free state (if the buffer has never been used before) or
    203     // in queued state (if the buffer has been dequeued and queued back to
    204     // BufferHubQueue).
    205     LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
    206                          !buffers_[slot].mBufferState.isQueued()),
    207                         "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot,
    208                         buffers_[slot].mBufferState.string());
    209 
    210     buffers_[slot].mBufferState.freeQueued();
    211     buffers_[slot].mBufferState.dequeue();
    212     ALOGV("dequeueBuffer: slot=%zu", slot);
    213 
    214     // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
    215     // just need to exopose that through |BufferHubQueue| once we need fence.
    216     *out_fence = Fence::NO_FENCE;
    217     *out_slot = int(slot);
    218     ret = NO_ERROR;
    219 
    220     if (buffers_[slot].mIsReallocating) {
    221         ret |= BUFFER_NEEDS_REALLOCATION;
    222         buffers_[slot].mIsReallocating = false;
    223     }
    224 
    225     return ret;
    226 }
    227 
    228 status_t BufferHubProducer::detachBuffer(int slot) {
    229     ALOGV("detachBuffer: slot=%d", slot);
    230     std::unique_lock<std::mutex> lock(mutex_);
    231 
    232     return DetachBufferLocked(static_cast<size_t>(slot));
    233 }
    234 
    235 status_t BufferHubProducer::DetachBufferLocked(size_t slot) {
    236     if (connected_api_ == kNoConnectedApi) {
    237         ALOGE("detachBuffer: BufferHubProducer is not connected.");
    238         return NO_INIT;
    239     }
    240 
    241     if (slot >= static_cast<size_t>(max_buffer_count_)) {
    242         ALOGE("detachBuffer: slot index %zu out of range [0, %d)", slot, max_buffer_count_);
    243         return BAD_VALUE;
    244     } else if (!buffers_[slot].mBufferState.isDequeued()) {
    245         ALOGE("detachBuffer: slot %zu is not owned by the producer (state = %s)", slot,
    246               buffers_[slot].mBufferState.string());
    247         return BAD_VALUE;
    248     } else if (!buffers_[slot].mRequestBufferCalled) {
    249         ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot);
    250         return BAD_VALUE;
    251     }
    252     std::shared_ptr<ProducerBuffer> producer_buffer = queue_->GetBuffer(slot);
    253     if (producer_buffer == nullptr || producer_buffer->buffer() == nullptr) {
    254         ALOGE("detachBuffer: Invalid ProducerBuffer at slot %zu.", slot);
    255         return BAD_VALUE;
    256     }
    257     sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
    258     if (graphic_buffer == nullptr) {
    259         ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot);
    260         return BAD_VALUE;
    261     }
    262 
    263     // Remove the ProducerBuffer from the ProducerQueue.
    264     status_t error = RemoveBuffer(slot);
    265     if (error != NO_ERROR) {
    266         ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error);
    267         return error;
    268     }
    269 
    270     // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject
    271     // the handle into the GraphicBuffer object at the requested slot.
    272     auto status_or_handle = producer_buffer->Detach();
    273     if (!status_or_handle.ok()) {
    274         ALOGE("detachBuffer: Failed to detach from a ProducerBuffer at slot %zu, error=%d.", slot,
    275               status_or_handle.error());
    276         return BAD_VALUE;
    277     }
    278 
    279     // TODO(b/70912269): Reimplement BufferHubProducer::DetachBufferLocked() once GraphicBuffer can
    280     // be directly backed by BufferHub.
    281     return INVALID_OPERATION;
    282 }
    283 
    284 status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) {
    285     ALOGV("detachNextBuffer.");
    286 
    287     if (out_buffer == nullptr || out_fence == nullptr) {
    288         ALOGE("detachNextBuffer: Invalid parameter: out_buffer=%p, out_fence=%p", out_buffer,
    289               out_fence);
    290         return BAD_VALUE;
    291     }
    292 
    293     std::unique_lock<std::mutex> lock(mutex_);
    294 
    295     if (connected_api_ == kNoConnectedApi) {
    296         ALOGE("detachNextBuffer: BufferHubProducer is not connected.");
    297         return NO_INIT;
    298     }
    299 
    300     // detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer, and detachBuffer in
    301     // sequence, except for two things:
    302     //
    303     // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the
    304     // function just returns whatever ProducerBuffer is available from the ProducerQueue and no
    305     // buffer allocation or re-allocation will happen.
    306     // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return
    307     // an error instead.
    308     size_t slot = 0;
    309     LocalHandle fence;
    310 
    311     // First, dequeue a ProducerBuffer from the ProducerQueue with no timeout. Report error
    312     // immediately if ProducerQueue::Dequeue() fails.
    313     auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence);
    314     if (!status_or_buffer.ok()) {
    315         ALOGE("detachNextBuffer: Failed to dequeue buffer, error=%d.", status_or_buffer.error());
    316         return NO_MEMORY;
    317     }
    318 
    319     std::shared_ptr<ProducerBuffer> producer_buffer = status_or_buffer.take();
    320     if (producer_buffer == nullptr) {
    321         ALOGE("detachNextBuffer: Dequeued buffer is null.");
    322         return NO_MEMORY;
    323     }
    324 
    325     // With the BufferHub backed solution, slot returned from |queue_->Dequeue| is guaranteed to
    326     // be available for producer's use. It's either in free state (if the buffer has never been used
    327     // before) or in queued state (if the buffer has been dequeued and queued back to
    328     // BufferHubQueue).
    329     if (!buffers_[slot].mBufferState.isFree() && !buffers_[slot].mBufferState.isQueued()) {
    330         ALOGE("detachNextBuffer: slot %zu is not free or queued, actual state: %s.", slot,
    331               buffers_[slot].mBufferState.string());
    332         return BAD_VALUE;
    333     }
    334     if (buffers_[slot].mProducerBuffer == nullptr) {
    335         ALOGE("detachNextBuffer: ProducerBuffer at slot %zu is null.", slot);
    336         return BAD_VALUE;
    337     }
    338     if (buffers_[slot].mProducerBuffer->id() != producer_buffer->id()) {
    339         ALOGE("detachNextBuffer: ProducerBuffer at slot %zu has mismatched id, actual: "
    340               "%d, expected: %d.",
    341               slot, buffers_[slot].mProducerBuffer->id(), producer_buffer->id());
    342         return BAD_VALUE;
    343     }
    344 
    345     ALOGV("detachNextBuffer: slot=%zu", slot);
    346     buffers_[slot].mBufferState.freeQueued();
    347     buffers_[slot].mBufferState.dequeue();
    348 
    349     // Second, request the buffer.
    350     sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
    351     buffers_[slot].mGraphicBuffer = producer_buffer->buffer()->buffer();
    352 
    353     // Finally, detach the buffer and then return.
    354     status_t error = DetachBufferLocked(slot);
    355     if (error == NO_ERROR) {
    356         *out_fence = new Fence(fence.Release());
    357         *out_buffer = graphic_buffer;
    358     }
    359     return error;
    360 }
    361 
    362 status_t BufferHubProducer::attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) {
    363     // In the BufferHub design, all buffers are allocated and owned by the BufferHub. Thus only
    364     // GraphicBuffers that are originated from BufferHub can be attached to a BufferHubProducer.
    365     ALOGV("queueBuffer: buffer=%p", buffer.get());
    366 
    367     if (out_slot == nullptr) {
    368         ALOGE("attachBuffer: out_slot cannot be NULL.");
    369         return BAD_VALUE;
    370     }
    371     if (buffer == nullptr) {
    372         ALOGE("attachBuffer: invalid GraphicBuffer.");
    373         return BAD_VALUE;
    374     }
    375 
    376     std::unique_lock<std::mutex> lock(mutex_);
    377 
    378     if (connected_api_ == kNoConnectedApi) {
    379         ALOGE("attachBuffer: BufferQueue has no connected producer");
    380         return NO_INIT;
    381     }
    382 
    383     // Before attaching the buffer, caller is supposed to call
    384     // IGraphicBufferProducer::setGenerationNumber to inform the
    385     // BufferHubProducer the next generation number.
    386     if (buffer->getGenerationNumber() != generation_number_) {
    387         ALOGE("attachBuffer: Mismatched generation number, buffer: %u, queue: %u.",
    388               buffer->getGenerationNumber(), generation_number_);
    389         return BAD_VALUE;
    390     }
    391 
    392     // TODO(b/70912269): Reimplement BufferHubProducer::DetachBufferLocked() once GraphicBuffer can
    393     // be directly backed by BufferHub.
    394     return INVALID_OPERATION;
    395 }
    396 
    397 status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
    398                                         QueueBufferOutput* output) {
    399     ALOGV("queueBuffer: slot %d", slot);
    400 
    401     if (output == nullptr) {
    402         return BAD_VALUE;
    403     }
    404 
    405     int64_t timestamp;
    406     bool is_auto_timestamp;
    407     android_dataspace dataspace;
    408     Rect crop(Rect::EMPTY_RECT);
    409     int scaling_mode;
    410     uint32_t transform;
    411     sp<Fence> fence;
    412 
    413     input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop, &scaling_mode, &transform,
    414                   &fence);
    415 
    416     // Check input scaling mode is valid.
    417     switch (scaling_mode) {
    418         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
    419         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
    420         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
    421         case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
    422             break;
    423         default:
    424             ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
    425             return BAD_VALUE;
    426     }
    427 
    428     // Check input fence is valid.
    429     if (fence == nullptr) {
    430         ALOGE("queueBuffer: fence is NULL");
    431         return BAD_VALUE;
    432     }
    433 
    434     std::unique_lock<std::mutex> lock(mutex_);
    435 
    436     if (connected_api_ == kNoConnectedApi) {
    437         ALOGE("queueBuffer: BufferQueue has no connected producer");
    438         return NO_INIT;
    439     }
    440 
    441     if (slot < 0 || slot >= max_buffer_count_) {
    442         ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
    443         return BAD_VALUE;
    444     } else if (!buffers_[slot].mBufferState.isDequeued()) {
    445         ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)", slot,
    446               buffers_[slot].mBufferState.string());
    447         return BAD_VALUE;
    448     } else if ((!buffers_[slot].mRequestBufferCalled || buffers_[slot].mGraphicBuffer == nullptr)) {
    449         ALOGE("queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
    450               "mGraphicBuffer=%p)",
    451               slot, buffers_[slot].mRequestBufferCalled, buffers_[slot].mGraphicBuffer.get());
    452         return BAD_VALUE;
    453     }
    454 
    455     // Post the producer buffer with timestamp in the metadata.
    456     const auto& producer_buffer = buffers_[slot].mProducerBuffer;
    457 
    458     // Check input crop is not out of boundary of current buffer.
    459     Rect buffer_rect(producer_buffer->width(), producer_buffer->height());
    460     Rect cropped_rect(Rect::EMPTY_RECT);
    461     crop.intersect(buffer_rect, &cropped_rect);
    462     if (cropped_rect != crop) {
    463         ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
    464         return BAD_VALUE;
    465     }
    466 
    467     LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
    468 
    469     DvrNativeBufferMetadata meta_data;
    470     meta_data.timestamp = timestamp;
    471     meta_data.is_auto_timestamp = int32_t(is_auto_timestamp);
    472     meta_data.dataspace = int32_t(dataspace);
    473     meta_data.crop_left = crop.left;
    474     meta_data.crop_top = crop.top;
    475     meta_data.crop_right = crop.right;
    476     meta_data.crop_bottom = crop.bottom;
    477     meta_data.scaling_mode = int32_t(scaling_mode);
    478     meta_data.transform = int32_t(transform);
    479 
    480     producer_buffer->PostAsync(&meta_data, fence_fd);
    481     buffers_[slot].mBufferState.queue();
    482 
    483     output->width = producer_buffer->width();
    484     output->height = producer_buffer->height();
    485     output->transformHint = 0; // default value, we don't use it yet.
    486 
    487     // |numPendingBuffers| counts of the number of buffers that has been enqueued
    488     // by the producer but not yet acquired by the consumer. Due to the nature
    489     // of BufferHubQueue design, this is hard to trace from the producer's client
    490     // side, but it's safe to assume it's zero.
    491     output->numPendingBuffers = 0;
    492 
    493     // Note that we are not setting nextFrameNumber here as it seems to be only
    494     // used by surface flinger. See more at b/22802885, ag/791760.
    495     output->nextFrameNumber = 0;
    496 
    497     return NO_ERROR;
    498 }
    499 
    500 status_t BufferHubProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
    501     ALOGV(__FUNCTION__);
    502 
    503     std::unique_lock<std::mutex> lock(mutex_);
    504 
    505     if (connected_api_ == kNoConnectedApi) {
    506         ALOGE("cancelBuffer: BufferQueue has no connected producer");
    507         return NO_INIT;
    508     }
    509 
    510     if (slot < 0 || slot >= max_buffer_count_) {
    511         ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
    512         return BAD_VALUE;
    513     } else if (!buffers_[slot].mBufferState.isDequeued()) {
    514         ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)", slot,
    515               buffers_[slot].mBufferState.string());
    516         return BAD_VALUE;
    517     } else if (fence == nullptr) {
    518         ALOGE("cancelBuffer: fence is NULL");
    519         return BAD_VALUE;
    520     }
    521 
    522     auto producer_buffer = buffers_[slot].mProducerBuffer;
    523     queue_->Enqueue(producer_buffer, size_t(slot), 0U);
    524     buffers_[slot].mBufferState.cancel();
    525     buffers_[slot].mFence = fence;
    526     ALOGV("cancelBuffer: slot %d", slot);
    527 
    528     return NO_ERROR;
    529 }
    530 
    531 status_t BufferHubProducer::query(int what, int* out_value) {
    532     ALOGV(__FUNCTION__);
    533 
    534     std::unique_lock<std::mutex> lock(mutex_);
    535 
    536     if (out_value == nullptr) {
    537         ALOGE("query: out_value was NULL");
    538         return BAD_VALUE;
    539     }
    540 
    541     int value = 0;
    542     switch (what) {
    543         case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
    544             // TODO(b/36187402) This should be the maximum number of buffers that this
    545             // producer queue's consumer can acquire. Set to be at least one. Need to
    546             // find a way to set from the consumer side.
    547             value = kDefaultUndequeuedBuffers;
    548             break;
    549         case NATIVE_WINDOW_BUFFER_AGE:
    550             value = 0;
    551             break;
    552         case NATIVE_WINDOW_WIDTH:
    553             value = int32_t(queue_->default_width());
    554             break;
    555         case NATIVE_WINDOW_HEIGHT:
    556             value = int32_t(queue_->default_height());
    557             break;
    558         case NATIVE_WINDOW_FORMAT:
    559             value = int32_t(queue_->default_format());
    560             break;
    561         case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
    562             // BufferHubQueue is always operating in async mode, thus semantically
    563             // consumer can never be running behind. See BufferQueueCore.cpp core
    564             // for more information about the original meaning of this flag.
    565             value = 0;
    566             break;
    567         case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
    568             // TODO(jwcai) This is currently not implement as we don't need
    569             // IGraphicBufferConsumer parity.
    570             value = 0;
    571             break;
    572         case NATIVE_WINDOW_DEFAULT_DATASPACE:
    573             // TODO(jwcai) Return the default value android::BufferQueue is using as
    574             // there is no way dvr::ConsumerQueue can set it.
    575             value = 0; // HAL_DATASPACE_UNKNOWN
    576             break;
    577         case NATIVE_WINDOW_STICKY_TRANSFORM:
    578             // TODO(jwcai) Return the default value android::BufferQueue is using as
    579             // there is no way dvr::ConsumerQueue can set it.
    580             value = 0;
    581             break;
    582         case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
    583             // In Daydream's implementation, the consumer end (i.e. VR Compostior)
    584             // knows how to handle protected buffers.
    585             value = 1;
    586             break;
    587         default:
    588             return BAD_VALUE;
    589     }
    590 
    591     ALOGV("query: key=%d, v=%d", what, value);
    592     *out_value = value;
    593     return NO_ERROR;
    594 }
    595 
    596 status_t BufferHubProducer::connect(const sp<IProducerListener>& /* listener */, int api,
    597                                     bool /* producer_controlled_by_app */,
    598                                     QueueBufferOutput* output) {
    599     // Consumer interaction are actually handled by buffer hub, and we need
    600     // to maintain consumer operations here. We only need to perform basic input
    601     // parameter checks here.
    602     ALOGV(__FUNCTION__);
    603 
    604     if (output == nullptr) {
    605         return BAD_VALUE;
    606     }
    607 
    608     std::unique_lock<std::mutex> lock(mutex_);
    609 
    610     if (connected_api_ != kNoConnectedApi) {
    611         return BAD_VALUE;
    612     }
    613 
    614     if (!queue_->is_connected()) {
    615         ALOGE("BufferHubProducer::connect: This BufferHubProducer is not "
    616               "connected to bufferhud. Has it been taken out as a parcelable?");
    617         return BAD_VALUE;
    618     }
    619 
    620     switch (api) {
    621         case NATIVE_WINDOW_API_EGL:
    622         case NATIVE_WINDOW_API_CPU:
    623         case NATIVE_WINDOW_API_MEDIA:
    624         case NATIVE_WINDOW_API_CAMERA:
    625             connected_api_ = api;
    626 
    627             output->width = queue_->default_width();
    628             output->height = queue_->default_height();
    629 
    630             // default values, we don't use them yet.
    631             output->transformHint = 0;
    632             output->numPendingBuffers = 0;
    633             output->nextFrameNumber = 0;
    634             output->bufferReplaced = false;
    635 
    636             break;
    637         default:
    638             ALOGE("BufferHubProducer::connect: unknow API %d", api);
    639             return BAD_VALUE;
    640     }
    641 
    642     return NO_ERROR;
    643 }
    644 
    645 status_t BufferHubProducer::disconnect(int api, DisconnectMode /*mode*/) {
    646     // Consumer interaction are actually handled by buffer hub, and we need
    647     // to maintain consumer operations here.  We only need to perform basic input
    648     // parameter checks here.
    649     ALOGV(__FUNCTION__);
    650 
    651     std::unique_lock<std::mutex> lock(mutex_);
    652 
    653     if (kNoConnectedApi == connected_api_) {
    654         return NO_INIT;
    655     } else if (api != connected_api_) {
    656         return BAD_VALUE;
    657     }
    658 
    659     FreeAllBuffers();
    660     connected_api_ = kNoConnectedApi;
    661     return NO_ERROR;
    662 }
    663 
    664 status_t BufferHubProducer::setSidebandStream(const sp<NativeHandle>& stream) {
    665     if (stream != nullptr) {
    666         // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
    667         // metadata.
    668         ALOGE("SidebandStream is not currently supported.");
    669         return INVALID_OPERATION;
    670     }
    671     return NO_ERROR;
    672 }
    673 
    674 void BufferHubProducer::allocateBuffers(uint32_t /* width */, uint32_t /* height */,
    675                                         PixelFormat /* format */, uint64_t /* usage */) {
    676     // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
    677     // of buffers permitted by the current BufferQueue configuration (aka
    678     // |max_buffer_count_|).
    679     ALOGE("BufferHubProducer::allocateBuffers not implemented.");
    680 }
    681 
    682 status_t BufferHubProducer::allowAllocation(bool /* allow */) {
    683     ALOGE("BufferHubProducer::allowAllocation not implemented.");
    684     return INVALID_OPERATION;
    685 }
    686 
    687 status_t BufferHubProducer::setGenerationNumber(uint32_t generation_number) {
    688     ALOGV(__FUNCTION__);
    689 
    690     std::unique_lock<std::mutex> lock(mutex_);
    691     generation_number_ = generation_number;
    692     return NO_ERROR;
    693 }
    694 
    695 String8 BufferHubProducer::getConsumerName() const {
    696     // BufferHub based implementation could have one to many producer/consumer
    697     // relationship, thus |getConsumerName| from the producer side does not
    698     // make any sense.
    699     ALOGE("BufferHubProducer::getConsumerName not supported.");
    700     return String8("BufferHubQueue::DummyConsumer");
    701 }
    702 
    703 status_t BufferHubProducer::setSharedBufferMode(bool shared_buffer_mode) {
    704     if (shared_buffer_mode) {
    705         ALOGE("BufferHubProducer::setSharedBufferMode(true) is not supported.");
    706         // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
    707         return INVALID_OPERATION;
    708     }
    709     // Setting to default should just work as a no-op.
    710     return NO_ERROR;
    711 }
    712 
    713 status_t BufferHubProducer::setAutoRefresh(bool auto_refresh) {
    714     if (auto_refresh) {
    715         ALOGE("BufferHubProducer::setAutoRefresh(true) is not supported.");
    716         return INVALID_OPERATION;
    717     }
    718     // Setting to default should just work as a no-op.
    719     return NO_ERROR;
    720 }
    721 
    722 status_t BufferHubProducer::setDequeueTimeout(nsecs_t timeout) {
    723     ALOGV(__FUNCTION__);
    724 
    725     std::unique_lock<std::mutex> lock(mutex_);
    726     dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
    727     return NO_ERROR;
    728 }
    729 
    730 status_t BufferHubProducer::getLastQueuedBuffer(sp<GraphicBuffer>* /* out_buffer */,
    731                                                 sp<Fence>* /* out_fence */,
    732                                                 float /*out_transform_matrix*/[16]) {
    733     ALOGE("BufferHubProducer::getLastQueuedBuffer not implemented.");
    734     return INVALID_OPERATION;
    735 }
    736 
    737 void BufferHubProducer::getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {
    738     ALOGE("BufferHubProducer::getFrameTimestamps not implemented.");
    739 }
    740 
    741 status_t BufferHubProducer::getUniqueId(uint64_t* out_id) const {
    742     ALOGV(__FUNCTION__);
    743 
    744     *out_id = unique_id_;
    745     return NO_ERROR;
    746 }
    747 
    748 status_t BufferHubProducer::getConsumerUsage(uint64_t* out_usage) const {
    749     ALOGV(__FUNCTION__);
    750 
    751     // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS
    752     *out_usage = 0;
    753     return NO_ERROR;
    754 }
    755 
    756 status_t BufferHubProducer::TakeAsParcelable(ProducerQueueParcelable* out_parcelable) {
    757     if (!out_parcelable || out_parcelable->IsValid()) return BAD_VALUE;
    758 
    759     if (connected_api_ != kNoConnectedApi) {
    760         ALOGE("BufferHubProducer::TakeAsParcelable: BufferHubProducer has "
    761               "connected client. Must disconnect first.");
    762         return BAD_VALUE;
    763     }
    764 
    765     if (!queue_->is_connected()) {
    766         ALOGE("BufferHubProducer::TakeAsParcelable: This BufferHubProducer "
    767               "is not connected to bufferhud. Has it been taken out as a "
    768               "parcelable?");
    769         return BAD_VALUE;
    770     }
    771 
    772     auto status = queue_->TakeAsParcelable();
    773     if (!status) {
    774         ALOGE("BufferHubProducer::TakeAsParcelable: Failed to take out "
    775               "ProducuerQueueParcelable from the producer queue, error: %s.",
    776               status.GetErrorMessage().c_str());
    777         return BAD_VALUE;
    778     }
    779 
    780     *out_parcelable = status.take();
    781     return NO_ERROR;
    782 }
    783 
    784 status_t BufferHubProducer::AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
    785                                            PixelFormat format, uint64_t usage) {
    786     auto status = queue_->AllocateBuffer(width, height, layer_count, uint32_t(format), usage);
    787     if (!status) {
    788         ALOGE("BufferHubProducer::AllocateBuffer: Failed to allocate buffer: %s",
    789               status.GetErrorMessage().c_str());
    790         return NO_MEMORY;
    791     }
    792 
    793     size_t slot = status.get();
    794     auto producer_buffer = queue_->GetBuffer(slot);
    795 
    796     LOG_ALWAYS_FATAL_IF(producer_buffer == nullptr,
    797                         "Failed to get the producer buffer at slot: %zu", slot);
    798 
    799     buffers_[slot].mProducerBuffer = producer_buffer;
    800 
    801     return NO_ERROR;
    802 }
    803 
    804 status_t BufferHubProducer::RemoveBuffer(size_t slot) {
    805     auto status = queue_->RemoveBuffer(slot);
    806     if (!status) {
    807         ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer at slot: %zu, error: %s.",
    808               slot, status.GetErrorMessage().c_str());
    809         return INVALID_OPERATION;
    810     }
    811 
    812     // Reset in memory objects related the the buffer.
    813     buffers_[slot].mProducerBuffer = nullptr;
    814     buffers_[slot].mBufferState.detachProducer();
    815     buffers_[slot].mFence = Fence::NO_FENCE;
    816     buffers_[slot].mGraphicBuffer = nullptr;
    817     buffers_[slot].mRequestBufferCalled = false;
    818     return NO_ERROR;
    819 }
    820 
    821 status_t BufferHubProducer::FreeAllBuffers() {
    822     for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
    823         // Reset in memory objects related the the buffer.
    824         buffers_[slot].mProducerBuffer = nullptr;
    825         buffers_[slot].mBufferState.reset();
    826         buffers_[slot].mFence = Fence::NO_FENCE;
    827         buffers_[slot].mGraphicBuffer = nullptr;
    828         buffers_[slot].mRequestBufferCalled = false;
    829     }
    830 
    831     auto status = queue_->FreeAllBuffers();
    832     if (!status) {
    833         ALOGE("BufferHubProducer::FreeAllBuffers: Failed to free all buffers on "
    834               "the queue: %s",
    835               status.GetErrorMessage().c_str());
    836     }
    837 
    838     if (queue_->capacity() != 0 || queue_->count() != 0) {
    839         LOG_ALWAYS_FATAL("BufferHubProducer::FreeAllBuffers: Not all buffers are freed.");
    840     }
    841 
    842     return NO_ERROR;
    843 }
    844 
    845 status_t BufferHubProducer::exportToParcel(Parcel* parcel) {
    846     status_t res = TakeAsParcelable(&pending_producer_parcelable_);
    847     if (res != NO_ERROR) return res;
    848 
    849     if (!pending_producer_parcelable_.IsValid()) {
    850         ALOGE("BufferHubProducer::exportToParcel: Invalid parcelable object.");
    851         return BAD_VALUE;
    852     }
    853 
    854     res = parcel->writeUint32(USE_BUFFER_HUB);
    855     if (res != NO_ERROR) {
    856         ALOGE("BufferHubProducer::exportToParcel: Cannot write magic, res=%d.", res);
    857         return res;
    858     }
    859 
    860     return pending_producer_parcelable_.writeToParcel(parcel);
    861 }
    862 
    863 IBinder* BufferHubProducer::onAsBinder() {
    864     ALOGE("BufferHubProducer::onAsBinder: BufferHubProducer should never be used as an Binder "
    865           "object.");
    866     return nullptr;
    867 }
    868 
    869 } // namespace android
    870