題外話
疫情隔離在家,週末還在努力學習的我 .....
一、前言
上一篇文章中,有基本講清楚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
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清除;
7. 誰呼叫了consumerConnect呢?
(1)ConsumerBase 的建構函式中呼叫 mConsumer->consumerConnect(proxy, controlledByApp);
(2)這裡的mConsumer是BLASTBufferQueue中建立BLASTBufferItemConsumer時一路設定下來的BufferQueueConsumer物件;
8. 設定是的Listener是從哪裡傳遞過來的呢?
(1)繼承關係
(2)BLASTBufferQueue的建構函式中:
9. 所以BufferQueueCore::mConsumerListener設定的就是ConsumerBase的例項
10. 因此,frameAvailableListener->onFrameAvailable(item)回撥時,會走到ConsumerBase::onFrameAvailable中
本文作者@二的次方 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方法
(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
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) 圖形顯示系統 - 開篇