Do not follow telecom manager audio routing requests if not connected to Android Auto and concerns Speaker or Earpiece

This commit is contained in:
Sylvain Berfini 2025-02-26 10:53:28 +01:00
parent 8eda500dae
commit 01c079440d
3 changed files with 26 additions and 6 deletions

View file

@ -1124,7 +1124,7 @@ class NotificationsManager
}
Log.i(
"Creating notification for [${if (isIncoming) "incoming" else "outgoing"}] [${if (isConference) "conference" else "call"}] with video [${if (isVideo) "enabled" else "disabled"}] on channel [$channel]"
"Creating notification for ${if (isIncoming) "[incoming] " else ""}[${if (isConference) "conference" else "call"}] with video [${if (isVideo) "enabled" else "disabled"}] on channel [$channel]"
)
val builder = NotificationCompat.Builder(

View file

@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.core.AudioDevice
import org.linphone.core.Call
import org.linphone.core.CallListenerStub
@ -51,6 +52,7 @@ class TelecomCallControlCallback(
private var availableEndpoints: List<CallEndpointCompat> = arrayListOf()
private var currentEndpoint = CallEndpointCompat.TYPE_UNKNOWN
private var endpointUpdateRequestFromLinphone: Boolean = false
private val callListener = object : CallListenerStub() {
@WorkerThread
@ -65,9 +67,14 @@ class TelecomCallControlCallback(
CallAttributesCompat.Companion.CALL_TYPE_AUDIO_CALL
}
scope.launch {
Log.i("$TAG Answering ${if (isVideo) "video" else "audio"} call")
Log.i("$TAG Answering [${if (isVideo) "video" else "audio"}] call")
callControl.answer(type)
}
if (isVideo && corePreferences.routeAudioToSpeakerWhenVideoIsEnabled) {
Log.i("$TAG Answering video call, routing audio to speaker")
AudioUtils.routeAudioToSpeaker(call)
}
} else {
scope.launch {
Log.i("$TAG Setting call active")
@ -156,11 +163,23 @@ class TelecomCallControlCallback(
}.launchIn(scope)
callControl.currentCallEndpoint.onEach { endpoint ->
Log.i("$TAG We're asked to use [${endpoint.name}] audio endpoint")
val type = endpoint.type
currentEndpoint = type
if (endpointUpdateRequestFromLinphone) {
Log.i("$TAG Linphone requests to use [${endpoint.name}] audio endpoint with type [$type]")
} else {
Log.i("$TAG Android requests us to use [${endpoint.name}] audio endpoint with type [$type]")
}
if (!endpointUpdateRequestFromLinphone && !coreContext.isConnectedToAndroidAuto && (type == CallEndpointCompat.Companion.TYPE_EARPIECE || type == CallEndpointCompat.Companion.TYPE_SPEAKER)) {
Log.w("$TAG Device isn't connected to Android Auto, do not follow system request to change audio endpoint to either earpiece or speaker")
return@onEach
}
// Change audio route in SDK, this way the usual listener will trigger
// and we'll be able to update the UI accordingly
val route = arrayListOf<AudioDevice.Type>()
when (endpoint.type) {
when (type) {
CallEndpointCompat.Companion.TYPE_EARPIECE -> {
route.add(AudioDevice.Type.Earpiece)
}
@ -176,7 +195,6 @@ class TelecomCallControlCallback(
}
}
if (route.isNotEmpty()) {
currentEndpoint = endpoint.type
coreContext.postOnCoreThread {
if (!AudioUtils.applyAudioRouteChangeInLinphone(call, route)) {
Log.w("$TAG Failed to apply audio route change, trying again in 200ms")
@ -186,6 +204,7 @@ class TelecomCallControlCallback(
}
}
}
endpointUpdateRequestFromLinphone = false
}.launchIn(scope)
callControl.isMuted.onEach { muted ->
@ -215,6 +234,7 @@ class TelecomCallControlCallback(
}
fun applyAudioRouteToCallWithId(routes: List<AudioDevice.Type>): Boolean {
endpointUpdateRequestFromLinphone = true
Log.i("$TAG Looking for audio endpoint with type [${routes.first()}]")
var wiredHeadsetFound = false

View file

@ -231,7 +231,7 @@ class LinphoneUtils {
val isIncoming = isCallIncoming(call.state)
return if (isConference || getConferenceInfoIfAny(call) != null) {
true
} else if (isIncoming) {
} else if (isIncoming || call.state == Call.State.Connected) { // In connected state call.currentParams.isVideoEnabled will return false...
call.remoteParams?.isVideoEnabled == true && call.remoteParams?.videoDirection != MediaDirection.Inactive
} else {
call.currentParams.isVideoEnabled && call.currentParams.videoDirection != MediaDirection.Inactive