Asserted identity: handle if needed and use the data

This commit is contained in:
ganfra 2021-06-01 18:12:10 +02:00
parent 0098d435b3
commit 0eca809b83
6 changed files with 70 additions and 14 deletions

View File

@ -144,6 +144,10 @@ android {
buildConfigField "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy", "outboundSessionKeySharingStrategy", "im.vector.app.features.crypto.keysrequest.OutboundSessionKeySharingStrategy.WhenTyping"
// If set, MSC3086 asserted identity messages sent on VoIP calls will cause the call to appear in the room corresponding to the asserted identity.
// This *must* only be set in trusted environments.
buildConfigField "Boolean", "handleCallAssertedIdentityEvents", "false"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// Keep abiFilter for the universalApk

View File

@ -221,7 +221,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
views.callStatusText.setText(R.string.call_held_by_you)
} else {
views.callActionText.isInvisible = true
state.callInfo.otherUserItem?.let {
state.callInfo?.opponentUserItem?.let {
views.callStatusText.text = getString(R.string.call_held_by_user, it.getBestName())
}
}
@ -255,7 +255,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
}
private fun configureCallInfo(state: VectorCallViewState, blurAvatar: Boolean = false) {
state.callInfo.otherUserItem?.let {
state.callInfo?.opponentUserItem?.let {
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
avatarRenderer.renderBlur(it, views.bgCallView, sampling = 20, rounded = false, colorFilter = colorFilter)
if (state.transferee is VectorCallViewState.TransfereeState.NoTransferee) {
@ -269,13 +269,13 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
avatarRenderer.render(it, views.otherMemberAvatar)
}
}
if (state.otherKnownCallInfo?.otherUserItem == null) {
if (state.otherKnownCallInfo?.opponentUserItem == null) {
views.otherKnownCallLayout.isVisible = false
} else {
val otherCall = callManager.getCallById(state.otherKnownCallInfo.callId)
val colorFilter = ContextCompat.getColor(this, R.color.bg_call_screen)
avatarRenderer.renderBlur(
matrixItem = state.otherKnownCallInfo.otherUserItem,
matrixItem = state.otherKnownCallInfo.opponentUserItem,
imageView = views.otherKnownCallAvatarView,
sampling = 20,
rounded = false,

View File

@ -34,11 +34,13 @@ import im.vector.app.features.call.webrtc.getOpponentAsMatrixItem
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.call.CallState
import org.matrix.android.sdk.api.session.call.MxCall
import org.matrix.android.sdk.api.session.call.MxPeerConnectionState
import org.matrix.android.sdk.api.session.room.model.call.supportCallTransfer
import org.matrix.android.sdk.api.util.MatrixItem
class VectorCallViewModel @AssistedInject constructor(
@Assisted initialState: VectorCallViewState,
@ -87,6 +89,12 @@ class VectorCallViewModel @AssistedInject constructor(
}
}
override fun assertedIdentityChanged(){
setState {
copy(callInfo = call?.extractCallInfo())
}
}
override fun onStateUpdate(call: MxCall) {
val callState = call.state
if (callState is CallState.Connected && callState.iceConnectionState == MxPeerConnectionState.CONNECTED) {
@ -160,8 +168,7 @@ class VectorCallViewModel @AssistedInject constructor(
if (otherCall == null) {
copy(otherKnownCallInfo = null)
} else {
val otherUserItem = otherCall.getOpponentAsMatrixItem(session)
copy(otherKnownCallInfo = VectorCallViewState.CallInfo(otherCall.callId, otherUserItem))
copy(otherKnownCallInfo = otherCall.extractCallInfo())
}
}
}
@ -175,7 +182,6 @@ class VectorCallViewModel @AssistedInject constructor(
} else {
call = webRtcCall
callManager.addCurrentCallListener(currentCallListener)
val item = webRtcCall.getOpponentAsMatrixItem(session)
webRtcCall.addListener(callListener)
val currentSoundDevice = callManager.audioManager.selectedDevice
if (currentSoundDevice == CallAudioManager.Device.PHONE) {
@ -185,7 +191,7 @@ class VectorCallViewModel @AssistedInject constructor(
copy(
isVideoCall = webRtcCall.mxCall.isVideoCall,
callState = Success(webRtcCall.mxCall.state),
callInfo = VectorCallViewState.CallInfo(callId, item),
callInfo = webRtcCall.extractCallInfo(),
device = currentSoundDevice ?: CallAudioManager.Device.PHONE,
isLocalOnHold = webRtcCall.isLocalOnHold,
isRemoteOnHold = webRtcCall.remoteOnHold,
@ -202,6 +208,22 @@ class VectorCallViewModel @AssistedInject constructor(
}
}
private fun WebRtcCall.extractCallInfo(): VectorCallViewState.CallInfo{
val assertedIdentity = this.remoteAssertedIdentity
val matrixItem = if(assertedIdentity != null){
val userId = if (MatrixPatterns.isUserId(assertedIdentity.id)) {
assertedIdentity.id!!
} else {
// Need an id starting with @
"@${assertedIdentity.displayName}"
}
MatrixItem.UserItem(userId,assertedIdentity.displayName, assertedIdentity.avatarUrl)
}else {
getOpponentAsMatrixItem(session)
}
return VectorCallViewState.CallInfo(callId, matrixItem)
}
override fun onCleared() {
callManager.removeCurrentCallListener(currentCallListener)
call?.removeListener(callListener)

View File

@ -20,6 +20,7 @@ import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.call.audio.CallAudioManager
import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.session.call.CallState
import org.matrix.android.sdk.api.util.MatrixItem
@ -39,7 +40,7 @@ data class VectorCallViewState(
val availableDevices: Set<CallAudioManager.Device> = emptySet(),
val callState: Async<CallState> = Uninitialized,
val otherKnownCallInfo: CallInfo? = null,
val callInfo: CallInfo = CallInfo(callId),
val callInfo: CallInfo? = null,
val formattedDuration: String = "",
val canOpponentBeTransferred: Boolean = false,
val transferee: TransfereeState = TransfereeState.NoTransferee
@ -53,7 +54,7 @@ data class VectorCallViewState(
data class CallInfo(
val callId: String,
val otherUserItem: MatrixItem? = null
val opponentUserItem: MatrixItem? = null,
)
constructor(callArgs: CallArgs) : this(

View File

@ -27,6 +27,7 @@ import im.vector.app.features.call.CameraProxy
import im.vector.app.features.call.CameraType
import im.vector.app.features.call.CaptureFormat
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.lookup.sipNativeLookup
import im.vector.app.features.call.utils.asWebRTC
import im.vector.app.features.call.utils.awaitCreateAnswer
import im.vector.app.features.call.utils.awaitCreateOffer
@ -882,10 +883,34 @@ class WebRtcCall(
}
fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
if (callAssertedIdentityContent.assertedIdentity == null) return
remoteAssertedIdentity = callAssertedIdentityContent.assertedIdentity
listeners.forEach {
tryOrNull { it.assertedIdentityChanged() }
sessionScope?.launch(dispatcher) {
val session = sessionProvider.get() ?: return@launch
val newAssertedIdentity = callAssertedIdentityContent.assertedIdentity ?: return@launch
if (newAssertedIdentity.id == null && newAssertedIdentity.displayName == null) {
Timber.v("Asserted identity received with no relevant information, skip")
return@launch
}
remoteAssertedIdentity = newAssertedIdentity
if (newAssertedIdentity.id != null) {
val nativeUserId = session.sipNativeLookup(newAssertedIdentity.id!!).firstOrNull()?.userId
if (nativeUserId != null) {
val resolvedUser = tryOrNull {
session.resolveUser(nativeUserId)
}
if (resolvedUser != null) {
remoteAssertedIdentity = newAssertedIdentity.copy(
id = nativeUserId,
avatarUrl = resolvedUser.avatarUrl,
displayName = resolvedUser.displayName
)
} else {
remoteAssertedIdentity = newAssertedIdentity.copy(id = nativeUserId)
}
}
}
listeners.forEach {
tryOrNull { it.assertedIdentityChanged() }
}
}
}

View File

@ -21,6 +21,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import im.vector.app.ActiveSessionDataSource
import im.vector.app.BuildConfig
import im.vector.app.core.services.CallService
import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.audio.CallAudioManager
@ -423,6 +424,9 @@ class WebRtcCallManager @Inject constructor(
}
override fun onCallAssertedIdentityReceived(callAssertedIdentityContent: CallAssertedIdentityContent) {
if(!BuildConfig.handleCallAssertedIdentityEvents){
return
}
val call = callsByCallId[callAssertedIdentityContent.callId]
?: return Unit.also {
Timber.w("onCallAssertedIdentityReceived for non active call? ${callAssertedIdentityContent.callId}")