Android 16 显示系统 | 从View 到屏幕系列 - 3 | BLASTBufferQueue

2,148 阅读5分钟

写在前面

BLastBufferQueue 的全称: Buffer Layer Async Transaction BufferQueue,BLastBufferQueue 作为桥梁连接了 App 和 SurfaceFlinger。App 需要通过事务 Transaction 来向 SurfaceFlinger 来提交 Buffer,然后再做进一步的合成。 BLastBufferQueue 由 Producer + Comsumer + BufferQueueCore 组成

  • Producer: 从 Buffer Queue 中申请 GraphicBuffer,当 App 把 UI 渲染到这块 Buffer 之后,负责把这块 Buffer 插入 Buffer Queue
  • Comsumer: 可以消费插入到 Buffer Queue 的 GraphicBuffer,并且把 GraphicBuffer 提交到 SurfaceFlinger
  • BufferQueueCore: 管理 Buffer Queue

BLastBufferQueue 整个架构图如下:

display_1.png

BLASTBufferQueue 的创建

BLASTBufferQueue 创建发生在 SurfaceControl 创建之后

 //frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
            int lastSyncSeqId, WindowRelayoutResult outRelayoutResult) {
        ...
        // 创建一个 SurfaceControl
        result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
        ...
        if (mSurfaceControl.isValid()) {
            updateBlastSurfaceIfNeeded();
        }
        ...
    }    

在 updateBlastSurfaceIfNeeded 中会创建 BLASTBufferQueue

    void updateBlastSurfaceIfNeeded() {
        // 创建 BLASTBufferQueue
        mBlastBufferQueue = new BLASTBufferQueue(mTag, true /* updateDestinationFrame */);
        mBlastBufferQueue.setApplyToken(mBbqApplyToken);
        mBlastBufferQueue.update(mSurfaceControl,  mSurfaceSize.x, mSurfaceSize.y,
                mWindowAttributes.format);
        mBlastBufferQueue.setTransactionHangCallback(sTransactionHangCallback);
        mBlastBufferQueue.setWaitForBufferReleaseCallback(mChoreographer::onWaitForBufferRelease);
        Surface blastSurface;
        // 创建 blastSurface
        if (addSchandleToVriSurface()) {
            blastSurface = mBlastBufferQueue.createSurfaceWithHandle();
        } else {
            blastSurface = mBlastBufferQueue.createSurface();
        }
        // Only call transferFrom if the surface has changed to prevent inc the generation ID and
        // 把创建的 blastSurface 给 mSurface
        mSurface.transferFrom(blastSurface);
        ...
    }

这里 new BLASTBufferQueue 会调用 BLASTBufferQueue 的构造函数

//frameworks/base/graphics/java/android/graphics/BLASTBufferQueue.java
public BLASTBufferQueue(String name, boolean updateDestinationFrame) {
    mNativeObject = nativeCreate(name, updateDestinationFrame);
}

nativeCreate 是一个 native方法

// frameworks/base/core/jni/android_graphics_BLASTBufferQueue.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName,
                          jboolean updateDestinationFrame) {
    
    sp<BLASTBufferQueue> queue = sp<BLASTBufferQueue>::make(name.c_str(), updateDestinationFrame);
    queue->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(queue.get());
}

在这里创建了 native 层的 BLASTBufferQueue 对象,它的构造函数如下

// frameworks/native/libs/gui/BLASTBufferQueue.cpp
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
      : mSurfaceControl(nullptr),
        mSize(1, 1),
        mRequestedSize(mSize),
        mFormat(PIXEL_FORMAT_RGBA_8888),
        mTransactionReadyCallback(nullptr),
        mSyncTransaction(nullptr),
        mUpdateDestinationFrame(updateDestinationFrame) {
    // 重点1:创建 BufferQueueCore,mProducer 和 mConsumer
    createBufferQueue(&mProducer, &mConsumer);
    // 重点2:创建 mBufferItemConsumer
    mBufferItemConsumer = sp<BLASTBufferItemConsumer>::make(mConsumer,GraphicBuffer::USAGE_HW_COMPOSER |GraphicBuffer::USAGE_HW_TEXTURE, 1, false, this);
    mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());

    static std::atomic<uint32_t> nextId = 0;
    mProducerId = nextId++;
    mName = name + "#" + std::to_string(mProducerId);
    auto consumerName = mName + "(BLAST Consumer)" + std::to_string(mProducerId);
    mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(mProducerId);
    mBufferItemConsumer->setName(String8(consumerName.c_str()));
    // 重点3:把 FrameAvailableListener 的回调设置成自己, 也就是 BLASTBufferQueue
    mBufferItemConsumer->setFrameAvailableListener(this);
    ...
}

