多重刷新率

Android 11 增加了對多種更新率裝置的支援。此功能由三個主要組成部分組成:

  • android.hardware.graphics.composer@2.4中引入了新的 HAL API。
  • 用於解析不同刷新率的設備配置並設定所需刷新率的平台程式碼
  • 新的 SDK 和 NDK API 允許應用程式設定所需的幀速率

執行

android.hardware.graphics.composer@2.4 HAL增加了對刷新率切換的專用支援。我們強烈建議使用此版本,因為先前版本的 Composer HAL 對刷新率切換的支援有限。

配置群組

新屬性CONFIG_GROUP已新增至IComposerClient::Attribute中,可使用getDisplayAttribute_2_4 API 進行查詢。此屬性允許供應商將顯示配置分組在一起。在大多數情況下,同一組中的配置允許它們之間的無縫切換。平台使用配置組來區分哪些配置可以在它們之間切換,以便切換配置的刷新率而不是其他屬性。

請考慮以下範例,此範例示範了在支援四種顯示配置的裝置上使用組態群組的優勢:

  • 1080p@60Hz
  • 1080p@90Hz
  • 1080i@72Hz
  • 1080i@48Hz

即使裝置支援 48Hz、60Hz、72Hz 和 90Hz 更新率,顯示器也會以不同的模式運行,從 60Hz 切換到 72Hz 會將顯示器配置從 1080p 變更為 1080i,這可能不是所需的行為。這是透過使用配置組來解決的。透過將 60Hz 和 90Hz 分組到一個配置組中,將 48Hz 和 72Hz 分組到另一個配置組。該平台知道它可以在 60Hz 和 90Hz 之間以及在 48Hz 和 72Hz 之間切換,但不能在 60Hz 和 72Hz 之間切換,因為這將導致配置更改,而不是簡單地更改刷新率。

作曲家 API 更新

取得顯示垂直同步週期
為了在更改刷新率時實現更好的控制和可預測性,添加了getDisplayVsyncPeriodgetDisplayVsyncPeriod返回顯示器運行時的目前更新率(以垂直同步週期表示)。當平台需要在刷新率和當前刷新率之間轉換來決定何時開始下一幀時,這尤其有用。
setActiveConfigWithConstraints
setActiveConfigWithConstraints方法是現有setActiveConfig方法的新擴展,並提供有關配置變更的更多資訊。約束條件作為vsyncPeriodChangeConstraints參數的一部分給出,並包含以下參數。
    期望時間奈秒
    CLOCK_MONOTONIC中的時間,在此之後 vsync 週期可能會更改(即 vsync 週期在此時間之前不得更改)。當平台想要提前規劃更新率變更但佇列中已經有一些緩衝區需要呈現時,這非常有用。平台相應地設定該時間以考慮這些緩衝區並確保刷新率轉換盡可能平滑。
    無縫必填
    如果為 true,則要求垂直同步週期變更必須無縫發生,且不會出現明顯的視覺偽影。當由於內容變更而需要更改更新率時(例如,裝置空閒且動畫開始),平台將使用此標誌。這使供應商有機會不允許某些配置更改,因為這些更改可能會導致明顯的視覺偽影。如果無法無縫變更配置且seamlessRequired設為true ,則實作預計將傳回SEAMLESS_NOT_POSSIBLE作為回傳程式碼,並在可以無縫完成相同的設定變更時呼叫新的onSeamlessPossible回呼。

成功後,實作會傳回一個VsyncPeriodChangeTimeline ,它告訴平台更新率何時會改變。 newVsyncAppliedTimeNanos參數需要設定為CLOCK_MONOTONIC中新顯示器將在新的垂直同步週期開始刷新的時間。這與desiredTimeNanos一起允許平台提前計劃刷新率切換並提前啟動應用程式以適應新的更新率。這允許刷新率的無縫過渡。

一些實現要求在發送刷新率之前發送刷新幀。為此,HAL具有refreshRequired參數來指示需要刷新幀,並refreshTimeNanos來指示需要在之後發送刷新幀的第一個vsync。

