SwallowJoe的博客

Be a real go-getter,
NEVER SETTLE!

0%

App申请帧率(1)--简述

背景

随着手机屏幕硬件能力的提升,越来越多的厂商提供支持多档次刷新率的Android设备。
而在Android Q上也是支持App指定当前屏幕帧率的,也有一套帧率分辨率切换的逻辑。

参考资料

  1. https://zhuanlan.zhihu.com/p/142212769?from_voters_page=true

查看设备可支持的刷新率和分辨率

使用命令:
adb shell dumpsys display dump |grep -A 10 -iE “mSupportedModes”

这里设备使用的是OnePlus8Pro,结果如下:

1
2
3
4
5
mSupportedModes=
DisplayModeRecord{mMode={id=1, width=1080, height=2376, fps=60.000004}}
DisplayModeRecord{mMode={id=2, width=1440, height=3168, fps=120.00001}}
DisplayModeRecord{mMode={id=3, width=1440, height=3168, fps=60.000004}}
DisplayModeRecord{mMode={id=4, width=1080, height=2376, fps=120.00001}}

可以看到是有四种模式:

  1. 1080 + 60Hz
  2. 2K + 120Hz
  3. 2K + 60Hz
  4. 1080 + 120Hz

App设置设备帧率

Android Q及以下版本

在Android Q或更低版本上,可以通过指定当前Window的帧率来设置屏幕刷新率,如选择设备可支持的最高刷新率:

1
2
3
4
5
6
7
8
var highestMode: Display.Mode = mWindowManager!!.defaultDisplay.supportedModes[0]
for (mode in mWindowManager!!.defaultDisplay.supportedModes) {
if (mode.refreshRate > highestMode.refreshRate) {
highestMode = mode
}
}

wmParams!!.preferredDisplayModeId = highestMode.modeId

Android R

Google建议利用可变刷新率

在较旧的 Android 版本 (Android 11 之前) 中并不存在 setFrameRate API,这时应用仍然可以通过直接将WindowManager.LayoutParams.preferredDisplayModeId设置为Display.getSupportedModes中的可用模式之一来影响刷新率。

从 Android 11 开始,我们不建议大家采用这种方法,因为平台会不知道应用的渲染意图。

例如,如果一个设备支持 48Hz、60Hz 和 120Hz,屏幕上有两个应用分别调用 setFrameRate(60, …) 和 setFrameRate(24, …),那么平台可以选择 120Hz 来同时满足这两个应用。

而如果这些应用使用了preferredDisplayModeId,它们很可能会把模式设置为 60Hz 和 48Hz,那这时平台就无法使用 120Hz 了。
这时平台只能从 60Hz 或 48Hz 中选择一个,从而影响到另一个应用的显示效果。

  1. 获取刷新率:

    1. SDK

通过 DisplayManager.DisplayListener 注册一个显示监听器,并通过 Display.getRefreshRate 查询刷新率。
2. NDK
使用 AChoreographer_registerRefreshRateCallback 注册回调 (API 级别30)。

  1. 设置刷新率应用可以调用以下方法之一:
    1. SDK
      1. Surface.setFrameRate
      2. SurfaceControl.Transaction.setFrameRate
    2. NDK
      1. ANativeWindow_setRrameRate
      2. ASurfaceTransaction_setFrameRate

欢迎关注我的其它发布渠道