在 BLASTBufferQueue 的构造函数中

  1. 初始化 BufferQueueCore, Comsumer 和 Producer
  2. 创建 BufferItemConsumer对象,和设置各种参数,特别地,把 FrameAvailableListener 的回调设置成 BLASTBufferQueue 自己,为什么会这么做,下一小节会提到。 接下来详细分析这两步的实现

createBufferQueue

void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                                         sp<IGraphicBufferConsumer>* outConsumer) {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    auto core = sp<BBQBufferQueueCore>::make(this);
#else
    auto core = sp<BufferQueueCore>::make();
#endif
    ...
    auto producer = sp<BBQBufferQueueProducer>::make(core, this);
    auto consumer = sp<BufferQueueConsumer>::make(core);
    *outProducer = producer;
    *outConsumer = consumer;
}

在 createBufferQueue 中

  1. 创建 BufferQueueCore
  2. 创建 BBQBufferQueueProducer 并赋给 mProducer
  3. 创建 BufferQueueConsumer 并赋给 mConsumer
创建 BufferQueueCore

BBQBufferQueueCore 是 BufferQueueCore 的一个装饰,比 BufferQueueCore 多了一个 notify Buffer released 的功能。所以我们可以只看 BufferQueueCore

BufferQueueCore::BufferQueueCore()
      : mMutex(),
        mIsAbandoned(false),
        mConsumerControlledByApp(false),
        mConsumerName(getUniqueName()),
        mConsumerListener(),
        mConsumerUsageBits(0),
        mConsumerIsProtected(false),
        mConnectedApi(NO_CONNECTED_API),
        mLinkedToDeath(),
        mConnectedProducerListener(),
        mBufferReleasedCbEnabled(false),
        mBufferAttachedCbEnabled(false),
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
#else
        mSlots(),
#endif
        mQueue(),
        mFreeSlots(),
        mFreeBuffers(),
        mUnusedSlots(),
        mActiveBuffers(),
        mDequeueCondition(),
        mDequeueBufferCannotBlock(false),
        mQueueBufferCanDrop(false),
        mLegacyBufferDrop(true),
        mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
        mDefaultWidth(1),
        mDefaultHeight(1),
        mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
        mAllowExtendedSlotCount(false),
#endif
        mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
        mMaxAcquiredBufferCount(1),
        mMaxDequeuedBufferCount(1),
        mBufferHasBeenQueued(false),
        mFrameCounter(0),
        mTransformHint(0),
        mIsAllocating(false),
        mIsAllocatingCondition(),
        mAllowAllocation(true),
        mBufferAge(0),
        mGenerationNumber(0),
        mAsyncMode(false),
        mSharedBufferMode(false),
        mAutoRefresh(false),
        mSharedBufferSlot(INVALID_BUFFER_SLOT),
        mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
                           HAL_DATASPACE_UNKNOWN),
        mLastQueuedSlot(INVALID_BUFFER_SLOT),
        mUniqueId(getUniqueId()),
        mAutoPrerotation(false),
        mTransformHintInUse(0) {
    int numStartingBuffers = getMaxBufferCountLocked();
    for (int s = 0; s < numStartingBuffers; s++) {
        mFreeSlots.insert(s);
    }
    for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
            s++) {
        mUnusedSlots.push_front(s);
    }
}

BufferQueueCore 的构造函数,只是对 BufferQueueCore 的成员变量进行初始化,这些成员变量中,比较重要的就是 mSlots 和 mQueue

frameworks/native/libs/gui/include/gui/BufferQueueCore.h
...
BufferQueueDefs::SlotsType mSlots;
// mQueue is a FIFO of queued buffers used in synchronous mode.
Fifo mQueue;
...
BufferQueueDefs::SlotsType mSlots

mSlots 是一个 BufferSlot 的 Vector

// frameworks/native/libs/gui/include/gui/BufferQueueDefs.h
typedef std::vector<BufferSlot> SlotsType;

而 BufferSlot 则用来表达一块 GraphicBuffer 以及这块 GraphicBuffer 的状态

// frameworks/native/libs/gui/include/gui/BufferSlot.h
struct BufferSlot {
    // mGraphicBuffer points to the buffer allocated for this slot or is NULL
    sp<GraphicBuffer> mGraphicBuffer;
    // mBufferState is the current state of this buffer slot.
    BufferState mBufferState;
    ...
}
Fifo mQueue

BufferQueueCore 的另外一个成员 mQueue 本质上也是一个 BufferItem 类型 Vector

// frameworks/native/libs/gui/include/gui/BufferQueueCore.h
typedef Vector<BufferItem> Fifo;

BufferItem 和 BufferSlot 类似,也是代表一个 GraphicBuffer

// 
class BufferItem : public Flattenable<BufferItem> {
    ...
    sp<GraphicBuffer> mGraphicBuffer;
    ...
}

