diff --git a/.changeset/audioswitch-start-stop-guard.md b/.changeset/audioswitch-start-stop-guard.md new file mode 100644 index 00000000..2a1dce65 --- /dev/null +++ b/.changeset/audioswitch-start-stop-guard.md @@ -0,0 +1,5 @@ +--- +"client-sdk-android": patch +--- + +Fix AudioSwitchHandler leaving audio routing active if stop() is called while start() is still setting up the audio switch diff --git a/livekit-android-sdk/src/main/java/io/livekit/android/audio/AudioSwitchHandler.kt b/livekit-android-sdk/src/main/java/io/livekit/android/audio/AudioSwitchHandler.kt index 1ab517a6..5c232415 100644 --- a/livekit-android-sdk/src/main/java/io/livekit/android/audio/AudioSwitchHandler.kt +++ b/livekit-android-sdk/src/main/java/io/livekit/android/audio/AudioSwitchHandler.kt @@ -221,9 +221,10 @@ constructor(private val context: Context) : AudioHandler { handler = Handler(thread!!.looper) } - if (audioSwitch == null) { - handler?.removeCallbacksAndMessages(null) - handler?.postAtFrontOfQueue { + val startHandler = handler + if (audioSwitch == null && startHandler != null) { + startHandler.removeCallbacksAndMessages(null) + startHandler.postAtFrontOfQueue { val switch = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { CommDeviceAudioSwitch( @@ -255,7 +256,15 @@ constructor(private val context: Context) : AudioHandler { switch.audioAttributeContentType = audioAttributeContentType switch.forceHandleAudioRouting = forceHandleAudioRouting - audioSwitch = switch + // stop() may have run while this switch was being created, and its teardown + // saw no switch to stop. Only publish the switch if this start is still current; + // otherwise drop it, since nothing is registered until switch.start() below. + synchronized(this@AudioSwitchHandler) { + if (handler !== startHandler) { + return@postAtFrontOfQueue + } + audioSwitch = switch + } switch.start(audioDeviceChangeDispatcher) switch.activate() }