Added ConnectionService.kt
This commit is contained in:
227
app/src/main/kotlin/com/tutpro/baresip/ConnectionService.kt
Normal file
227
app/src/main/kotlin/com/tutpro/baresip/ConnectionService.kt
Normal file
@ -0,0 +1,227 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.content.Intent
|
||||
import android.telecom.CallAudioState
|
||||
import android.telecom.Connection
|
||||
import android.telecom.ConnectionRequest
|
||||
import android.telecom.ConnectionService
|
||||
import android.telecom.DisconnectCause
|
||||
import android.telecom.PhoneAccountHandle
|
||||
import android.telecom.TelecomManager
|
||||
import android.net.Uri
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class ConnectionService : ConnectionService() {
|
||||
|
||||
private val TAG = "BaresipConnection"
|
||||
|
||||
companion object {
|
||||
val connections = ConcurrentHashMap<Long, BaresipConnection>()
|
||||
var pendingOutgoingConnection: BaresipConnection? = null
|
||||
|
||||
fun promoteOutgoingConnection(callp: Long) {
|
||||
pendingOutgoingConnection?.let {
|
||||
it.callp = callp
|
||||
connections[callp] = it
|
||||
pendingOutgoingConnection = null
|
||||
}
|
||||
}
|
||||
|
||||
fun onCallClosed(callp: Long) {
|
||||
connections[callp]?.let {
|
||||
it.setDisconnected(DisconnectCause(DisconnectCause.REMOTE))
|
||||
it.destroy()
|
||||
connections.remove(callp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateIncomingConnection(
|
||||
connectionManagerPhoneAccount: PhoneAccountHandle?,
|
||||
request: ConnectionRequest?
|
||||
): Connection {
|
||||
val extras = request?.extras
|
||||
val uap = extras?.getLong("uap") ?: 0L
|
||||
val callp = extras?.getLong("callp") ?: 0L
|
||||
val peerUri = extras?.getString("peerUri") ?: ""
|
||||
|
||||
Log.d(TAG, "onCreateIncomingConnection for $peerUri")
|
||||
|
||||
val connection = BaresipConnection(uap, callp)
|
||||
connections[callp] = connection
|
||||
connection.setAddress(Uri.fromParts("sip", peerUri, null), TelecomManager.PRESENTATION_ALLOWED)
|
||||
connection.connectionCapabilities = Connection.CAPABILITY_SUPPORT_HOLD or Connection.CAPABILITY_HOLD
|
||||
|
||||
val call = Call.ofCallp(callp)
|
||||
if (call != null)
|
||||
BaresipService.instance?.handleIncomingCall(call)
|
||||
|
||||
val ua = UserAgent.ofUap(uap)
|
||||
if (ua != null) {
|
||||
// Check speakerphone setting
|
||||
if (BaresipService.speakerPhone) {
|
||||
@Suppress("DEPRECATION")
|
||||
connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER)
|
||||
}
|
||||
|
||||
// Check for Auto-Answer
|
||||
if (ua.account.answerMode == Api.ANSWERMODE_AUTO) {
|
||||
Log.d(TAG, "Auto-answering call $callp")
|
||||
connection.onAnswer()
|
||||
} else {
|
||||
connection.setRinging()
|
||||
}
|
||||
}
|
||||
|
||||
return connection
|
||||
}
|
||||
|
||||
override fun onCreateIncomingConnectionFailed(
|
||||
connectionManagerPhoneAccount: PhoneAccountHandle?,
|
||||
request: ConnectionRequest?
|
||||
) {
|
||||
Log.e(TAG, "onCreateIncomingConnectionFailed")
|
||||
}
|
||||
|
||||
override fun onCreateOutgoingConnection(
|
||||
connectionManagerPhoneAccount: PhoneAccountHandle?,
|
||||
request: ConnectionRequest?
|
||||
): Connection {
|
||||
val rootExtras = request?.extras
|
||||
val nestedExtras = rootExtras?.getBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)
|
||||
|
||||
// Try root extras first, then fallback to nested
|
||||
val uap = rootExtras?.getLong("uap", 0L).takeIf { it != 0L }
|
||||
?: nestedExtras?.getLong("uap") ?: 0L
|
||||
|
||||
val conferenceCall = rootExtras?.getBoolean("conferenceCall", false) ?:
|
||||
nestedExtras?.getBoolean("conferenceCall") ?: false
|
||||
|
||||
val onHoldCallp = rootExtras?.getLong("onHoldCallp", 0L).takeIf { it != 0L }
|
||||
?: nestedExtras?.getLong("onHoldCallp") ?: 0L
|
||||
|
||||
val destination = request?.address?.schemeSpecificPart ?: ""
|
||||
|
||||
Log.d(TAG, "onCreateOutgoingConnection to $destination (uap=$uap)")
|
||||
|
||||
val connection = BaresipConnection(uap, 0L)
|
||||
pendingOutgoingConnection = connection
|
||||
|
||||
if (BaresipService.speakerPhone) {
|
||||
@Suppress("DEPRECATION")
|
||||
connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER)
|
||||
}
|
||||
|
||||
connection.setAddress(request?.address, TelecomManager.PRESENTATION_ALLOWED)
|
||||
connection.connectionCapabilities = Connection.CAPABILITY_SUPPORT_HOLD or Connection.CAPABILITY_HOLD
|
||||
|
||||
// Start the SIP connection logic
|
||||
if (uap != 0L) {
|
||||
val sipUri = if (destination.startsWith("sip:")) destination else "sip:$destination"
|
||||
BaresipService.instance?.runCall(uap, sipUri, conferenceCall, onHoldCallp)
|
||||
} else {
|
||||
Log.e(TAG, "Cannot start outgoing call: uap is 0")
|
||||
connection.setDisconnected(DisconnectCause(DisconnectCause.ERROR, "No Account"))
|
||||
connection.destroy()
|
||||
pendingOutgoingConnection = null
|
||||
}
|
||||
|
||||
connection.setDialing()
|
||||
return connection
|
||||
}
|
||||
|
||||
override fun onCreateOutgoingConnectionFailed(
|
||||
connectionManagerPhoneAccount: PhoneAccountHandle?,
|
||||
request: ConnectionRequest?
|
||||
) {
|
||||
Log.e(TAG, "onCreateOutgoingConnectionFailed")
|
||||
pendingOutgoingConnection = null
|
||||
}
|
||||
|
||||
inner class BaresipConnection(val uap: Long, var callp: Long) : Connection() {
|
||||
|
||||
override fun onAnswer() {
|
||||
Log.d(TAG, "Telecom Connection onAnswer $callp")
|
||||
val intent = Intent(this@ConnectionService, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
intent.putExtra("action", "call answer")
|
||||
intent.putExtra("callp", callp)
|
||||
startActivity(intent)
|
||||
BaresipService.instance?.updateStatusNotification()
|
||||
setActive()
|
||||
}
|
||||
|
||||
override fun onReject() {
|
||||
Log.d(TAG, "Telecom Connection onReject $callp")
|
||||
Api.ua_hangup(uap, callp, 486, "Rejected")
|
||||
setDisconnected(DisconnectCause(DisconnectCause.REJECTED))
|
||||
connections.remove(callp)
|
||||
destroy()
|
||||
}
|
||||
|
||||
override fun onDisconnect() {
|
||||
Log.d(TAG, "Telecom Connection onDisconnect $callp")
|
||||
if (callp != 0L) {
|
||||
Api.ua_hangup(uap, callp, 0, "")
|
||||
connections.remove(callp)
|
||||
} else {
|
||||
pendingOutgoingConnection = null
|
||||
}
|
||||
setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
|
||||
destroy()
|
||||
}
|
||||
|
||||
override fun onAbort() {
|
||||
Log.d(TAG, "Telecom Connection onAbort $callp")
|
||||
if (callp != 0L) {
|
||||
Api.ua_hangup(uap, callp, 0, "")
|
||||
connections.remove(callp)
|
||||
} else {
|
||||
pendingOutgoingConnection = null
|
||||
}
|
||||
setDisconnected(DisconnectCause(DisconnectCause.CANCELED))
|
||||
destroy()
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onCallAudioStateChanged(state: CallAudioState?) {
|
||||
super.onCallAudioStateChanged(state)
|
||||
Log.d(TAG, "onCallAudioStateChanged: $state")
|
||||
state?.let {
|
||||
if (BaresipService.isMicMuted != it.isMuted) {
|
||||
BaresipService.isMicMuted = it.isMuted
|
||||
Api.calls_mute(it.isMuted)
|
||||
BaresipService.postServiceEvent(
|
||||
ServiceEvent("mic muted,${it.isMuted}", arrayListOf(uap, callp),
|
||||
System.nanoTime())
|
||||
)
|
||||
}
|
||||
val isSpeaker = it.route == CallAudioState.ROUTE_SPEAKER
|
||||
BaresipService.postServiceEvent(
|
||||
ServiceEvent("speaker,${isSpeaker}", arrayListOf(uap, callp), System.nanoTime())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHold() {
|
||||
Log.d(TAG, "Telecom Connection onHold $callp")
|
||||
Api.call_hold(callp, true)
|
||||
setOnHold()
|
||||
}
|
||||
|
||||
override fun onUnhold() {
|
||||
Log.d(TAG, "Telecom Connection onUnhold $callp")
|
||||
Api.call_hold(callp, false)
|
||||
setActive()
|
||||
}
|
||||
|
||||
override fun onPlayDtmfTone(c: Char) {
|
||||
Log.d(TAG, "Telecom Connection onPlayDtmfTone $c")
|
||||
if (callp != 0L) {
|
||||
val call = Call.ofCallp(callp)
|
||||
call?.sendDigit(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user