onVsyncPeriodTimingChanged [回呼]
HAL 可以呼叫新的回調,以向平台指示時間軸的某些參數發生更改,並且平台需要調整其時間軸。如果由於某種原因,由於 HAL 上的處理時間較長或刷新幀較晚而錯過了舊時間線,則預計會調用此回調。

平台如何決定改變刷新率?

刷新率選擇發生在以下兩個系統服務:

顯示管理器
DisplayManager設定有關刷新率的進階策略。它設定預設顯示配置,與 Composer HAL 配置相同。此外,它還設定了SurfaceFlinger可以選擇的刷新率的最小值和最大值範圍。
SurfaceFlinger
透過設定與預設配置位於同一組態群組中且刷新率在最小/最大範圍內的配置來決定刷新率。

顯示管理器透過以下步驟運作來決定策略:

  • 透過從SurfaceFlinger查詢活動配置來尋找預設配置 ID
  • 透過迭代系統條件來限制最小值和最大值的範圍
    • 預設刷新率設定:預設刷新率值在R.integer.config_defaultRefreshRate配置覆蓋層中設定。該值用於確定動畫和觸控互動的標準設備更新率。
    • 峰值刷新率設定:峰值刷新率值從Settings.System.PEAK_REFRESH_RATE讀取。該值在運行時更改以反映當前設備設定(例如來自選單選項)。預設值在R.integer.config_defaultPeakRefreshRate配置覆蓋中設定。
    • 最小刷新率設定:最小刷新率值從Settings.System.MIN_REFRESH_RATE讀取。該值可以在運行時更改以反映當前裝置設定(例如從選單選項)。預設值為 0,因此沒有預設最小值。
    • 應用程式請求的 ModeId :應用程式可以設定WindowManager.LayoutParams.preferredDisplayModeId以反映顯示器應運行的首選配置。在大多數情況下, DisplayManager會相應地設定預設配置 ID,並設定最小和最大刷新率以匹配配置的刷新率。
    • 省電模式:當設備處於低功耗模式時,刷新率被限制為 60Hz 或更低,這透過Settings.Global.LOW_POWER_MODE.

DisplayManager設定策略後, SurfaceFlinger將根據活動層(對幀更新進行排隊的層)設定更新率。如果圖層的擁有者設定了幀速率,SurfaceFlinger 會嘗試將刷新率設定為該速率的倍數。例如,如果兩個活動圖層將其幀速率設定為 24 和 60,SurfaceFlinger 將選擇 120Hz(如果可用)。如果 SurfaceFlinger 無法使用這樣的更新率,它將嘗試選擇幀率誤差最小的刷新率。有關更多信息,請參閱developer.android.com上的開發人員文檔

SurfaceFlinger維護以下標誌來控制如何決定更新率:

  • ro.surface_flinger.use_content_detection_for_refresh_rate:如果設定,即使未設定幀速率,刷新率也會根據活動圖層決定。 SurfaceFlinger 維護一種啟發式方法,透過查看附加到緩衝區的呈現時間戳來尋找該層正在發布緩衝區的平均 fps。
  • ro.surface_flinger.set_touch_timer_ms :如果 > 0,則當使用者在配置的逾時時間內觸碰螢幕時,將使用預設刷新率。完成此啟發式是為了為動畫的預設更新率做好準備。
  • ro.surface_flinger.set_idle_timer_ms :如果 > 0,則在配置的逾時時間內沒有螢幕更新時將使用最小刷新率。
  • ro.surface_flinger.set_display_power_timer_ms :如果 > 0,則在配置的逾時時間內開啟顯示器(或退出 AOD 時)時將使用預設刷新率。

幀率API

幀速率 API 允許應用程式告知 Android 平台其預期幀速率,並且可在面向 Android 11 的應用上使用。要了解有關幀速率 API 的更多信息,請查看developer.android.com上的開發人員文檔。

開發者選項

選單中新增了一個新的開發人員選項,可以使用目前刷新率切換顯示器上的覆蓋層。新選項位於「設定」 > “系統”> “開發人員選項” > “顯示更新率”下。