参考资料
- https://zhuanlan.zhihu.com/p/142212769?from_voters_page=true
前言
在了解HWC工作之前,我觉得还是有必要看看Android一次完整的Vsync帧率切换的流程,从App发起请求开始。
背景
随着手机屏幕硬件能力的提升,越来越多的厂商提供支持多档次刷新率的Android设备。
而在Android Q上也是支持App指定当前屏幕帧率的,也有一套帧率分辨率切换的逻辑。
查看设备可支持的刷新率和分辨率
使用命令:
adb shell dumpsys display dump |grep -A 10 -iE “mSupportedModes”
这里设备使用的是OnePlus8Pro,结果如下:
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}}
可以看到是有四种模式:
- 1080 + 60Hz
- 2K + 120Hz
- 2K + 60Hz
- 1080 + 120Hz
App设置设备帧率
Android Q及以下版本
在Android Q或更低版本上,可以通过指定当前Window的帧率来设置屏幕刷新率,如选择设备可支持的最高刷新率:
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 中选择一个,从而影响到另一个应用的显示效果。
-
获取刷新率:
- SDK
通过 DisplayManager.DisplayListener 注册一个显示监听器,并通过 Display.getRefreshRate 查询刷新率。 - NDK
使用 AChoreographer_registerRefreshRateCallback 注册回调 (API 级别30)。
- SDK
-
设置刷新率应用可以调用以下方法之一:
- SDK
- NDK
- ANativeWindow_setRrameRate
- ASurfaceTransaction_setFrameRate