自 2025 年 3 月 27 日起,我們建議您使用 android-latest-release
而非 aosp-main
建構及貢獻 AOSP。詳情請參閱「Android 開放原始碼計畫變更」。
多種刷新率
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
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 則歸入另一個設定群組。平台知道可以切換 60 Hz 和 90 Hz 之間,以及 48 Hz 和 72 Hz 之間,但不能切換 60 Hz 和 72 Hz 之間,因為這會導致設定變更,而非單純變更刷新率。
Composer API 更新
- getDisplayVsyncPeriod
- 為提供更佳的控管功能和可預測性,我們已新增
getDisplayVsyncPeriod
。getDisplayVsyncPeriod
會傳回螢幕目前的刷新率 (以 vsync 週期為準)。這在轉換螢幕更新率時特別實用,因為平台需要根據目前的螢幕更新率決定何時開始顯示下一個影格。
- setActiveConfigWithConstraints
setActiveConfigWithConstraints
方法是現有 setActiveConfig
方法的新擴充功能,可提供更多設定變更資訊。限制條件會提供為 vsyncPeriodChangeConstraints
參數的一部分,並包含下列參數。
- desiredTimeNanos
CLOCK_MONOTONIC
中的時間,此時間過後,vsync 週期可能會變更 (也就是說,vsync 週期必須在這個時間之前變更)。當平台想要提前規劃刷新率變更,但佇列中已有要顯示的緩衝區時,這項功能就非常實用。平台會根據這些緩衝區設定這段時間,確保螢幕刷新率轉換過程盡可能順暢。
- seamlessRequired
- 如果為 true,則要求 vsync 期間變更必須無縫進行,且不會出現明顯的視覺瑕疵。當內容變更導致需要變更更新率時 (例如裝置處於閒置狀態且動畫開始播放),平台會使用這個旗標。這樣一來,供應商就能在特定設定變更可能導致明顯視覺瑕疵時,禁止變更。如果無法順利變更設定,且
seamlessRequired
已設為 true
,則實作應會傳回 SEAMLESS_NOT_POSSIBLE
做為傳回碼,並在可順利變更相同設定時呼叫新的 onSeamlessPossible
回呼。
實作成功後,實作會傳回 VsyncPeriodChangeTimeline
,告知平台何時應發生更新率變更。newVsyncAppliedTimeNanos
參數必須設為 CLOCK_MONOTONIC
中的時間,以便新顯示器開始以新的 vsync 週期進行重新整理。搭配 desiredTimeNanos
後,平台就能提前規劃螢幕更新率切換作業,並提前開始為應用程式啟用新螢幕更新率。這樣就能流暢地轉換刷新率。
部分實作方式需要先傳送刷新影格,才能傳送刷新率。為此,HAL 提供 refreshRequired
參數,用於指出需要刷新影格,並提供 refreshTimeNanos
,用於指出需要在哪個 vsync 之後傳送刷新影格。
- onVsyncPeriodTimingChanged [回呼]
- HAL 可呼叫的新回呼,用於向平台指出時間軸的某些參數已變更,且平台需要調整時間軸。如果舊時間表因 HAL 的處理時間過長或刷新影格延遲而錯過,則會呼叫這個回呼。
系統會在下列兩個系統服務中選取更新率:
- DisplayManager
DisplayManager
會設定刷新率的高層級政策。它會設定預設顯示設定,這與作曲家 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) 時,系統會在設定的逾時期間使用預設的更新率。
Frame Rate API
影格速率 API 可讓應用程式向 Android 平台告知其預期的影格速率,並適用於指定 Android 11 為目標版本的應用程式。如要進一步瞭解影格速率 API,請參閱 developer.android.com 的開發人員說明文件。
開發人員選項
選單中已新增一個開發人員選項,可切換顯示目前刷新率的疊加層。新選項位於「設定」 >「系統」 >「開發人員選項」 >「顯示更新率」。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Multiple refresh rate\n\nAndroid 11 adds support for devices with multiple refresh rates. There are\nthree main components to this feature:\n\n- New HAL APIs introduced in `android.hardware.graphics.composer@2.4`.\n- Platform code to parse device configs for different refresh rates and set the desired refresh rate\n- New SDK and NDK APIs to allow apps to set their desired frame rate\n\nImplementation\n--------------\n\nDedicated support for refresh rate switching has been added to\n`android.hardware.graphics.composer@2.4 HAL`.\nWe strongly recommend using this version since previous versions of\ncomposer HAL have limited support for refresh rate switching.\n\n### Config groups\n\nA new attribute `CONFIG_GROUP` was added to\n`IComposerClient::Attribute` that is queryable using the\n`getDisplayAttribute_2_4` API. This attribute allows vendors to group\ntogether display configurations. Configurations in the same group allows\nseamless switching between them in most of the cases. The config group is used\nby the platform to differentiate which configurations can be switched between\nthem in order to switch the refresh rate and not other attributes for a\nconfig.\n\nConsider the following example that demonstrates the benefits of using config\ngroups with a device that supports four display configurations:\n\n- 1080p@60Hz\n- 1080p@90Hz\n- 1080i@72Hz\n- 1080i@48Hz\n\nEven though the device supports 48Hz, 60Hz, 72Hz, and 90Hz refresh rates the\ndisplay operates at a different mode and switching from 60Hz to 72Hz changes the\ndisplay config from 1080p to 1080i, which might not be the desired behavior.\nThis is solved by using config groups. By grouping 60Hz and 90Hz together in one\nconfig group and 48Hz and 72Hz in another config group. The platform knows that\nit can switch between 60Hz and 90Hz and between 48Hz and 72Hz but not between\n60Hz and 72Hz as this will result in a config change rather than simply changing\nthe refresh rate. \n\n### Composer API updates\n\ngetDisplayVsyncPeriod\n: For better control and predictability when changing refresh rates\n `getDisplayVsyncPeriod `has been added.\n `getDisplayVsyncPeriod` returns the current refresh rate (in terms of\n vsync period) the display operates at. This is especially useful while\n transitioning between refresh rate and the current refresh rate is needed by the\n platform to decide when to start the next frame.\n\nsetActiveConfigWithConstraints\n: The `setActiveConfigWithConstraints `method is a new extension\n to the existing `setActiveConfig` method and provides more\n information about the config change. The constraints are given as part of the\n `vsyncPeriodChangeConstraints` parameters and contain the following\n parameters.\n\n: Upon success the implementation returns a\n `VsyncPeriodChangeTimeline` which tells the platform when to expect\n the refresh rate change to occur. `newVsyncAppliedTimeNanos`\n parameters need to be set to the time in `CLOCK_MONOTONIC` when the\n new display will start to refresh at the new vsync period. This, together with\n `desiredTimeNanos` allows the platform to plan in advance the refresh\n rate switch and start ticking apps for the new refresh rate in advance. This\n allows a seamless transition of the refresh rate.\n\n Some implementations require a refresh frame to be sent before the refresh\n rate can be sent. For that, the HAL has the `refreshRequired`\n parameter to indicate that a refresh frame is needed and\n `refreshTimeNanos` to indicate the first vsync where a refresh frame\n needs to be sent after.\n\nonVsyncPeriodTimingChanged \\[callback\\]\n: A new callback that can be called by the HAL to indicate to the platform that some\n parameter of the timeline changed and the platform needs to adjust its timeline.\n This callback is expected to be called if for some reason the old timeline was\n missed because of a long processing time on the HAL or a late refresh\n frame.\n\nHow does the platform decide to change the refresh rate?\n--------------------------------------------------------\n\nThe refresh rate selection happens in the following two system services:\n\nDisplayManager\n: The `DisplayManager` sets the high level policy\n around the refresh rate. It sets a default display config, which is the same as\n the composer HAL config. Additionally, it sets a range of minimum and maximum\n values for `SurfaceFlinger` to choose as the refresh\n rate.\n\nSurfaceFlinger\n: Determines the refresh rate by setting a config which is in the same config\n group as the default config and with a refresh rate within the min/max\n range.\n\nThe Display Manager runs through the following steps to determine the\npolicy:\n\n- Finds the default config ID by querying the active config from `SurfaceFlinger`\n- Restricting the range of minimum and maximum values by iterating over the system conditions\n - **Default refresh rate setting** : The default refresh rate value is set in the `R.integer.config_defaultRefreshRate` config overlay. This value is used to determine the standard device refresh rate for animations and touch interactions.\n - **Peak refresh rate setting** : The peak refresh rate value is read from `Settings.System.PEAK_REFRESH_RATE`. This value is changed in runtime to reflect the current device setting (such as from a menu option). The default value is set in the `R.integer.config_defaultPeakRefreshRate` config overlay.\n - **Minimum refresh rate setting** : The minimum refresh rate value is read from `Settings.System.MIN_REFRESH_RATE`. This value can be changed in runtime to reflect the current device setting (such as from a menu option). The default value is 0, so there is no default minimum.\n - **Application requested ModeId** : Apps can set [`WindowManager.LayoutParams.preferredDisplayModeId`](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#preferredDisplayModeId) to reflect a preferred config the display should operate at. In most conditions the `DisplayManager` sets the default config ID accordingly and sets the minimum and maximum refresh rate to match the config's refresh rate.\n - **Battery Saver** : The refresh rate is restricted to 60Hz or lower when the device is in low power mode, which is indicated through `Settings.Global.LOW_POWER_MODE.`\n\nOnce `DisplayManager` sets the policy,\n`SurfaceFlinger` sets the refresh rate based on the active layers (layers that queue\nframe updates). If the owner of the layer sets a , SurfaceFlinger\ntries to set the refresh rate to something that is a multiplier of that rate.\nFor example if two active layers set their frame rate to 24 and 60 SurfaceFlinger\nwill pick 120Hz if it is available. If such refresh rate is not available to\nSurfaceFlinger, it will try to pick the refresh rate which has the minimal\nerror for the frame rate. For more information see the developer documentation on [developer.android.com](https://developer.android.com/guide/topics/media/frame-rate)\n\n`SurfaceFlinger` maintains the following flags to\ncontrol how the refresh rate is decided:\n\n- `ro.surface_flinger.use_content_detection_for_refresh_rate:` If set the refresh rate is decided based on the active layers, even if a frame rate was not set. SurfaceFlinger maintains a heuristic where it finds the average fps the layer is posting buffers by looking at the presentation timestamp attached to the buffer.\n- `ro.surface_flinger.set_touch_timer_ms`: if \\\u003e 0, the default refresh rate will be used when a user touches the screen for the configured timeout. This heuristic is done to be ready with the default refresh rate for animations.\n- `ro.surface_flinger.set_idle_timer_ms`: if \\\u003e 0, min refresh rate will be used when there are no screen updates for the configured timeout.\n- `ro.surface_flinger.set_display_power_timer_ms`: if \\\u003e 0, the default refresh rate will be used when turning on the display (or when going out of AOD) for the configured timeout.\n\nFrame Rate API\n--------------\n\nThe frame rate API lets apps inform the Android platform of their intended\nframe rate and is available on apps that target\nAndroid 11. To learn more about\nthe frame rate API, check out the developer documentation on [developer.android.com](https://developer.android.com/guide/topics/media/frame-rate).\n\nDeveloper options\n-----------------\n\nA new developer option has been added to the menu that toggles an overlay on\nthe display with the current refresh rate. The new option is under\n**Settings** \\\u003e **System** \\\u003e **Developer\noptions** \\\u003e **Show refresh rate.**"]]