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

1,450 阅读5分钟

写在前面

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

  • Producer:Buffer Queue 中申请 GraphicBuffer,当 App 把 UI 渲染到这块 Buffer 之后,负责把这块 Buffer 插入 Buffer Queue
  • Comsumer: 可以消费插入到 Buffer QueueGraphicBuffer,并且把 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, ComsumerProducer
  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

BBQBufferQueueCoreBufferQueueCore 的一个装饰,比 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 的成员变量进行初始化,这些成员变量中,比较重要的就是 mSlotsmQueue

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;

BufferItemBufferSlot 类似,也是代表一个 GraphicBuffer

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

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

  1. ProducermSlots 中拿到一块 BufferSlot, 写入
  2. BufferSlot 转换成 BufferItem 插入 mQueue
  3. ComsumermQueue 中取出 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 中提供了 acquireBufferreleaseBuffer 等核心方法

// 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);
}

这里把 BLASTBufferItemConsumerBufferQueueConsumer 通过 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。