SurfaceFlinger 和 WindowManager

SurfaceFlinger 會接受緩衝區、組合緩衝區,並將緩衝區傳送至螢幕畫面。WindowManager 會為 SurfaceFlinger 提供緩衝區和視窗中繼資料,SurfaceFlinger 會使用這些資料將途徑合成至螢幕。

SurfaceFlinger

SurfaceFlinger 可透過兩種方式接受緩衝區:透過 BufferQueue 和 SurfaceControl,或透過 ASurfaceControl。

SurfaceFlinger 接受緩衝區的方式之一,是透過 BufferQueue 和 SurfaceControl。應用程式進入前景時,會向 WindowManager 要求緩衝區。接著,WindowManager 會向 SurfaceFlinger 要求圖層。圖層是 surfaceSurfaceControl 的組合,前者包含 BufferQueue,後者則包含顯示框架等圖層中繼資料。SurfaceFlinger 會建立圖層,並將圖層傳送至 WindowManager。接著,WindowManager 會將介面傳送至應用程式,但會保留 SurfaceControl,以便操控應用程式在螢幕上的外觀。

Android 10 新增了 ASurfaceControl,這是 SurfaceFlinger 可接受緩衝區的另一種方式。ASurfaceControl 會將表面和 SurfaceControl 合併為一個交易包,並傳送至 SurfaceFlinger。ASurfaceControl 與圖層相關聯,應用程式會透過 ASurfaceTransactions 更新圖層。接著,應用程式會透過回呼取得 ASurfaceTransactions 相關資訊,這些回呼會傳遞包含資訊的 ASurfaceTransactionStats,例如鎖定時間、取得時間等等。

下表詳細說明 ASurfaceControl 及其相關元件。

元件 說明
ASurfaceControl 包裝 SurfaceControl,並讓應用程式建立與螢幕上層級相對應的 SurfaceControl。

可做為 ANativeWindow 的子項或其他 ASurfaceControl 的子項建立。
ASurfaceTransaction 包裝交易,讓用戶端能夠編輯圖層的描述性屬性 (例如幾何圖形),並將更新的緩衝區傳送至 SurfaceFlinger。
ASurfaceTransactionStats 透過預先註冊的回呼,將已提交交易的相關資訊 (例如鎖定時間、取得時間和先前釋放柵欄) 傳送至應用程式。

雖然應用程式可隨時提交緩衝區,但 SurfaceFlinger 只會在顯示器重新整理期間喚醒,以便接受緩衝區,這可能因裝置而異。這麼做可盡量減少記憶體用量,並避免在螢幕上出現撕裂現象,這類現象可能會在更新螢幕時發生。

當螢幕處於重新整理之間時,螢幕會將 VSYNC 信號傳送至 SurfaceFlinger。VSYNC 信號表示螢幕可以重新整理,而不會出現撕裂。當 SurfaceFlinger 收到 VSYNC 信號時,SurfaceFlinger 會逐一檢查圖層清單,尋找新的緩衝區。如果 SurfaceFlinger 找到新的緩衝區,就會取得該緩衝區;如果沒有,則會繼續使用先前取得的緩衝區。SurfaceFlinger 必須一律顯示內容,因此會掛在一個緩衝區。如果未曾在圖層上提交緩衝區,系統會忽略該圖層。

SurfaceFlinger 收集可見圖層的所有緩衝區後,會詢問硬體合成器 (HWC) 應如何執行合成作業。如果 HWC 將圖層組合類型標示為用戶端組合,SurfaceFlinger 就會將這些圖層組合。接著,SurfaceFlinger 會將輸出緩衝區傳遞至 HWC

WindowManager

WindowManager 會控制視窗物件,這是 View 物件的容器。視窗物件一律由表面物件支援。WindowManager 會監督視窗的生命週期、輸入和焦點事件、螢幕方向、轉場、動畫、位置、轉換、z 順序和其他多項相關事項。WindowManager 會將所有視窗中繼資料傳送至 SurfaceFlinger,讓 SurfaceFlinger 可使用該資料在螢幕上合成介面。

預先旋轉

許多硬體覆疊層都不支援旋轉 (即使支援,也會消耗處理效能);解決方法是在緩衝區到達 SurfaceFlinger 之前轉換緩衝區。Android 支援 ANativeWindow 中的查詢提示 (NATIVE_WINDOW_TRANSFORM_HINT),用於代表 SurfaceFlinger 最有可能套用至緩衝區的轉換。GL 驅動程式可使用這項提示,在緩衝區抵達 SurfaceFlinger 之前預先轉換緩衝區,以便在緩衝區抵達時正確轉換。

舉例來說,當您收到旋轉 90 度的提示時,請產生並套用矩陣至緩衝區,以免畫面跑到網頁結尾。為節省電力,請執行這項預先旋轉作業。詳情請參閱 system/core/include/system/window.h 中定義的 ANativeWindow 介面。