VoIP: add call transfer method

This commit is contained in:
ganfra 2020-12-17 17:05:39 +01:00 committed by ganfra
parent 9c5fe81792
commit 8797d7562d
4 changed files with 44 additions and 5 deletions

View File

@ -89,6 +89,11 @@ interface MxCall : MxCallDetail {
*/ */
fun sendLocalIceCandidateRemovals(candidates: List<CallCandidate>) fun sendLocalIceCandidateRemovals(candidates: List<CallCandidate>)
/**
* Send a m.call.replaces event to initiate call transfer.
*/
suspend fun transfer(targetUserId: String, targetRoomId: String?)
fun addListener(listener: StateListener) fun addListener(listener: StateListener)
fun removeListener(listener: StateListener) fun removeListener(listener: StateListener)

View File

@ -71,11 +71,11 @@ data class CallReplacesContent(
/** /**
* Optional. The display name of the transfer target. * Optional. The display name of the transfer target.
*/ */
@Json(name = "display_name") val displayName: String, @Json(name = "display_name") val displayName: String?,
/** /**
* Optional. The avatar URL of the transfer target. * Optional. The avatar URL of the transfer target.
*/ */
@Json(name = "avatar_url") val avatarUrl: String @Json(name = "avatar_url") val avatarUrl: String?
) )
} }

View File

@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.DeviceId
import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.call.model.MxCallImpl import org.matrix.android.sdk.internal.session.call.model.MxCallImpl
import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
import java.math.BigDecimal import java.math.BigDecimal
@ -35,6 +36,7 @@ internal class MxCallFactory @Inject constructor(
private val localEchoEventFactory: LocalEchoEventFactory, private val localEchoEventFactory: LocalEchoEventFactory,
private val eventSenderProcessor: EventSenderProcessor, private val eventSenderProcessor: EventSenderProcessor,
private val matrixConfiguration: MatrixConfiguration, private val matrixConfiguration: MatrixConfiguration,
private val getProfileInfoTask: GetProfileInfoTask,
@UserId private val userId: String @UserId private val userId: String
) { ) {
@ -50,7 +52,8 @@ internal class MxCallFactory @Inject constructor(
isVideoCall = content.isVideo(), isVideoCall = content.isVideo(),
localEchoEventFactory = localEchoEventFactory, localEchoEventFactory = localEchoEventFactory,
eventSenderProcessor = eventSenderProcessor, eventSenderProcessor = eventSenderProcessor,
matrixConfiguration = matrixConfiguration matrixConfiguration = matrixConfiguration,
getProfileInfoTask = getProfileInfoTask
).apply { ).apply {
opponentPartyId = Optional.from(content.partyId) opponentPartyId = Optional.from(content.partyId)
opponentVersion = content.version?.let { BigDecimal(it).intValueExact() } ?: MxCall.VOIP_PROTO_VERSION opponentVersion = content.version?.let { BigDecimal(it).intValueExact() } ?: MxCall.VOIP_PROTO_VERSION
@ -69,7 +72,8 @@ internal class MxCallFactory @Inject constructor(
isVideoCall = isVideoCall, isVideoCall = isVideoCall,
localEchoEventFactory = localEchoEventFactory, localEchoEventFactory = localEchoEventFactory,
eventSenderProcessor = eventSenderProcessor, eventSenderProcessor = eventSenderProcessor,
matrixConfiguration = matrixConfiguration matrixConfiguration = matrixConfiguration,
getProfileInfoTask = getProfileInfoTask
) )
} }
} }

View File

