Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

二的次方發表於2022-03-22

題外話

疫情隔離在家,週末還在努力學習的我  .....

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)


 

一、前言


上一篇文章中,有基本講清楚Producer一端的處理邏輯,最後也留下了一個疑問:

Consumer是什麼時候來消費資料的?他是自己主動來取的?還是收到了某種通知後再來處理的?

這篇文章,就帶著這些疑問來開始分析原始碼。開頭還是把這種流程圖貼一下

 

二、Listener監聽器的回撥過程解析


生產者寫完資料,把buffer還給buffer queue後,又是怎樣通知消費者來使用的呢?

下面這些解析步驟,就是回答上面的問題

1. 生產者把資料寫入buffer後,呼叫BufferQueueProducer::queueBuffer 入佇列這個buffer;

2. 怎麼去通知消費者來取呢? queueBuffer函式中會呼叫frameAvailableListener->onFrameAvailable(item);

3. frameAvailableListener是什麼呢?frameAvailableListener = mCore->mConsumerListener;

4. mCore即為BufferQueueCore, BufferQueueCore中有成員 sp<IConsumerListener> mConsumerListener

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)
5. BufferQueueCore::mConsumerListener 是什麼時候設定的呢?

    (1) BufferQueueConsumer::connect中設定

status_t BufferQueueConsumer::connect(
        const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
    ....
    mCore->mConsumerListener = consumerListener;
    mCore->mConsumerControlledByApp = controlledByApp;
}

    (2) BufferQueueConsumer::disconnect中清除

status_t BufferQueueConsumer::disconnect() {
    ...
    mCore->mConsumerListener = nullptr;
}

    注:BufferQueueProducer和BufferQueueConsumer是BufferQueueCore的友元類,所以可以直接訪問其私有成員

6. BufferQueueConsumer::connect、disconnect是在哪裡呼叫的呢?

    (1)BufferQueueConsumer::consumerConnect中呼叫connect設定監聽器;

    (2)BufferQueueConsumer::consumerDisconnect中呼叫disconnect清除;

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

7. 誰呼叫了consumerConnect呢?

    (1)ConsumerBase 的建構函式中呼叫 mConsumer->consumerConnect(proxy, controlledByApp);

    (2)這裡的mConsumer是BLASTBufferQueue中建立BLASTBufferItemConsumer時一路設定下來的BufferQueueConsumer物件;

8. 設定是的Listener是從哪裡傳遞過來的呢?

    (1)繼承關係

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

     (2)BLASTBufferQueue的建構函式中:

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)
9. 所以BufferQueueCore::mConsumerListener設定的就是ConsumerBase的例項

10. 因此,frameAvailableListener->onFrameAvailable(item)回撥時,會走到ConsumerBase::onFrameAvailable中

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

 


本文作者@二的次方  2022-03-22釋出於部落格園


=========== 再接著下一個階段 ==========

11. ConsumerBase::onFrameAvailable中繼續呼叫


void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    CB_LOGV("onFrameAvailable");

    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock lock(mFrameAvailableMutex);
        listener = mFrameAvailableListener.promote();
    }

    if (listener != nullptr) {
        CB_LOGV("actually calling onFrameAvailable");
        listener->onFrameAvailable(item);
    }
}

12. ConsumerBase中的成員mFrameAvailableListener是什麼東西呢?

    (1)ConsumerBase類中成員定義 wp<FrameAvailableListener> mFrameAvailableListener;

    (2)繼承關係 BLASTBufferQueue繼承自ConsumerBase::FrameAvailableListener,並實現onFrameAvailable方法

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

    (3)在BLASTBufferQueue的建構函式中:mBufferItemConsumer->setFrameAvailableListener(this);

    (4)最終會呼叫到ConsumerBase::setFrameAvailableListener

    (5)所以ConsumerBase中的成員mFrameAvailableListener指向的是BLASTBufferQueue例項物件

13. 所以,ConsumerBase::onFrameAvailable再繼續回撥時,流程就回到了BLASTBufferQueue::onFrameAvailable

void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
    ....
    processNextBufferLocked(nextTransactionSet /* useNextTransaction */);
}

14. 繼續走就進到BLASTBufferQueue::processNextBufferLocked

void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
    ....
    BufferItem bufferItem;
    status_t status =
            mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
    ....
}

15. 消費者呼叫acquireBuffer去BufferQueue中請求一個可以處理的buffer

Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

16. 處理就回到了BufferQueue的acquireBuffer邏輯

 


為了驗證分析正確,在BufferQueueConsumer中加log,列印stack dump:

11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#00 pc 00056f69  /system/lib/libgui.so (android::BufferQueueConsumer::acquireBuffer(android::BufferItem*, long long, unsigned long long)+72)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#01 pc 00076967  /system/lib/libgui.so (android::ConsumerBase::acquireBufferLocked(android::BufferItem*, long long, unsigned long long)+62)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#02 pc 000756cd  /system/lib/libgui.so (android::BufferItemConsumer::acquireBuffer(android::BufferItem*, long long, bool)+44)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#03 pc 0006c8b5  /system/lib/libgui.so (android::BLASTBufferQueue::processNextBufferLocked(bool)+164)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#04 pc 0006d8d9  /system/lib/libgui.so (android::BLASTBufferQueue::onFrameAvailable(android::BufferItem const&)+132)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#05 pc 000761ab  /system/lib/libgui.so (android::ConsumerBase::onFrameAvailable(android::BufferItem const&)+110)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#06 pc 000563e9  /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+52)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#07 pc 0005da6f  /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+1858)
11-13 01:23:57.893  3016  3064 E BufferQueueConsumer: stackdump:#08 pc 000a0d8b  /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+442)

如logcat所示,符合我們分析的邏輯過程。

 

千辛萬苦終於走到BufferQueueConsumer::acquireBuffer的地方!

此時流程已經到了開頭圖片的右半邊描述的邏輯,我們下篇文章繼續分析

 

三、小結


這篇文章主要解析了Produncer呼叫queueBuffer後,如何通過FrameAvailableListener把資訊通知到Consumer,也解析了FrameAvailableListener是在哪裡設定的。

 


必讀:

Android 12(S) 圖形顯示系統 - 開篇

 



Android 12(S) 圖形顯示系統 - BufferQueue的工作流程(十)

 

相關文章