Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: open ongoing call screen when answering an incoming call (WPB-15555) #3875

Merged
merged 5 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading