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 之间切换,因为这将导致配置更改,而不仅仅是更改刷新率。


Composer API 更新
- getDisplayVsyncPeriod
- 为了在更改刷新率时获得更好的控制和可预测性,添加了
getDisplayVsyncPeriod
。getDisplayVsyncPeriod
返回显示器当前运行的刷新率(以垂直同步周期为单位)。这在刷新率转换期间尤其有用,平台需要知道当前的刷新率,以决定何时开始下一帧。 - setActiveConfigWithConstraints
setActiveConfigWithConstraints
方法是对现有setActiveConfig
方法的新扩展,并提供有关配置更改的更多信息。约束条件作为vsyncPeriodChangeConstraints
参数的一部分给出,并包含以下参数。- desiredTimeNanos
- 垂直同步周期可能更改之后的时间(以
CLOCK_MONOTONIC
为单位)(即,垂直同步周期不得在此时间之前更改)。当平台想要提前计划刷新率更改,但队列中已经有一些缓冲区要呈现时,这很有用。平台会相应地设置此时间,以考虑这些缓冲区并确保刷新率转换尽可能平滑。 - seamlessRequired
- 如果为 true,则要求垂直同步周期更改必须无缝发生,且没有明显的视觉伪影。当由于内容更改而需要刷新率更改时(例如,设备处于空闲状态并且动画开始),平台会使用此标志。这为供应商提供了机会,以便在某些配置更改可能导致明显的视觉伪影时不允许这些更改。如果无法无缝更改配置,并且
seamlessRequired
设置为true
,则实现应返回SEAMLESS_NOT_POSSIBLE
作为返回代码,并在可以无缝完成相同的配置更改时调用新的onSeamlessPossible
回调。 成功后,实现会返回一个
VsyncPeriodChangeTimeline
,告知平台何时预期会发生刷新率更改。newVsyncAppliedTimeNanos
参数需要设置为CLOCK_MONOTONIC
中的时间,在该时间,新显示器将开始以新的垂直同步周期刷新。这与desiredTimeNanos
一起,允许平台提前计划刷新率切换,并提前开始为新的刷新率计时应用。这允许刷新率的无缝转换。某些实现需要先发送刷新帧,然后才能发送刷新率。为此,HAL 具有
refreshRequired
参数来指示需要刷新帧,并具有refreshTimeNanos
来指示需要发送刷新帧的第一个垂直同步。- onVsyncPeriodTimingChanged [回调]
- HAL 可以调用新的回调来向平台指示时间线的某些参数已更改,并且平台需要调整其时间线。如果由于 HAL 上的处理时间过长或刷新帧延迟而错过了旧时间线,则预计会调用此回调。
平台如何决定更改刷新率?
刷新率选择发生在以下两个系统服务中
- DisplayManager
DisplayManager
设置围绕刷新率的高级策略。它设置默认显示配置,这与 composer HAL 配置相同。此外,它还为SurfaceFlinger
设置了最小和最大值的范围,以选择作为刷新率。- SurfaceFlinger
- 通过设置与默认配置在同一配置组中且刷新率在最小/最大范围内的配置来确定刷新率。
Display Manager 运行以下步骤来确定策略
- 通过从
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 的开发者文档。
开发者选项

菜单中添加了一个新的开发者选项,用于切换显示器上具有当前刷新率的叠加层。新选项位于设置 > 系统 > 开发者选项 > 显示刷新率下。