從 Android 13 開始,只要顯示分辨率發生變化,就會分配在客戶端組合期間使用的新幀緩衝區。此分配由 SurfaceFlinger 在分辨率更改後的下一個無效週期執行。
分辨率切換期間的幀緩衝區管理
由於以下兩種情況之一,會發生分辨率更改:
由 Hardware Composer (HWC) 發起的熱插拔事件,當從一個外部顯示器交換到具有不同默認分辨率的另一個外部顯示器時會發生該事件。
在熱插拔事件期間,當舊的顯示數據被釋放時,舊的幀緩衝區的句柄被釋放。
由 SurfaceFlinger 發起的顯示模式切換,當用戶使用user settings更改分辨率,或者應用程序使用
preferredDisplayModeId
更改分辨率時,會發生這種切換。在顯示模式切換期間,SurfaceFlinger 在調用
setActiveConfig
或setActiveConfigWithConstraints
之前釋放現有客戶端幀緩衝區的句柄。
為了避免在沒有為新舊幀緩衝區保留足夠內存的設備上出現災難性問題(例如內存碎片),HWC 停止使用舊幀緩衝區並釋放這些幀緩衝區的任何句柄至關重要,如下例所示:
對於熱插拔事件,在調用
onHotplug
之前。對於模式切換,在調用
setActiveConfig
或setActiveConfigWithConstraints
之後立即進行。
釋放句柄允許在 SurfaceFlinger 在下一個無效週期期間執行的新幀緩衝區分配之前完全釋放幀緩衝區內存。
幀緩衝區管理建議
如果 HWC 沒有及時釋放舊幀緩衝區的句柄,則新幀緩衝區分配將在舊幀緩衝區釋放之前進行。當新的分配由於碎片或其他問題而失敗時,這可能會導致災難性的問題。更糟糕的是,如果 HWC 根本不釋放這些句柄,則可能會發生內存洩漏。
為了避免災難性的分配失敗,請遵循以下建議:
如果HWC 需要繼續使用舊的客戶端幀緩衝區,直到提供新的客戶端幀緩衝區,則為新舊幀緩衝區保留足夠的內存至關重要,並且可能在幀緩衝區內存空間上運行碎片整理算法。
為幀緩衝區分配一個與圖形緩衝區內存的其餘部分分開的專用內存池。這很重要,因為在幀緩衝區的釋放和重新分配之間,第三方進程可以嘗試分配圖形內存。如果幀緩衝區使用相同的圖形內存池,並且圖形內存已滿,則第三方進程可能會佔用幀緩衝區先前分配的圖形內存,從而導致幀緩衝區重新分配的內存不足,或者可能導致內存空間碎片化。
測試幀緩衝區管理
建議 OEM 測試其設備的跨分辨率切換是否正確的客戶端幀緩衝區內存管理,如下所述:
對於熱插拔事件,只需拔下並重新連接具有不同分辨率的兩個不同顯示器即可。
對於模式切換,請使用
ModeSwitchingTestActivity
CTS Verifier 測試啟動模式切換以測試幀緩衝區內存行為。該測試可以直觀地識別難以通過編程方式檢測到的問題。