多重刷新率

Android 11 增加了對具有多種刷新率的設備的支持。此功能包含三個主要組件:

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

執行

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

配置組

IComposerClient::Attribute添加了一個新屬性CONFIG_GROUP ,該屬性可使用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 更新

getDisplayVsyncPeriod
為了在更改刷新率時獲得更好的控制和可預測性,添加了getDisplayVsyncPeriodgetDisplayVsyncPeriod返回顯示器運行的當前刷新率(根據垂直同步週期)。當平台需要在刷新率和當前刷新率之間轉換來決定何時開始下一幀時,這尤其有用。
setActiveConfigWithConstraints
setActiveConfigWithConstraints方法是對現有setActiveConfig方法的新擴展,並提供有關配置更改的更多信息。約束作為vsyncPeriodChangeConstraints參數的一部分給出,並包含以下參數。
    期望時間納米
    CLOCK_MONOTONIC 中的時間,之後CLOCK_MONOTONIC週期可能會更改(即 vsync 週期在此時間之前不得更改)。當平台想要提前計劃刷新率更改但隊列中已經有一些緩衝區要呈現時,這很有用。平台會相應地設置此時間以考慮這些緩衝區,並確保刷新率轉換盡可能平滑。
    無縫需要
    如果為真,則要求垂直同步週期更改必須無縫發生,而不會出現明顯的視覺偽影。當由於內容更改而需要更改刷新率時(例如,設備空閒並且動畫開始),平台會使用此標誌。這使供應商有機會在某些配置更改可能導致明顯的視覺偽影時不允許它們進行更改。如果無法無縫更改配置並且將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 上的開發者文檔。

開發人員選項

菜單中添加了一個新的開發人員選項,可使用當前刷新率切換顯示屏上的覆蓋。新選項位於設置>系統>開發人員選項>顯示刷新率下。