![Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)的線程模型分析_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/24/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b1.gif)
![Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)的線程模型分析_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/24/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b2.gif)
![Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)的線程模型分析_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/24/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b3.gif)
![Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)的線程模型分析_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/24/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b4.gif)
![Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)的線程模型分析_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/24/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b/e1fd4e9f-590b-4b95-9f4e-bbe5ae8eb31b5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、精選文檔Android系統(tǒng)Surface機制的SurfaceFlinger服務(wù)的線程模型分析在前面兩篇文章中,我們分析了SurfaceFlinger服務(wù)的啟動過程以及SurfaceFlinger服務(wù)初始化硬件幀緩沖區(qū)的過程。從這兩個過程可以知道,SurfaceFlinger服務(wù)在啟動的過程中,一共涉及到了三種類型的線程,它們分別是Binder線程、UI渲染線程和把握臺大事監(jiān)控線程。在本文中,我們就將具體分SurfaceFlinger服務(wù)的線程模型,即上述三種類型的線程是如何運行和交互的。 從 一文可以知道,SurfaceFlinger服務(wù)是在System進程的主線程中啟動的。System進程的
2、主線程在啟動系統(tǒng)的關(guān)鍵服務(wù)之前,會先啟動一個Binder線程池。這樣運行在System進程中的系統(tǒng)關(guān)系服務(wù)就可以與其它進程執(zhí)行Binder進程間通信了。SurfaceFlinger服務(wù)雖然是由System進程的主線程來負責啟動的,但是最終它會運行在一個獨立的線程中。我們將這個獨立的線程稱為UI渲染線程,由于它負責渲染系統(tǒng)的UI。 從 一文可以知道,SurfaceFlinger服務(wù)的UI渲染線程的啟動的時候,會對系統(tǒng)的硬件幀緩沖區(qū)進行初始化。在初始化的過程,又會創(chuàng)建另外一個線程來監(jiān)控硬件幀緩沖區(qū)的睡眠/喚醒狀態(tài)切換大事。為了便利描述,我們這個線程稱稱為把握臺大事監(jiān)控線程。 上述的三種類型的線程的
3、啟動挨次,可以通過圖1來描述,如下所示:從圖1就可以清楚地看到,System進程的主線程負責啟動Binder線程池,以及UI渲染線程,而UI渲染線程又負責啟動把握臺大事監(jiān)控線程。在這三種類型的線程中,UI渲染線程是主角,Binder線程和把握臺大事監(jiān)控線程是配角。Binder線程池是為了讓其它進程,例如Android應(yīng)用程序進程,可以與SurfaceFlinger服務(wù)進行Binder進程間通信的,有一部分通信所執(zhí)行的操作便是讓UI渲染線程更新系統(tǒng)的UI。把握臺大事監(jiān)控線程是為了監(jiān)控硬件幀緩沖區(qū)的睡眠/喚醒狀態(tài)切換大事的。一旦硬件幀緩沖區(qū)要進入睡眠或者喚醒狀態(tài),把握臺大事監(jiān)控線程都需要通知UI渲
4、染線程,以便UI渲染線程可以執(zhí)行關(guān)閉或者啟動顯示屏的操作。 接下來,為了弄清楚SurfaceFlinger服務(wù)的線程模型,我們就首先簡要分析UI渲染線程的運行模型,接著再分析Binder線程與UI渲染線程的交互過程,最終分析把握臺大事監(jiān)控線程與UI渲染線程的交互過程。 1. UI渲染線程的運行模型 在前面 一文中提到,SurfaceFlinger服務(wù)的UI渲染線程有一個消息隊列。當消息隊列為空時,SurfaceFlinger服務(wù)的UI渲染線程就會進入睡眠等待狀態(tài)。一旦SurfaceFlinger服務(wù)的Binder線程接收到其它進程發(fā)送過來的渲染UI的懇求時,它就會往SurfaceFlinger
5、服務(wù)的UI渲染線程的消息隊列中發(fā)送一個消息,以便可以將SurfaceFlinger服務(wù)的UI渲染線程喚醒起來執(zhí)行渲染的操作。同樣,一旦SurfaceFlinger服務(wù)的把握臺大事監(jiān)控線程發(fā)覺硬件幀緩沖區(qū)即將要進入睡眠或者喚醒狀態(tài)時,它就會往SurfaceFlinger服務(wù)的UI渲染線程的消息隊列中發(fā)送一個消息,以便SurfaceFlinger服務(wù)的UI渲染線程可以執(zhí)行凍結(jié)或者解凍顯示屏的操作。 從前面 一文又可以知道,SurfaceFlinger服務(wù)的UI渲染線程是以SurfaceFlinger類的成員函數(shù)threadLoop為線程執(zhí)行體的,即SurfaceFlinger服務(wù)的UI渲染線程會不
6、斷地循環(huán)執(zhí)行SurfaceFlinger類的成員函數(shù)threadLoop。接下來,我們就通過SurfaceFlinger類的成員函數(shù)threadLoop的實現(xiàn)來分析SurfaceFlinger服務(wù)的UI渲染線程的運行模型,如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片bool SurfaceFlinger:threadLoop() waitForEvent(); / check for transactions if (UNLIKELY(mConsoleSignals) handleConsoleEvents(); if (LIKELY(mTransa
7、ctionCount = 0) / if we're in a global transaction, don't do anything. const uint32_t mask = eTransactionNeeded | eTraversalNeeded; uint32_t transactionFlags = getTransactionFlags(mask); if (LIKELY(transactionFlags) handleTransaction(transactionFlags); / post surfaces (if needed) handlePageF
8、lip(); const DisplayHardware& hw(graphicPlane(0).displayHardware(); if (LIKELY(hw.canDraw() && !isFrozen() #ifdef USE_COMPOSITION_BYPASS if (handleBypassLayer() unlockClients(); return true; #endif / repaint the framebuffer (if needed) const int index = hw.getCurrentBufferIndex(); Graphi
9、cLog& logger(GraphicLog:getInstance(); logger.log(GraphicLog:SF_REPAINT, index); handleRepaint(); / inform the h/w that we're done compositing logger.log(GraphicLog:SF_COMPOSITION_COMPLETE, index); positionComplete(); logger.log(GraphicLog:SF_SWAP_BUFFERS, index); postFramebuffer(); logger.l
10、og(GraphicLog:SF_REPAINT_DONE, index); else / pretend we did the post positionComplete(); usleep(16667); / 60 fps period return true; 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 從前面 一文可以知道,SurfaceFlinger類的成員函數(shù)threadLoop的工作過程如下所示: 1. 調(diào)用SurfaceFlinger類的成員函數(shù)waitForEvent中檢查Surf
11、aceFlinger服務(wù)的UI渲染線程的消息隊列是否為空。假如不為空,那么就會馬上返回來執(zhí)行其它的操作,否則的話,SurfaceFlinger服務(wù)的UI渲染線程就會進入睡眠等狀態(tài),直到被SurfaceFlinger服務(wù)的Binder線程或者把握臺大事監(jiān)控線程喚醒為止。 2. 當SurfaceFlinger服務(wù)的UI渲染線程被把握臺大事監(jiān)控線程喚醒時,SurfaceFlinger類的成員變量mConsoleSignals的值就會不等于0。在這種狀況下,SurfaceFlinger類的成員函數(shù)threadLoop就會調(diào)用另外一個成員函數(shù)handleConsoleEvents來處理把握臺大事。后面在
12、分析SurfaceFlinger服務(wù)的UI渲染線程和把握臺大事監(jiān)控線程的交互過程時,我們再分析這個成員函數(shù)的實現(xiàn)。 3. SurfaceFlinger類的成員變量mTransactionCount用來描述SurfaceFlinger服務(wù)是否正在執(zhí)行事務(wù)。假如SurfaceFlinger服務(wù)正在執(zhí)行事務(wù),那么SurfaceFlinger類的成員變量mTransactionCount的值就會大于0。怎么理解SurfaceFlinger服務(wù)所執(zhí)行的事務(wù)是什么呢?這些事務(wù)是用來處理系統(tǒng)的顯示屬性的。這些屬性劃分為兩種類型。一種類型是與整個顯示屏屬性相關(guān)的,例如屏幕旋轉(zhuǎn)方向發(fā)生了變化,另一外類型是與某一
13、個應(yīng)用程序的Surface相關(guān)的,例如某一個Surface的大小或者Z軸位置發(fā)生了變化。一般來說,每當系統(tǒng)的顯示屬性發(fā)生了變化的時候,SurfaceFlinger服務(wù)的UI渲染線程都需要馬上刷新系統(tǒng)UI,以便可以反映真實狀況。但是,為了削減屏幕的閃爍,有時候可以將多個屬性變化組合成一個事務(wù)來刷新系統(tǒng)UI。例如,我們可以在修改了一個Surface的大小和Z軸位置之后,才要求SurfaceFlinger服務(wù)的UI渲染線程去刷新系統(tǒng)UI,這樣就可以削減一個刷新系統(tǒng)UI的操作。因此,只有當SurfaceFlinger類的成員變量mTransactionCount的值的等于0的時候,SurfaceFli
14、nger類的成員函數(shù)threadLoop才會推斷系統(tǒng)的顯示屬性是否發(fā)生了變化。假如發(fā)生了變化,那么就會調(diào)用另外一個成員函數(shù)handleTransaction來進一步處理。在接下來的一篇文章中分析SurfaceFlinger服務(wù)的UI渲染過程時,我們就具體分析這個成員函數(shù)的實現(xiàn)。 4. SurfaceFlinger服務(wù)的UI渲染線程接下來調(diào)用SurfaceFlinger類的成員函數(shù)handlePageFlip來通知各個應(yīng)用程序的Surface將接下來要渲染的圖形緩沖區(qū)設(shè)置為當前激活的圖形緩沖區(qū),以便接下來可以渲染到硬件幀緩沖區(qū)中去。我們同樣會在接下來的一篇文章中分析SurfaceFlinger服
15、務(wù)的UI渲染過程時,具體分析這個成員函數(shù)的實現(xiàn)。 5. 假如SurfaceFlinger服務(wù)的UI渲染線程目前只有一個Surface需要渲染,并且SurfaceFlinger類在編譯時,指定了USE_COMPOSITION_BYPASS宏,那么SurfaceFlinger類的成員函數(shù)threadLoop就會直接調(diào)用另外一個成員函數(shù)handleBypassLayer來將這個Surface直接渲染到硬件幀緩沖區(qū)中去。這是一個優(yōu)化操作,避開執(zhí)行接下來的Surface合成操作。 6. 假如SurfaceFlinger服務(wù)的UI渲染線程目前有多個Surface需要渲染,或者SurfaceFlinger類
16、在編譯時沒指定USE_COMPOSITION_BYPASS宏,那么SurfaceFlinger類的成員函數(shù)threadLoop接下來就會調(diào)用另外一個成員函數(shù)handleRepaint來將各個Surface的圖形緩沖區(qū)合成起來,以便接下來可以渲染到硬件幀緩沖區(qū)中去。Surface的合成操作比較簡單,由于它涉及到可見性計算等。我們同樣會在接下來的一篇文章中分析SurfaceFlinger服務(wù)的UI渲染過程時,具體分析這個成員函數(shù)的實現(xiàn)。 7. 要渲染的各個Surface的圖形緩沖區(qū)被合成之后,SurfaceFlinger類的成員函數(shù)threadLoop接下來前面獲得的用來描述系統(tǒng)主顯示屏的Disp
17、layHardware對象hw的成員函數(shù)compositionComplete來通知HAL層Gralloc模塊中的fb設(shè)備,以便這個fb設(shè)備可以在Surface合成操作完成時執(zhí)行一些規(guī)律。這一步是可選的,取決于HAL層Gralloc模塊中的fb設(shè)備是否需要接收這個Surface合成完成通知。 8. 上述步驟都執(zhí)行完成之后,SurfaceFlinger類的成員函數(shù)threadLoop最終就可以調(diào)用SurfaceFlinger類的成員函數(shù)postFramebuffer來將合成后得到的圖形緩沖區(qū)渲染到硬件幀緩沖區(qū)去了,這樣就可以將系統(tǒng)的最新UI渲染出來,或者說刷新了系統(tǒng)的UI。 在本小節(jié)中,我們只關(guān)
18、注第1步的處理過程,即SurfaceFlinger類的成員函數(shù)waitForEvent的實現(xiàn),以便可以了解SurfaceFlinger服務(wù)的UI渲染線程是如何圍繞它的消息隊列來運行的。 SurfaceFlinger類的成員函數(shù)waitForEvent的實現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void SurfaceFlinger:waitForEvent() while (true) nsecs_t timeout = -1; const nsecs_t freezeDisplayTimeout = ms2ns(5000); if (UNLI
19、KELY(isFrozen() / wait 5 seconds const nsecs_t now = systemTime(); if (mFreezeDisplayTime = 0) mFreezeDisplayTime = now; nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); timeout = waitTime>0 ? waitTime : 0; sp<MessageBase> msg = mEventQueue.waitMessage(timeout); / see i
20、f we timed out if (isFrozen() const nsecs_t now = systemTime(); nsecs_t frozenTime = (now - mFreezeDisplayTime); if (frozenTime >= freezeDisplayTimeout) / we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); mFreezeD
21、isplayTime = 0; mFreezeCount = 0; mFreezeDisplay = false; if (msg != 0) switch (msg->what) case MessageQueue:INVALIDATE: / invalidate message, just return to the main loop return; 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 在分析這個函數(shù)的實現(xiàn)之前,我們首先了解一下SurfaceFlinger類的三個成員變量mFre
22、ezeDisplay、mFreezeDisplayTime和mFreezeCount的含義。 外部進程,例如,應(yīng)用程序進程,可以懇求SurfaceFlinger服務(wù)將顯示屏凍結(jié),這時候SurfaceFlinger類的成員變量mFreezeDisplay的值就會等于true。當顯示屏被凍結(jié)時,SurfaceFlinger服務(wù)同時也會記錄被凍結(jié)的起始時間,記錄在SurfaceFlinger類的成員變量mFreezeDisplayTime中。另一方面,SurfaceFlinger服務(wù)在修改某一個Surface的顯示屬性時,例如,修改它的大小時,假如發(fā)覺顯示屏此時正處于被凍結(jié)的狀態(tài),這時候就會將Sur
23、faceFlinger類的成員變量mFreezeCount的值增加1,表示這個Surface也需要凍結(jié)顯示屏。 從SurfaceFlinger類的成員函數(shù)threadLoop的實現(xiàn)可以知道,SurfaceFlinger服務(wù)都會調(diào)用SurfaceFlinger類的另外一個成員函數(shù)isFrozen來推斷顯示屏是否處于凍結(jié)狀態(tài)。假如是的話,那么SurfaceFlinger服務(wù)是不行以執(zhí)行渲染UI的操作的。SurfaceFlinger類的成員函數(shù)isFrozen的實現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片class SurfaceFlinger : p
24、ublic BinderService<SurfaceFlinger>, public BnSurfaceComposer, protected Thread . private: . inline bool isFrozen() const return (mFreezeDisplay | mFreezeCount>0) && mBootFinished; . ; 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.h中。 SurfaceFlinger類的另外一個成員變量mBootF
25、inished用來表示系統(tǒng)是否已經(jīng)啟動完成的。從前面 一文可以知道,當系統(tǒng)啟動完成時,第三個開機畫面,即開動動畫,就會被停止,同時SurfaceFlinger類的成員變量mBootFinished的值會被設(shè)置為true。從SurfaceFlinger類的成員函數(shù)isFrozen的實現(xiàn)也可以看出,只有當系統(tǒng)啟動完成之后,顯示屏才會有凍結(jié)的概念。由于在系統(tǒng)啟動的過程中,顯示屏都是依次被三個開機畫面獨占的,而在獨占的期間,不會消滅同時去修改顯示屬性的問題,因此就不需要去凍結(jié)顯示屏。 由于將顯示屏凍結(jié)的目的一般是為了修改顯示屏的顯示屬性,例如修改某一個Surface的大小或者修改顯示并的旋轉(zhuǎn)方向等,因
26、此,通過SurfaceFlinger類的兩個成員變量mFreezeDisplay和mFreezeCount,SurfaceFlinger服務(wù)就可以將多個顯示屬性變化合并在一起去渲染UI,避開單獨為每一個顯示屬性變化執(zhí)行一次UI渲染操作。單獨為每一個顯示屬性變化執(zhí)行一次UI渲染操作會消滅什么狀況呢?假如有兩個顯示屬性是同時發(fā)生變化的,那么執(zhí)行兩次UI渲染操作就會可能導(dǎo)致沖突,從而造成一些畫面上的誤差。 理解了SurfaceFlinger類的三個成員變量mFreezeDisplay、mFreezeDisplayTime和mFreezeCount的含義之后,接下來我們就可以分析SurfaceFlin
27、ger類的成員函數(shù)waitForEvent的實現(xiàn)了。 當消息隊列為空時,SurfaceFlinger服務(wù)的UI渲染線程每一次進行睡眠等待狀態(tài)的默認時間被設(shè)置為5000毫秒,保存在變量freezeDisplayTimeout中。但是假如顯示屏當前正處于凍結(jié)狀態(tài),那么這個等待的時間就會從默認值減去已經(jīng)被凍結(jié)的時間。這樣做的目的是避開顯示屏長時間被凍結(jié)而導(dǎo)致UI不能被渲染,即相當于是將顯示屏的最長凍結(jié)時間設(shè)置為5000毫秒。 最終得到的等待時間就保存在變量timeout中,接下來SurfaceFlinger類的成員函數(shù)waitForEvent就會調(diào)用成員變量mEventQueue所描述的一個消息隊列
28、的成員函數(shù)waitMessage來檢查是否有新的消息需要處理。假如沒有,那么SurfaceFlinger服務(wù)的UI渲染線程就會進入到睡眠等待狀態(tài)中去,直到消息隊列有新的消息需要處理或者等待超時為止。 SurfaceFlinger服務(wù)的UI渲染線程從SurfaceFlinger類的成員變量mEventQueue所描述的一個消息隊列的成員函數(shù)waitMessage返回來時,假如有新的消息需要處理,那么變量msg就指向這個需要處理的新消息,即變量msg的值不等于0。目前SurfaceFlinger服務(wù)的UI渲染線程只處理一種類型為MessageQueue:INVALIDATE的消息,因此,變量msg
29、所指向的消息的類型為MessageQueue:INVALIDATE時,SurfaceFlinger服務(wù)的UI渲染線程就會從SurfaceFlinger類的成員函數(shù)waitForEvent中返回到調(diào)用它的成員函數(shù)threadLoop中去,以便可以處理把握臺大事或者渲染UI的操作。 留意,當SurfaceFlinger服務(wù)的UI渲染線程從SurfaceFlinger類的成員變量mEventQueue所描述的一個消息隊列的成員函數(shù)waitMessage返回來時,假如這時候顯示屏仍舊處于凍結(jié)狀態(tài),那么SurfaceFlinger類的成員函數(shù)waitForEvent就需要檢查顯示屏的凍結(jié)時間是否已經(jīng)大于
30、等于5000毫秒。假如大于等于的話,那么就會自動對顯示屏執(zhí)行解凍操作,即分別將SurfaceFlinger類的成員變量mFreezeDisplayTime、mFreezeCount和mFreezeDisplay的值重置為0、0和false。 SurfaceFlinger類的成員變量mEventQueue所描述的一個消息隊列的類型為MessageQueue,實現(xiàn)在文件frameworks/base/services/surfaceflinger/MessageQueue.cpp,它與 的實現(xiàn)思路是類似的,不過會更簡潔一些。簡潔來說,這個消息隊列就是由一個消息列表以及一個條件變量組成。當消息列表為
31、空時,調(diào)用MessageQueue類的成員函數(shù)waitMessage的線程就會在MessageQueue類內(nèi)部的條件變量上進入睡眠等狀態(tài)。而當其它線程向這個消息隊列添加一個新消息的時候,就會通過MessageQueue類內(nèi)部的條件變量來將前面正在等待的線程喚醒起來,以它可以將前面加入到它的消息隊列中的新消息取出來處理。 至此,我們就分析完成SurfaceFlinger服務(wù)的UI渲染線程的運行模型了,在下一篇文章中我們還會連續(xù)具體分析這個線程是如何執(zhí)行UI渲染操作的,接下來我們接著分析Binder線程與UI渲染線程的交互過程。 2. Binder線程與UI渲染線程的交互過程 前面提到,Syste
32、m進程在啟動SurfaceFlinger服務(wù)之前,首先會啟動一個Binder線程池。Binder線程池的啟動過程可以參考 一文。System進程中的Binder線程池啟動起來之后,其它進程,例如Android應(yīng)用程序進程,就可以懇求SurfaceFlinger服務(wù)來渲染系統(tǒng)的UI了。 以 為例,當它需要刷新自己的UI時,就會通過它所運行在的進程的SurfaceClient單例的成員函數(shù)signalServer來向SurfaceFlinger服務(wù)發(fā)送一個Binder進程間通信懇求,這一點可以參考 一文。接下來,我們就從SurfaceClient類的成員函數(shù)signalServer來分析Surfa
33、ceFlinger服務(wù)的Binder線程與UI渲染線程的交互過程。 SurfaceClient類的成員函數(shù)signalServer的實現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片class SurfaceClient : public Singleton<SurfaceClient> / all these attributes are constants sp<ISurfaceComposer> mComposerService; . public: . void signalServer() const mCompose
34、rService->signal(); ; 這個函數(shù)定義在文件frameworks/base/libs/surfaceflinger_client/Surface.cpp中。 SurfaceClient類的成員變量mComposerService指向的是一個類型為BpSurfaceComposer的Binder代理對象,這個Binder代理對象引用了SurfaceFlinger服務(wù),因此,SurfaceClient類的成員函數(shù)signalServer實際上就是通過BpSurfaceComposer類的成員函數(shù)signal來向SurfaceFlinger服務(wù)發(fā)送一個進程間通信懇求。 BpS
35、urfaceComposer類的成員函數(shù)signal的實現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片class BpSurfaceComposer : public BpInterface<ISurfaceComposer> public: . virtual void signal() const Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer:getInterfaceDescriptor(); remote()->transact(BnSurfaceC
36、omposer:SIGNAL, data, &reply, IBinder:FLAG_ONEWAY); ; 這個函數(shù)定義在文件frameworks/base/libs/surfaceflinger_client/ISurfaceComposer.cpp中。 從這里就可以看出,BpSurfaceComposer類的成員函數(shù)signal所執(zhí)行的操作就是向SurfaceFlinger服務(wù)發(fā)送一個類型為BnSurfaceComposer:SIGNAL的進程間通信懇求,而SurfaceFlinger服務(wù)是在SurfaceFlinger類的成員函數(shù)signal中處理類型為BnSurfaceComp
37、oser:SIGNAL的進程間通信懇求的,如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void SurfaceFlinger:signal() const / this is the IPC call const_cast<SurfaceFlinger*>(this)->signalEvent(); 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 SurfaceFlinger類的成員函數(shù)signal調(diào)用了另外一個成員函數(shù)signalEvent
38、來進一步處理類型為BnSurfaceComposer:SIGNAL的進程間通信懇求的,如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void SurfaceFlinger:signalEvent() mEventQueue.invalidate(); 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 前面提到,SurfaceFlinger類的成員變量mEventQueue指向的是SurfaceFlinger服務(wù)的UI渲染線程的消息隊列,這個消息隊列的類型為Mess
39、ageQueue。SurfaceFlinger類的成員函數(shù)signalEvent要執(zhí)行的操作便是向SurfaceFlinger服務(wù)的UI渲染線程的消息隊列發(fā)送一個類型為MessageQueue:INVALIDATE的消息,這是通過調(diào)用MessageQueue類的成員函數(shù)invalidate來實現(xiàn)的,如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片status_t MessageQueue:invalidate() Mutex:Autolock _l(mLock); mInvalidate = true; mCondition.signal(); retu
40、rn NO_ERROR; 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/MessageQueue.cpp中。 MessageQueue類的成員函數(shù)invalidate并不是真的向SurfaceFlinger服務(wù)的UI渲染線程的消息隊列發(fā)送一個消息,而是將MessageQueue的類成員變量mInvalidate的值設(shè)置為true,并且通過MessageQueue類的成員變量mCondition所描述的一個條件變量來將SurfaceFlinger服務(wù)的UI渲染線程喚醒。當SurfaceFlinger服務(wù)的UI渲染線程被喚醒時,就會檢查Messa
41、geQueue的類成員變量mInvalidate是否為true。假如是的話,那么就會獲得一個類型為MessageQueue:INVALIDATE的消息,這個消息最終是在SurfaceFlinger類的成員函數(shù)threadLoop中處理的,如前面第1部分的內(nèi)容所示。 至此,我們就分析完成SurfaceFlinger服務(wù)的Binder線程與UI渲染線程的交互過程了,接下來我們再分析SurfaceFlinger服務(wù)的把握臺大事監(jiān)控線程與UI渲染線程的交互過程。 3. 把握臺大事監(jiān)控線程與UI渲染線程的交互過程 從前面 一文可以知道,SurfaceFlinger服務(wù)的把握臺大事監(jiān)控線程是以Displa
42、yEventThread類的成員函數(shù)threadLoop為執(zhí)行體的,即SurfaceFlinger服務(wù)的把握臺大事監(jiān)控線程會不斷地循環(huán)調(diào)用DisplayEventThread類的成員函數(shù)threadLoop,以便可以監(jiān)控硬件幀緩沖區(qū)的睡眠/喚醒狀態(tài)切換大事。 DisplayEventThread類的成員函數(shù)threadLoop的實現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片bool DisplayHardwareBase:DisplayEventThread:threadLoop() int err = 0; char buf; int fd; f
43、d = open(kSleepFileName, O_RDONLY, 0); do err = read(fd, &buf, 1); while (err < 0 && errno = EINTR); close(fd); LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno); if (err >= 0) sp<SurfaceFlinger> flinger = mFmote(); LOGD("Abou
44、t to give-up screen, flinger = %p", flinger.get(); if (flinger != 0) mBarrier.close(); flinger->screenReleased(0); mBarrier.wait(); fd = open(kWakeFileName, O_RDONLY, 0); do err = read(fd, &buf, 1); while (err < 0 && errno = EINTR); close(fd); LOGW_IF(err<0, "ANDROID_W
45、AIT_FOR_FB_WAKE failed (%s)", strerror(errno); if (err >= 0) sp<SurfaceFlinger> flinger = mFmote(); LOGD("Screen about to return, flinger = %p", flinger.get(); if (flinger != 0) flinger->screenAcquired(0); return true; 這個函數(shù)定義在文件frameworks/base/services/surfacefli
46、nger/DisplayHardware/DisplayHardwareBase.cpp中。 從前面 一文可以知道,DisplayEventThread類的成員變量kSleepFileName要么指向文件/sys/power/wait_for_fb_sleep,要么是指向文件/sys/android_power/wait_for_fb_sleep,而DisplayEventThread類的成員變量kWakeFileName要么指向文件/sys/power/wait_for_fb_wake,要么指向文件/sys/android_power/wait_for_fb_wake。 文件/sys/pow
47、er/wait_for_fb_sleep和文件/sys/android_power/wait_for_fb_sleep是用來監(jiān)控硬件幀緩沖區(qū)的睡眠大事的,而文件/sys/power/wait_for_fb_wake和文件/sys/android_power/wait_for_fb_wake是用來監(jiān)控硬件幀緩沖區(qū)的喚醒大事的。文件/sys/power/wait_for_fb_sleep和文件/sys/power/wait_for_fb_wake是硬件幀緩沖區(qū)把握臺供應(yīng)的新式接口,而文件/sys/android_power/wait_for_fb_sleep和文件/sys/android_powe
48、r/wait_for_fb_wake是件幀緩沖區(qū)把握臺供應(yīng)的舊式接口。 DisplayEventThread類的成員函數(shù)threadLoop首先是監(jiān)控硬件幀緩沖區(qū)的睡眠大事,這是通過監(jiān)控文件kSleepFileName的內(nèi)容來實現(xiàn)的,即首先調(diào)用函數(shù)open來打開文件kSleepFileName,然后再調(diào)用函數(shù)read來檢查這個文件是否有內(nèi)容可讀。當文件kSleepFileName有新的內(nèi)容可讀時,那么就說明硬件幀緩沖區(qū)要進入睡眠狀態(tài)了,這時候SurfaceFlinger服務(wù)的把握臺大事監(jiān)控線程就需要通知UI渲染線程來釋放系統(tǒng)的顯示屏。 DisplayEventThread類的成員變量mFlin
49、ger指向了系統(tǒng)中的SurfaceFlinger服務(wù),因此,DisplayEventThread類的成員函數(shù)threadLoop就可以調(diào)用它的成員函數(shù)screenReleased來通知SurfaceFlinger服務(wù)的UI渲染線程來釋放系統(tǒng)的顯示屏。由于DisplayEventThread類的成員變量mFlinger是一個類型為SurfaceFlinger的弱指針,因此,在使用它之前,首先要調(diào)用它的成員函數(shù)promote來將它升級為一個強指針flinger。假如升級成功,那么才說明它所指向的SurfaceFlinger服務(wù)還活著。弱指針升級為強指針的原理可以參考前面 一文。 SurfaceFl
50、inger服務(wù)的把握臺大事監(jiān)控線程調(diào)用SurfaceFlinger類的成員函數(shù)screenReleased來通知UI渲染線程來釋放系統(tǒng)的顯示屏之后,就會通過DisplayEventThread類的成員變量mBarrier所描述的一個屏障的成員函數(shù)wait來進入到睡眠等待狀態(tài),直到被SurfaceFlinger服務(wù)的UI渲染線程喚醒為止。接下來,我們就通過SurfaceFlinger類的成員函數(shù)screenReleased來分析SurfaceFlinger服務(wù)的UI渲染線程是如何釋放系統(tǒng)的顯示屏以及喚醒把握臺大事監(jiān)控線程的。 SurfaceFlinger類的成員函數(shù)screenReleased的
51、實現(xiàn)如下所示:cpp view plain copy 在CODE上查看代碼片派生到我的代碼片void SurfaceFlinger:screenReleased(int dpy) / this may be called by a signal handler, we can't do too much in here android_atomic_or(eConsoleReleased, &mConsoleSignals); Event(); 這個函數(shù)定義在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。 SurfaceFlinger類的成員函數(shù)screenReleased的實現(xiàn)很簡潔,它首先將SurfaceFlinger類的成員變量mConsoleSignals的eConsoleReleased位設(shè)置為1,接著再通過SurfaceFlinger類的成員函數(shù)signalEvent來喚醒UI渲染線程。從前面第1部分的內(nèi)容可知道,UI渲染線程被喚醒之后,就會調(diào)用SurfaceFlinger類的成員函數(shù)handleConsoleEvents來處理硬件幀緩沖區(qū)的睡眠
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度公司研發(fā)項目材料采購合同范本
- 2025年度建筑工程起重機租賃及施工人員培訓(xùn)合同
- 2025年度機床設(shè)備租賃與維修保養(yǎng)服務(wù)合同
- 2025年度建筑節(jié)能改造施工合同證據(jù)匯編
- 2025年度企業(yè)中長期貸款合同續(xù)簽協(xié)議
- 2025年度智慧社區(qū)物業(yè)承包服務(wù)合同
- 2025年度跨國企業(yè)貨物銷售合同范本
- 2025年度農(nóng)村電商雞類產(chǎn)品溯源購銷合同范本
- 2025年度房地產(chǎn)項目居間代理服務(wù)合同范本
- 2025年度園林景觀規(guī)劃設(shè)計服務(wù)合同(含生態(tài)旅游)
- 5《這些事我來做》(說課稿)-部編版道德與法治四年級上冊
- 2025年度高端商務(wù)車輛聘用司機勞動合同模板(專業(yè)版)4篇
- 2025年福建福州市倉山區(qū)國有投資發(fā)展集團有限公司招聘筆試參考題庫附帶答案詳解
- 2025年人教版新教材數(shù)學(xué)一年級下冊教學(xué)計劃(含進度表)
- GB/T 45107-2024表土剝離及其再利用技術(shù)要求
- 2025長江航道工程局招聘101人歷年高頻重點提升(共500題)附帶答案詳解
- 2025年黑龍江哈爾濱市面向社會招聘社區(qū)工作者1598人歷年高頻重點提升(共500題)附帶答案詳解
- 2025年國新國際投資有限公司招聘筆試參考題庫含答案解析
- 2025年八省聯(lián)考四川高考生物試卷真題答案詳解(精校打印)
- 《供電營業(yè)規(guī)則》
- 執(zhí)行總經(jīng)理崗位職責
評論
0/150
提交評論