// Allocates buffers based on the given dimensions/format.
//
// This function will allocate up to the maximum number of buffers
// permitted by the current BufferQueue configuration. It will use the
// given format, dimensions, and usage bits, which are interpreted in the
// same way as for dequeueBuffer, and the async flag must be set the same
// way as for dequeueBuffer to ensure that the correct number of buffers are
// allocated. This is most useful to avoid an allocation delay during
// dequeueBuffer. If there are already the maximum number of buffers
// allocated, this function has no effect.
void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
        PixelFormat format, uint64_t usage) {

根据参数分配 buffer,该函数会根据 BufferQueue 允许的最大数量分配 buffer。它的最大用处是避免分配延迟,但没看到哪里在使用。

还是简单把实现机制说明一下。

while (true) {
    { // Autolock scope
        std::unique_lock<std::mutex> lock(mCore->mMutex);
        mCore->waitWhileAllocatingLocked(lock);

        if (!mCore->mAllowAllocation) {
            BQ_LOGE("allocateBuffers: allocation is not allowed for this "
                    "BufferQueue");
            return;
        }

        // Only allocate one buffer at a time to reduce risks of overlapping an allocation from
        // both allocateBuffers and dequeueBuffer.
        newBufferCount = mCore->mFreeSlots.empty() ? 0 : 1;
        if (newBufferCount == 0) {
            return;
        }

        mCore->mIsAllocating = true;
    } // Autolock scope

Vector<sp<GraphicBuffer>> buffers;
for (size_t i = 0; i < newBufferCount; ++i) {
    sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
            allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
            allocUsage, allocName);

    status_t result = graphicBuffer->initCheck();

    if (result != NO_ERROR) {
        BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
                " %u, usage %#" PRIx64 ")", width, height, format, usage);
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        mCore->mIsAllocating = false;
        mCore->mIsAllocatingCondition.notify_all();
        return;
    }
    buffers.push_back(graphicBuffer);
}
{ // Autolock scope
    if (checkWidth != allocWidth || checkHeight != allocHeight ||
        checkFormat != allocFormat || checkUsage != allocUsage) {
        // Something changed while we released the lock. Retry.
        BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying.");
        mCore->mIsAllocating = false;
        mCore->mIsAllocatingCondition.notify_all();
        continue;
    }

    for (size_t i = 0; i < newBufferCount; ++i) {
        if (mCore->mFreeSlots.empty()) {
            BQ_LOGV("allocateBuffers: a slot was occupied while "
                    "allocating. Dropping allocated buffer.");
            continue;
        }
        auto slot = mCore->mFreeSlots.begin();
        mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
        mSlots[*slot].mGraphicBuffer = buffers[i];
        mSlots[*slot].mFence = Fence::NO_FENCE;

        // freeBufferLocked puts this slot on the free slots list. Since
        // we then attached a buffer, move the slot to free buffer list.
        mCore->mFreeBuffers.push_front(*slot);

        BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
                *slot);

        // Make sure the erase is done after all uses of the slot
        // iterator since it will be invalid after this point.
        mCore->mFreeSlots.erase(slot);
    }

        mCore->mIsAllocating = false;
        mCore->mIsAllocatingCondition.notify_all();
        VALIDATE_CONSISTENCY();

        // If dequeue is waiting for to allocate a buffer, release the lock until it's not
        // waiting anymore so it can use the buffer we just allocated.
        while (mDequeueWaitingForAllocation) {
            mDequeueWaitingForAllocationCondition.wait(lock);
        }
    } // Autolock scope
} // while