但是 BufferItem 和 BufferSlot 不同的是,BufferItem 支持序列化,意味着它可以通过 IPC 传递,那这两者之间是如何协作的呢?

  1. Producer 从 mSlots 中拿到一块 BufferSlot, 写入
  2. BufferSlot 转换成 BufferItem 插入 mQueue
  3. Comsumer 从 mQueue 中取出 BufferItem
  4. BufferItem 转换成 BufferSlot 提交给 SurfaceFlinger 所以,我们可以看出 mQueue 的主要作用是 “控制 Buffer 的出队顺序”

创建 BBQBufferQueueProducer

BBQBufferQueueProducer 负责从 BufferQueueCore 里面 queuebuffer

class BBQBufferQueueProducer : public BufferQueueProducer {
public:
    BBQBufferQueueProducer(const sp<BufferQueueCore>& core, const wp<BLASTBufferQueue>& bbq)
          : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
            mBLASTBufferQueue(bbq) {}
}

BBQBufferQueueProducer 构造函数中创建了它的父类 BufferQueueProducer,在 BufferQueueProducer 中提供了核心方法

// frameworks/native/libs/gui/include/gui/BufferQueueProducer.h
...
virtual status_t queueBuffer(int slot,
            const QueueBufferInput& input, QueueBufferOutput* output);
...

创建 BufferQueueConsumer

BufferQueueConsumer 负责从 BufferQueueCore 获取 GraphicBuffer,所以在 BufferQueueConsumer 中提供了 acquireBuffer 和 releaseBuffer 等核心方法

// prebuilts/vndk/v30/arm/include/frameworks/native/libs/gui/include/gui/BufferQueueConsumer.h
class BufferQueueConsumer : public BnGraphicBufferConsumer {
    ...
    virtual status_t acquireBuffer(BufferItem* outBuffer,
            nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;
            
    virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
            EGLDisplay display, EGLSyncKHR fence,
            const sp<Fence>& releaseFence) {
        return releaseBuffer(buf, frameNumber, releaseFence, display, fence);
    }
    ...
    sp<BufferQueueCore> mCore;
}

创建 BLASTBufferItemConsumer

// frameworks/native/libs/gui/BLASTBufferQueue.cpp
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
      : mSurfaceControl(nullptr),
        mSize(1, 1),
        mRequestedSize(mSize),
        mFormat(PIXEL_FORMAT_RGBA_8888),
        mTransactionReadyCallback(nullptr),
        mSyncTransaction(nullptr),
        mUpdateDestinationFrame(updateDestinationFrame) {
    ...
    mBufferItemConsumer = sp<BLASTBufferItemConsumer>::make(mConsumer,GraphicBuffer::USAGE_HW_COMPOSER |GraphicBuffer::USAGE_HW_TEXTURE, 1, false, this);
    ...
}

BLASTBufferItemConsumer 的构造函数如下

// prebuilts/vndk/v30/x86/include/frameworks/native/libs/gui/include/gui/BLASTBufferQueue.h
    BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,int bufferCount, bool controlledByApp)
          : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
            mCurrentlyConnected(false),
            mPreviouslyConnected(false) {}

BLASTBufferItemConsumer 的构造函数会调用父类 BufferItemConsumer 的构造函数

// frameworks/native/libs/gui/BufferItemConsumer.cpp
BufferItemConsumer::BufferItemConsumer(
        const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
        int bufferCount, bool controlledByApp) :
    ConsumerBase(consumer, controlledByApp)
{
    initialize(consumerUsage, bufferCount);
}

进而调用 ConsumerBase 的构造函数

// frameworks/native/libs/gui/ConsumerBase.cpp
ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp)
      :
        mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
        mAbandoned(false),
        mConsumer(bufferQueue),
        mPrevFinalReleaseFence(Fence::NO_FENCE) {
    initialize(controlledByApp);
}


void ConsumerBase::initialize(bool controlledByApp) {
    ...
    // 这个 listener 就是 BLASTBufferItemConsumer 本身
    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
    // mConsumer是 BufferQueueConsumer
    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
}

这里把 BLASTBufferItemConsumer 和 BufferQueueConsumer 通过 consumerConnect 关联起来,我们接下来看 consumerConnect 做了什么

    // frameworks/native/libs/gui/include/gui/BufferQueueConsumer.h
    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
            bool controlledByApp) {
        return connect(consumer, controlledByApp);
    }
    
    // frameworks/native/libs/gui/BufferQueueConsumer.cpp
    status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ...
    把 BufferQueueCore 的 mConsumerListener 设置成 BLASTBufferItemConsumer
    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;

    return NO_ERROR;
} 

这里绕了一大圈,最终实现的就是把 BufferQueueCore->mConsumerListener 设置成BLASTBufferItemConsumer, 为什么要这么做,在下一个小节会提到。

到这里为止,BLASTBufferQueue 就介绍完了,BLASTBufferQueue 连接了 App 和 SurfaceFlinger。