From 7958bb4692da8842d7a0c195b95e82bd769378fb Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 25 Jul 2025 13:36:23 +0200 Subject: [PATCH] Prevent crash caused by re-release of wakelock in calls (#5077) --- .../call/impl/utils/WebViewAudioManager.kt | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt index b7d1fdf466..51f758a3bb 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/WebViewAudioManager.kt @@ -21,6 +21,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlinx.serialization.json.Json @@ -84,6 +86,11 @@ class WebViewAudioManager( ?.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "${webView.context.packageName}:ProximitySensorCallWakeLock") } + /** + * Used to ensure that only one coroutine can access the proximity sensor wake lock at a time, preventing re-acquiring or re-releasing it. + */ + private val proximitySensorMutex = Mutex() + /** * This listener tracks the current communication device and updates the WebView when it changes. */ @@ -208,8 +215,12 @@ class WebViewAudioManager( return } - if (proximitySensorWakeLock?.isHeld == true) { - proximitySensorWakeLock?.release() + coroutineScope.launch { + proximitySensorMutex.withLock { + if (proximitySensorWakeLock?.isHeld == true) { + proximitySensorWakeLock?.release() + } + } } audioManager.mode = AudioManager.MODE_NORMAL @@ -397,13 +408,17 @@ class WebViewAudioManager( expectedNewCommunicationDeviceId = null - @Suppress("WakeLock", "WakeLockTimeout") - if (device?.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && proximitySensorWakeLock?.isHeld == false) { - // If the device is the built-in earpiece, we need to acquire the proximity sensor wake lock - proximitySensorWakeLock?.acquire() - } else if (proximitySensorWakeLock?.isHeld == true) { - // If the device is no longer the earpiece, we need to release the wake lock - proximitySensorWakeLock?.release() + coroutineScope.launch { + proximitySensorMutex.withLock { + @Suppress("WakeLock", "WakeLockTimeout") + if (device?.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && proximitySensorWakeLock?.isHeld == false) { + // If the device is the built-in earpiece, we need to acquire the proximity sensor wake lock + proximitySensorWakeLock?.acquire() + } else if (proximitySensorWakeLock?.isHeld == true) { + // If the device is no longer the earpiece, we need to release the wake lock + proximitySensorWakeLock?.release() + } + } } }