Skip to content

Commit

Permalink
feat: open ongoing call screen when answering an incoming call (WPB-1…
Browse files Browse the repository at this point in the history
…5555) (#3875)
  • Loading branch information
ohassine authored Feb 21, 2025
1 parent e942709 commit f017b0f
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.jetbrains.annotations.VisibleForTesting
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

Expand Down Expand Up @@ -143,12 +142,6 @@ class CallNotificationManager @Inject constructor(

private fun StatusBarNotification.hideIncomingCallNotification() {
appLogger.i("$TAG: hiding incoming call")

// This delay is just so when the user receives two calling signals one straight after the other [INCOMING -> CANCEL]
// Due to the signals being one after the other we are creating a notification when we are trying to cancel it, it wasn't
// properly cancelling vibration as probably when we were cancelling, the vibration object was still being created and started
// and thus never stopped.
TimeUnit.MILLISECONDS.sleep(CANCEL_CALL_NOTIFICATION_DELAY)
notificationManager.cancel(tag, id)
}

Expand All @@ -167,7 +160,6 @@ class CallNotificationManager @Inject constructor(

companion object {
private const val TAG = "CallNotificationManager"
private const val CANCEL_CALL_NOTIFICATION_DELAY = 300L

@VisibleForTesting
internal const val DEBOUNCE_TIME = 200L
Expand Down Expand Up @@ -278,7 +270,7 @@ class CallNotificationBuilder @Inject constructor(
)
)
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
.setContentIntent(openOngoingCallPendingIntent(context, conversationIdString))
.setContentIntent(openOngoingCallPendingIntent(context, conversationIdString, userIdString))
.build()
}

Expand Down Expand Up @@ -330,8 +322,6 @@ class CallNotificationBuilder @Inject constructor(

data class IncomingCallsForUser(val userId: UserId, val userName: String, val incomingCalls: List<Call>)

data class CallNotificationIds(val userIdString: String, val conversationIdString: String)

data class CallNotificationData(
val userId: QualifiedID,
val userName: String,
Expand Down
45 changes: 23 additions & 22 deletions app/src/main/kotlin/com/wire/android/notification/PendingIntents.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import com.wire.android.notification.broadcastreceivers.StopAudioMessageReceiver
import com.wire.android.ui.WireActivity
import com.wire.android.ui.calling.CallActivity.Companion.EXTRA_CONVERSATION_ID
import com.wire.android.ui.calling.CallActivity.Companion.EXTRA_SCREEN_TYPE
import com.wire.android.ui.calling.CallActivity.Companion.EXTRA_SHOULD_ANSWER_CALL
import com.wire.android.ui.calling.CallActivity.Companion.EXTRA_USER_ID
import com.wire.android.ui.calling.StartingCallActivity
import com.wire.android.ui.calling.StartingCallScreenType
import com.wire.android.ui.calling.getIncomingCallIntent
Expand Down Expand Up @@ -80,10 +82,6 @@ fun otherUserProfilePendingIntent(context: Context, destinationUserId: String, u
)
}

// TODO
fun callMessagePendingIntent(context: Context, conversationId: String, userId: String?): PendingIntent =
messagePendingIntent(context, conversationId, userId)

fun summaryMessagePendingIntent(context: Context): PendingIntent = openAppPendingIntent(context)

fun replyMessagePendingIntent(context: Context, conversationId: String, userId: String?): PendingIntent = PendingIntent.getBroadcast(
Expand All @@ -93,9 +91,13 @@ fun replyMessagePendingIntent(context: Context, conversationId: String, userId:
PendingIntent.FLAG_MUTABLE
)

fun openOngoingCallPendingIntent(context: Context, conversationId: String): PendingIntent {
val intent = openOngoingCallIntent(context, conversationId)

fun openOngoingCallPendingIntent(
context: Context,
conversationId: String,
userId: String,
shouldAnswerCall: Boolean = false
): PendingIntent {
val intent = ongoingCallIntent(context, conversationId, userId, shouldAnswerCall)
return PendingIntent.getActivity(
context.applicationContext,
OPEN_ONGOING_CALL_REQUEST_CODE,
Expand Down Expand Up @@ -140,21 +142,15 @@ fun answerCallPendingIntent(context: Context, conversationId: String, userId: St
} != null
val shouldAnswerCallFromNotificationButton = !isAlreadyHavingACall &&
(ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)
if (shouldAnswerCallFromNotificationButton) {
val intent = IncomingCallActionReceiver.newIntent(
return if (shouldAnswerCallFromNotificationButton) {
openOngoingCallPendingIntent(
context = context,
conversationId = conversationId,
userId = userId,
action = IncomingCallActionReceiver.ACTION_ANSWER_CALL
)
return PendingIntent.getBroadcast(
context.applicationContext,
getRequestCode(ANSWER_CALL_REQUEST_CODE, userId, conversationId),
intent,
PendingIntent.FLAG_IMMUTABLE
shouldAnswerCall = true
)
} else {
return fullScreenIncomingCallPendingIntent(context, conversationId, userId)
fullScreenIncomingCallPendingIntent(context, conversationId, userId)
}
}

Expand Down Expand Up @@ -186,10 +182,16 @@ private fun openOutgoingCallIntent(context: Context, conversationId: String) =
putExtra(EXTRA_SCREEN_TYPE, StartingCallScreenType.Outgoing.name)
}

private fun openOngoingCallIntent(context: Context, conversationId: String) =
Intent(context.applicationContext, OngoingCallActivity::class.java).apply {
putExtra(EXTRA_CONVERSATION_ID, conversationId)
}
private fun ongoingCallIntent(
context: Context,
conversationId: String,
userId: String,
shouldAnswerCall: Boolean
) = Intent(context.applicationContext, OngoingCallActivity::class.java).apply {
putExtra(EXTRA_CONVERSATION_ID, conversationId)
putExtra(EXTRA_USER_ID, userId)
putExtra(EXTRA_SHOULD_ANSWER_CALL, shouldAnswerCall)
}

private fun openMigrationLoginIntent(context: Context, userHandle: String) =
Intent(context.applicationContext, WireActivity::class.java).apply {
Expand Down Expand Up @@ -246,7 +248,6 @@ fun stopAudioPendingIntent(context: Context): PendingIntent {

private const val MESSAGE_NOTIFICATIONS_SUMMARY_REQUEST_CODE = 0
private const val DECLINE_CALL_REQUEST_CODE = "decline_call_"
private const val ANSWER_CALL_REQUEST_CODE = "answer_call_"
private const val FULL_SCREEN_REQUEST_CODE = "incoming_call_"
private const val OPEN_ONGOING_CALL_REQUEST_CODE = 4
private const val OPEN_MIGRATION_LOGIN_REQUEST_CODE = 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import com.wire.android.di.ApplicationScope
import com.wire.android.di.KaliumCoreLogic
import com.wire.android.di.NoSession
import com.wire.android.notification.CallNotificationManager
import com.wire.android.services.ServicesManager
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.kalium.logger.obfuscateId
import com.wire.kalium.logic.CoreLogic
Expand Down Expand Up @@ -60,9 +59,6 @@ class IncomingCallActionReceiver : BroadcastReceiver() {
@Inject
lateinit var callNotificationManager: CallNotificationManager

@Inject
lateinit var servicesManager: ServicesManager

@Suppress("ReturnCount")
override fun onReceive(context: Context, intent: Intent) {
val conversationIdString: String = intent.getStringExtra(EXTRA_CONVERSATION_ID) ?: run {
Expand All @@ -82,9 +78,8 @@ class IncomingCallActionReceiver : BroadcastReceiver() {
coroutineScope.launch(Dispatchers.Default) {
with(coreLogic.getSessionScope(userId)) {
val conversationId = qualifiedIdMapper.fromStringToQualifiedID(conversationIdString)
when (action) {
ACTION_DECLINE_CALL -> calls.rejectCall(conversationId)
ACTION_ANSWER_CALL -> servicesManager.startCallServiceToAnswer(userId, conversationId)
if (action == ACTION_DECLINE_CALL) {
calls.rejectCall(conversationId)
}
}
callNotificationManager.hideIncomingCallNotification(userId.toString(), conversationIdString)
Expand All @@ -97,18 +92,16 @@ class IncomingCallActionReceiver : BroadcastReceiver() {
private const val EXTRA_ACTION = "action_extra"

const val ACTION_DECLINE_CALL = "action_decline_call"
const val ACTION_ANSWER_CALL = "action_answer_call"

fun newIntent(
context: Context,
conversationId: String,
userId: String,
action: String
): Intent =
Intent(context, IncomingCallActionReceiver::class.java).apply {
putExtra(EXTRA_CONVERSATION_ID, conversationId)
putExtra(EXTRA_RECEIVER_USER_ID, userId)
putExtra(EXTRA_ACTION, action)
}
): Intent = Intent(context, IncomingCallActionReceiver::class.java).apply {
putExtra(EXTRA_CONVERSATION_ID, conversationId)
putExtra(EXTRA_RECEIVER_USER_ID, userId)
putExtra(EXTRA_ACTION, action)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ abstract class CallActivity : AppCompatActivity() {
const val EXTRA_CONVERSATION_ID = "conversation_id"
const val EXTRA_USER_ID = "user_id"
const val EXTRA_SCREEN_TYPE = "screen_type"
const val EXTRA_SHOULD_ANSWER_CALL = "should_answer_call"
}

private val callActivityViewModel: CallActivityViewModel by viewModels()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ import androidx.compose.ui.semantics.testTagsAsResourceId
import com.wire.android.R
import com.wire.android.appLogger
import com.wire.android.navigation.style.TransitionAnimationType
import com.wire.android.notification.CallNotificationManager
import com.wire.android.notification.endOngoingCallPendingIntent
import com.wire.android.services.ServicesManager
import com.wire.android.ui.LocalActivity
import com.wire.android.ui.calling.CallActivity
import com.wire.android.ui.calling.CallActivity.Companion.EXTRA_CONVERSATION_ID
Expand All @@ -69,12 +71,20 @@ class OngoingCallActivity : CallActivity() {
@Inject
lateinit var proximitySensorManager: ProximitySensorManager

@Inject
lateinit var servicesManager: ServicesManager

@Inject
lateinit var callNotificationManager: CallNotificationManager

var conversationId: String? by mutableStateOf(null)
var userId: String? by mutableStateOf(null)
private var shouldAnswerCall: Boolean by mutableStateOf(false)

private fun handleNewIntent(intent: Intent) {
conversationId = intent.extras?.getString(EXTRA_CONVERSATION_ID)
userId = intent.extras?.getString(EXTRA_USER_ID)
shouldAnswerCall = intent.extras?.getBoolean(EXTRA_SHOULD_ANSWER_CALL) ?: false
switchAccountIfNeeded(userId)
}

Expand All @@ -94,6 +104,14 @@ class OngoingCallActivity : CallActivity() {

handleNewIntent(intent)

if (shouldAnswerCall && userId != null && conversationId != null) {
callNotificationManager.hideIncomingCallNotification(userId!!, conversationId!!)
servicesManager.startCallServiceToAnswer(
qualifiedIdMapper.fromStringToQualifiedID(userId!!),
qualifiedIdMapper.fromStringToQualifiedID(conversationId!!),
)
}

appLogger.i("$TAG Initializing proximity sensor..")
proximitySensorManager.initialize()

Expand Down

0 comments on commit f017b0f

Please sign in to comment.