mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 00:59:49 +01:00
Reintroduce preliminary telecom support for 1:1 calling.
This commit is contained in:
committed by
Michelle Tang
parent
1b6cfe9fc6
commit
a62f07db11
@@ -16,6 +16,7 @@ import kotlinx.collections.immutable.toImmutableList
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.service.webrtc.AndroidTelecomUtil
|
||||
import org.thoughtcrime.securesms.webrtc.audio.AudioDeviceMapping
|
||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager
|
||||
import org.signal.core.ui.R as CoreUiR
|
||||
@@ -38,17 +39,40 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
WebRtcAudioOutput.WIRED_HEADSET -> SignalAudioManager.AudioDevice.WIRED_HEADSET
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeviceList(context: Context): Pair<List<AudioOutputOption>, Int>? {
|
||||
val telecomDevices = AndroidTelecomUtil.getAvailableAudioOutputOptions()
|
||||
if (telecomDevices != null) {
|
||||
return telecomDevices to AndroidTelecomUtil.getCurrentEndpointDeviceId()
|
||||
}
|
||||
|
||||
val am = AppDependencies.androidCallAudioManager
|
||||
val devices = am.availableCommunicationDevices
|
||||
.map { AudioOutputOption(it.toFriendlyName(context).toString(), AudioDeviceMapping.fromPlatformType(it.type), it.id) }
|
||||
.distinctBy { it.deviceType.name }
|
||||
.filterNot { it.deviceType == SignalAudioManager.AudioDevice.NONE }
|
||||
if (devices.isEmpty()) return null
|
||||
return devices to (am.communicationDevice?.id ?: -1)
|
||||
}
|
||||
|
||||
private fun AudioDeviceInfo.toFriendlyName(context: Context): CharSequence {
|
||||
return when (this.type) {
|
||||
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> context.getString(R.string.WebRtcAudioOutputToggle__phone_earpiece)
|
||||
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> context.getString(R.string.WebRtcAudioOutputToggle__speaker)
|
||||
AudioDeviceInfo.TYPE_WIRED_HEADPHONES -> context.getString(R.string.WebRtcAudioOutputToggle__wired_headphones)
|
||||
AudioDeviceInfo.TYPE_WIRED_HEADSET -> context.getString(R.string.WebRtcAudioOutputToggle__wired_headset)
|
||||
AudioDeviceInfo.TYPE_USB_HEADSET -> context.getString(R.string.WebRtcAudioOutputToggle__wired_headset_usb)
|
||||
else -> this.productName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showPicker(fragmentActivity: FragmentActivity, threshold: Int, onDismiss: (DialogInterface) -> Unit): DialogInterface? {
|
||||
val am = AppDependencies.androidCallAudioManager
|
||||
if (am.availableCommunicationDevices.isEmpty()) {
|
||||
val (devices, currentDeviceId) = getDeviceList(fragmentActivity) ?: run {
|
||||
Toast.makeText(fragmentActivity, R.string.WebRtcAudioOutputToggleButton_no_eligible_audio_i_o_detected, Toast.LENGTH_LONG).show()
|
||||
return null
|
||||
}
|
||||
|
||||
val devices: List<AudioOutputOption> = am.availableCommunicationDevices.map { AudioOutputOption(it.toFriendlyName(fragmentActivity).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 null
|
||||
@@ -68,8 +92,8 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
fun Picker(threshold: Int) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val am = AppDependencies.androidCallAudioManager
|
||||
if (am.availableCommunicationDevices.isEmpty()) {
|
||||
val deviceList = getDeviceList(context)
|
||||
if (deviceList == null) {
|
||||
LaunchedEffect(Unit) {
|
||||
Toast.makeText(context, R.string.WebRtcAudioOutputToggleButton_no_eligible_audio_i_o_detected, Toast.LENGTH_LONG).show()
|
||||
stateUpdater.hidePicker()
|
||||
@@ -77,8 +101,7 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
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
|
||||
val (devices, currentDeviceId) = deviceList
|
||||
if (devices.size < threshold) {
|
||||
LaunchedEffect(Unit) {
|
||||
Log.d(TAG, "Only found $devices devices, not showing picker.")
|
||||
@@ -101,7 +124,12 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
@RequiresApi(31)
|
||||
val onAudioDeviceSelected: (AudioOutputOption) -> Unit = {
|
||||
Log.d(TAG, "User selected audio device of type ${it.deviceType}")
|
||||
audioOutputChangedListener.audioOutputChanged(WebRtcAudioDevice(it.toWebRtcAudioOutput(), it.deviceId))
|
||||
val webRtcDevice = if (AndroidTelecomUtil.hasActiveController()) {
|
||||
WebRtcAudioDevice(it.toWebRtcAudioOutput(), null)
|
||||
} else {
|
||||
WebRtcAudioDevice(it.toWebRtcAudioOutput(), it.deviceId)
|
||||
}
|
||||
audioOutputChangedListener.audioOutputChanged(webRtcDevice)
|
||||
|
||||
when (it.deviceType) {
|
||||
SignalAudioManager.AudioDevice.WIRED_HEADSET -> {
|
||||
@@ -123,35 +151,22 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
|
||||
}
|
||||
}
|
||||
|
||||
private fun AudioDeviceInfo.toFriendlyName(context: Context): CharSequence {
|
||||
return when (this.type) {
|
||||
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> context.getString(R.string.WebRtcAudioOutputToggle__phone_earpiece)
|
||||
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> context.getString(R.string.WebRtcAudioOutputToggle__speaker)
|
||||
AudioDeviceInfo.TYPE_WIRED_HEADPHONES -> context.getString(R.string.WebRtcAudioOutputToggle__wired_headphones)
|
||||
AudioDeviceInfo.TYPE_WIRED_HEADSET -> context.getString(R.string.WebRtcAudioOutputToggle__wired_headset)
|
||||
AudioDeviceInfo.TYPE_USB_HEADSET -> context.getString(R.string.WebRtcAudioOutputToggle__wired_headset_usb)
|
||||
else -> this.productName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 }
|
||||
val (devices, currentDeviceId) = getDeviceList(AppDependencies.application) ?: run {
|
||||
Log.w(TAG, "cycleToNextDevice: no available communication devices")
|
||||
return
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -1285,7 +1285,16 @@ class WebRtcCallActivity : BaseActivity(), SafetyNumberChangeDialog.Callback, Re
|
||||
@RequiresApi(31)
|
||||
override fun onAudioOutputChanged31(audioOutput: WebRtcAudioDevice) {
|
||||
maybeDisplaySpeakerphonePopup(audioOutput.webRtcAudioOutput)
|
||||
AppDependencies.signalCallManager.selectAudioDevice(ChosenAudioDeviceIdentifier(audioOutput.deviceId!!))
|
||||
if (audioOutput.deviceId != null) {
|
||||
AppDependencies.signalCallManager.selectAudioDevice(ChosenAudioDeviceIdentifier(audioOutput.deviceId))
|
||||
} else {
|
||||
when (audioOutput.webRtcAudioOutput) {
|
||||
WebRtcAudioOutput.HANDSET -> handleSetAudioHandset()
|
||||
WebRtcAudioOutput.SPEAKER -> handleSetAudioSpeaker()
|
||||
WebRtcAudioOutput.BLUETOOTH_HEADSET -> handleSetAudioBluetooth()
|
||||
WebRtcAudioOutput.WIRED_HEADSET -> handleSetAudioWiredHeadset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onVideoChanged(isVideoEnabled: Boolean) {
|
||||
|
||||
Reference in New Issue
Block a user