From d81182633dcd8e6c898fd0205d5bcda8c4e5a041 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 24 Sep 2024 10:23:10 -0400 Subject: [PATCH] Fix group call update backup import/export. --- .../database/CallLinkTableBackupExtensions.kt | 4 +- .../v2/database/ChatItemExportIterator.kt | 214 +++++++++--------- .../v2/database/ChatItemImportInserter.kt | 27 ++- 3 files changed, 128 insertions(+), 117 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallLinkTableBackupExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallLinkTableBackupExtensions.kt index 9af0f228ee..fdf2dbe61d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallLinkTableBackupExtensions.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/CallLinkTableBackupExtensions.kt @@ -76,7 +76,9 @@ class BackupCallLinkIterator(private val cursor: Cursor) : Iterator { - ChatUpdateMessage( - individualCall = IndividualCall( - type = IndividualCall.Type.AUDIO_CALL, - state = IndividualCall.State.MISSED, - direction = IndividualCall.Direction.INCOMING - ) + if (call != null) { + return call.toCallUpdate(this) + } + + return when { + MessageTypes.isMissedAudioCall(this.type) -> { + ChatUpdateMessage( + individualCall = IndividualCall( + type = IndividualCall.Type.AUDIO_CALL, + state = IndividualCall.State.MISSED, + direction = IndividualCall.Direction.INCOMING ) - } - MessageTypes.isMissedVideoCall(this.type) -> { - ChatUpdateMessage( - individualCall = IndividualCall( - type = IndividualCall.Type.VIDEO_CALL, - state = IndividualCall.State.MISSED, - direction = IndividualCall.Direction.INCOMING - ) + ) + } + MessageTypes.isMissedVideoCall(this.type) -> { + ChatUpdateMessage( + individualCall = IndividualCall( + type = IndividualCall.Type.VIDEO_CALL, + state = IndividualCall.State.MISSED, + direction = IndividualCall.Direction.INCOMING ) - } - MessageTypes.isIncomingAudioCall(this.type) -> { - ChatUpdateMessage( - individualCall = IndividualCall( - type = IndividualCall.Type.AUDIO_CALL, - state = IndividualCall.State.ACCEPTED, - direction = IndividualCall.Direction.INCOMING - ) + ) + } + MessageTypes.isIncomingAudioCall(this.type) -> { + ChatUpdateMessage( + individualCall = IndividualCall( + type = IndividualCall.Type.AUDIO_CALL, + state = IndividualCall.State.ACCEPTED, + direction = IndividualCall.Direction.INCOMING ) - } - MessageTypes.isIncomingVideoCall(this.type) -> { - ChatUpdateMessage( - individualCall = IndividualCall( - type = IndividualCall.Type.VIDEO_CALL, - state = IndividualCall.State.ACCEPTED, - direction = IndividualCall.Direction.INCOMING - ) + ) + } + MessageTypes.isIncomingVideoCall(this.type) -> { + ChatUpdateMessage( + individualCall = IndividualCall( + type = IndividualCall.Type.VIDEO_CALL, + state = IndividualCall.State.ACCEPTED, + direction = IndividualCall.Direction.INCOMING ) - } - MessageTypes.isOutgoingAudioCall(this.type) -> { - ChatUpdateMessage( - individualCall = IndividualCall( - type = IndividualCall.Type.AUDIO_CALL, - state = IndividualCall.State.ACCEPTED, - direction = IndividualCall.Direction.OUTGOING - ) + ) + } + MessageTypes.isOutgoingAudioCall(this.type) -> { + ChatUpdateMessage( + individualCall = IndividualCall( + type = IndividualCall.Type.AUDIO_CALL, + state = IndividualCall.State.ACCEPTED, + direction = IndividualCall.Direction.OUTGOING ) - } - MessageTypes.isOutgoingVideoCall(this.type) -> { - ChatUpdateMessage( - individualCall = IndividualCall( - type = IndividualCall.Type.VIDEO_CALL, - state = IndividualCall.State.ACCEPTED, - direction = IndividualCall.Direction.OUTGOING - ) + ) + } + MessageTypes.isOutgoingVideoCall(this.type) -> { + ChatUpdateMessage( + individualCall = IndividualCall( + type = IndividualCall.Type.VIDEO_CALL, + state = IndividualCall.State.ACCEPTED, + direction = IndividualCall.Direction.OUTGOING ) - } - MessageTypes.isGroupCall(this.type) -> { - try { - val groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(this.body) - ChatUpdateMessage( - groupCall = GroupCall( - state = GroupCall.State.GENERIC, - startedCallRecipientId = UuidUtil.parseOrNull(groupCallUpdateDetails.startedCallUuid)?.let { recipients.getByAci(ACI.from(it)).getOrNull()?.toLong() }, - startedCallTimestamp = groupCallUpdateDetails.startedCallTimestamp, - endedCallTimestamp = groupCallUpdateDetails.endedCallTimestamp - ) - ) - } catch (exception: IOException) { - null - } - } - else -> { - null - } + ) + } + else -> { + null } } } - private fun CallTable.Call.toCallUpdate(): ChatUpdateMessage? { - return if (this.type == CallTable.Type.GROUP_CALL) { - ChatUpdateMessage( - groupCall = GroupCall( - callId = this.messageId, - state = when (this.event) { - CallTable.Event.MISSED -> GroupCall.State.MISSED - CallTable.Event.ONGOING -> GroupCall.State.GENERIC - CallTable.Event.ACCEPTED -> GroupCall.State.ACCEPTED - CallTable.Event.NOT_ACCEPTED -> GroupCall.State.GENERIC - CallTable.Event.MISSED_NOTIFICATION_PROFILE -> GroupCall.State.MISSED_NOTIFICATION_PROFILE - CallTable.Event.GENERIC_GROUP_CALL -> GroupCall.State.GENERIC - CallTable.Event.JOINED -> GroupCall.State.JOINED - CallTable.Event.RINGING -> GroupCall.State.RINGING - CallTable.Event.DECLINED -> GroupCall.State.DECLINED - CallTable.Event.OUTGOING_RING -> GroupCall.State.OUTGOING_RING - CallTable.Event.DELETE -> return null - }, - ringerRecipientId = this.ringerRecipient?.toLong(), - startedCallRecipientId = this.ringerRecipient?.toLong(), - startedCallTimestamp = this.timestamp + private fun CallTable.Call.toCallUpdate(messageRecord: BackupMessageRecord): ChatUpdateMessage? { + return when (this.type) { + CallTable.Type.GROUP_CALL -> { + val groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(messageRecord.body) + + ChatUpdateMessage( + groupCall = GroupCall( + callId = this.callId, + state = when (this.event) { + CallTable.Event.MISSED -> GroupCall.State.MISSED + CallTable.Event.ONGOING -> GroupCall.State.GENERIC + CallTable.Event.ACCEPTED -> GroupCall.State.ACCEPTED + CallTable.Event.NOT_ACCEPTED -> GroupCall.State.GENERIC + CallTable.Event.MISSED_NOTIFICATION_PROFILE -> GroupCall.State.MISSED_NOTIFICATION_PROFILE + CallTable.Event.GENERIC_GROUP_CALL -> GroupCall.State.GENERIC + CallTable.Event.JOINED -> GroupCall.State.JOINED + CallTable.Event.RINGING -> GroupCall.State.RINGING + CallTable.Event.DECLINED -> GroupCall.State.DECLINED + CallTable.Event.OUTGOING_RING -> GroupCall.State.OUTGOING_RING + CallTable.Event.DELETE -> return null + }, + ringerRecipientId = this.ringerRecipient?.toLong(), + startedCallRecipientId = ACI.parseOrNull(groupCallUpdateDetails.startedCallUuid)?.let { recipients.getByAci(it).getOrNull()?.toLong() }, + startedCallTimestamp = this.timestamp, + endedCallTimestamp = groupCallUpdateDetails.endedCallTimestamp, + read = messageRecord.read + ) ) - ) - } else if (this.type != CallTable.Type.AD_HOC_CALL) { - ChatUpdateMessage( - individualCall = IndividualCall( - callId = this.callId, - type = if (this.type == CallTable.Type.VIDEO_CALL) IndividualCall.Type.VIDEO_CALL else IndividualCall.Type.AUDIO_CALL, - direction = if (this.direction == CallTable.Direction.INCOMING) IndividualCall.Direction.INCOMING else IndividualCall.Direction.OUTGOING, - state = when (this.event) { - CallTable.Event.MISSED -> IndividualCall.State.MISSED - CallTable.Event.MISSED_NOTIFICATION_PROFILE -> IndividualCall.State.MISSED_NOTIFICATION_PROFILE - CallTable.Event.ACCEPTED -> IndividualCall.State.ACCEPTED - CallTable.Event.NOT_ACCEPTED -> IndividualCall.State.NOT_ACCEPTED - else -> IndividualCall.State.UNKNOWN_STATE - }, - startedCallTimestamp = this.timestamp + } + + CallTable.Type.AD_HOC_CALL -> { + ChatUpdateMessage( + individualCall = IndividualCall( + callId = this.callId, + type = if (this.type == CallTable.Type.VIDEO_CALL) IndividualCall.Type.VIDEO_CALL else IndividualCall.Type.AUDIO_CALL, + direction = if (this.direction == CallTable.Direction.INCOMING) IndividualCall.Direction.INCOMING else IndividualCall.Direction.OUTGOING, + state = when (this.event) { + CallTable.Event.MISSED -> IndividualCall.State.MISSED + CallTable.Event.MISSED_NOTIFICATION_PROFILE -> IndividualCall.State.MISSED_NOTIFICATION_PROFILE + CallTable.Event.ACCEPTED -> IndividualCall.State.ACCEPTED + CallTable.Event.NOT_ACCEPTED -> IndividualCall.State.NOT_ACCEPTED + else -> IndividualCall.State.UNKNOWN_STATE + }, + startedCallTimestamp = this.timestamp + ) ) - ) - } else { - null + } + + else -> null } } @@ -1074,7 +1067,8 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize: MessageTypes.isReportedSpam(this) || MessageTypes.isMessageRequestAccepted(this) || MessageTypes.isBlocked(this) || - MessageTypes.isUnblocked(this) + MessageTypes.isUnblocked(this) || + MessageTypes.isGroupCall(this) } private fun String.e164ToLong(): Long? { diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt index c82c8e3c14..68dcaf4e60 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt @@ -262,12 +262,15 @@ class ChatItemImportInserter( } } else if (this.updateMessage.groupCall != null && this.updateMessage.groupCall.callId != null) { followUp = { messageRowId -> + val ringer: RecipientId? = this.updateMessage.groupCall.ringerRecipientId?.let { importState.remoteToLocalRecipientId[it] } + val values = contentValuesOf( CallTable.CALL_ID to updateMessage.groupCall.callId, CallTable.MESSAGE_ID to messageRowId, CallTable.PEER to chatRecipientId.serialize(), + CallTable.RINGER to ringer?.serialize(), CallTable.TYPE to CallTable.Type.serialize(CallTable.Type.GROUP_CALL), - CallTable.DIRECTION to CallTable.Direction.serialize(if (importState.remoteToLocalRecipientId[updateMessage.groupCall.ringerRecipientId] == selfId) CallTable.Direction.OUTGOING else CallTable.Direction.INCOMING), + CallTable.DIRECTION to CallTable.Direction.serialize(if (ringer == selfId) CallTable.Direction.OUTGOING else CallTable.Direction.INCOMING), CallTable.EVENT to CallTable.Event.serialize( when (updateMessage.groupCall.state) { GroupCall.State.ACCEPTED -> CallTable.Event.ACCEPTED @@ -673,15 +676,26 @@ class ChatItemImportInserter( } updateMessage.individualCall != null -> { if (updateMessage.individualCall.state == IndividualCall.State.MISSED || updateMessage.individualCall.state == IndividualCall.State.MISSED_NOTIFICATION_PROFILE) { - typeFlags = if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) MessageTypes.MISSED_AUDIO_CALL_TYPE else MessageTypes.MISSED_VIDEO_CALL_TYPE + typeFlags = if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) { + MessageTypes.MISSED_AUDIO_CALL_TYPE + } else { + MessageTypes.MISSED_VIDEO_CALL_TYPE + } } else { typeFlags = if (updateMessage.individualCall.direction == IndividualCall.Direction.OUTGOING) { - if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) MessageTypes.OUTGOING_AUDIO_CALL_TYPE else MessageTypes.OUTGOING_VIDEO_CALL_TYPE + if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) { + MessageTypes.OUTGOING_AUDIO_CALL_TYPE + } else { + MessageTypes.OUTGOING_VIDEO_CALL_TYPE + } } else { - if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) MessageTypes.INCOMING_AUDIO_CALL_TYPE else MessageTypes.INCOMING_VIDEO_CALL_TYPE + if (updateMessage.individualCall.type == IndividualCall.Type.AUDIO_CALL) { + MessageTypes.INCOMING_AUDIO_CALL_TYPE + } else { + MessageTypes.INCOMING_VIDEO_CALL_TYPE + } } } - this.put(MessageTable.TYPE, typeFlags) } updateMessage.groupCall != null -> { val startedCallRecipientId = if (updateMessage.groupCall.startedCallRecipientId != null) { @@ -695,7 +709,8 @@ class ChatItemImportInserter( null } this.put(MessageTable.BODY, GroupCallUpdateDetailsUtil.createBodyFromBackup(updateMessage.groupCall, startedCall)) - this.put(MessageTable.TYPE, MessageTypes.GROUP_CALL_TYPE) + this.put(MessageTable.READ, updateMessage.groupCall.read.toInt()) + typeFlags = MessageTypes.GROUP_CALL_TYPE } updateMessage.groupChange != null -> { put(MessageTable.BODY, "")