雙屏異顯系統(tǒng)提供了Presentation類,可以實現(xiàn)在兩塊屏幕上同時顯示不同的內(nèi)容;Presentation是一個特殊的dialog,它的目的是顯示內(nèi)容到第二屏幕。 image.png
基本原理image.png
1 獲得顯示設(shè)備信息: 2 應(yīng)用程序端指定其應(yīng)用ContextImpl的Display。 3 應(yīng)用程序獲得Surface和配置Surface,這個surface對應(yīng)于SurfaceFlinger中的Layer; WindowManagerService作為一個系統(tǒng)服務(wù),主要管理系統(tǒng)中所有的應(yīng)用的Window。在WMS中,每個Window都有一個對應(yīng)的WindowState對象。 3.1 addWindow,該函數(shù)在WindowManagerService當中,由WindowManagerImpl中的addView函數(shù)調(diào)用到,并且將Window所在的Display作為參數(shù)帶到WMS當中。 3.2在addWindow函數(shù),WMS首先找到窗口所在的Display,創(chuàng)建WindowState,然后將窗口加到Display中的Windowlist當中。win.mToken.addWindow(win); 3.3 WindowState,獲取對應(yīng)Display的layerstack將其放置在WindowStateAnimator當中,并且將值設(shè)置到SurfaceFlinger當中與之對應(yīng)的Layer中,告知SurfaceFlinger自己所在Display。mSurfaceControl.setLayerStack(mLayerStack); 4 繪制Surface image.png
SurfaceFlinger需要利用HWC, Compose 屬于每個Display的layer,并且將其輸出到具體的DisplayDivice當中。 image.png
源碼分析1 新設(shè)備加入流程DisplayManagerService image.png
LocalDisplayAdapter image.png
當驅(qū)動層發(fā)現(xiàn)設(shè)備加入時會發(fā)出事件,framework檢測到這個事件會調(diào)用onHotplug;如果是connected,那么調(diào)用tryConnectDisplayLocked,創(chuàng)建LocalDisplayDevice并保存到mDevices,發(fā)送DISPLAY_DEVICE_ENVENT_CHANGED; image.png
image.png
最終會調(diào)用DisplayManagerService中的handleDisplayDeviceAddedLocked; image.png
handleDisplayDeviceAddedLocked函數(shù)中添加邏輯設(shè)備;并且分配默認的displayId和Layerstack 2 異顯示流程2.1 在Presentation創(chuàng)建的時候關(guān)聯(lián)一個目標設(shè)備,確定Presentation要顯示在那個設(shè)備上。根據(jù)這個設(shè)備的信息來配置Presentation的context和resources信息,每一個display擁有自己的管理對象以及context對象,這樣雙屏的操作互相獨立;對于上層而言,其即意味著一個屏幕。 image.png
2.2 調(diào)用show函數(shù)顯示view;實際調(diào)用WindowManagerImpl的addview函數(shù); ![]() image.png
WindowManagerImpl的addview 函數(shù)創(chuàng)建ViewRootImp,并調(diào)用ViewRootImpl的setView函數(shù);ViewRootImpl類中創(chuàng)建了WindowSession和IWindow對象負責和Windowmanagerservice之間跨進程通信; ![]() image.png
ViewRootImpl setview函數(shù),調(diào)用了requestLayout 和WindowSession addToDisplay; ViewRootImpl中requestLayout函數(shù)調(diào)用mWindowSession.relayout,最終調(diào)用WindowManagerservice 的relayoutWindow,這個函數(shù)會配置Display信息; WindowStateAnimator創(chuàng)建Surfacecontrol,通過SurfaceControl,設(shè)置Layerstack; ![]() image.png
SurfaceControl 事務(wù)SurfaceControl開始事務(wù),設(shè)置參數(shù),結(jié)束事務(wù) ![]() image.png
WindowManagerservice addWindow函數(shù)1 通過displayId 獲取顯示設(shè)備 final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId); 2 創(chuàng)建WindowState, WindowState函數(shù)中創(chuàng)建了WindowStateAnimator對象負責窗口的管理 final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid, SurfaceControl 調(diào)用本地層方法android_view_SurfaceControl 設(shè)置surfaceflinger ![]() image.png
![]() image.png
SurfaceComposerClient對象負責和surfaceflinger通信;配置好參數(shù),結(jié)束事務(wù),跨進程調(diào)用surfaceflinger setTransactionState ![]() image.png
![]() image.png
Surfaceflinger 對display設(shè)備和layer層操作,設(shè)置layerstack, layer和第二塊屏綁定setDisplayStateLocked ![]() image.png
![]() image.png
Surfaceflinger輸出過程:1 handleTransaction handPageFlip用戶進程更新Surface圖像時會調(diào)用,來更新Layer對象 handleTransaction函數(shù)的作用的就是處理系統(tǒng)在兩次刷新期間的各種變化。 包括: 處理Layer的事務(wù),檢測是否需要更新; 處理顯示設(shè)備的變化: 1.顯示設(shè)備減少了,需要把顯示設(shè)備對應(yīng)的DisplayDevice移除 2.顯示設(shè)備發(fā)生了變化,例如用戶設(shè)置了Surface、重新設(shè)置了layerStack、旋轉(zhuǎn)了屏幕等,這就需要重新設(shè)置顯示對象的屬性 3.顯示設(shè)備增加了,創(chuàng)建新的DisplayDevice加入系統(tǒng)中。 設(shè)置設(shè)置和顯示設(shè)備關(guān)聯(lián)在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack)的TransformHint(主要指設(shè)備的顯示方向orientation) ![]() image.png
處理Layer增加情況 設(shè)置mDrawingState 2 VSync信號定時的調(diào)用handleMessageRefresh進行屏幕數(shù)據(jù)的刷新,輸出到屏幕; ![]() image.png
preComposition函數(shù),遍歷所有的Layer對象,調(diào)用其onPreComposition函數(shù)來檢測Layer層中的圖像是否有變化。 rebuildLayerStacks函數(shù)的作用是重建每個顯示設(shè)備的可見layer對象列表。通過判斷l(xiāng)ayerstack 和display設(shè)備的layerstack是否相同,來決定該layer是否在那個display設(shè)備顯示; ![]() image.png
setUpHWComposer函數(shù)的作用是更新HWComposer對象中圖層對象列表以及圖層屬性。 doComposition函數(shù)是合成所有層的圖像 postFramebuffer先判斷系統(tǒng)是否支持composer,如果不支持,我們知道圖像已經(jīng)在doComposition函數(shù)時調(diào)用hw->swapBuffers輸出了,就返回了。如果支持硬件composer,postFramebuffer函數(shù)將調(diào)用HWComposer的commit函數(shù)繼續(xù)執(zhí)行。 |
|