Completed multiple simulataneous calls feature

This commit is contained in:
Juha Heinanen
2026-04-05 09:50:54 +03:00
parent 6c2419dd05
commit 535c2cacf5
3 changed files with 17 additions and 30 deletions

View File

@ -889,27 +889,19 @@ class BaresipService: Service() {
val newHeldState = when (ev[1].toInt()) {Api.SDP_INACTIVE, Api.SDP_RECVONLY -> true val newHeldState = when (ev[1].toInt()) {Api.SDP_INACTIVE, Api.SDP_RECVONLY -> true
else -> false else -> false
} }
val connection = ConnectionService.connections[callp] val connection = ConnectionService.connections[callp]
// Handle Remote Un-hold
if (call!!.held && !newHeldState) { if (call!!.held && !newHeldState) {
Log.d(TAG, "Call ${call.callp} un-held by peer.") Log.d(TAG, "Call ${call.callp} un-held by peer.")
// Clear our local manual hold flag so resume() can execute
call.onhold = false call.onhold = false
// Use a Coroutine with a small delay to let the SIP
// We use a Coroutine with a small delay to let the SIP
// transaction (the re-INVITE from the peer) finish // transaction (the re-INVITE from the peer) finish
// before we try to hold the other call and resume this one. // before trying to hold the other call and resume this one.
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
delay(100) delay(100)
call.resume() call.resume()
} }
} }
call.held = newHeldState call.held = newHeldState
if (newHeldState) { if (newHeldState) {
// Peer put us on hold // Peer put us on hold
call.showOnHoldNotice.value = true call.showOnHoldNotice.value = true
@ -918,15 +910,12 @@ class BaresipService: Service() {
} else { } else {
// Peer un-held us // Peer un-held us
call.showOnHoldNotice.value = false call.showOnHoldNotice.value = false
// Only clear the UI if we aren't also manually holding it // Only clear the UI if we aren't also manually holding it
// (If we just called call.resume() above, it will handle this)
if (!call.onhold) { if (!call.onhold) {
call.callOnHold.value = false call.callOnHold.value = false
connection?.setActive() connection?.setActive()
} }
} }
if (call.state() == Api.CALL_STATE_EARLY) { if (call.state() == Api.CALL_STATE_EARLY) {
if ((ev[1].toInt() and Api.SDP_RECVONLY) != 0) if ((ev[1].toInt() and Api.SDP_RECVONLY) != 0)
stopMediaPlayer() stopMediaPlayer()
@ -935,7 +924,6 @@ class BaresipService: Service() {
playRingBack() playRingBack()
} }
} }
if (call.status.value == "connected" && !call.held && !call.onhold) { if (call.status.value == "connected" && !call.held && !call.onhold) {
if (call.callOnHold.value || call.showOnHoldNotice.value) { if (call.callOnHold.value || call.showOnHoldNotice.value) {
Log.d(TAG, "Safety guard: Clearing stuck hold flags for ${call.callp}") Log.d(TAG, "Safety guard: Clearing stuck hold flags for ${call.callp}")
@ -1006,9 +994,17 @@ class BaresipService: Service() {
} }
"call closed" -> { "call closed" -> {
Log.d(TAG, "AoR $aor call $callp is closed prm: ${ev[1]}") Log.d(TAG, "AoR $aor call $callp is closed prm: ${ev[1]}")
ConnectionService.connections[callp]?.let { val connection = ConnectionService.connections[callp]
it.setDisconnected(DisconnectCause(DisconnectCause.REMOTE)) if (connection != null) {
it.destroy() val cause = when {
ev[1].contains("200") -> DisconnectCause.LOCAL
ev[1].contains("486") -> DisconnectCause.BUSY
ev[1].contains("404") -> DisconnectCause.ERROR
ev[1].contains("403") || ev[1].contains("401") -> DisconnectCause.RESTRICTED
else -> DisconnectCause.REMOTE
}
connection.setDisconnected(DisconnectCause(cause))
connection.destroy()
ConnectionService.connections.remove(callp) ConnectionService.connections.remove(callp)
} }
nm.cancel(CALL_NOTIFICATION_ID) nm.cancel(CALL_NOTIFICATION_ID)
@ -1032,9 +1028,10 @@ class BaresipService: Service() {
onHoldCall.referTo = "" onHoldCall.referTo = ""
call.onHoldCall = null call.onHoldCall = null
} }
val isConference = call.conferenceCall
call.remove() call.remove()
updateStatusNotification() updateStatusNotification()
if (call.conferenceCall && ua.calls().isEmpty()) if (isConference && ua.calls().isEmpty())
Api.module_unload("mixminus") Api.module_unload("mixminus")
val reason = ev[1] val reason = ev[1]
val tone = ev[2] val tone = ev[2]

View File

@ -62,8 +62,6 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
if (Api.call_hold(callp, true)) { if (Api.call_hold(callp, true)) {
onhold = true onhold = true
callOnHold.value = true callOnHold.value = true
// Fix: Do NOT set showOnHoldNotice to true here.
// That notice is for when the PEER holds us.
showOnHoldNotice.value = false showOnHoldNotice.value = false
ConnectionService.connections[callp]?.setOnHold() ConnectionService.connections[callp]?.setOnHold()
return true return true
@ -73,7 +71,6 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
fun resume(): Boolean { fun resume(): Boolean {
if (!onhold && !held) return true if (!onhold && !held) return true
// 1. Hold other calls first // 1. Hold other calls first
for (c in BaresipService.calls) { for (c in BaresipService.calls) {
if (c.callp != this.callp && !c.onhold && !c.held) { if (c.callp != this.callp && !c.onhold && !c.held) {
@ -81,15 +78,12 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
c.hold() c.hold()
} }
} }
val connection = ConnectionService.connections[callp] val connection = ConnectionService.connections[callp]
// 2. SIP Signaling // 2. SIP Signaling
if (Api.call_hold(callp, false)) { if (Api.call_hold(callp, false)) {
onhold = false onhold = false
callOnHold.value = false callOnHold.value = false
showOnHoldNotice.value = false showOnHoldNotice.value = false
// 3. Telecom Sync // 3. Telecom Sync
connection?.setAddress("sip:$peerUri".toUri(), android.telecom.TelecomManager.PRESENTATION_ALLOWED) connection?.setAddress("sip:$peerUri".toUri(), android.telecom.TelecomManager.PRESENTATION_ALLOWED)
connection?.setActive() connection?.setActive()
@ -99,10 +93,8 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
} }
fun transfer(uri: String): Boolean { fun transfer(uri: String): Boolean {
if (!Api.call_hold(callp, true)) if (!onhold) hold()
return false Log.d(TAG, "Transferring call $callp to $uri")
onhold = true
referTo = uri
return Api.call_transfer(callp, uri) == 0 return Api.call_transfer(callp, uri) == 0
} }

View File

@ -201,8 +201,6 @@ class ConnectionService : ConnectionService() {
} }
override fun onHold() { override fun onHold() {
// Do NOT call super.onHold() first, as it might change internal state
// before we can grab the call object.
Log.d(TAG, "Telecom Connection onHold $callp") Log.d(TAG, "Telecom Connection onHold $callp")
val call = Call.ofCallp(callp) val call = Call.ofCallp(callp)
if (call != null && !call.conferenceCall) { if (call != null && !call.conferenceCall) {