SurfaceControl.Transaction.setFrameRate()

SurfaceControl.Transaction的setFrameRate()的方法是对系统层进行设置刷新率还是只针对app进行设置呢?
如果通过系统层进行固定屏幕刷新率实现用户动态切换的效果如何实现呢?.setFrameRate()该如何使用和实现。
(尽可能写个demo)

img

MainActivity

 //设置屏幕刷新率
    public void  setRefreshRate(float targetRefreshRate){
        try {
            DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);

            Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);

            /** 获取所有支持的显示模式 */
            Display.Mode[] modes = display.getSupportedModes();

            /** 通过setFrameRate设置目标刷新率 */
            SurfaceControl.Transaction st = new SurfaceControl.Transaction();

            需要大佬进行补充一下了,在android studio中使用的SDK 33的版本。
            


            /** 获取当前设备显示管理器*/
        }catch (Exception e){
            e.printStackTrace();
        }
    }


Display.Mode[] modes = display.getSupportedModes();
SurfaceControl.Transaction st = new SurfaceControl.Transaction();
st.setFrameRate(surfaceControl, mode.getRefreshRate());
st.apply();

SurfaceControl.Transaction的setFrameRate()方法主要是对应用程序层面进行设置屏幕刷新率的。如果您要在系统层面进行固定屏幕刷新率并实现用户动态切换的效果,需要使用setDisplayManager的setDisplayProperties()方法,并借助Display.Mode类来实现。
具体实现的代码如下:

// 获取当前显示器的引用
DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);

// 获取屏幕支持的所有刷新率
Display.Mode[] modes = display.getSupportedModes();

// 自定义刷新率
float refreshRate = 60.0f;

// 选择最接近自定义刷新率的模式
Display.Mode bestMode = null;
float bestRate = Float.MAX_VALUE;
for (Display.Mode mode : modes) {
    if (Math.abs(mode.getRefreshRate() - refreshRate) < bestRate) {
        bestMode = mode;
        bestRate = Math.abs(mode.getRefreshRate() - refreshRate);
    }
}

if (bestMode != null) {
    // 设置默认显示模式
    Display.Mode defaultMode = display.getMode();
    if (!defaultMode.equals(bestMode)) {
        dm.setDisplayProperties(display, Collections.singletonMap(
                DisplayManager.KEY_DISPLAY_MODE, bestMode.getModeId()));
    }
}


以上代码会将当前系统屏幕的默认刷新率设置为60Hz,并且也会根据当前设备所支持的刷新率来选择合适的模式。

引用chatGPT作答,根据官方文档,SurfaceControl.Transaction的setFrameRate()方法是用于设置应用程序渲染的刷新率,而不是系统层的刷新率。如果需要设置系统层的刷新率,您需要使用DisplayManager中的setDisplayMode()方法。

要实现用户动态切换屏幕刷新率的效果,您需要在运行时使用setDisplayMode()方法更改设备的显示模式,并使用setFrameRate()方法设置所需的刷新率。

以下是一个简单的示例,演示如何使用SurfaceControl.Transaction的setFrameRate()方法设置屏幕刷新率:

public void setRefreshRate(float targetRefreshRate) {
    try {
        DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);

        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);

        // 获取所有支持的显示模式
        Display.Mode[] modes = display.getSupportedModes();

        // 查找支持目标刷新率的显示模式
        Display.Mode targetMode = null;
        for (Display.Mode mode : modes) {
            if (mode.getRefreshRate() == targetRefreshRate) {
                targetMode = mode;
                break;
            }
        }

        if (targetMode == null) {
            // 如果找不到支持目标刷新率的显示模式,则打印错误消息并返回
            Log.e(TAG, "Unable to find display mode with refresh rate: " + targetRefreshRate);
            return;
        }

        // 使用setDisplayMode()方法更改显示模式
        displayManager.setDisplayMode(display, targetMode);

        // 使用SurfaceControl.Transaction的setFrameRate()方法设置刷新率
        SurfaceControl.Transaction st = new SurfaceControl.Transaction();
        st.setFrameRate(display, targetRefreshRate, SurfaceControl.FRAME_RATE_COMPAT_MODE);
        st.apply();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

内容来源与ChatGpt4及newbing和百度:


setFrameRate()方法是针对Surface的,而不仅仅是应用程序。如果要实现用户动态切换屏幕刷新率的效果,可以使用以下代码:

DisplayManager mDisplayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
Display.Mode mode = display.getMode();
int refreshRate = mode.getRefreshRate();

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.setFrameRate(refreshRate * 2); // 设置为原始刷新率的两倍
transaction.apply();

这将把Surface的刷新率设置为当前显示模式的两倍。您可以根据需要更改要应用的刷新率。


祝您问题迎刃而解

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
SurfaceControl.Transaction.setFrameRate()方法是针对指定Surface的刷新率进行设置的,如果要实现整个系统层面的刷新率设置,可以使用Display.Mode对象的getRefreshRate()方法获取所有支持的刷新率,然后找到所需要的刷新率对应的Display.Mode对象,使用Display的setDisplayMode()方法设置即可。

以下是一个简单的示例代码:

public void setRefreshRate(float targetRefreshRate) {
    try {
        // 获取系统显示管理器
        DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
        // 获取默认显示器
        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
        // 获取所有支持的显示模式
        Display.Mode[] modes = display.getSupportedModes();
        // 找到目标刷新率所对应的显示模式
        Display.Mode targetMode = null;
        for (Display.Mode mode : modes) {
            if (Math.abs(mode.getRefreshRate() - targetRefreshRate) < 0.1) {
                targetMode = mode;
                break;
            }
        }
        // 如果找到了目标显示模式,则设置为当前显示模式
        if (targetMode != null) {
            display.requestMode(targetMode.getModeId());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

该代码利用了Display的requestMode()方法来切换显示模式,从而实现系统层面的刷新率设置。需要注意的是,该方法只能在Android 10或更高版本中使用。
如果我的回答解决了您的问题,请采纳!