相關文件:
frameworks\native\include\gui\BufferQueue.h
frameworks\native\include\gui\BufferQueueCore.h
frameworks\native\include\ui\BufferQueueDefs.h
顧名思義,BufferQueue是用來保存buffer的queue。Android顯示系統中為此提供了兩個類BufferQueue和BufferQueueCore,從名字上看兩個類都是buffer queue相關,但后者似乎是更核心一些,下面來具體分析這兩個類之間的關系。
BufferQueue
BufferQueue類一開始就定義了幾個非常重要的關鍵屬性值。
- NUM_BUFFER_SLOTS:BufferQueue類定義了一個queue中能夠保存的buffer的最大數量NUM_BUFFER_SLOTS,其數量為64,這是android::BufferQueueDefs命令空間中定義的一個靜態常量NUM_BUFFER_SLOTS,因此無法在runtime過程中改變此值。
- INVALID_BUFFER_SLOT:BufferSlot的默認狀態,即此BufferSlot還未指向已經存在並且有效的buffer時的狀態
- NO_BUFFER_AVAILABLE:一般dequeueBuffer前要查詢BufferQueue中是否有buffer可用,如果沒有,則返回NO_BUFFER_AVAILABLE,表示當前BufferQueue中沒有pending狀態的buffer可用。
- PRESENT_LATER:dequeueBuffer時,如果此時buffer還沒有准備好,則返回PRESENT_LATER,表示此時dequeueBuffer太早了,等會再來dequeue。
- MAX_MAX_ACQUIRED_BUFFERS:當處於異步模式時,系統要預留2個slot以保證producer和consumer之間的異步關系,因此該值等於NUM_BUFFER_SLOTS-2。
BufferQueue類中還定義了一個ProxyConsumerListener類,其繼承關系如下圖所示:
從繼承關系上看,ProxyConsumerListener類是一個Bn端(服務端)的監聽類(從類名上看,似乎使用代理模式,這點待進一步研究)。ProxyConsumerListener類是ConsumerListener類的實現,主要用來保存一個指向真正的consumer object的weak引用。ProxyConsumerListener的主要目的是避免BufferQueue對象和consumer對象的循環引用。
class ProxyConsumerListener : public BnConsumerListener { public: explicit ProxyConsumerListener(const wp<ConsumerListener>& consumerListener); ~ProxyConsumerListener() override; void onDisconnect() override; void onFrameAvailable(const BufferItem& item) override; void onFrameReplaced(const BufferItem& item) override; void onBuffersReleased() override; void onSidebandStreamChanged() override; void addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override; private: // mConsumerListener is a weak reference to the IConsumerListener. This is // the raison d'etre of ProxyConsumerListener. wp<ConsumerListener> mConsumerListener; };
ProxyConsumerListener的使用在ConsumerBase類。
ProxyConsumerListener的實現比較簡單,幾個函數的功能如下表所示,顯然主要是監聽一些動作,當這些對應的事件發生后,及時通知另一端。這里顯然做數據同步的功能,具體同步的肯定是producer和consumer兩端的關系,這一部分內容待補充。
成員函數 |
功能描述 |
onDisconnect |
通知遠端已經斷開鏈接了 |
onFrameAvailable |
通知遠端frame已經准備好了 |
onFrameReplaced |
通知遠端frame被替換了 |
onBuffersReleased |
通知遠端buffer已經release了 |
onSidebandStreamChanged |
|
addAndGetFrameTimestamps |
|
看完ProxyConsumerListener類,BufferQueu就剩下最后一個成員了,也是最重要的一個成員:createBufferQueue函數。
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger = false);
顯然,這個函數是用來創建buffer queue的,其入參即buffer queue的producer和consumer,最后一個參數指明consumer是否為SurfaceFlinger。該函數的使用有兩個地方,一個一個在BufferLayer::onFirstRef函數中,一個在SurfaceFlinger:: processDisplayChangesLocked函數中,這里暫時只講BufferLayer::onFirstRef里面的使用。該函數似乎是給外接屏使用的,這里暫時不深入。
void BufferLayer::onFirstRef() { // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); if (mFlinger->isLayerTripleBufferingDisabled()) { mProducer->setMaxDequeuedBufferCount(2); } const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); }
BufferLayer::onFirstRef是在上層應用請求SurfaceFlinger創建Layer時調用的,即應用告訴SurfaceFlinger它要創建一個Layer(即APP端的窗口、Native層的Surface),此時SurfaceFlinger就會創建創建對應Layer,並為此Layer創建一個對應的BufferQueue,即應用的一個窗口對應一個BufferQueue。那么顯然,這里的producer是指應用端對應的窗口,consumer即指SurfaceFlinger(第三個參數指定的)。BufferLayer::onFirstRef函數這里不深入研究。
繼續看createBufferQueue函數的源代碼,刪除次要的代碼,其主要代碼部分如下:
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger) { …… sp<BufferQueueCore> core(new BufferQueueCore()); sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger)); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); *outProducer = producer; *outConsumer = consumer; }
首先,他調用BufferQueueCore的構建函數創建了一個core對象,顯然這是在說,BufferQueueCore才是buffer queue的核心,真正干活的其實是BufferQueueCore這個類,BufferQueue只是個外殼而已。其次分別創建了producer和consumer對象,返回給了對應的Layer,然后BufferLayer將這兩個添加了其內部的Consuerm Listener監聽器中,這樣創建出來的layer就可以與SurfaceFlinger之間進行相關的數據互動操作了,這里不在深入具體細節,后續專門介紹。
BufferQueueCore
從前面的分析可以看到,BufferQueue類其實只做了一件事情:創建BufferQueueCore。其他什么事情都沒做。那么這個BufferQueueCore肯定是非常重要的了。接下來看BufferQueueCore這個類。
BufferQueueCore沒有復雜的繼承關系,直接繼承了RefBase類。
BufferQueueCore定義了當前queue的狀態:
- CURRENTLY_CONNECTED_API:值為-1,表示當前有producer連接到buffer queue
- NO_CONNECTED_API:值為0,表示當前沒有producer連接到buffer queue
BufferQueueCore
成員變量 |
描述 |
mMutex |
被mutable修飾,表明此鎖的狀態是隨時變化的 |
mIsAbandoned |
該變量表示buffer queue已經不在繼續消費push到其中的image buffer數據,初始化時默認為false,當consumerDisconnect時,被設置成true。 |
mConsumerControlledByApp |
表示已經連接的consumer是否被application所控制 |
mConsumerName |
該buffer queue對應的consumer的名字,用於在log中標識buffer queue的所有者 |
mConsumerListener |
用於向已連接的consumer發送通知消息。默認初始化時為NULL,當consumerConnect或consumerDisconnect時寫入有效值。 |
mConsumerUsageBits |
包含了consumer想要的flags信息 |
mConsumerIsProtected |
表示conumser是否准備處理受保護的buffer |
mConnectedApi |
表示當前連接到buffer queue的producer API,默認為NO_CONNECTED_API,當connect或disconnect時會發生變化 |
mConnectedPid |
最后一個成功連接到該buffer queue的進程的pid |
mConnectedProducerListener |
該監聽器用於處理onBufferRelease通知消息 |
mSlots |
即BufferSlot數組,最大保存NUM_BUFFER_SLOTS個BufferSlot。 mSlots必須與producer側成鏡像狀態,這使buffer的所有權在producer和consumer之間進行轉換時,可以不用通過Binder來發送GraphicBuffer就能實現。整個數組在初始化時被設置為NULL,當requestBuffer時,才會為slot分配buffer。 |
mFreeSlots |
set<int>類型變量,包含所有處於FREE狀態的slot序號,這些slot當前並沒有與某個buffer關聯起來,完全處於FREE狀態。 |
mFreeBuffers |
list<int>類型變量,包含當前所有處於FREE狀態的slot,但是這些slot都已經被關聯到了特定的buffer。 |
mUnusedSlots |
list<int>類型變量,表示當前所有沒有被使用的slot,這些slot都是FREE狀態,也沒有與buffer相關聯。 |
mActiveBuffers |
set<int>類型變量,包含當前所有與非FREE狀態Buffer關聯的slot |
mQueue |
Vector<BufferItem>類型變量,同步模式中使用的FIFO隊列 |
mDequeueCondition |
在同時模式中,供dequeueBuffer方法使用的一個條件變量 |
mDequeueBufferCannotBlock |
表示dequeueBuffer操作是否可以被block。這個標志在producer和consumer被Application所控制的情況下,做connect操作時設置。 |
mDefaultBufferFormat |
buffer format的默認格式,如果dequeueBuffer時沒有指定buffer format,則使用此變量所設置的format |
mDefaultWidth |
所分配的buffer的默認寬度,在dequeueBuffer中使用,默認為0 |
mDefaultHeight |
所分配的buffer的默認高度,在dequeueBuffer中使用,默認為0 |
mDefaultBufferDataSpace |
queueBuffer時,如果指定DATA_DATASPACE_UNKNOWN了,則使用此值 |
mMaxBufferCount |
指定一次最大分配的buffer數量,可以由consumer進行設置 |
mMaxAcquiredBufferCount |
指定consumer端一次最大acquire的buffer數量,默認為1.consumer端可以通過調用setMaxAcquiredBufferCount來改變此值,但也僅限在尚有producer連接到buffer queue時生效,This value is used to derive the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer. |
mMaxDequeuedBufferCount |
producer端一次最大dequeue的buffer數量,默認為1,producer端可以通過setMaxDequeuedBufferCount函數修改此值。 |
mBufferHasBeenQueued |
當一個buffer被queue進buffer queue時,會將此值設置為true。當因某種原因使得所有buffer都被free時,此值會被重置。 |
mFrameCounter |
每當queueBuffer或buffer allocation成功時,這個值都會增長 |
mTransformHint |
用於優化屏幕旋轉 |
mSidebandStream |
a handle to the sideband buffer stream |
mIsAllocating |
表示一個producer是否正在分配buffers,當該變量值為true時,producer不應該修改任何FREE狀態的slot。當此變量值變成false時,mIsAllocatingCondition會被signaled,表明producer已經分配完buffer。 |
mIsAllocatingCondition |
與mIsAllocating配合使用 |
mAllowAllocation |
用來決定dequeueBuffer操作時是否可以分配新的buffer |
mBufferAge |
tracks the age of the contents of the most recently dequeued buffer as the number of frames that have elapsed since it was last queued |
mGenerationNumber |
stores the current generation number of the attached producer. Any attempt to attach a buffer with a different generation number will fail. |
mAsyncMode |
指示異步模式是否被開啟。在異步模式中,需要分配額外的buffer以保證producer在enqueue buffer時不被blocking。 |
mSharedBufferMode |
indicates whether or not shared buffer mode is enabled. |
mAutoRefresh |
若為enabled,表示即使BufferQueue沒有通知buffer已經准備好了,consumer也應該自動acquire buffer, |
mSharedBufferSlot |
當sharedBufferMode開啟后,該變量用來跟蹤哪個slot包含了shared buffer。 |
mLastQueuedSlot |
最后一次被queue的buffer的序號 |
mUniqueId |
唯一的標識ID |
mSharedBufferCache |
shared buffer的Cached data |