From 58d577066a03a40e2d7a8c160cfc13c1694ab2a7 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Sun, 16 May 2021 19:52:08 +0500 Subject: [PATCH] Release terminal beep SoundPool resources on activity stop to attempt to prevent exception The following exception may be thrown, likely because of unreleased resources. Related https://stackoverflow.com/a/28708351/14686958 java.util.concurrent.TimeoutException: android.media.SoundPool.finalize() timed out after 10 seconds at android.media.SoundPool.native_release(Native Method) at android.media.SoundPool.release(SoundPool.java:177) at android.media.SoundPool.finalize(SoundPool.java:182) at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250) at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237) at java.lang.Daemons$Daemon.run(Daemons.java:103) at java.lang.Thread.run(Thread.java:764) --- .../terminal/TermuxTerminalSessionClient.java | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java b/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java index 7d11689048..7033ac5084 100644 --- a/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java +++ b/app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionClient.java @@ -37,20 +37,39 @@ public class TermuxTerminalSessionClient extends TermuxTerminalSessionClientBase private static final int MAX_SESSIONS = 8; - private final SoundPool mBellSoundPool = new SoundPool.Builder().setMaxStreams(1).setAudioAttributes( - new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()).build(); + private SoundPool mBellSoundPool; - private final int mBellSoundId; + private int mBellSoundId; private static final String LOG_TAG = "TermuxTerminalSessionClient"; public TermuxTerminalSessionClient(TermuxActivity activity) { this.mActivity = activity; + } + + /** + * Should be called when mActivity.onResume() is called + */ + public void onResume() { + // Just initialize the mBellSoundPool and load the sound, otherwise bell might not run + // the first time bell key is pressed and play() is called, since sound may not be loaded + // quickly enough before the call to play(). https://stackoverflow.com/questions/35435625 + getBellSoundPool(); + } - mBellSoundId = mBellSoundPool.load(activity, R.raw.bell, 1); + /** + * Should be called when mActivity.onStop() is called + */ + public void onStop() { + // Release mBellSoundPool resources, specially to prevent exceptions like the following to be thrown + // java.util.concurrent.TimeoutException: android.media.SoundPool.finalize() timed out after 10 seconds + // Bell is not played in background anyways + // Related: https://stackoverflow.com/a/28708351/14686958 + releaseBellSoundPool(); } + + @Override public void onTextChanged(TerminalSession changedSession) { if (!mActivity.isVisible()) return; @@ -122,13 +141,12 @@ public void onBell(TerminalSession session) { BellHandler.getInstance(mActivity).doBell(); break; case TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_BEEP: - mBellSoundPool.play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f); + getBellSoundPool().play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f); break; case TermuxPropertyConstants.IVALUE_BELL_BEHAVIOUR_IGNORE: // Ignore the bell character. break; } - } @Override @@ -152,6 +170,29 @@ public void onTerminalCursorStateChange(boolean enabled) { + /** Initialize and get mBellSoundPool */ + private synchronized SoundPool getBellSoundPool() { + if (mBellSoundPool == null) { + mBellSoundPool = new SoundPool.Builder().setMaxStreams(1).setAudioAttributes( + new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()).build(); + + mBellSoundId = mBellSoundPool.load(mActivity, R.raw.bell, 1); + } + + return mBellSoundPool; + } + + /** Release mBellSoundPool resources */ + private synchronized void releaseBellSoundPool() { + if (mBellSoundPool != null) { + mBellSoundPool.release(); + mBellSoundPool = null; + } + } + + + /** Try switching to session. */ public void setCurrentSession(TerminalSession session) { if (session == null) return;