自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
多种刷新率
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
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 对其进行查询。通过此属性,供应商可以将屏幕配置组合在一起。在大多数情况下,同一组中的配置允许无缝切换这些配置。平台使用配置群组来区分可以相互切换的不同配置,用以切换刷新率而不是其他配置属性。
下面的示例演示了在支持 4 种屏幕配置的设备上使用群组的好处:
- 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 之间切换,因为这会导致配置更改,而不仅仅是简单地变换刷新率。
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
,告知平台预计何时会变换刷新率。当新屏幕要开始以新的 vsync 周期刷新时,newVsyncAppliedTimeNanos
参数需要设置为 CLOCK_MONOTONIC
中的时间。此标志与 desiredTimeNanos
结合使用时,平台可以预先规划刷新率开关,并提前使应用进入切换到新刷新率的倒计时。这样可以实现刷新频率的无缝过渡。
某些实现要求在发送刷新频率之前发送刷新帧。为此,HAL 采用了两个参数:一个是 refreshRequired
,用于指示需要某个刷新帧;另一个是 refreshTimeNanos
,用于指示需要在其后发送刷新帧的第一个 vsync。
- onVsyncPeriodTimingChanged [callback]
- 可由 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,并设置最小和最大刷新频率以匹配配置的刷新频率。
- 省电模式:当设备处于低功耗模式(通过
Settings.Global.LOW_POWER_MODE.
指示)时,刷新率上限为 60Hz。
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 上的开发者文档。
开发者选项
菜单中新增了一个开发者选项,它可以使用当前刷新率在屏幕上切换叠加层。新选项位于设置 > 系统 > 开发者选项 > 显示刷新频率下。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-26。
[null,null,["最后更新时间 (UTC):2025-03-26。"],[],[],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.**"]]