Notify of ringing call when there's an active call (#3003)

* Add `CallNotificationEventResolver` to be able to force the new ringing notification to be non-ringing given an existing ringing one.
This commit is contained in:
Jorge Martin Espinosa 2024-06-10 17:03:06 +02:00 committed by GitHub
parent 02d6fa7a92
commit f07ec61ecc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 232 additions and 81 deletions

View file

@ -89,6 +89,7 @@ class DefaultActiveCallManager @Inject constructor(
override fun registerIncomingCall(notificationData: CallNotificationData) {
if (activeCall.value != null) {
displayMissedCallNotification(notificationData)
Timber.w("Already have an active call, ignoring incoming call: $notificationData")
return
}
@ -99,7 +100,6 @@ class DefaultActiveCallManager @Inject constructor(
)
timedOutCallJob = coroutineScope.launch {
registerIncomingCall(notificationData)
showIncomingCallNotification(notificationData)
// Wait for the call to end
@ -115,13 +115,7 @@ class DefaultActiveCallManager @Inject constructor(
cancelIncomingCallNotification()
coroutineScope.launch {
onMissedCallNotificationHandler.addMissedCallNotification(
sessionId = previousActiveCall.sessionId,
roomId = previousActiveCall.roomId,
eventId = notificationData.eventId,
)
}
displayMissedCallNotification(notificationData)
}
override fun hungUpCall() {
@ -174,6 +168,16 @@ class DefaultActiveCallManager @Inject constructor(
private fun cancelIncomingCallNotification() {
notificationManagerCompat.cancel(NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.INCOMING_CALL))
}
private fun displayMissedCallNotification(notificationData: CallNotificationData) {
coroutineScope.launch {
onMissedCallNotificationHandler.addMissedCallNotification(
sessionId = notificationData.sessionId,
roomId = notificationData.roomId,
eventId = notificationData.eventId,
)
}
}
}
/**

View file

@ -27,6 +27,7 @@ import io.element.android.features.call.test.aCallNotificationData
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
import io.element.android.libraries.matrix.test.A_SESSION_ID
@ -39,10 +40,12 @@ import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolde
import io.element.android.libraries.push.test.notifications.FakeOnMissedCallNotificationHandler
import io.element.android.libraries.push.test.notifications.push.FakeNotificationBitmapLoader
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -77,9 +80,14 @@ class DefaultActiveCallManagerTest {
verify { notificationManagerCompat.notify(notificationId, any()) }
}
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `registerIncomingCall - when there is an already active call does nothing`() = runTest {
val manager = createActiveCallManager()
fun `registerIncomingCall - when there is an already active call adds missed call notification`() = runTest {
val addMissedCallNotificationLambda = lambdaRecorder<SessionId, RoomId, EventId, Unit> { _, _, _ -> }
val onMissedCallNotificationHandler = FakeOnMissedCallNotificationHandler(addMissedCallNotificationLambda = addMissedCallNotificationLambda)
val manager = createActiveCallManager(
onMissedCallNotificationHandler = onMissedCallNotificationHandler,
)
// Register existing call
val callNotificationData = aCallNotificationData()
@ -91,6 +99,12 @@ class DefaultActiveCallManagerTest {
assertThat(manager.activeCall.value).isEqualTo(activeCall)
assertThat(manager.activeCall.value?.roomId).isNotEqualTo(A_ROOM_ID_2)
advanceTimeBy(1)
addMissedCallNotificationLambda.assertions()
.isCalledOnce()
.with(value(A_SESSION_ID), value(A_ROOM_ID_2), value(AN_EVENT_ID))
}
@Test
@ -119,12 +133,10 @@ class DefaultActiveCallManagerTest {
assertThat(manager.activeCall.value).isNotNull()
manager.incomingCallTimedOut()
advanceTimeBy(1)
assertThat(manager.activeCall.value).isNull()
runCurrent()
addMissedCallNotificationLambda.assertions().isCalledOnce()
verify { notificationManagerCompat.cancel(notificationId) }
}