android: Rework MemoryUtil

Uses string templates and rounds up memory amount for potentially inaccurate checks now
This commit is contained in:
Charles Lombardo 2023-06-28 16:51:27 -04:00
parent a1dd5dfba5
commit 11991fbd7f
3 changed files with 85 additions and 25 deletions

View file

@ -47,6 +47,7 @@ import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.MemoryUtil import org.yuzu.yuzu_emu.utils.MemoryUtil
import org.yuzu.yuzu_emu.utils.NfcReader import org.yuzu.yuzu_emu.utils.NfcReader
import org.yuzu.yuzu_emu.utils.ThemeHelper import org.yuzu.yuzu_emu.utils.ThemeHelper
import java.text.NumberFormat
import kotlin.math.roundToInt import kotlin.math.roundToInt
class EmulationActivity : AppCompatActivity(), SensorEventListener { class EmulationActivity : AppCompatActivity(), SensorEventListener {
@ -106,13 +107,17 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
inputHandler = InputHandler() inputHandler = InputHandler()
inputHandler.initialize() inputHandler.initialize()
if (MemoryUtil.isLessThan(8, MemoryUtil.Gb)) { if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.Gb)) {
Toast.makeText( Toast.makeText(
this, this,
getString( getString(
R.string.device_memory_inadequate, R.string.device_memory_inadequate,
MemoryUtil.getDeviceRAM(), MemoryUtil.getDeviceRAM(),
"8 ${getString(R.string.memory_gigabyte)}" getString(
R.string.memory_formatted,
NumberFormat.getInstance().format(MemoryUtil.REQUIRED_MEMORY),
getString(R.string.memory_gigabyte)
)
), ),
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()

View file

@ -5,44 +5,101 @@ package org.yuzu.yuzu_emu.utils
import android.app.ActivityManager import android.app.ActivityManager
import android.content.Context import android.content.Context
import android.os.Build
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import java.util.Locale import java.util.Locale
import kotlin.math.ceil
object MemoryUtil { object MemoryUtil {
private val context get() = YuzuApplication.appContext private val context get() = YuzuApplication.appContext
private val Long.floatForm: String private val Float.hundredths: String
get() = String.format(Locale.ROOT, "%.2f", this.toDouble()) get() = String.format(Locale.ROOT, "%.2f", this)
const val Kb: Long = 1024 // Required total system memory
const val REQUIRED_MEMORY = 8
const val Kb: Float = 1024F
const val Mb = Kb * 1024 const val Mb = Kb * 1024
const val Gb = Mb * 1024 const val Gb = Mb * 1024
const val Tb = Gb * 1024 const val Tb = Gb * 1024
const val Pb = Tb * 1024 const val Pb = Tb * 1024
const val Eb = Pb * 1024 const val Eb = Pb * 1024
private fun bytesToSizeUnit(size: Long): String { private fun bytesToSizeUnit(size: Float): String =
return when { when {
size < Kb -> "${size.floatForm} ${context.getString(R.string.memory_byte)}" size < Kb -> {
size < Mb -> "${(size / Kb).floatForm} ${context.getString(R.string.memory_kilobyte)}" context.getString(
size < Gb -> "${(size / Mb).floatForm} ${context.getString(R.string.memory_megabyte)}" R.string.memory_formatted,
size < Tb -> "${(size / Gb).floatForm} ${context.getString(R.string.memory_gigabyte)}" size.hundredths,
size < Pb -> "${(size / Tb).floatForm} ${context.getString(R.string.memory_terabyte)}" context.getString(R.string.memory_byte)
size < Eb -> "${(size / Pb).floatForm} ${context.getString(R.string.memory_petabyte)}" )
else -> "${(size / Eb).floatForm} ${context.getString(R.string.memory_exabyte)}" }
size < Mb -> {
context.getString(
R.string.memory_formatted,
(size / Kb).hundredths,
context.getString(R.string.memory_kilobyte)
)
}
size < Gb -> {
context.getString(
R.string.memory_formatted,
(size / Mb).hundredths,
context.getString(R.string.memory_megabyte)
)
}
size < Tb -> {
context.getString(
R.string.memory_formatted,
(size / Gb).hundredths,
context.getString(R.string.memory_gigabyte)
)
}
size < Pb -> {
context.getString(
R.string.memory_formatted,
(size / Tb).hundredths,
context.getString(R.string.memory_terabyte)
)
}
size < Eb -> {
context.getString(
R.string.memory_formatted,
(size / Pb).hundredths,
context.getString(R.string.memory_petabyte)
)
}
else -> {
context.getString(
R.string.memory_formatted,
(size / Eb).hundredths,
context.getString(R.string.memory_exabyte)
)
}
} }
}
private val totalMemory = // Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for
with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) { // the potential error created by memInfo.totalMem
private val totalMemory: Float
get() {
val memInfo = ActivityManager.MemoryInfo() val memInfo = ActivityManager.MemoryInfo()
getMemoryInfo(memInfo) with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) {
memInfo.totalMem getMemoryInfo(memInfo)
}
return ceil(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
memInfo.advertisedMem.toFloat()
} else {
memInfo.totalMem.toFloat()
}
)
} }
fun isLessThan(minimum: Int, size: Long): Boolean { fun isLessThan(minimum: Int, size: Float): Boolean =
return when (size) { when (size) {
Kb -> totalMemory < Mb && totalMemory < minimum Kb -> totalMemory < Mb && totalMemory < minimum
Mb -> totalMemory < Gb && (totalMemory / Mb) < minimum Mb -> totalMemory < Gb && (totalMemory / Mb) < minimum
Gb -> totalMemory < Tb && (totalMemory / Gb) < minimum Gb -> totalMemory < Tb && (totalMemory / Gb) < minimum
@ -51,9 +108,6 @@ object MemoryUtil {
Eb -> totalMemory / Eb < minimum Eb -> totalMemory / Eb < minimum
else -> totalMemory < Kb && totalMemory < minimum else -> totalMemory < Kb && totalMemory < minimum
} }
}
fun getDeviceRAM(): String { fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory)
return bytesToSizeUnit(totalMemory)
}
} }

View file

@ -273,6 +273,7 @@
<string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string> <string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string>
<string name="performance_warning">Turning off this setting will significantly reduce emulation performance! For the best experience, it is recommended that you leave this setting enabled.</string> <string name="performance_warning">Turning off this setting will significantly reduce emulation performance! For the best experience, it is recommended that you leave this setting enabled.</string>
<string name="device_memory_inadequate">Device RAM: %1$s\nRecommended: %2$s</string> <string name="device_memory_inadequate">Device RAM: %1$s\nRecommended: %2$s</string>
<string name="memory_formatted">%1$s %2$s</string>
<!-- Region Names --> <!-- Region Names -->
<string name="region_japan">Japan</string> <string name="region_japan">Japan</string>