mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 02:33:32 +00:00
Fix Android RAM overlay instant crash
Use getMainLooper() instead of myLooper() in Handler initialization and add view attachment checks to prevent crashes. Reported-by: Shadai (theonlyshadai) on Discord Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
@@ -526,11 +526,16 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
if (emulationViewModel.emulationStarted.value &&
|
||||
!emulationViewModel.isEmulationStopping.value
|
||||
) {
|
||||
val perfStats = NativeLibrary.getPerfStats()
|
||||
if (_binding != null) {
|
||||
if (_binding != null && binding.fpsIndicatorView.isAttachedToWindow) {
|
||||
val perfStats = NativeLibrary.getPerfStats()
|
||||
binding.fpsIndicatorView.updateFps(perfStats[FPS].toFloat())
|
||||
perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800)
|
||||
}
|
||||
} else {
|
||||
// Stop the updater if emulation is stopping
|
||||
if (perfStatsUpdater != null) {
|
||||
perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
|
||||
}
|
||||
perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800)
|
||||
}
|
||||
}
|
||||
perfStatsUpdateHandler.post(perfStatsUpdater!!)
|
||||
@@ -549,11 +554,16 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
if (emulationViewModel.emulationStarted.value &&
|
||||
!emulationViewModel.isEmulationStopping.value
|
||||
) {
|
||||
if (_binding != null) {
|
||||
if (_binding != null && binding.thermalIndicatorView.isAttachedToWindow) {
|
||||
val temperature = getBatteryTemperature(requireContext())
|
||||
binding.thermalIndicatorView.updateTemperature(temperature)
|
||||
thermalStatsUpdateHandler.postDelayed(thermalStatsUpdater!!, 2000)
|
||||
}
|
||||
} else {
|
||||
// Stop the updater if emulation is stopping
|
||||
if (thermalStatsUpdater != null) {
|
||||
thermalStatsUpdateHandler.removeCallbacks(thermalStatsUpdater!!)
|
||||
}
|
||||
thermalStatsUpdateHandler.postDelayed(thermalStatsUpdater!!, 2000)
|
||||
}
|
||||
}
|
||||
thermalStatsUpdateHandler.post(thermalStatsUpdater!!)
|
||||
@@ -572,10 +582,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
if (emulationViewModel.emulationStarted.value &&
|
||||
!emulationViewModel.isEmulationStopping.value
|
||||
) {
|
||||
if (_binding != null) {
|
||||
if (_binding != null && binding.ramMeterView.isAttachedToWindow) {
|
||||
binding.ramMeterView.updateRamUsage()
|
||||
ramStatsUpdateHandler.postDelayed(ramStatsUpdater!!, 1500)
|
||||
}
|
||||
} else {
|
||||
// Stop the updater if emulation is stopping
|
||||
if (ramStatsUpdater != null) {
|
||||
ramStatsUpdateHandler.removeCallbacks(ramStatsUpdater!!)
|
||||
}
|
||||
ramStatsUpdateHandler.postDelayed(ramStatsUpdater!!, 1500)
|
||||
}
|
||||
}
|
||||
ramStatsUpdateHandler.post(ramStatsUpdater!!)
|
||||
@@ -1161,9 +1176,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
private val thermalStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
private val ramStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
private val shaderStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
private val perfStatsUpdateHandler = Handler(Looper.getMainLooper())
|
||||
private val thermalStatsUpdateHandler = Handler(Looper.getMainLooper())
|
||||
private val ramStatsUpdateHandler = Handler(Looper.getMainLooper())
|
||||
private val shaderStatsUpdateHandler = Handler(Looper.getMainLooper())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,18 @@ class RamMeterView @JvmOverloads constructor(
|
||||
|
||||
fun updateRamUsage() {
|
||||
try {
|
||||
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||
// Safety check: ensure view is attached and has valid dimensions
|
||||
if (!isAttachedToWindow || width <= 0 || height <= 0) {
|
||||
Log.w("RamMeter", "View not ready for update (attached: $isAttachedToWindow, width: $width, height: $height)")
|
||||
return
|
||||
}
|
||||
|
||||
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager
|
||||
if (activityManager == null) {
|
||||
Log.e("RamMeter", "ActivityManager service not available")
|
||||
return
|
||||
}
|
||||
|
||||
val memoryInfo = ActivityManager.MemoryInfo()
|
||||
activityManager.getMemoryInfo(memoryInfo)
|
||||
|
||||
@@ -61,7 +72,6 @@ class RamMeterView @JvmOverloads constructor(
|
||||
ramUsagePercent = 0f
|
||||
usedRamMB = 0L
|
||||
totalRamMB = 0L
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,16 +102,26 @@ class RamMeterView @JvmOverloads constructor(
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
// Draw simple text-based RAM display
|
||||
val usedGB = usedRamMB / 1024f
|
||||
val totalGB = totalRamMB / 1024f
|
||||
val ramText = if (totalGB >= 1.0f) {
|
||||
"RAM: ${ramUsagePercent.roundToInt()}% (%.1fGB/%.1fGB)".format(usedGB, totalGB)
|
||||
} else {
|
||||
"RAM: ${ramUsagePercent.roundToInt()}% (${usedRamMB}MB/${totalRamMB}MB)"
|
||||
// Safety check: ensure view has valid dimensions
|
||||
if (width <= 0 || height <= 0) {
|
||||
Log.w("RamMeter", "onDraw called with invalid dimensions (width: $width, height: $height)")
|
||||
return
|
||||
}
|
||||
canvas.drawText(ramText, 8f, height - 8f, textPaint)
|
||||
|
||||
Log.d("RamMeter", "onDraw called - RAM: $ramText")
|
||||
try {
|
||||
// Draw simple text-based RAM display
|
||||
val usedGB = usedRamMB / 1024f
|
||||
val totalGB = totalRamMB / 1024f
|
||||
val ramText = if (totalGB >= 1.0f) {
|
||||
"RAM: ${ramUsagePercent.roundToInt()}% (%.1fGB/%.1fGB)".format(usedGB, totalGB)
|
||||
} else {
|
||||
"RAM: ${ramUsagePercent.roundToInt()}% (${usedRamMB}MB/${totalRamMB}MB)"
|
||||
}
|
||||
canvas.drawText(ramText, 8f, height - 8f, textPaint)
|
||||
|
||||
Log.d("RamMeter", "onDraw called - RAM: $ramText")
|
||||
} catch (e: Exception) {
|
||||
Log.e("RamMeter", "Error in onDraw", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user