From 4979bca7043e771646e341dcb963b7620f949134 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Sun, 16 Mar 2025 18:57:35 +0100 Subject: [PATCH] Prevent system call notification to be stuck if call was ended in Linphone SDK before being added to TelecomManager's --- .../notifications/NotificationsManager.kt | 9 +- .../telecom/TelecomCallControlCallback.kt | 87 +++++++++++-------- 2 files changed, 58 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index e5012898b..3c80ff6cb 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -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) diff --git a/app/src/main/java/org/linphone/telecom/TelecomCallControlCallback.kt b/app/src/main/java/org/linphone/telecom/TelecomCallControlCallback.kt index 6d551839d..b99043b2e 100644 --- a/app/src/main/java/org/linphone/telecom/TelecomCallControlCallback.kt +++ b/app/src/main/java/org/linphone/telecom/TelecomCallControlCallback.kt @@ -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"