From 14565b08644e3c6c2ba177187a26e6ce6c308cda Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Tue, 13 Jul 2021 19:33:42 -0400 Subject: [PATCH] Fix crash when building notification state for messages without threads. --- .../securesms/database/DatabaseFactory.java | 2 ++ .../database/helpers/SQLCipherOpenHelper.java | 9 ++++++- .../v2/NotificationStateProvider.kt | 26 ++++++++++--------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java index 2fa8a94ce..8e08e377f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java @@ -208,6 +208,8 @@ public class DatabaseFactory { synchronized (lock) { getInstance(context).databaseHelper.onUpgrade(database, database.getVersion(), -1); getInstance(context).databaseHelper.markCurrent(database); + getInstance(context).sms.deleteAbandonedMessages(); + getInstance(context).mms.deleteAbandonedMessages(); getInstance(context).mms.trimEntriesForExpiredMessages(); getInstance(context).getRawDatabase().rawExecSQL("DROP TABLE IF EXISTS key_value"); getInstance(context).getRawDatabase().rawExecSQL("DROP TABLE IF EXISTS megaphone"); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 9772118ac..84056e375 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -202,8 +202,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab private static final int MESSAGE_DUPE_INDEX = 104; private static final int MESSAGE_LOG = 105; private static final int MESSAGE_LOG_2 = 106; + private static final int ABANDONED_MESSAGE_CLEANUP = 107; - private static final int DATABASE_VERSION = 106; + private static final int DATABASE_VERSION = 107; private static final String DATABASE_NAME = "signal.db"; private final Context context; @@ -1635,6 +1636,12 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab db.execSQL("CREATE TRIGGER msl_attachment_delete AFTER DELETE ON part BEGIN DELETE FROM msl_payload WHERE _id IN (SELECT payload_id FROM msl_message WHERE message_id = old.mid AND is_mms = 1); END"); } + if (oldVersion < ABANDONED_MESSAGE_CLEANUP) { + int smsDeleteCount = db.delete("sms", "thread_id NOT IN (SELECT _id FROM thread)", null); + int mmsDeleteCount = db.delete("mms", "thread_id NOT IN (SELECT _id FROM thread)", null); + Log.i(TAG, "Deleted " + smsDeleteCount + " sms and " + mmsDeleteCount + " mms"); + } + db.setTransactionSuccessful(); } finally { db.endTransaction(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationStateProvider.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationStateProvider.kt index 6e9428e4a..5b0551bda 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationStateProvider.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationStateProvider.kt @@ -28,15 +28,18 @@ object NotificationStateProvider { MmsSmsDatabase.readerFor(unreadMessages).use { reader -> var record: MessageRecord? = reader.next while (record != null) { - messages += NotificationMessage( - messageRecord = record, - threadRecipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(record.threadId)?.resolve() ?: Recipient.UNKNOWN, - threadId = record.threadId, - stickyThread = stickyThreads.containsKey(record.threadId), - isUnreadMessage = CursorUtil.requireInt(unreadMessages, MmsSmsColumns.READ) == 0, - hasUnreadReactions = CursorUtil.requireInt(unreadMessages, MmsSmsColumns.REACTIONS_UNREAD) == 1, - lastReactionRead = CursorUtil.requireLong(unreadMessages, MmsSmsColumns.REACTIONS_LAST_SEEN) - ) + val threadRecipient: Recipient? = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(record.threadId) + if (threadRecipient != null) { + messages += NotificationMessage( + messageRecord = record, + threadRecipient = threadRecipient, + threadId = record.threadId, + stickyThread = stickyThreads.containsKey(record.threadId), + isUnreadMessage = CursorUtil.requireInt(unreadMessages, MmsSmsColumns.READ) == 0, + hasUnreadReactions = CursorUtil.requireInt(unreadMessages, MmsSmsColumns.REACTIONS_UNREAD) == 1, + lastReactionRead = CursorUtil.requireLong(unreadMessages, MmsSmsColumns.REACTIONS_LAST_SEEN) + ) + } record = reader.next } } @@ -82,14 +85,13 @@ object NotificationStateProvider { val lastReactionRead: Long ) { private val isUnreadIncoming: Boolean = isUnreadMessage && !messageRecord.isOutgoing - private val unknownOrNotMutedThread: Boolean = threadRecipient == Recipient.UNKNOWN || threadRecipient.isNotMuted fun includeMessage(): Boolean { - return (isUnreadIncoming || stickyThread) && (unknownOrNotMutedThread || (threadRecipient.isAlwaysNotifyMentions && messageRecord.hasSelfMention())) + return (isUnreadIncoming || stickyThread) && (threadRecipient.isNotMuted || (threadRecipient.isAlwaysNotifyMentions && messageRecord.hasSelfMention())) } fun includeReaction(reaction: ReactionRecord): Boolean { - return reaction.author != Recipient.self().id && messageRecord.isOutgoing && reaction.dateReceived > lastReactionRead && unknownOrNotMutedThread + return reaction.author != Recipient.self().id && messageRecord.isOutgoing && reaction.dateReceived > lastReactionRead && threadRecipient.isNotMuted } private val Recipient.isNotMuted: Boolean