android: Re-fixed game termination bug (#1357)

* EmulationActivity and EmulationFragment clear only their own hooks

* EmulationLifecycleUtil: Rename `remove()` to `removeHook()`

* EmulationLifecycleUtil: Removed unused function `clear()`

* Corrected somewhat incorrect usage of the word "hook"

* Define `onShutdown` and `onPause` hook functions in constructors

* Formatting nitpicks

* Updated license header

* Re-added log messages for attempting to add duplicate hooks

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
This commit is contained in:
David Griswold 2025-09-05 17:05:35 +03:00 committed by OpenSauce04
parent e0078b2407
commit a2e6891f01
3 changed files with 43 additions and 20 deletions

View File

@ -60,7 +60,15 @@ class EmulationActivity : AppCompatActivity() {
private lateinit var binding: ActivityEmulationBinding private lateinit var binding: ActivityEmulationBinding
private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil
private lateinit var hotkeyUtility: HotkeyUtility private lateinit var hotkeyUtility: HotkeyUtility
private lateinit var secondaryDisplay: SecondaryDisplay; private lateinit var secondaryDisplay: SecondaryDisplay
private val onShutdown = Runnable {
if (intent.getBooleanExtra("launched_from_shortcut", false)) {
finishAffinity()
} else {
this.finish()
}
}
private val emulationFragment: EmulationFragment private val emulationFragment: EmulationFragment
get() { get() {
@ -77,8 +85,8 @@ class EmulationActivity : AppCompatActivity() {
ThemeUtil.setTheme(this) ThemeUtil.setTheme(this)
settingsViewModel.settings.loadSettings() settingsViewModel.settings.loadSettings()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
secondaryDisplay = SecondaryDisplay(this); secondaryDisplay = SecondaryDisplay(this)
secondaryDisplay.updateDisplay(); secondaryDisplay.updateDisplay()
binding = ActivityEmulationBinding.inflate(layoutInflater) binding = ActivityEmulationBinding.inflate(layoutInflater)
screenAdjustmentUtil = ScreenAdjustmentUtil(this, windowManager, settingsViewModel.settings) screenAdjustmentUtil = ScreenAdjustmentUtil(this, windowManager, settingsViewModel.settings)
@ -101,13 +109,7 @@ class EmulationActivity : AppCompatActivity() {
windowManager.defaultDisplay.rotation windowManager.defaultDisplay.rotation
) )
EmulationLifecycleUtil.addShutdownHook(hook = { EmulationLifecycleUtil.addShutdownHook(onShutdown)
if (intent.getBooleanExtra("launched_from_shortcut", false)) {
finishAffinity()
} else {
this.finish()
}
})
isEmulationRunning = true isEmulationRunning = true
instance = this instance = this
@ -165,12 +167,12 @@ class EmulationActivity : AppCompatActivity() {
} }
override fun onDestroy() { override fun onDestroy() {
EmulationLifecycleUtil.clear() EmulationLifecycleUtil.removeHook(onShutdown)
NativeLibrary.playTimeManagerStop() NativeLibrary.playTimeManagerStop()
isEmulationRunning = false isEmulationRunning = false
instance = null instance = null
secondaryDisplay.releasePresentation() secondaryDisplay.releasePresentation()
secondaryDisplay.releaseVD(); secondaryDisplay.releaseVD()
super.onDestroy() super.onDestroy()
} }

View File

@ -101,6 +101,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
private val emulationViewModel: EmulationViewModel by activityViewModels() private val emulationViewModel: EmulationViewModel by activityViewModels()
private val settingsViewModel: SettingsViewModel by viewModels() private val settingsViewModel: SettingsViewModel by viewModels()
private val onPause = Runnable{ togglePause() }
private val onShutdown = Runnable{ emulationState.stop() }
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
super.onAttach(context) super.onAttach(context)
if (context is EmulationActivity) { if (context is EmulationActivity) {
@ -156,8 +159,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
emulationState = EmulationState(game.path) emulationState = EmulationState(game.path)
emulationActivity = requireActivity() as EmulationActivity emulationActivity = requireActivity() as EmulationActivity
screenAdjustmentUtil = ScreenAdjustmentUtil(requireContext(), requireActivity().windowManager, settingsViewModel.settings) screenAdjustmentUtil = ScreenAdjustmentUtil(requireContext(), requireActivity().windowManager, settingsViewModel.settings)
EmulationLifecycleUtil.addShutdownHook(hook = { emulationState.stop() }) EmulationLifecycleUtil.addPauseResumeHook(onPause)
EmulationLifecycleUtil.addPauseResumeHook(hook = { togglePause() }) EmulationLifecycleUtil.addShutdownHook(onShutdown)
} }
override fun onCreateView( override fun onCreateView(
@ -507,6 +510,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
super.onDetach() super.onDetach()
} }
override fun onDestroy() {
EmulationLifecycleUtil.removeHook(onPause)
EmulationLifecycleUtil.removeHook(onShutdown)
super.onDestroy()
}
private fun setupCitraDirectoriesThenStartEmulation() { private fun setupCitraDirectoriesThenStartEmulation() {
val directoryInitializationState = DirectoryInitialization.start() val directoryInitializationState = DirectoryInitialization.start()
if (directoryInitializationState === if (directoryInitializationState ===

View File

@ -1,4 +1,4 @@
// Copyright 2023 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -18,15 +18,27 @@ object EmulationLifecycleUtil {
} }
fun addShutdownHook(hook: Runnable) { fun addShutdownHook(hook: Runnable) {
shutdownHooks.add(hook) if (shutdownHooks.contains(hook)) {
Log.warning("[EmulationLifecycleUtil] Tried to add shutdown hook for function that already existed. Skipping.")
} else {
shutdownHooks.add(hook)
}
} }
fun addPauseResumeHook(hook: Runnable) { fun addPauseResumeHook(hook: Runnable) {
pauseResumeHooks.add(hook) if (pauseResumeHooks.contains(hook)) {
Log.warning("[EmulationLifecycleUtil] Tried to add pause resume hook for function that already existed. Skipping.")
} else {
pauseResumeHooks.add(hook)
}
} }
fun clear() { fun removeHook(hook: Runnable) {
pauseResumeHooks.clear() if (pauseResumeHooks.contains(hook)) {
shutdownHooks.clear() pauseResumeHooks.remove(hook)
}
if (shutdownHooks.contains(hook)) {
shutdownHooks.remove(hook)
}
} }
} }