Android 双屏显示分析
雙屏異顯
系統提供了Presentation類,可以實現在兩塊屏幕上同時顯示不同的內容;Presentation是一個特殊的dialog,它的目的是顯示內容到第二屏幕。
image.png
基本原理
image.png
1 獲得顯示設備信息:
 DisplayManagerService 啟動后從SurfaceFlinger當中獲取到系統默認的Display 與HDMI display的信息。
2 應用程序端指定其應用ContextImpl的Display。
3 應用程序獲得Surface和配置Surface,這個surface對應于SurfaceFlinger中的Layer;
WindowManagerService作為一個系統服務,主要管理系統中所有的應用的Window。在WMS中,每個Window都有一個對應的WindowState對象。
3.1 addWindow,該函數在WindowManagerService當中,由WindowManagerImpl中的addView函數調用到,并且將Window所在的Display作為參數帶到WMS當中。
3.2在addWindow函數,WMS首先找到窗口所在的Display,創建WindowState,然后將窗口加到Display中的Windowlist當中。win.mToken.addWindow(win);
3.3 WindowState,獲取對應Display的layerstack將其放置在WindowStateAnimator當中,并且將值設置到SurfaceFlinger當中與之對應的Layer中,告知SurfaceFlinger自己所在Display。mSurfaceControl.setLayerStack(mLayerStack);
4 繪制Surface
 SurfaceFlinger作為Android在native層比較重要的一個系統服務,主要作用是compose所有的layer,將其繪制輸出到顯示設備當中,也就是物理Display當中。
 SurfaceFlinger根據Layer當中的layerStack成員,獲知需要將該Layer繪制到具體哪一個Display當中。
?
image.png
SurfaceFlinger需要利用HWC, Compose 屬于每個Display的layer,并且將其輸出到具體的DisplayDivice當中。
?
image.png
源碼分析
1 新設備加入流程
DisplayManagerService
?
image.png
LocalDisplayAdapter
?
image.png
當驅動層發現設備加入時會發出事件,framework檢測到這個事件會調用onHotplug;如果是connected,那么調用tryConnectDisplayLocked,創建LocalDisplayDevice并保存到mDevices,發送DISPLAY_DEVICE_ENVENT_CHANGED;
image.png
image.png
最終會調用DisplayManagerService中的handleDisplayDeviceAddedLocked;
?
image.png
?
handleDisplayDeviceAddedLocked函數中添加邏輯設備;并且分配默認的displayId和Layerstack
2 異顯示流程
2.1 在Presentation創建的時候關聯一個目標設備,確定Presentation要顯示在那個設備上。根據這個設備的信息來配置Presentation的context和resources信息,每一個display擁有自己的管理對象以及context對象,這樣雙屏的操作互相獨立;對于上層而言,其即意味著一個屏幕。
?
image.png
?
2.2 調用show函數顯示view;實際調用WindowManagerImpl的addview函數;
?
image.png
 WindowManagerImpl的addview 函數創建ViewRootImp,并調用ViewRootImpl的setView函數;ViewRootImpl類中創建了WindowSession和IWindow對象負責和Windowmanagerservice之間跨進程通信;
image.png
ViewRootImpl setview函數,調用了requestLayout 和WindowSession addToDisplay;
ViewRootImpl中requestLayout函數調用mWindowSession.relayout,最終調用WindowManagerservice 的relayoutWindow,這個函數會配置Display信息; WindowStateAnimator創建Surfacecontrol,通過SurfaceControl,設置Layerstack;
?
image.png
SurfaceControl 事務
SurfaceControl開始事務,設置參數,結束事務
image.png
WindowManagerservice addWindow函數
1 通過displayId 獲取顯示設備
final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);
2 創建WindowState, WindowState函數中創建了WindowStateAnimator對象負責窗口的管理
final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid,
 session.mCanAddInternalSystemWindow);
SurfaceControl 調用本地層方法android_view_SurfaceControl 設置surfaceflinger
?
image.png
?
image.png
?
SurfaceComposerClient對象負責和surfaceflinger通信;配置好參數,結束事務,跨進程調用surfaceflinger setTransactionState
?
image.png
?
image.png
 Surfaceflinger 對display設備和layer層操作,設置layerstack, layer和第二塊屏綁定setDisplayStateLocked
image.png
?
image.png
Surfaceflinger輸出過程:
1 handleTransaction handPageFlip用戶進程更新Surface圖像時會調用,來更新Layer對象
handleTransaction函數的作用的就是處理系統在兩次刷新期間的各種變化。
包括:
處理Layer的事務,檢測是否需要更新;
處理顯示設備的變化:
1.顯示設備減少了,需要把顯示設備對應的DisplayDevice移除
2.顯示設備發生了變化,例如用戶設置了Surface、重新設置了layerStack、旋轉了屏幕等,這就需要重新設置顯示對象的屬性
3.顯示設備增加了,創建新的DisplayDevice加入系統中。
設置設置和顯示設備關聯在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack)的TransformHint(主要指設備的顯示方向orientation)
image.png
處理Layer增加情況
設置mDrawingState
2 VSync信號定時的調用handleMessageRefresh進行屏幕數據的刷新,輸出到屏幕;
image.png
preComposition函數,遍歷所有的Layer對象,調用其onPreComposition函數來檢測Layer層中的圖像是否有變化。
rebuildLayerStacks函數的作用是重建每個顯示設備的可見layer對象列表。通過判斷layerstack 和display設備的layerstack是否相同,來決定該layer是否在那個display設備顯示;
?
image.png
setUpHWComposer函數的作用是更新HWComposer對象中圖層對象列表以及圖層屬性。
doComposition函數是合成所有層的圖像
postFramebuffer先判斷系統是否支持composer,如果不支持,我們知道圖像已經在doComposition函數時調用hw->swapBuffers輸出了,就返回了。如果支持硬件composer,postFramebuffer函數將調用HWComposer的commit函數繼續執行。
 作者:NiceDream
 鏈接:https://www.jianshu.com/p/c3349146b38d
 來源:簡書
 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的Android 双屏显示分析的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 双线性光强插值(Gouraud明暗处理)
- 下一篇: FastAPI 是什么?
