從 Android 13 開始,每當螢幕解析度變更時,系統就會分配新的緩衝區,用於用戶端組合。解析度變更後,SurfaceFlinger 會在下一個失效週期執行這項分配作業。
解析度切換期間的 Framebuffer 管理
解析度變更的原因有下列兩種:
熱插拔事件是由硬體合成器 (HWC) 啟動,當從一個外部螢幕切換到預設解析度不同的另一個外部螢幕時,就會發生這類事件。
在熱插拔事件期間,HWC 會在取消分配舊螢幕資料時,釋放舊緩衝區的控制代碼。
由 SurfaceFlinger 啟動的顯示模式切換,發生於您使用使用者設定變更解析度時,或應用程式使用
preferredDisplayModeId變更解析度時。在切換顯示模式期間,SurfaceFlinger 會先釋出現有用戶端緩衝區的控制代碼,再呼叫
setActiveConfig或setActiveConfigWithConstraints。
為避免發生災難性問題,例如 framebuffer 記憶體不足的裝置上出現記憶體片段化,HWC 必須釋出舊 framebuffer 的控制代碼。在下列情況中,這項功能至關重要:
如果是熱插拔事件,請在呼叫
onHotplug之前立即執行此操作。如要切換模式,請在呼叫
setActiveConfig或setActiveConfigWithConstraints後立即執行這項操作。
釋出控制代碼可讓影格緩衝區記憶體在 SurfaceFlinger 於下一個 invalidate 週期分配新影格緩衝區前,完全解除分配。
緩衝區管理建議
如果 HWC 未及時將控制代碼發布至舊的 Framebuffer,系統就會在舊的 Framebuffer 解除分配前,分配新的 Framebuffer。如果因片段化或其他問題導致新配置失敗,可能會造成嚴重問題。更糟的是,如果 HWC 完全未釋出這些控制代碼,就可能發生記憶體流失。
為避免災難性的分配失敗,請參考下列建議:
如果 HWC 需要繼續使用舊的用戶端訊框緩衝區,直到提供新的用戶端訊框緩衝區為止,請務必為舊的和新的訊框緩衝區保留足夠的記憶體,並可能在訊框緩衝區記憶體空間上執行重組演算法。
為訊框緩衝區分配專屬記憶體集區,與其餘的圖像緩衝區記憶體分開。這點很重要,因為第三方程序可能會嘗試在緩衝區取消分配和重新分配之間分配圖像記憶體。如果訊框緩衝區使用相同的圖形記憶體集區,且圖形記憶體已滿,第三方程序可能會佔用訊框緩衝區先前分配的記憶體。這可能會導致記憶體不足,無法重新分配 Framebuffer,或造成記憶體片段化。
測試畫面緩衝區管理
建議 OEM 針對裝置的解析度切換測試適當的用戶端 Framebuffer 記憶體管理,如下所述:
如果是熱插拔事件,請拔除並重新連接兩個解析度不同的螢幕。
如要切換模式,請使用
ModeSwitchingTestActivityCTS 驗證器測試,啟動模式切換,測試影格緩衝區記憶體行為。這項測試可以透過視覺化方式找出難以透過程式輔助偵測到的問題。