diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt index 13b3aca2a88fb..27fe747e6be85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt @@ -70,7 +70,15 @@ class NotificationInterruptLogger @Inject constructor( buffer.log(TAG, DEBUG, { str1 = entry.logKey }, { - "No alerting: snoozed package: $str1" + "No heads up: snoozed package: $str1" + }) + } + + fun logHeadsUpPackageSnoozeBypassedHasFsi(entry: NotificationEntry) { + buffer.log(TAG, DEBUG, { + str1 = entry.logKey + }, { + "Heads up: package snooze bypassed because notification has full-screen intent: $str1" }) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index 9bcf92d63b8f4..afeb72fa9eebd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.interruption; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD; import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR; +import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI; import android.app.Notification; import android.app.NotificationManager; @@ -87,7 +88,10 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD(1236), @UiEvent(doc = "HUN suppressed for old when") - HUN_SUPPRESSED_OLD_WHEN(1237); + HUN_SUPPRESSED_OLD_WHEN(1237), + + @UiEvent(doc = "HUN snooze bypassed for potentially suppressed FSI") + HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI(1269); private final int mId; @@ -409,7 +413,15 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter return false; } - if (isSnoozedPackage(sbn)) { + final boolean isSnoozedPackage = isSnoozedPackage(sbn); + final boolean fsiRequiresKeyguard = mFlags.fullScreenIntentRequiresKeyguard(); + final boolean hasFsi = sbn.getNotification().fullScreenIntent != null; + + // Assume any notification with an FSI is time-sensitive (like an alarm or incoming call) + // and ignore whether HUNs have been snoozed for the package. + final boolean shouldBypassSnooze = fsiRequiresKeyguard && hasFsi; + + if (isSnoozedPackage && !shouldBypassSnooze) { if (log) mLogger.logNoHeadsUpPackageSnoozed(entry); return false; } @@ -447,6 +459,19 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter return false; } } + + if (isSnoozedPackage) { + if (log) { + mLogger.logHeadsUpPackageSnoozeBypassedHasFsi(entry); + final int uid = entry.getSbn().getUid(); + final String packageName = entry.getSbn().getPackageName(); + mUiEventLogger.log(HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI, uid, + packageName); + } + + return true; + } + if (log) mLogger.logHeadsUp(entry); return true; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java index 03af527eb9f32..fbec95bcc874b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java @@ -741,7 +741,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { } @Test - public void testShouldFullScreen_snoozed_occluding_withStrictRules() throws Exception { + public void testShouldNotFullScreen_snoozed_occluding_withStrictRules() throws Exception { when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); when(mPowerManager.isInteractive()).thenReturn(true); @@ -753,16 +753,41 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { when(mKeyguardStateController.isOccluded()).thenReturn(true); assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry)) - .isEqualTo(FullScreenIntentDecision.FSI_KEYGUARD_OCCLUDED); + .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN); assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) - .isTrue(); - verify(mLogger, never()).logNoFullscreen(any(), any()); + .isFalse(); + verify(mLogger).logNoFullscreen(entry, "Expected to HUN"); verify(mLogger, never()).logNoFullscreenWarning(any(), any()); - verify(mLogger).logFullscreen(entry, "Expected not to HUN while keyguard occluded"); + verify(mLogger, never()).logFullscreen(any(), any()); } @Test - public void testShouldFullScreen_snoozed_lockedShade_withStrictRules() throws Exception { + public void testShouldHeadsUp_snoozed_occluding_withStrictRules() throws Exception { + when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); + NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); + when(mPowerManager.isInteractive()).thenReturn(true); + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mDreamManager.isDreaming()).thenReturn(false); + when(mStatusBarStateController.getState()).thenReturn(SHADE); + when(mHeadsUpManager.isSnoozed("a")).thenReturn(true); + when(mKeyguardStateController.isShowing()).thenReturn(true); + when(mKeyguardStateController.isOccluded()).thenReturn(true); + + assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue(); + + verify(mLogger).logHeadsUpPackageSnoozeBypassedHasFsi(entry); + verify(mLogger, never()).logHeadsUp(any()); + + assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1); + UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0); + assertThat(fakeUiEvent.eventId).isEqualTo( + NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI.getId()); + assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid()); + assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName()); + } + + @Test + public void testShouldNotFullScreen_snoozed_lockedShade_withStrictRules() throws Exception { when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); when(mPowerManager.isInteractive()).thenReturn(true); @@ -774,12 +799,37 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { when(mKeyguardStateController.isOccluded()).thenReturn(false); assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry)) - .isEqualTo(FullScreenIntentDecision.FSI_LOCKED_SHADE); + .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN); assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) - .isTrue(); - verify(mLogger, never()).logNoFullscreen(any(), any()); + .isFalse(); + verify(mLogger).logNoFullscreen(entry, "Expected to HUN"); verify(mLogger, never()).logNoFullscreenWarning(any(), any()); - verify(mLogger).logFullscreen(entry, "Keyguard is showing and not occluded"); + verify(mLogger, never()).logFullscreen(any(), any()); + } + + @Test + public void testShouldHeadsUp_snoozed_lockedShade_withStrictRules() throws Exception { + when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); + NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); + when(mPowerManager.isInteractive()).thenReturn(true); + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mDreamManager.isDreaming()).thenReturn(false); + when(mStatusBarStateController.getState()).thenReturn(SHADE_LOCKED); + when(mHeadsUpManager.isSnoozed("a")).thenReturn(true); + when(mKeyguardStateController.isShowing()).thenReturn(true); + when(mKeyguardStateController.isOccluded()).thenReturn(false); + + assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue(); + + verify(mLogger).logHeadsUpPackageSnoozeBypassedHasFsi(entry); + verify(mLogger, never()).logHeadsUp(any()); + + assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1); + UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0); + assertThat(fakeUiEvent.eventId).isEqualTo( + NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI.getId()); + assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid()); + assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName()); } @Test @@ -795,21 +845,41 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { when(mKeyguardStateController.isOccluded()).thenReturn(false); assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry)) - .isEqualTo(FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD); + .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN); assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) .isFalse(); - verify(mLogger, never()).logNoFullscreen(any(), any()); - verify(mLogger).logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard"); + verify(mLogger).logNoFullscreen(entry, "Expected to HUN"); + verify(mLogger, never()).logNoFullscreenWarning(any(), any()); verify(mLogger, never()).logFullscreen(any(), any()); + } + + @Test + public void testShouldHeadsUp_snoozed_unlocked_withStrictRules() throws Exception { + when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true); + NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false); + when(mPowerManager.isInteractive()).thenReturn(true); + when(mPowerManager.isScreenOn()).thenReturn(true); + when(mDreamManager.isDreaming()).thenReturn(false); + when(mStatusBarStateController.getState()).thenReturn(SHADE); + when(mHeadsUpManager.isSnoozed("a")).thenReturn(true); + when(mKeyguardStateController.isShowing()).thenReturn(false); + when(mKeyguardStateController.isOccluded()).thenReturn(false); + + assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue(); + + verify(mLogger).logHeadsUpPackageSnoozeBypassedHasFsi(entry); + verify(mLogger, never()).logHeadsUp(any()); assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1); UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0); assertThat(fakeUiEvent.eventId).isEqualTo( - NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD.getId()); + NotificationInterruptEvent.HUN_SNOOZE_BYPASSED_POTENTIALLY_SUPPRESSED_FSI.getId()); assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid()); assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName()); } + /* TODO: Verify the FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD UiEvent some other way. */ + /** * Bubbles can happen. */