Skip to content

Commit 97c4fde

Browse files
authored
CommDeviceAudioSwitch upgrade (#910)
* Update AudioSwitch and use communication device api for S and above * Update audioswitch lib * Allow changing preferredDeviceList while AudioSwitchHandler is started * spotless and changesets * spotless
1 parent e70789b commit 97c4fde

6 files changed

Lines changed: 62 additions & 7 deletions

File tree

.changeset/cuddly-moose-try.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"client-sdk-android": patch
3+
---
4+
5+
Update audio handling to use AudioManager communication device APIs on S and above

.changeset/great-zoos-boil.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"client-sdk-android": patch
3+
---
4+
5+
Implement changing preferred audio device list on AudioSwitchHandler mid-call

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ androidx-camera = "1.4.2"
77
androidx-core = "1.13.1"
88
androidx-fragment = "1.5.1"
99
androidx-lifecycle = "2.8.0"
10-
audioswitch = "89582c47c9a04c62f90aa5e57251af4800a62c9a"
10+
audioswitch = "70efa204dda4f468f989b4b3e1b5ecb6ffe56ceb"
1111
autoService = '1.0.1'
1212
coroutines = "1.6.0"
1313
dagger = "2.46"

livekit-android-sdk/src/main/java/io/livekit/android/audio/AudioSwitchHandler.kt

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2025 LiveKit, Inc.
2+
* Copyright 2023-2026 LiveKit, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import com.twilio.audioswitch.AbstractAudioSwitch
2727
import com.twilio.audioswitch.AudioDevice
2828
import com.twilio.audioswitch.AudioDeviceChangeListener
2929
import com.twilio.audioswitch.AudioSwitch
30+
import com.twilio.audioswitch.CommDeviceAudioSwitch
3031
import com.twilio.audioswitch.LegacyAudioSwitch
3132
import io.livekit.android.room.Room
3233
import io.livekit.android.util.LKLog
@@ -48,7 +49,7 @@ constructor(private val context: Context) : AudioHandler {
4849
/**
4950
* Toggle whether logging is enabled for [AudioSwitch]. By default, this is set to false.
5051
*/
51-
var loggingEnabled = false
52+
var loggingEnabled = true
5253

5354
/**
5455
* Listen to changes in the available and active audio devices.
@@ -96,6 +97,9 @@ constructor(private val context: Context) : AudioHandler {
9697
}
9798
}
9899

100+
@Volatile
101+
private var preferredDeviceListBacking: List<Class<out AudioDevice>>? = null
102+
99103
/**
100104
* The preferred priority of audio devices to use. The first available audio device will be used.
101105
*
@@ -104,8 +108,27 @@ constructor(private val context: Context) : AudioHandler {
104108
* 2. WiredHeadset
105109
* 3. Speakerphone
106110
* 4. Earpiece
111+
*
112+
* Changes to this value after [start] has been called will still be applied
113+
* to the underlying [AbstractAudioSwitch] instance.
107114
*/
108-
var preferredDeviceList: List<Class<out AudioDevice>>? = null
115+
var preferredDeviceList: List<Class<out AudioDevice>>?
116+
get() = preferredDeviceListBacking
117+
set(value) {
118+
preferredDeviceListBacking = value
119+
val list = value ?: defaultPreferredDeviceList
120+
val h = handler
121+
val sw = audioSwitch
122+
if (h != null && sw != null) {
123+
if (Looper.myLooper() == h.looper) {
124+
sw.setPreferredDeviceList(list)
125+
} else {
126+
h.post {
127+
audioSwitch?.setPreferredDeviceList(list)
128+
}
129+
}
130+
}
131+
}
109132

110133
/**
111134
* When true, AudioSwitchHandler will request audio focus on start and abandon on stop.
@@ -199,7 +222,14 @@ constructor(private val context: Context) : AudioHandler {
199222
handler?.removeCallbacksAndMessages(null)
200223
handler?.postAtFrontOfQueue {
201224
val switch =
202-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
225+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
226+
CommDeviceAudioSwitch(
227+
context = context,
228+
loggingEnabled = loggingEnabled,
229+
audioFocusChangeListener = onAudioFocusChangeDispatcher,
230+
preferredDeviceList = preferredDeviceList ?: defaultPreferredDeviceList,
231+
)
232+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
203233
AudioSwitch(
204234
context = context,
205235
loggingEnabled = loggingEnabled,

sample-app-compose/src/main/java/io/livekit/android/composesample/CallActivity.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2025 LiveKit, Inc.
2+
* Copyright 2023-2026 LiveKit, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import android.os.Parcelable
2222
import android.view.WindowManager
2323
import android.widget.Toast
2424
import androidx.activity.compose.setContent
25+
import androidx.activity.enableEdgeToEdge
2526
import androidx.activity.result.contract.ActivityResultContracts
2627
import androidx.appcompat.app.AppCompatActivity
2728
import androidx.compose.foundation.background
@@ -35,6 +36,7 @@ import androidx.compose.foundation.layout.fillMaxSize
3536
import androidx.compose.foundation.layout.fillMaxWidth
3637
import androidx.compose.foundation.layout.height
3738
import androidx.compose.foundation.layout.padding
39+
import androidx.compose.foundation.layout.safeDrawingPadding
3840
import androidx.compose.foundation.layout.size
3941
import androidx.compose.foundation.layout.wrapContentSize
4042
import androidx.compose.foundation.lazy.LazyRow
@@ -107,6 +109,7 @@ class CallActivity : AppCompatActivity() {
107109

108110
@OptIn(ExperimentalMaterialApi::class)
109111
override fun onCreate(savedInstanceState: Bundle?) {
112+
enableEdgeToEdge()
110113
super.onCreate(savedInstanceState)
111114
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
112115

@@ -198,6 +201,7 @@ class CallActivity : AppCompatActivity() {
198201
ConstraintLayout(
199202
modifier = Modifier
200203
.fillMaxSize()
204+
.safeDrawingPadding()
201205
.background(MaterialTheme.colors.background),
202206
) {
203207
val (speakerView, audienceRow, buttonBar) = createRefs()

sample-app/src/main/java/io/livekit/android/sample/CallActivity.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2025 LiveKit, Inc.
2+
* Copyright 2023-2026 LiveKit, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,9 +22,12 @@ import android.os.Parcelable
2222
import android.view.WindowManager
2323
import android.widget.EditText
2424
import android.widget.Toast
25+
import androidx.activity.enableEdgeToEdge
2526
import androidx.activity.result.contract.ActivityResultContracts
2627
import androidx.appcompat.app.AlertDialog
2728
import androidx.appcompat.app.AppCompatActivity
29+
import androidx.core.view.ViewCompat
30+
import androidx.core.view.WindowInsetsCompat
2831
import androidx.lifecycle.Lifecycle
2932
import androidx.lifecycle.lifecycleScope
3033
import androidx.lifecycle.repeatOnLifecycle
@@ -70,11 +73,19 @@ class CallActivity : AppCompatActivity() {
7073

7174
@androidx.camera.camera2.interop.ExperimentalCamera2Interop
7275
override fun onCreate(savedInstanceState: Bundle?) {
76+
enableEdgeToEdge()
7377
super.onCreate(savedInstanceState)
7478
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
7579
binding = CallActivityBinding.inflate(layoutInflater)
7680

7781
setContentView(binding.root)
82+
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
83+
val bars = windowInsets.getInsets(
84+
WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout(),
85+
)
86+
v.setPadding(bars.left, bars.top, bars.right, bars.bottom)
87+
windowInsets
88+
}
7889

7990
// Audience row setup
8091
val audienceAdapter = GroupieAdapter()

0 commit comments

Comments
 (0)