@@ -4,9 +4,13 @@ import android.Manifest
44import android.annotation.SuppressLint
55import android.content.Context
66import android.content.pm.PackageManager
7+ import android.hardware.usb.UsbDevice
78import android.media.AudioFormat
9+ import android.media.AudioManager
810import android.media.AudioRecord
911import android.media.MediaRecorder
12+ import android.os.Build
13+ import androidx.annotation.RequiresApi
1014import androidx.core.content.ContextCompat
1115import kotlinx.coroutines.Dispatchers
1216import kotlinx.coroutines.channels.awaitClose
@@ -32,7 +36,7 @@ import org.operatorfoundation.signalbridge.exceptions.AudioRecordException
3236 * - State management beyond AudioRecord
3337 * - Audio output/playback
3438 */
35- internal class AudioRecordManager (private val context : Context )
39+ internal class AudioRecordManager (private val context : Context , private val usbDevice : UsbDevice ? = null )
3640{
3741 companion object
3842 {
@@ -56,6 +60,8 @@ internal class AudioRecordManager(private val context: Context)
5660 private var workingAudioSource: Int = - 1
5761 private var bufferSize: Int = 0
5862 private var detectedSampleRate: Int = SAMPLE_RATE // Will be updated during initialization
63+ private val audioManager = context.getSystemService(Context .AUDIO_SERVICE ) as android.media.AudioManager
64+
5965
6066 /* *
6167 * Tests multiple audio sources and initializes AudioRecord with the first working one.
@@ -65,6 +71,14 @@ internal class AudioRecordManager(private val context: Context)
6571 {
6672 Timber .d(" Initializing AudioRecord" )
6773
74+ // Set USB audio routing if we have a USB device
75+ if (usbDevice != null )
76+ {
77+ val routingSet = setUsbAudioRouting()
78+ if (routingSet) Timber .i(" USB audio routing configured successfully" )
79+ else Timber .w(" Failed to set USB audio routing, continuing with default routing" )
80+ }
81+
6882 // Test each audio source until we find one that works
6983 for (audioSource in AUDIO_SOURCES_TO_TEST )
7084 {
@@ -214,6 +228,41 @@ internal class AudioRecordManager(private val context: Context)
214228 }
215229 }
216230
231+ /* *
232+ * Sets USB audio device as the preferred audio input routing
233+ */
234+ private fun setUsbAudioRouting (): Boolean
235+ {
236+ return try
237+ {
238+ // Get the list of available communication devices
239+ val availableDevices = audioManager.availableCommunicationDevices
240+
241+ val audioDeviceInfo = availableDevices.find { device ->
242+ device.type == android.media.AudioDeviceInfo .TYPE_USB_DEVICE &&
243+ device.productName?.toString() == usbDevice?.productName
244+ }
245+
246+ if (audioDeviceInfo != null )
247+ {
248+ val success = audioManager.setCommunicationDevice(audioDeviceInfo)
249+ Timber .d(" Set USB device as communication device: $success " )
250+ success
251+ }
252+ else
253+ {
254+ Timber .w(" USB audio device not found in available communication devices" )
255+ Timber .w(" Available devices: ${availableDevices.map { it.productName }} " )
256+ false
257+ }
258+ }
259+ catch (e: Exception )
260+ {
261+ Timber .e(e, " Failed to set USB audio routing" )
262+ false
263+ }
264+ }
265+
217266 /* *
218267 * Starts recording and returns a flow of raw audio samples
219268 * This is a pure data stream with no processing or state management
0 commit comments