status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
                                          nsecs_t expectedPresentTime) {
    // updateTexImage() below might drop the some buffers at the head of the queue if there is a
    // buffer behind them which is timely to be presented. However this buffer may not be signaled
    // yet. The code below makes sure that this wouldn't happen by setting maxFrameNumber to the
    // last buffer that was signaled.
    uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived;
    {
        Mutex::Autolock lock(mQueueItemLock);
        for (int i = 0; i < mQueueItems.size(); i++) {
            bool fenceSignaled =
                    mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
            if (!fenceSignaled) {
                break;
            }
            lastSignaledFrameNumber = mQueueItems[i].mFrameNumber;
        }
    }
    const uint64_t maxFrameNumberToAcquire =
            std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);

下面的 BufferQueueLayer::updateTexImage() 会调用 BufferQueueConsumer::acquireBuffer(),而该函数根据策略可能会丢弃头部的 buffer。然而,丢弃之后的剩余的 buffer 可能还没收到信号,所以要计算 maxFrameNumberToAcquire

BufferQueueLayer::mQueueItemsmLastFrameNumberReceived 是在 onFrameAvailable()onFrameReplaced() 中更新的。

    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
                                                      &queuedBuffer, maxFrameNumberToAcquire);

BufferLayerConsumer::updateTexImage() 中先调用 BufferLayerConsumer::acquireBufferLocked() 获取 BufferItem,然后调用 BufferLayerConsumer::updateAndReleaseLocked() 更新 mCurrentTextureBuffer 同时释放上一个 buffer。

BufferLayerConsumer::bindTextureImageLocked() 中调用 RenderEngine 的 bindExternalTextureBuffer() 时传递 mCurrentTextureBuffer->graphicBuffer()

    if (updateResult == BufferQueue::PRESENT_LATER) {
        // Producer doesn't want buffer to be displayed yet.  Signal a
        // layer update so we check again at the next opportunity.
        mFlinger->signalLayerUpdate();
        return BAD_VALUE;
    }

如果返回了 PRESENT_LATER,表示未到 buffer 期望显示时间,调用 signalLayerUpdate() 后返回 BAD_VALUE

     else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
        // If the buffer has been rejected, remove it from the shadow queue
        // and return early
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            if (mQueuedFrames > 0) {
              mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
              mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
              mQueueItems.removeAt(0);
              mQueuedFrames--;
            } else {
                ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
            }
        }
        return BAD_VALUE;
    }
    bool more_frames_pending = false;
    if (queuedBuffer) {
        // Autolock scope
        auto currentFrameNumber = mConsumer->getFrameNumber();
        Mutex::Autolock lock(mQueueItemLock);

        // Remove any stale buffers that have been dropped during
        // updateTexImage
        while (mQueuedFrames > 0 && mQueueItems[0].mFrameNumber != currentFrameNumber) {
            mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage);
            mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber);
            mQueueItems.removeAt(0);
            mQueuedFrames--;
        }

        if (mQueuedFrames > 0) {
          uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
          mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
          mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
                                                 FrameTracer::FrameEvent::LATCH);

          mQueueItems.removeAt(0);
          more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1);
        } else {
                ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
        }
    }

    // Decrement the queued-frames count.  Signal another event if we
    // have more frames pending.
    if ((queuedBuffer && more_frames_pending) || mAutoRefresh) {
        mFlinger->signalLayerUpdate();
    }

    return NO_ERROR;
}