@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.LocalEcho import org.matrix.android.sdk.api.session.events.model.LocalEcho
import org.matrix.android.sdk.api.session.events.model.UnsignedData import org.matrix.android.sdk.api.session.events.model.UnsignedData
import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.profile.ProfileService
import org.matrix.android.sdk.api.session.room.model.call.CallAnswerContent import org.matrix.android.sdk.api.session.room.model.call.CallAnswerContent
import org.matrix.android.sdk.api.session.room.model.call.CallCandidate import org.matrix.android.sdk.api.session.room.model.call.CallCandidate
import org.matrix.android.sdk.api.session.room.model.call.CallCandidatesContent import org.matrix.android.sdk.api.session.room.model.call.CallCandidatesContent
@ -33,13 +34,16 @@ import org.matrix.android.sdk.api.session.room.model.call.CallHangupContent
import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent
import org.matrix.android.sdk.api.session.room.model.call.CallNegotiateContent import org.matrix.android.sdk.api.session.room.model.call.CallNegotiateContent
import org.matrix.android.sdk.api.session.room.model.call.CallRejectContent import org.matrix.android.sdk.api.session.room.model.call.CallRejectContent
import org.matrix.android.sdk.api.session.room.model.call.CallReplacesContent
import org.matrix.android.sdk.api.session.room.model.call.CallSelectAnswerContent import org.matrix.android.sdk.api.session.room.model.call.CallSelectAnswerContent
import org.matrix.android.sdk.api.session.room.model.call.SdpType import org.matrix.android.sdk.api.session.room.model.call.SdpType
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.internal.session.call.DefaultCallSignalingService import org.matrix.android.sdk.internal.session.call.DefaultCallSignalingService
import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask
import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory import org.matrix.android.sdk.internal.session.room.send.LocalEchoEventFactory
import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
import timber.log.Timber import timber.log.Timber
import java.util.UUID
internal class MxCallImpl( internal class MxCallImpl(
override val callId: String, override val callId: String,
@ -51,7 +55,8 @@ internal class MxCallImpl(
override val ourPartyId: String, override val ourPartyId: String,
private val localEchoEventFactory: LocalEchoEventFactory, private val localEchoEventFactory: LocalEchoEventFactory,
private val eventSenderProcessor: EventSenderProcessor, private val eventSenderProcessor: EventSenderProcessor,
private val matrixConfiguration: MatrixConfiguration private val matrixConfiguration: MatrixConfiguration,
private val getProfileInfoTask: GetProfileInfoTask
) : MxCall { ) : MxCall {
override var opponentPartyId: Optional<String>? = null override var opponentPartyId: Optional<String>? = null
@ -197,6 +202,31 @@ internal class MxCallImpl(
.also { eventSenderProcessor.postEvent(it) } .also { eventSenderProcessor.postEvent(it) }
} }
override suspend fun transfer(targetUserId: String, targetRoomId: String?) {
val profileInfoParams = GetProfileInfoTask.Params(targetUserId)
val profileInfo = try {
getProfileInfoTask.execute(profileInfoParams)
} catch (failure: Throwable) {
Timber.v("Fail fetching profile info of $targetUserId while transferring call")
null
}
CallReplacesContent(
callId = callId,
partyId = ourPartyId,
replacementId = UUID.randomUUID().toString(),
version = MxCall.VOIP_PROTO_VERSION.toString(),
targetUser = CallReplacesContent.TargetUser(
id = targetUserId,
displayName = profileInfo?.get(ProfileService.DISPLAY_NAME_KEY) as? String,
avatarUrl = profileInfo?.get(ProfileService.AVATAR_URL_KEY) as? String
),
targerRoomId = targetRoomId,
createCall = UUID.randomUUID().toString()
)
.let { createEventAndLocalEcho(type = EventType.CALL_REPLACES, roomId = roomId, content = it.toContent()) }
.also { eventSenderProcessor.postEvent(it) }
}
private fun createEventAndLocalEcho(localId: String = LocalEcho.createLocalEchoId(), type: String, roomId: String, content: Content): Event { private fun createEventAndLocalEcho(localId: String = LocalEcho.createLocalEchoId(), type: String, roomId: String, content: Content): Event {
return Event( return Event(
roomId = roomId, roomId = roomId,