From bcb123a05ef2195d84397b71d12cfc2a4a6b61a9 Mon Sep 17 00:00:00 2001 From: Ilia Demianenko Date: Mon, 17 Apr 2023 20:47:53 -0700 Subject: [PATCH] app: [Android] Set high refresh rate on startup Some devices with high refresh rates limit SurfaceView apps to 60hz and need a specific API call to set it back. Same approach is used by https://github.com/ajinasokan/flutter_displaymode. The extra work is skipped on the devices that don't need it. Signed-off-by: Ilia Demianenko --- app/GioView.java | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/app/GioView.java b/app/GioView.java index 80dd0d13..9d223d00 100644 --- a/app/GioView.java +++ b/app/GioView.java @@ -26,6 +26,7 @@ import android.text.SpannableStringBuilder; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Choreographer; +import android.view.Display; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; @@ -105,6 +106,8 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal scrollYScale = px; } + setHighRefreshRate(); + accessManager = (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE); imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); nhandle = onCreateView(this); @@ -255,6 +258,59 @@ public final class GioView extends SurfaceView implements Choreographer.FrameCal this.setBarColor(Bar.NAVIGATION, color, luminance); } + private void setHighRefreshRate() { + Context context = getContext(); + Display display = context.getDisplay(); + Display.Mode[] supportedModes = display.getSupportedModes(); + if (supportedModes.length <= 1) { + // Nothing to set + return; + } + + Display.Mode currentMode = display.getMode(); + int currentWidth = currentMode.getPhysicalWidth(); + int currentHeight = currentMode.getPhysicalHeight(); + + float minRefreshRate = -1; + float maxRefreshRate = -1; + float bestRefreshRate = -1; + int bestModeId = -1; + for (Display.Mode mode : supportedModes) { + float refreshRate = mode.getRefreshRate(); + float width = mode.getPhysicalWidth(); + float height = mode.getPhysicalHeight(); + + if (minRefreshRate == -1 || refreshRate < minRefreshRate) { + minRefreshRate = refreshRate; + } + if (maxRefreshRate == -1 || refreshRate > maxRefreshRate) { + maxRefreshRate = refreshRate; + } + + boolean refreshRateIsBetter = bestRefreshRate == -1 || refreshRate > bestRefreshRate; + if (width == currentWidth && height == currentHeight && refreshRateIsBetter) { + int modeId = mode.getModeId(); + bestRefreshRate = refreshRate; + bestModeId = modeId; + } + } + + if (bestModeId == -1) { + // Not expecting this but just in case + return; + } + + if (minRefreshRate == maxRefreshRate) { + // Can't improve the refresh rate + return; + } + + Window window = ((Activity) context).getWindow(); + WindowManager.LayoutParams layoutParams = window.getAttributes(); + layoutParams.preferredDisplayModeId = bestModeId; + window.setAttributes(layoutParams); + } + @Override protected boolean dispatchHoverEvent(MotionEvent event) { if (!accessManager.isTouchExplorationEnabled()) { return super.dispatchHoverEvent(event); -- 2.45.2