mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 00:29:11 +01:00
Fix issue with initial audio output setting.
Co-authored-by: Greyson Parrelli <greyson@signal.org>
This commit is contained in:
@@ -7,6 +7,7 @@ import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
@@ -28,6 +29,15 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
|
||||
companion object {
|
||||
const val TAG = "WebRtcAudioPicker31"
|
||||
|
||||
private fun WebRtcAudioOutput.toSignalAudioDevice(): SignalAudioManager.AudioDevice {
|
||||
return when (this) {
|
||||
WebRtcAudioOutput.HANDSET -> SignalAudioManager.AudioDevice.EARPIECE
|
||||
WebRtcAudioOutput.SPEAKER -> SignalAudioManager.AudioDevice.SPEAKER_PHONE
|
||||
WebRtcAudioOutput.BLUETOOTH_HEADSET -> SignalAudioManager.AudioDevice.BLUETOOTH
|
||||
WebRtcAudioOutput.WIRED_HEADSET -> SignalAudioManager.AudioDevice.WIRED_HEADSET
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showPicker(fragmentActivity: FragmentActivity, threshold: Int, onDismiss: (DialogInterface) -> Unit): DialogInterface? {
|
||||
@@ -60,20 +70,20 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
|
||||
val am = AppDependencies.androidCallAudioManager
|
||||
if (am.availableCommunicationDevices.isEmpty()) {
|
||||
Toast.makeText(context, R.string.WebRtcAudioOutputToggleButton_no_eligible_audio_i_o_detected, Toast.LENGTH_LONG).show()
|
||||
LaunchedEffect(Unit) {
|
||||
Toast.makeText(context, R.string.WebRtcAudioOutputToggleButton_no_eligible_audio_i_o_detected, Toast.LENGTH_LONG).show()
|
||||
stateUpdater.hidePicker()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val devices: List<AudioOutputOption> = am.availableCommunicationDevices.map { AudioOutputOption(it.toFriendlyName(context).toString(), AudioDeviceMapping.fromPlatformType(it.type), it.id) }.distinctBy { it.deviceType.name }.filterNot { it.deviceType == SignalAudioManager.AudioDevice.NONE }
|
||||
val currentDeviceId = am.communicationDevice?.id ?: -1
|
||||
if (devices.size < threshold) {
|
||||
Log.d(TAG, "Only found $devices devices, not showing picker.")
|
||||
if (devices.isEmpty()) return
|
||||
|
||||
val index = devices.indexOfFirst { it.deviceId == currentDeviceId }
|
||||
if (index == -1) return
|
||||
|
||||
onAudioDeviceSelected(devices[(index + 1) % devices.size])
|
||||
LaunchedEffect(Unit) {
|
||||
Log.d(TAG, "Only found $devices devices, not showing picker.")
|
||||
cycleToNextDevice()
|
||||
}
|
||||
return
|
||||
} else {
|
||||
Log.d(TAG, "Found $devices devices, showing picker.")
|
||||
@@ -124,6 +134,37 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycles to the next audio device without showing a picker.
|
||||
* Uses the system device list to resolve the actual device ID, falling back to
|
||||
* type-based lookup from app-tracked state when the current communication device is unknown.
|
||||
*/
|
||||
fun cycleToNextDevice() {
|
||||
val am = AppDependencies.androidCallAudioManager
|
||||
val devices: List<AudioOutputOption> = am.availableCommunicationDevices
|
||||
.map { AudioOutputOption("", AudioDeviceMapping.fromPlatformType(it.type), it.id) }
|
||||
.distinctBy { it.deviceType.name }
|
||||
.filterNot { it.deviceType == SignalAudioManager.AudioDevice.NONE }
|
||||
|
||||
if (devices.isEmpty()) {
|
||||
Log.w(TAG, "cycleToNextDevice: no available communication devices")
|
||||
return
|
||||
}
|
||||
|
||||
val currentDeviceId = am.communicationDevice?.id ?: -1
|
||||
val index = devices.indexOfFirst { it.deviceId == currentDeviceId }
|
||||
|
||||
if (index != -1) {
|
||||
onAudioDeviceSelected(devices[(index + 1) % devices.size])
|
||||
} else {
|
||||
val nextOutput = outputState.peekNext()
|
||||
val targetDeviceType = nextOutput.toSignalAudioDevice()
|
||||
val targetDevice = devices.firstOrNull { it.deviceType == targetDeviceType } ?: devices.first()
|
||||
Log.d(TAG, "cycleToNextDevice: communicationDevice unknown, selecting ${targetDevice.deviceType} by type")
|
||||
onAudioDeviceSelected(targetDevice)
|
||||
}
|
||||
}
|
||||
|
||||
private fun AudioOutputOption.toWebRtcAudioOutput(): WebRtcAudioOutput {
|
||||
return when (this.deviceType) {
|
||||
SignalAudioManager.AudioDevice.WIRED_HEADSET -> WebRtcAudioOutput.WIRED_HEADSET
|
||||
|
||||
@@ -185,11 +185,13 @@ class AudioOutputPickerController(
|
||||
|
||||
val isLegacy = Build.VERSION.SDK_INT < 31
|
||||
if (!willDisplayPicker) {
|
||||
if (isLegacy) {
|
||||
LaunchedEffect(Unit) {
|
||||
displaySheet = false
|
||||
onSelectedDeviceChanged(WebRtcAudioDevice(outputState.peekNext(), null))
|
||||
} else {
|
||||
newApiController!!.Picker(threshold = SHOW_PICKER_THRESHOLD)
|
||||
if (isLegacy) {
|
||||
onSelectedDeviceChanged(WebRtcAudioDevice(outputState.peekNext(), null))
|
||||
} else {
|
||||
newApiController!!.cycleToNextDevice()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -205,7 +205,6 @@ class FullSignalAudioManagerApi31(context: Context, eventListener: EventListener
|
||||
Log.i(TAG, "startIncomingRinger: uri: ${if (ringtoneUri != null) "present" else "null"} vibrate: $vibrate currentMode: ${getModeName(androidAudioManager.mode)}")
|
||||
androidAudioManager.mode = AudioManager.MODE_RINGTONE
|
||||
setMicrophoneMute(false)
|
||||
setDefaultAudioDevice(recipientId = null, newDefaultDevice = AudioDevice.SPEAKER_PHONE, clearUserEarpieceSelection = false)
|
||||
incomingRinger.start(ringtoneUri, vibrate)
|
||||
}
|
||||
|
||||
|
||||
@@ -429,7 +429,6 @@ class FullSignalAudioManager(context: Context, eventListener: EventListener?) :
|
||||
Log.i(TAG, "startIncomingRinger(): uri: ${if (ringtoneUri != null) "present" else "null"} vibrate: $vibrate")
|
||||
androidAudioManager.mode = AudioManager.MODE_RINGTONE
|
||||
setMicrophoneMute(false)
|
||||
setDefaultAudioDevice(recipientId = null, newDefaultDevice = AudioDevice.SPEAKER_PHONE, clearUserEarpieceSelection = false)
|
||||
|
||||
incomingRinger.start(ringtoneUri, vibrate)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user