From 97296ca7d7e3c7af0043ce782d4f56162ba76e27 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Thu, 15 Apr 2021 15:08:27 -0400 Subject: [PATCH] Fix bugs with preference and lock state changes. --- .../ApplicationDependencyProvider.java | 2 +- .../NotificationCancellationHelper.java | 26 +++++++++++++++++++ .../OptimizedMessageNotifier.java | 5 ++-- .../notifications/v2/MessageNotifierV2.kt | 14 +++++++++- .../notifications/v2/NotificationBuilder.kt | 16 +++++------- .../v2/NotificationConversation.kt | 7 ++++- .../notifications/v2/NotificationFactory.kt | 11 +++++--- .../notifications/v2/NotificationItemV2.kt | 2 +- 8 files changed, 63 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java index ffa7f01fb..d29fec5f7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java @@ -186,7 +186,7 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr @Override public @NonNull MessageNotifier provideMessageNotifier() { - return new OptimizedMessageNotifier(); + return new OptimizedMessageNotifier(context); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCancellationHelper.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCancellationHelper.java index 9575eb54b..ab04f95db 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCancellationHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationCancellationHelper.java @@ -72,6 +72,32 @@ public final class NotificationCancellationHelper { } } + public static void cancelMessageSummaryIfSoleNotification(@NonNull Context context) { + if (Build.VERSION.SDK_INT >= 23) { + try { + NotificationManager notifications = ServiceUtil.getNotificationManager(context); + StatusBarNotification[] activeNotifications = notifications.getActiveNotifications(); + boolean soleMessageSummary = false; + + for (StatusBarNotification activeNotification : activeNotifications) { + if (isSingleThreadNotification(activeNotification)) { + soleMessageSummary = false; + break; + } else if (activeNotification.getId() == NotificationIds.MESSAGE_SUMMARY) { + soleMessageSummary = true; + } + } + + if (soleMessageSummary) { + Log.d(TAG, "Cancelling sole message summary"); + cancelLegacy(context, NotificationIds.MESSAGE_SUMMARY); + } + } catch (Throwable e) { + Log.w(TAG, e); + } + } + } + /** * @return whether this is a non-summary notification that is a member of the NOTIFICATION_GROUP group. */ diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java index f152806fd..9f85e290c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/OptimizedMessageNotifier.java @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.notifications; +import android.app.Application; import android.content.Context; import android.os.Handler; @@ -25,10 +26,10 @@ public class OptimizedMessageNotifier implements MessageNotifier { private final MessageNotifierV2 messageNotifierV2; @MainThread - public OptimizedMessageNotifier() { + public OptimizedMessageNotifier(@NonNull Application context) { this.limiter = new LeakyBucketLimiter(5, 1000, new Handler(SignalExecutors.getAndStartHandlerThread("signal-notifier").getLooper())); this.messageNotifierV1 = new DefaultMessageNotifier(); - this.messageNotifierV2 = new MessageNotifierV2(); + this.messageNotifierV2 = new MessageNotifierV2(context); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/MessageNotifierV2.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/MessageNotifierV2.kt index 1eb5fc89d..99750c1fb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/MessageNotifierV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/MessageNotifierV2.kt @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.notifications.v2 import android.app.AlarmManager +import android.app.Application import android.app.NotificationManager import android.app.PendingIntent import android.content.Context @@ -20,6 +21,7 @@ import org.thoughtcrime.securesms.notifications.MessageNotifier import org.thoughtcrime.securesms.notifications.MessageNotifier.ReminderReceiver import org.thoughtcrime.securesms.notifications.NotificationCancellationHelper import org.thoughtcrime.securesms.notifications.NotificationIds +import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.util.BubbleUtil.BubbleState @@ -38,11 +40,13 @@ import kotlin.math.max /** * MessageNotifier implementation using the new system for creating and showing notifications. */ -class MessageNotifierV2 : MessageNotifier { +class MessageNotifierV2(context: Application) : MessageNotifier { @Volatile private var visibleThread: Long = -1 @Volatile private var lastDesktopActivityTimestamp: Long = -1 @Volatile private var lastAudibleNotification: Long = -1 @Volatile private var lastScheduledReminder: Long = 0 + @Volatile private var previousLockedStatus: Boolean = KeyCachingService.isLocked(context) + @Volatile private var previousPrivacyPreference: NotificationPrivacyPreference = TextSecurePreferences.getNotificationPrivacy(context) private val threadReminders: MutableMap = ConcurrentHashMap() @@ -120,6 +124,12 @@ class MessageNotifierV2 : MessageNotifier { return } + val currentLockStatus: Boolean = KeyCachingService.isLocked(context) + val currentPrivacyPreference: NotificationPrivacyPreference = TextSecurePreferences.getNotificationPrivacy(context) + val notificationConfigurationChanged: Boolean = currentLockStatus != previousLockedStatus || currentPrivacyPreference != previousPrivacyPreference + previousLockedStatus = currentLockStatus + previousPrivacyPreference = currentPrivacyPreference + val alertOverrides: Set = threadReminders.filter { (_, reminder) -> reminder.lastNotified < System.currentTimeMillis() - REMINDER_TIMEOUT }.keys val threadsThatAlerted: Set = NotificationFactory.notify( @@ -129,6 +139,7 @@ class MessageNotifierV2 : MessageNotifier { targetThreadId = threadId, defaultBubbleState = defaultBubbleState, lastAudibleNotification = lastAudibleNotification, + notificationConfigurationChanged = notificationConfigurationChanged, alertOverrides = alertOverrides ) @@ -241,6 +252,7 @@ class MessageNotifierV2 : MessageNotifier { } } } + NotificationCancellationHelper.cancelMessageSummaryIfSoleNotification(context) } catch (e: Throwable) { Log.w(TAG, e) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationBuilder.kt index 9b8a2dcfe..2fae2a845 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationBuilder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationBuilder.kt @@ -45,6 +45,7 @@ private const val BIG_PICTURE_DIMEN = 500 sealed class NotificationBuilder(protected val context: Context) { private val privacy: NotificationPrivacyPreference = TextSecurePreferences.getNotificationPrivacy(context) + private val isNotLocked: Boolean = !KeyCachingService.isLocked(context) abstract fun setSmallIcon(@DrawableRes drawable: Int) abstract fun setColor(@ColorInt color: Int) @@ -87,7 +88,7 @@ sealed class NotificationBuilder(protected val context: Context) { } fun setShortcutId(shortcutId: String) { - if (privacy.isDisplayContact) { + if (privacy.isDisplayContact && isNotLocked) { setShortcutIdActual(shortcutId) } } @@ -105,18 +106,13 @@ sealed class NotificationBuilder(protected val context: Context) { } fun addReplyActions(conversation: NotificationConversation) { - if (!privacy.isDisplayMessage || - KeyCachingService.isLocked(context) || - !RecipientUtil.isMessageRequestAccepted(context, conversation.recipient) - ) { - return + if (privacy.isDisplayMessage && isNotLocked && RecipientUtil.isMessageRequestAccepted(context, conversation.recipient)) { + addActions(ReplyMethod.forRecipient(context, conversation.recipient), conversation) } - - addActions(ReplyMethod.forRecipient(context, conversation.recipient), conversation) } fun addMarkAsReadAction(state: NotificationStateV2) { - if (privacy.isDisplayMessage) { + if (privacy.isDisplayMessage && isNotLocked) { addMarkAsReadActionActual(state) } } @@ -134,7 +130,7 @@ sealed class NotificationBuilder(protected val context: Context) { } fun setBubbleMetadata(conversation: NotificationConversation, bubbleState: BubbleUtil.BubbleState) { - if (privacy.isDisplayContact) { + if (privacy.isDisplayContact && isNotLocked) { setBubbleMetadataActual(conversation, bubbleState) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationConversation.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationConversation.kt index d2ccc31e1..6cf4120d8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationConversation.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationConversation.kt @@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.notifications.RemoteReplyReceiver import org.thoughtcrime.securesms.notifications.ReplyMethod import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.Util @@ -84,7 +85,11 @@ class NotificationConversation( } fun getSlideBigPictureUri(context: Context): Uri? { - return if (notificationItems.size == 1 && TextSecurePreferences.getNotificationPrivacy(context).isDisplayMessage) mostRecentNotification.getBigPictureUri() else null + return if (notificationItems.size == 1 && TextSecurePreferences.getNotificationPrivacy(context).isDisplayMessage && !KeyCachingService.isLocked(context)) { + mostRecentNotification.getBigPictureUri() + } else { + null + } } fun getContentText(context: Context): CharSequence? { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationFactory.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationFactory.kt index a85c9cbd4..ec76d5107 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationFactory.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationFactory.kt @@ -44,6 +44,7 @@ object NotificationFactory { targetThreadId: Long, defaultBubbleState: BubbleUtil.BubbleState, lastAudibleNotification: Long, + notificationConfigurationChanged: Boolean, alertOverrides: Set ): Set { if (state.isEmpty) { @@ -57,7 +58,7 @@ object NotificationFactory { if (conversation.threadId == visibleThreadId && conversation.hasNewNotifications()) { Log.internal().i(TAG, "Thread is visible, notifying in thread. notificationId: ${conversation.notificationId}") notifyInThread(context, conversation.recipient, lastAudibleNotification) - } else if (conversation.hasNewNotifications() || alertOverrides.contains(conversation.threadId)) { + } else if (notificationConfigurationChanged || conversation.hasNewNotifications() || alertOverrides.contains(conversation.threadId)) { if (conversation.hasNewNotifications()) { threadsThatNewlyAlerted += conversation.threadId @@ -67,7 +68,8 @@ object NotificationFactory { context = context, conversation = conversation, targetThreadId = targetThreadId, - defaultBubbleState = defaultBubbleState + defaultBubbleState = defaultBubbleState, + shouldAlert = conversation.hasNewNotifications() || alertOverrides.contains(conversation.threadId) ) } } @@ -112,7 +114,8 @@ object NotificationFactory { context: Context, conversation: NotificationConversation, targetThreadId: Long, - defaultBubbleState: BubbleUtil.BubbleState + defaultBubbleState: BubbleUtil.BubbleState, + shouldAlert: Boolean ) { val builder: NotificationBuilder = NotificationBuilder.create(context) @@ -135,7 +138,7 @@ object NotificationFactory { setSortKey(conversation.sortKey.toString()) setWhen(conversation) addReplyActions(conversation) - setOnlyAlertOnce(false) + setOnlyAlertOnce(!shouldAlert) addMessages(conversation) setPriority(TextSecurePreferences.getNotificationPriority(context)) setLights() diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationItemV2.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationItemV2.kt index f97eca720..2ed51f3c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationItemV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/v2/NotificationItemV2.kt @@ -195,7 +195,7 @@ class MessageNotification(threadRecipient: Recipient, record: MessageRecord) : N } override fun getThumbnailInfo(context: Context): ThumbnailInfo { - return if (TextSecurePreferences.getNotificationPrivacy(context).isDisplayMessage) { + return if (TextSecurePreferences.getNotificationPrivacy(context).isDisplayMessage && !KeyCachingService.isLocked(context)) { val thumbnailSlide: Slide? = slideDeck?.thumbnailSlide ThumbnailInfo(thumbnailSlide?.publicUri, thumbnailSlide?.contentType) } else {