mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 03:18:06 +00:00
Another bluetooth proto
This commit is contained in:
parent
ae7a3c5bce
commit
d4baa8e588
3 changed files with 79 additions and 13 deletions
|
|
@ -26,13 +26,11 @@ import androidx.core.telecom.CallControlResult
|
||||||
import androidx.core.telecom.CallControlScope
|
import androidx.core.telecom.CallControlScope
|
||||||
import androidx.core.telecom.CallEndpointCompat
|
import androidx.core.telecom.CallEndpointCompat
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.core.AudioDevice
|
|
||||||
import org.linphone.core.Call
|
import org.linphone.core.Call
|
||||||
import org.linphone.core.CallListenerStub
|
import org.linphone.core.CallListenerStub
|
||||||
import org.linphone.core.Reason
|
import org.linphone.core.Reason
|
||||||
|
|
@ -143,14 +141,14 @@ class TelecomCallControlCallback(
|
||||||
}.launchIn(scope)
|
}.launchIn(scope)
|
||||||
|
|
||||||
callControl.currentCallEndpoint.onEach { endpoint ->
|
callControl.currentCallEndpoint.onEach { endpoint ->
|
||||||
var newEndpointToUse = endpoint
|
// var newEndpointToUse = endpoint
|
||||||
if (endpointUpdateRequestFromLinphone) {
|
if (endpointUpdateRequestFromLinphone) {
|
||||||
Log.i("$TAG Linphone requests to use [${endpoint.name}] audio endpoint with type [${endpointTypeToString(endpoint.type)}]")
|
Log.i("$TAG Linphone requests to use [${endpoint.name}] audio endpoint with type [${endpointTypeToString(endpoint.type)}]")
|
||||||
} else {
|
} else {
|
||||||
Log.i("$TAG Android requests us to use [${endpoint.name}] audio endpoint with type [${endpointTypeToString(endpoint.type)}]")
|
Log.i("$TAG Android requests us to use [${endpoint.name}] audio endpoint with type [${endpointTypeToString(endpoint.type)}]")
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestedEndpoint = latestLinphoneRequestedEndpoint
|
/*val requestedEndpoint = latestLinphoneRequestedEndpoint
|
||||||
if (endpointUpdateRequestFromLinphone && requestedEndpoint != null && requestedEndpoint != endpoint) {
|
if (endpointUpdateRequestFromLinphone && requestedEndpoint != null && requestedEndpoint != endpoint) {
|
||||||
Log.w("$TAG WARNING: Linphone requested endpoint [${requestedEndpoint.name}] but Telecom Manager notified endpoint [${endpoint.name}], trying to use the one we requested anyway")
|
Log.w("$TAG WARNING: Linphone requested endpoint [${requestedEndpoint.name}] but Telecom Manager notified endpoint [${endpoint.name}], trying to use the one we requested anyway")
|
||||||
newEndpointToUse = requestedEndpoint
|
newEndpointToUse = requestedEndpoint
|
||||||
|
|
@ -163,7 +161,13 @@ class TelecomCallControlCallback(
|
||||||
Log.w("$TAG Device isn't connected to Android Auto, do not follow system request to change audio endpoint to [${newEndpointToUse.name}] with type [${endpointTypeToString(type)}]")
|
Log.w("$TAG Device isn't connected to Android Auto, do not follow system request to change audio endpoint to [${newEndpointToUse.name}] with type [${endpointTypeToString(type)}]")
|
||||||
return@onEach
|
return@onEach
|
||||||
}
|
}
|
||||||
endpointUpdateRequestFromLinphone = false
|
endpointUpdateRequestFromLinphone = false*/
|
||||||
|
/*val type = endpoint.type
|
||||||
|
if (!endpointUpdateRequestFromLinphone && !coreContext.isConnectedToAndroidAuto && (type == CallEndpointCompat.Companion.TYPE_EARPIECE || type == CallEndpointCompat.Companion.TYPE_SPEAKER)) {
|
||||||
|
endpointUpdateRequestFromLinphone = false
|
||||||
|
Log.w("$TAG Device isn't connected to Android Auto, do not follow system request to change audio endpoint to [${endpoint.name}] with type [${endpointTypeToString(type)}]")
|
||||||
|
return@onEach
|
||||||
|
}
|
||||||
|
|
||||||
// Change audio route in SDK, this way the usual listener will trigger
|
// Change audio route in SDK, this way the usual listener will trigger
|
||||||
// and we'll be able to update the UI accordingly
|
// and we'll be able to update the UI accordingly
|
||||||
|
|
@ -186,6 +190,7 @@ class TelecomCallControlCallback(
|
||||||
}
|
}
|
||||||
if (route.isNotEmpty()) {
|
if (route.isNotEmpty()) {
|
||||||
coreContext.postOnCoreThread {
|
coreContext.postOnCoreThread {
|
||||||
|
Log.i("$TAG Requesting Linphone to change audio route to [$route]([${endpointTypeToString(endpoint.type)}])")
|
||||||
if (!AudioUtils.applyAudioRouteChangeInLinphone(call, route)) {
|
if (!AudioUtils.applyAudioRouteChangeInLinphone(call, route)) {
|
||||||
Log.w("$TAG Failed to apply audio route change, trying again in 200ms")
|
Log.w("$TAG Failed to apply audio route change, trying again in 200ms")
|
||||||
coreContext.postOnCoreThreadDelayed({
|
coreContext.postOnCoreThreadDelayed({
|
||||||
|
|
@ -193,7 +198,7 @@ class TelecomCallControlCallback(
|
||||||
}, 200)
|
}, 200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}.launchIn(scope)
|
}.launchIn(scope)
|
||||||
|
|
||||||
callControl.isMuted.onEach { muted ->
|
callControl.isMuted.onEach { muted ->
|
||||||
|
|
@ -224,7 +229,7 @@ class TelecomCallControlCallback(
|
||||||
}.launchIn(scope)
|
}.launchIn(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyAudioRouteToCallWithId(routes: List<AudioDevice.Type>): Boolean {
|
/*fun applyAudioRouteToCallWithId(routes: List<AudioDevice.Type>): Boolean {
|
||||||
Log.i("$TAG Looking for audio endpoint with type [${routes.first()}]")
|
Log.i("$TAG Looking for audio endpoint with type [${routes.first()}]")
|
||||||
|
|
||||||
var wiredHeadsetFound = false
|
var wiredHeadsetFound = false
|
||||||
|
|
@ -260,13 +265,14 @@ class TelecomCallControlCallback(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var endpointChangeSuccessful = false
|
||||||
scope.launch {
|
scope.launch {
|
||||||
Log.i("$TAG Requesting audio endpoint change to [${endpoint.name}] with type [${endpointTypeToString(endpoint.type)}]")
|
Log.i("$TAG Requesting audio endpoint change to [${endpoint.name}] with type [${endpointTypeToString(endpoint.type)}]")
|
||||||
endpointUpdateRequestFromLinphone = true
|
endpointUpdateRequestFromLinphone = true
|
||||||
latestLinphoneRequestedEndpoint = endpoint
|
latestLinphoneRequestedEndpoint = endpoint
|
||||||
var result: CallControlResult = callControl.requestEndpointChange(endpoint)
|
var result: CallControlResult = callControl.requestEndpointChange(endpoint)
|
||||||
var attempts = 1
|
var attempts = 1
|
||||||
while (result is CallControlResult.Error && attempts <= 10) {
|
while (result is CallControlResult.Error && attempts <= 2) {
|
||||||
delay(100)
|
delay(100)
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Previous attempt failed [$result], requesting again audio endpoint change to [${endpoint.name}] with type [${endpointTypeToString(endpoint.type)}]"
|
"$TAG Previous attempt failed [$result], requesting again audio endpoint change to [${endpoint.name}] with type [${endpointTypeToString(endpoint.type)}]"
|
||||||
|
|
@ -282,10 +288,11 @@ class TelecomCallControlCallback(
|
||||||
"$TAG It took [$attempts] attempt(s) to change endpoint audio device..."
|
"$TAG It took [$attempts] attempt(s) to change endpoint audio device..."
|
||||||
)
|
)
|
||||||
currentEndpoint = endpoint.type
|
currentEndpoint = endpoint.type
|
||||||
|
endpointChangeSuccessful = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return endpointChangeSuccessful
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,7 +304,7 @@ class TelecomCallControlCallback(
|
||||||
Log.e("$TAG No matching endpoint found")
|
Log.e("$TAG No matching endpoint found")
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private fun answerCall() {
|
private fun answerCall() {
|
||||||
val isVideo = LinphoneUtils.isVideoEnabled(call)
|
val isVideo = LinphoneUtils.isVideoEnabled(call)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
package org.linphone.telecom
|
package org.linphone.telecom
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.media.AudioDeviceInfo
|
||||||
|
import android.media.AudioManager
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.core.telecom.CallAttributesCompat
|
import androidx.core.telecom.CallAttributesCompat
|
||||||
import androidx.core.telecom.CallException
|
import androidx.core.telecom.CallException
|
||||||
|
|
@ -29,13 +31,14 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.core.AudioDevice
|
|
||||||
import org.linphone.core.Call
|
import org.linphone.core.Call
|
||||||
import org.linphone.core.Core
|
import org.linphone.core.Core
|
||||||
import org.linphone.core.CoreListenerStub
|
import org.linphone.core.CoreListenerStub
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import org.linphone.core.AudioDevice
|
||||||
|
import org.linphone.utils.AudioUtils
|
||||||
|
|
||||||
class TelecomManager
|
class TelecomManager
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|
@ -66,6 +69,9 @@ class TelecomManager
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override fun onLastCallEnded(core: Core) {
|
override fun onLastCallEnded(core: Core) {
|
||||||
currentlyFollowedCalls = 0
|
currentlyFollowedCalls = 0
|
||||||
|
val audioManager = coreContext.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
Log.i("$TAG Clearing communication device")
|
||||||
|
audioManager.clearCommunicationDevice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,6 +93,18 @@ class TelecomManager
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("$TAG Can't init TelecomManager: $e")
|
Log.e("$TAG Can't init TelecomManager: $e")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val listener =
|
||||||
|
AudioManager.OnCommunicationDeviceChangedListener { device -> // Handle changes
|
||||||
|
Log.i("$TAG Communication device changed: $device")
|
||||||
|
if (device?.type != AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
|
||||||
|
AudioUtils.applyAudioRouteChangeInLinphone(null, listOf(AudioDevice.Type.Speaker), true)
|
||||||
|
} else {
|
||||||
|
AudioUtils.applyAudioRouteChangeInLinphone(null, listOf(AudioDevice.Type.Bluetooth), true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
audioManager.addOnCommunicationDeviceChangedListener(context.mainExecutor, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|
@ -214,12 +232,33 @@ class TelecomManager
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Looking for audio endpoint with type [${routes.first()}] for call with ID [$callId]"
|
"$TAG Looking for audio endpoint with type [${routes.first()}] for call with ID [$callId]"
|
||||||
)
|
)
|
||||||
val callControlCallback = map[callId]
|
/*val callControlCallback = map[callId]
|
||||||
if (callControlCallback == null) {
|
if (callControlCallback == null) {
|
||||||
Log.w("$TAG Failed to find callbacks for call with ID [$callId]")
|
Log.w("$TAG Failed to find callbacks for call with ID [$callId]")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return callControlCallback.applyAudioRouteToCallWithId(routes)
|
return callControlCallback.applyAudioRouteToCallWithId(routes)*/
|
||||||
|
val audioManager = coreContext.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
if (AudioDevice.Type.Bluetooth in routes) {
|
||||||
|
val devices = audioManager.availableCommunicationDevices
|
||||||
|
for (device in devices) {
|
||||||
|
if (device.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO && device.isSink) {
|
||||||
|
Log.i("$TAG [Telecom] Setting communication device: $device")
|
||||||
|
audioManager.setCommunicationDevice(device)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val devices = audioManager.availableCommunicationDevices
|
||||||
|
for (device in devices) {
|
||||||
|
if (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER && device.isSink) {
|
||||||
|
Log.i("$TAG [Telecom] Setting communication device: $device")
|
||||||
|
audioManager.setCommunicationDevice(device)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,26 @@ class AudioUtils {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*val audioManager = coreContext.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
if (AudioDevice.Type.Bluetooth in types) {
|
||||||
|
val devices = audioManager.availableCommunicationDevices
|
||||||
|
for (device in devices) {
|
||||||
|
if (device.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO && device.isSink) {
|
||||||
|
Log.i("$TAG [Telecom] Setting communication device: $device")
|
||||||
|
audioManager.setCommunicationDevice(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val devices = audioManager.availableCommunicationDevices
|
||||||
|
for (device in devices) {
|
||||||
|
if (device.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER && device.isSink) {
|
||||||
|
Log.i("$TAG [Telecom] Setting communication device: $device")
|
||||||
|
audioManager.setCommunicationDevice(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// applyAudioRouteChangeInLinphone(currentCall, types, output)
|
||||||
if (!skipTelecom) {
|
if (!skipTelecom) {
|
||||||
val callId = currentCall?.callLog?.callId.orEmpty()
|
val callId = currentCall?.callLog?.callId.orEmpty()
|
||||||
Log.i("$TAG Trying to change audio endpoint using Telecom Manager APIs")
|
Log.i("$TAG Trying to change audio endpoint using Telecom Manager APIs")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue