Prevent system call notification to be stuck if call was ended in Linphone SDK before being added to TelecomManager's

This commit is contained in:
Sylvain Berfini 2025-03-16 18:57:35 +01:00
parent 3e49e0f014
commit 4979bca704
2 changed files with 58 additions and 38 deletions

View file

@ -1127,19 +1127,20 @@ class NotificationsManager
)
}
val channel = if (isIncoming) {
val channelId = if (isIncoming) {
context.getString(R.string.notification_channel_incoming_call_id)
} else {
context.getString(R.string.notification_channel_call_id)
}
val channel = notificationManager.getNotificationChannel(channelId)
val importance = channel?.importance ?: NotificationManagerCompat.IMPORTANCE_NONE
Log.i(
"Creating notification for ${if (isIncoming) "[incoming] " else ""}[${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] with importance [$importance]"
)
val builder = NotificationCompat.Builder(
context,
channel
channelId
).apply {
try {
style.setIsVideo(isVideo)

View file

@ -82,41 +82,9 @@ class TelecomCallControlCallback(
}
}
} else if (state == Call.State.End) {
val reason = call.reason
val direction = call.dir
scope.launch {
val disconnectCause = when (reason) {
Reason.NotAnswered -> DisconnectCause.REMOTE
Reason.Declined -> DisconnectCause.REJECTED
Reason.Busy -> {
if (direction == Call.Dir.Incoming) {
DisconnectCause.MISSED
} else {
DisconnectCause.BUSY
}
}
else -> DisconnectCause.LOCAL
}
Log.i("$TAG Disconnecting [${if (direction == Call.Dir.Incoming)"incoming" else "outgoing"}] call with cause [${disconnectCauseToString(disconnectCause)}] because it has ended with reason [$reason]")
try {
callControl.disconnect(DisconnectCause(disconnectCause))
} catch (ise: IllegalArgumentException) {
Log.e("$TAG Couldn't disconnect call control with cause [${disconnectCauseToString(disconnectCause)}]: $ise")
}
}
callEnded()
} else if (state == Call.State.Error) {
val reason = call.reason
scope.launch {
// For some reason DisconnectCause.ERROR or DisconnectCause.BUSY triggers an IllegalArgumentException with following message
// Valid DisconnectCause codes are limited to [DisconnectCause.LOCAL, DisconnectCause.REMOTE, DisconnectCause.MISSED, or DisconnectCause.REJECTED]
val disconnectCause = DisconnectCause.REJECTED
Log.w("$TAG Disconnecting call with cause [${disconnectCauseToString(disconnectCause)}] due to error [$message] and reason [$reason]")
try {
callControl.disconnect(DisconnectCause(disconnectCause))
} catch (ise: IllegalArgumentException) {
Log.e("$TAG Couldn't disconnect call control with cause [${disconnectCauseToString(disconnectCause)}]: $ise")
}
}
callError(message)
} else if (state == Call.State.Pausing) {
scope.launch {
Log.i("$TAG Pausing call")
@ -144,6 +112,17 @@ class TelecomCallControlCallback(
"$TAG Callback have been set for call, Telecom call ID is [${callControl.getCallId()}]"
)
coreContext.postOnCoreThread {
val state = call.state
Log.i("$TAG Call state currently is [$state]")
when (state) {
Call.State.End -> callEnded()
Call.State.Error -> callError("")
Call.State.Released -> callEnded()
else -> {} // doing nothing
}
}
callControl.availableEndpoints.onEach { list ->
Log.i("$TAG New available audio endpoints list")
if (availableEndpoints != list) {
@ -303,6 +282,46 @@ class TelecomCallControlCallback(
return false
}
private fun callEnded() {
val reason = call.reason
val direction = call.dir
scope.launch {
val disconnectCause = when (reason) {
Reason.NotAnswered -> DisconnectCause.REMOTE
Reason.Declined -> DisconnectCause.REJECTED
Reason.Busy -> {
if (direction == Call.Dir.Incoming) {
DisconnectCause.MISSED
} else {
DisconnectCause.BUSY
}
}
else -> DisconnectCause.LOCAL
}
Log.i("$TAG Disconnecting [${if (direction == Call.Dir.Incoming)"incoming" else "outgoing"}] call with cause [${disconnectCauseToString(disconnectCause)}] because it has ended with reason [$reason]")
try {
callControl.disconnect(DisconnectCause(disconnectCause))
} catch (ise: IllegalArgumentException) {
Log.e("$TAG Couldn't disconnect call control with cause [${disconnectCauseToString(disconnectCause)}]: $ise")
}
}
}
private fun callError(message: String) {
val reason = call.reason
scope.launch {
// For some reason DisconnectCause.ERROR or DisconnectCause.BUSY triggers an IllegalArgumentException with following message
// Valid DisconnectCause codes are limited to [DisconnectCause.LOCAL, DisconnectCause.REMOTE, DisconnectCause.MISSED, or DisconnectCause.REJECTED]
val disconnectCause = DisconnectCause.REJECTED
Log.w("$TAG Disconnecting call with cause [${disconnectCauseToString(disconnectCause)}] due to error [$message] and reason [$reason]")
try {
callControl.disconnect(DisconnectCause(disconnectCause))
} catch (ise: IllegalArgumentException) {
Log.e("$TAG Couldn't disconnect call control with cause [${disconnectCauseToString(disconnectCause)}]: $ise")
}
}
}
private fun disconnectCauseToString(cause: Int): String {
return when (cause) {
DisconnectCause.UNKNOWN -> "UNKNOWN"