diff options
4 files changed, 162 insertions, 0 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt index 73bac872f0a6..538be142b8f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt @@ -183,6 +183,20 @@ class PulseLowImportanceSuppressor() : override fun shouldSuppress(entry: NotificationEntry) = entry.importance < IMPORTANCE_DEFAULT } +class HunGroupAlertBehaviorSuppressor() : + VisualInterruptionFilter( + types = setOf(PEEK, PULSE), + reason = "suppressive group alert behavior" + ) { + override fun shouldSuppress(entry: NotificationEntry) = + entry.sbn.let { it.isGroup && it.notification.suppressAlertingDueToGrouping() } +} + +class HunJustLaunchedFsiSuppressor() : + VisualInterruptionFilter(types = setOf(PEEK, PULSE), reason = "just launched FSI") { + override fun shouldSuppress(entry: NotificationEntry) = entry.hasJustLaunchedFullScreenIntent() +} + class BubbleNotAllowedSuppressor() : VisualInterruptionFilter(types = setOf(BUBBLE), reason = "not allowed") { override fun shouldSuppress(entry: NotificationEntry) = !entry.canBubble() @@ -196,3 +210,10 @@ class BubbleNoMetadataSuppressor() : override fun shouldSuppress(entry: NotificationEntry) = !isValidMetadata(entry.bubbleMetadata) } + +class AlertKeyguardVisibilitySuppressor( + private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider +) : VisualInterruptionFilter(types = setOf(PEEK, PULSE, BUBBLE), reason = "hidden on keyguard") { + override fun shouldSuppress(entry: NotificationEntry) = + keyguardNotificationVisibilityProvider.shouldHideNotification(entry) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt index b319a74c6292..f0fe56db9fdd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt @@ -41,6 +41,7 @@ constructor( private val batteryController: BatteryController, private val globalSettings: GlobalSettings, private val headsUpManager: HeadsUpManager, + private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider, private val logger: NotificationInterruptLogger, @Main private val mainHandler: Handler, private val powerManager: PowerManager, @@ -67,6 +68,9 @@ constructor( addFilter(PulseLowImportanceSuppressor()) addFilter(BubbleNotAllowedSuppressor()) addFilter(BubbleNoMetadataSuppressor()) + addFilter(HunGroupAlertBehaviorSuppressor()) + addFilter(HunJustLaunchedFsiSuppressor()) + addFilter(AlertKeyguardVisibilitySuppressor(keyguardNotificationVisibilityProvider)) started = true } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt index ff89bdb6dbde..eda65e671676 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt @@ -29,6 +29,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro batteryController, globalSettings, headsUpManager, + keyguardNotificationVisibilityProvider, logger, mainHandler, powerManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt index cedf1eac4d14..35ce027e8c41 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt @@ -20,6 +20,9 @@ import android.app.ActivityManager import android.app.Notification import android.app.Notification.BubbleMetadata import android.app.Notification.FLAG_BUBBLE +import android.app.Notification.GROUP_ALERT_ALL +import android.app.Notification.GROUP_ALERT_CHILDREN +import android.app.Notification.GROUP_ALERT_SUMMARY import android.app.Notification.VISIBILITY_PRIVATE import android.app.NotificationChannel import android.app.NotificationManager.IMPORTANCE_DEFAULT @@ -305,6 +308,110 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { assertShouldNotHeadsUp(buildPulseEntry { importance = IMPORTANCE_LOW }) } + private fun withPeekAndPulseEntry( + extendEntry: EntryBuilder.() -> Unit, + block: (NotificationEntry) -> Unit + ) { + ensurePeekState() + block(buildPeekEntry(extendEntry)) + + ensurePulseState() + block(buildPulseEntry(extendEntry)) + } + + @Test + fun testShouldHeadsUp_groupedSummaryNotif_groupAlertAll() { + withPeekAndPulseEntry({ + isGrouped = true + isGroupSummary = true + groupAlertBehavior = GROUP_ALERT_ALL + }) { + assertShouldHeadsUp(it) + } + } + + @Test + fun testShouldHeadsUp_groupedSummaryNotif_groupAlertSummary() { + withPeekAndPulseEntry({ + isGrouped = true + isGroupSummary = true + groupAlertBehavior = GROUP_ALERT_SUMMARY + }) { + assertShouldHeadsUp(it) + } + } + + @Test + fun testShouldNotHeadsUp_groupedSummaryNotif_groupAlertChildren() { + withPeekAndPulseEntry({ + isGrouped = true + isGroupSummary = true + groupAlertBehavior = GROUP_ALERT_CHILDREN + }) { + assertShouldNotHeadsUp(it) + } + } + + @Test + fun testShouldHeadsUp_ungroupedSummaryNotif_groupAlertChildren() { + withPeekAndPulseEntry({ + isGrouped = false + isGroupSummary = true + groupAlertBehavior = GROUP_ALERT_CHILDREN + }) { + assertShouldHeadsUp(it) + } + } + + @Test + fun testShouldHeadsUp_groupedChildNotif_groupAlertAll() { + withPeekAndPulseEntry({ + isGrouped = true + isGroupSummary = false + groupAlertBehavior = GROUP_ALERT_ALL + }) { + assertShouldHeadsUp(it) + } + } + + @Test + fun testShouldHeadsUp_groupedChildNotif_groupAlertChildren() { + withPeekAndPulseEntry({ + isGrouped = true + isGroupSummary = false + groupAlertBehavior = GROUP_ALERT_CHILDREN + }) { + assertShouldHeadsUp(it) + } + } + + @Test + fun testShouldNotHeadsUp_groupedChildNotif_groupAlertSummary() { + withPeekAndPulseEntry({ + isGrouped = true + isGroupSummary = false + groupAlertBehavior = GROUP_ALERT_SUMMARY + }) { + assertShouldNotHeadsUp(it) + } + } + + @Test + fun testShouldHeadsUp_ungroupedChildNotif_groupAlertSummary() { + withPeekAndPulseEntry({ + isGrouped = false + isGroupSummary = false + groupAlertBehavior = GROUP_ALERT_SUMMARY + }) { + assertShouldHeadsUp(it) + } + } + + @Test + fun testShouldNotHeadsUp_justLaunchedFsi() { + withPeekAndPulseEntry({ hasJustLaunchedFsi = true }) { assertShouldNotHeadsUp(it) } + } + @Test fun testShouldBubble_withIntentAndIcon() { ensureBubbleState() @@ -358,6 +465,18 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { } @Test + fun testShouldNotAlert_hiddenOnKeyguard() { + ensurePeekState({ keyguardShouldHideNotification = true }) + assertShouldNotHeadsUp(buildPeekEntry()) + + ensurePulseState({ keyguardShouldHideNotification = true }) + assertShouldNotHeadsUp(buildPulseEntry()) + + ensureBubbleState({ keyguardShouldHideNotification = true }) + assertShouldNotBubble(buildBubbleEntry()) + } + + @Test fun testShouldFsi_notInteractive() { ensureNotInteractiveFsiState() assertShouldFsi(buildFsiEntry()) @@ -507,6 +626,10 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { var hasBubbleMetadata = false var bubbleIsShortcut = false var bubbleSuppressesNotification: Boolean? = null + var isGrouped = false + var isGroupSummary: Boolean? = null + var groupAlertBehavior: Int? = null + var hasJustLaunchedFsi = false private fun buildBubbleMetadata(): BubbleMetadata { val builder = @@ -544,6 +667,14 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { if (hasBubbleMetadata) { setBubbleMetadata(buildBubbleMetadata()) } + + if (isGrouped) { + setGroup(TEST_GROUP_KEY) + } + + isGroupSummary?.let { setGroupSummary(it) } + + groupAlertBehavior?.let { setGroupAlertBehavior(it) } } .build() .apply { @@ -564,6 +695,10 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() { } .build()!! .also { + if (hasJustLaunchedFsi) { + it.notifyFullScreenIntentLaunched() + } + modifyRanking(it) .apply { suppressedVisualEffects?.let { setSuppressedVisualEffects(it) } @@ -608,3 +743,4 @@ private const val TEST_CHANNEL_ID = "test_channel" private const val TEST_CHANNEL_NAME = "Test Channel" private const val TEST_PACKAGE = "test_package" private const val TEST_TAG = "test_tag" +private const val TEST_GROUP_KEY = "test_group_key" |