Support forcing 60Hz display on Xiaomi MIUI

Uses an API found through RE since none of the AOSP APIs work, additionaly the code for setting RR was consolidated to a single function that can be ran after all display updates.
This commit is contained in:
Billy Laws 2022-06-07 20:44:30 +01:00
parent 42c365fe70
commit b75a06af1b

View File

@ -10,11 +10,13 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.AssetManager import android.content.res.AssetManager
import android.graphics.PointF import android.graphics.PointF
import android.hardware.display.DisplayManager
import android.os.* import android.os.*
import android.util.Log import android.util.Log
import android.util.Rational import android.util.Rational
import android.view.* import android.view.*
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.updateMargins import androidx.core.view.updateMargins
@ -27,8 +29,9 @@ import java.io.File
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
@AndroidEntryPoint @AndroidEntryPoint
class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTouchListener { class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTouchListener, DisplayManager.DisplayListener {
companion object { companion object {
private val Tag = EmulationActivity::class.java.simpleName private val Tag = EmulationActivity::class.java.simpleName
val ReturnToMainTag = "returnToMain" val ReturnToMainTag = "returnToMain"
@ -178,6 +181,26 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
updateControllers() updateControllers()
} }
/**
* Forces a 60Hz refresh rate for the primary display when [enable] is true, otherwise selects the highest available refresh rate
*/
private fun force60HzRefreshRate(enable : Boolean) {
// Hack for MIUI devices since they don't support the standard Android APIs
try {
val setFpsIntent = Intent("com.miui.powerkeeper.SET_ACTIVITY_FPS")
setFpsIntent.putExtra("package_name", "skyline.emu")
setFpsIntent.putExtra("isEnter", enable)
sendBroadcast(setFpsIntent)
} catch (_ : Exception) {
}
@Suppress("DEPRECATION") val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display!! else windowManager.defaultDisplay
if (enable)
display?.supportedModes?.minByOrNull { abs(it.refreshRate - 60f) }?.let { window.attributes.preferredDisplayModeId = it.modeId }
else
display?.supportedModes?.maxByOrNull { it.refreshRate }?.let { window.attributes.preferredDisplayModeId = it.modeId }
}
/** /**
* Return from emulation to either [MainActivity] or the activity on the back stack * Return from emulation to either [MainActivity] or the activity on the back stack
*/ */
@ -275,12 +298,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
} }
} }
@Suppress("DEPRECATION") val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display!! else windowManager.defaultDisplay force60HzRefreshRate(!settings.maxRefreshRate)
if (settings.maxRefreshRate) { getSystemService<DisplayManager>()?.registerDisplayListener(this, null)
display?.supportedModes?.maxByOrNull { it.refreshRate * it.physicalHeight * it.physicalWidth }?.let { window.attributes.preferredDisplayModeId = it.modeId; desiredRefreshRate = it.refreshRate }
} else {
display?.supportedModes?.minByOrNull { abs(it.refreshRate - 60f) }?.let { window.attributes.preferredDisplayModeId = it.modeId }
}
binding.gameView.setOnTouchListener(this) binding.gameView.setOnTouchListener(this)
@ -343,6 +362,10 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
stopEmulation(false) stopEmulation(false)
vibrators.forEach { (_, vibrator) -> vibrator.cancel() } vibrators.forEach { (_, vibrator) -> vibrator.cancel() }
vibrators.clear() vibrators.clear()
// Stop forcing 60Hz on exit to allow the skyline UI to run at high refresh rates
getSystemService<DisplayManager>()?.unregisterDisplayListener(this)
force60HzRefreshRate(false);
} }
override fun surfaceCreated(holder : SurfaceHolder) { override fun surfaceCreated(holder : SurfaceHolder) {
@ -573,4 +596,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
} }
insets insets
} }
override fun onDisplayChanged(displayId : Int) {
val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display!! else windowManager.defaultDisplay
if (display.displayId == displayId)
force60HzRefreshRate(!settings.maxRefreshRate)
}
override fun onDisplayAdded(displayId : Int) {}
override fun onDisplayRemoved(displayId : Int) {}
} }