davidliu
Committed by GitHub

Route AudioSwitch calls through main thread (#120)

@@ -2,6 +2,8 @@ package io.livekit.android.audio @@ -2,6 +2,8 @@ package io.livekit.android.audio
2 2
3 import android.content.Context 3 import android.content.Context
4 import android.media.AudioManager 4 import android.media.AudioManager
  5 +import android.os.Handler
  6 +import android.os.Looper
5 import com.twilio.audioswitch.AudioDevice 7 import com.twilio.audioswitch.AudioDevice
6 import com.twilio.audioswitch.AudioDeviceChangeListener 8 import com.twilio.audioswitch.AudioDeviceChangeListener
7 import com.twilio.audioswitch.AudioSwitch 9 import com.twilio.audioswitch.AudioSwitch
@@ -19,8 +21,13 @@ constructor(private val context: Context) : AudioHandler { @@ -19,8 +21,13 @@ constructor(private val context: Context) : AudioHandler {
19 21
20 private var audioSwitch: AudioSwitch? = null 22 private var audioSwitch: AudioSwitch? = null
21 23
  24 + // AudioSwitch is not threadsafe, so all calls should be done on the main thread.
  25 + private val handler = Handler(Looper.getMainLooper())
  26 +
22 override fun start() { 27 override fun start() {
23 if (audioSwitch == null) { 28 if (audioSwitch == null) {
  29 + handler.removeCallbacksAndMessages(null)
  30 + handler.post {
24 val switch = AudioSwitch( 31 val switch = AudioSwitch(
25 context = context, 32 context = context,
26 loggingEnabled = loggingEnabled, 33 loggingEnabled = loggingEnabled,
@@ -32,11 +39,15 @@ constructor(private val context: Context) : AudioHandler { @@ -32,11 +39,15 @@ constructor(private val context: Context) : AudioHandler {
32 switch.activate() 39 switch.activate()
33 } 40 }
34 } 41 }
  42 + }
35 43
36 override fun stop() { 44 override fun stop() {
  45 + handler.removeCallbacksAndMessages(null)
  46 + handler.post {
37 audioSwitch?.stop() 47 audioSwitch?.stop()
38 audioSwitch = null 48 audioSwitch = null
39 } 49 }
  50 + }
40 51
41 val selectedAudioDevice: AudioDevice? 52 val selectedAudioDevice: AudioDevice?
42 get() = audioSwitch?.selectedAudioDevice 53 get() = audioSwitch?.selectedAudioDevice
@@ -19,21 +19,23 @@ import io.livekit.android.room.participant.Participant @@ -19,21 +19,23 @@ import io.livekit.android.room.participant.Participant
19 import io.livekit.android.room.participant.RemoteParticipant 19 import io.livekit.android.room.participant.RemoteParticipant
20 import io.livekit.android.room.track.* 20 import io.livekit.android.room.track.*
21 import io.livekit.android.util.flow 21 import io.livekit.android.util.flow
22 -import kotlinx.coroutines.ExperimentalCoroutinesApi  
23 import kotlinx.coroutines.flow.* 22 import kotlinx.coroutines.flow.*
24 import kotlinx.coroutines.launch 23 import kotlinx.coroutines.launch
25 import livekit.LivekitRtc 24 import livekit.LivekitRtc
26 25
27 -@OptIn(ExperimentalCoroutinesApi::class)  
28 class CallViewModel( 26 class CallViewModel(
29 val url: String, 27 val url: String,
30 val token: String, 28 val token: String,
31 application: Application 29 application: Application
32 ) : AndroidViewModel(application) { 30 ) : AndroidViewModel(application) {
33 31
  32 + val audioHandler = AudioSwitchHandler(application)
34 val room = LiveKit.create( 33 val room = LiveKit.create(
35 appContext = application, 34 appContext = application,
36 options = RoomOptions(adaptiveStream = true, dynacast = true), 35 options = RoomOptions(adaptiveStream = true, dynacast = true),
  36 + overrides = LiveKitOverrides(
  37 + audioHandler = audioHandler
  38 + )
37 ) 39 )
38 40
39 val participants = room::remoteParticipants.flow 41 val participants = room::remoteParticipants.flow
@@ -73,7 +75,6 @@ class CallViewModel( @@ -73,7 +75,6 @@ class CallViewModel(
73 private val mutablePermissionAllowed = MutableStateFlow(true) 75 private val mutablePermissionAllowed = MutableStateFlow(true)
74 val permissionAllowed = mutablePermissionAllowed.hide() 76 val permissionAllowed = mutablePermissionAllowed.hide()
75 77
76 - val audioHandler = AudioSwitchHandler(application)  
77 init { 78 init {
78 viewModelScope.launch { 79 viewModelScope.launch {
79 launch { 80 launch {