Vector<BufferItem> mQueueItems;
////
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
    ...
    mQueueItems.push_back(item);
    mQueuedFrames++;
    // Wake up any pending callbacks
    mLastFrameNumberReceived = item.mFrameNumber;
    mQueueItemCondition.broadcast();
    ...
    mConsumer->onBufferAvailable(item);
}

void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
    ...
    mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
    // Wake up any pending callbacks
    mLastFrameNumberReceived = item.mFrameNumber;
    mQueueItemCondition.broadcast();
    ...
    mConsumer->onBufferAvailable(item);
}

mQueueItems 是 BufferItem 向量。在 onFrameAvailable() 中把可用 BufferItem 插入,在 onFrameReplaced() 中把最后一个替换成新的 BufferItem。

status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
                                          nsecs_t expectedPresentTime) {
    ...
    status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh,
                                                      &queuedBuffer, maxFrameNumberToAcquire);
    ...
    } 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) {
                ...
                mQueueItems.removeAt(0);
                mQueuedFrames--;
            } else {
                ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
            }
        }
        return BAD_VALUE;
    } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
        // This can occur if something goes wrong when trying to create the
        // EGLImage for this buffer. If this happens, the buffer has already
        // been released, so we need to clean up the queue and bug out
        // early.
        if (queuedBuffer) {
            Mutex::Autolock lock(mQueueItemLock);
            mQueueItems.clear();
            mQueuedFrames = 0;
            ...
        }
        return BAD_VALUE;
    }

如果 BufferLayerConsumer::updateTexImage() 返回了 BUFFER_REJECTED,则移除该 BufferItem。如果返回了非 NO_ERROR,则清空 mQueueItems

// Remove any stale buffers that have been dropped during
// updateTexImage
while (mQueuedFrames > 0 && mQueueItems[0].mFrameNumber != currentFrameNumber) {
    ...
    mQueueItems.removeAt(0);
    mQueuedFrames--;
}

if (mQueuedFrames > 0) {
    uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
    mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
    ...
    mQueueItems.removeAt(0);
    more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1);
} else {
        ALOGE("mQueuedFrames <= 0 or mQueueItems.size() = %zu\\n", mQueueItems.size());
}

BufferLayerConsumer::updateTexImage() 返回 NO_ERROR 时,先把 stale buffer 都移除,判断条件是 buffer 的帧数不等于当前帧数。

如果 mQueuedFrames 大于零,则设置 latch time 后移除第一个 BufferItem。