Add an enum for decisions about whether to launch FSI.

This change splits shouldLaunchFullScreenIntentWhenAdded into two parts: one that returns the specific decision for whether to launch a full screen intent for an entry, and one that logs that decision.

It also adds a sub-category of "suppressed by DND" called "suppressed only by DND", where DND is the only thing stopping an FSI from launching but all other cases would allow it.

Bug: 248325248
Test: NotificationInterruptStateProviderImplTest

Change-Id: Idd1299312edb58d005e089d89db7921c15c6e2bc
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
index 6cf4bf3..7136cad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -25,6 +25,79 @@
  */
 public interface NotificationInterruptStateProvider {
     /**
+     * Enum representing a decision of whether to show a full screen intent. While many of the
+     * relevant properties could overlap, the decision represents the deciding factor for whether
+     * the full screen intent should or shouldn't launch.
+     */
+    enum FullScreenIntentDecision {
+        /**
+         * No full screen intent included, so there is nothing to show.
+         */
+        NO_FULL_SCREEN_INTENT(false),
+        /**
+         * Suppressed by DND settings.
+         */
+        NO_FSI_SUPPRESSED_BY_DND(false),
+        /**
+         * Full screen intent was suppressed *only* by DND, and if not for DND would have shown. We
+         * track this separately in order to allow the intent to be shown if the DND decision
+         * changes.
+         */
+        NO_FSI_SUPPRESSED_ONLY_BY_DND(false),
+        /**
+         * Notification importance not high enough to show FSI.
+         */
+        NO_FSI_NOT_IMPORTANT_ENOUGH(false),
+        /**
+         * Notification should not FSI due to having suppressive GroupAlertBehavior. This blocks a
+         * potentially malicious use of flags that previously allowed apps to escalate a HUN to an
+         * FSI even while the device was unlocked.
+         */
+        NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false),
+        /**
+         * Device screen is off, so the FSI should launch.
+         */
+        FSI_DEVICE_NOT_INTERACTIVE(true),
+        /**
+         * Device is currently dreaming, so FSI should launch.
+         */
+        FSI_DEVICE_IS_DREAMING(true),
+        /**
+         * Keyguard is showing, so FSI should launch.
+         */
+        FSI_KEYGUARD_SHOWING(true),
+        /**
+         * The notification is expected to show heads-up, so FSI is not needed.
+         */
+        NO_FSI_EXPECTED_TO_HUN(false),
+        /**
+         * The notification is not expected to HUN while the keyguard is occluded, so show FSI.
+         */
+        FSI_KEYGUARD_OCCLUDED(true),
+        /**
+         * The notification is not expected to HUN when the keyguard is showing but not occluded,
+         * which likely means that the shade is showing over the lockscreen; show FSI in this case.
+         */
+        FSI_LOCKED_SHADE(true),
+        /**
+         * FSI requires keyguard to be showing, but there is no keyguard. This is a (potentially
+         * malicious) warning state where we suppress the FSI because the device is in use knowing
+         * that the HUN will probably not display.
+         */
+        NO_FSI_NO_HUN_OR_KEYGUARD(false),
+        /**
+         * No conditions blocking FSI launch.
+         */
+        FSI_EXPECTED_NOT_TO_HUN(true);
+
+        public final boolean shouldLaunch;
+
+        FullScreenIntentDecision(boolean shouldLaunch) {
+            this.shouldLaunch = shouldLaunch;
+        }
+    }
+
+    /**
      * If the device is awake (not dozing):
      *  Whether the notification should peek in from the top and alert the user.
      *
@@ -66,6 +139,27 @@
     boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry);
 
     /**
+     * Whether an entry's full screen intent would be launched.
+     *
+     * This method differs from shouldLaunchFullScreenIntentWhenAdded by returning more information
+     * on the decision, and only optionally logging the outcome. It should be used in cases where
+     * the caller needs to know what the decision would be, but may not actually launch the full
+     * screen intent.
+     *
+     * @param entry the entry to evaluate
+     * @return FullScreenIntentDecision representing the decision for whether to show the intent
+     */
+    FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry);
+
+    /**
+     * Write the full screen launch decision for the given entry to logs.
+     *
+     * @param entry the NotificationEntry for which the decision applies
+     * @param decision reason for launch or no-launch of FSI for entry
+     */
+    void logFullScreenIntentDecision(NotificationEntry entry, FullScreenIntentDecision decision);
+
+    /**
      * Add a component that can suppress visual interruptions.
      */
     void addSuppressor(NotificationInterruptSuppressor suppressor);
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 c4f5a3a..f8ff4d2 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
@@ -207,20 +207,49 @@
      */
     @Override
     public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
-        if (entry.getSbn().getNotification().fullScreenIntent == null) {
-            return false;
+        FullScreenIntentDecision decision = getFullScreenIntentDecision(entry);
+        logFullScreenIntentDecision(entry, decision);
+        return decision.shouldLaunch;
+    }
+
+    // Given whether the relevant entry was suppressed by DND, and the full screen intent launch
+    // decision independent of the DND decision, returns the combined FullScreenIntentDecision that
+    // results. If the entry was suppressed by DND but the decision otherwise would launch the
+    // FSI, then it is suppressed *only* by DND, whereas (because the DND decision happens before
+    // all others) if the entry would not otherwise have launched the FSI, DND is the effective
+    // suppressor.
+    //
+    // If the entry was not suppressed by DND, just returns the given decision.
+    private FullScreenIntentDecision getDecisionGivenSuppression(FullScreenIntentDecision decision,
+            boolean suppressedByDND) {
+        if (suppressedByDND) {
+            return decision.shouldLaunch
+                    ? FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND
+                    : FullScreenIntentDecision.NO_FSI_SUPPRESSED_BY_DND;
         }
+        return decision;
+    }
+
+    @Override
+    public FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry) {
+        if (entry.getSbn().getNotification().fullScreenIntent == null) {
+            return FullScreenIntentDecision.NO_FULL_SCREEN_INTENT;
+        }
+
+        // Boolean indicating whether this FSI would have been suppressed by DND. Because we
+        // want to be able to identify when something would have shown an FSI if not for being
+        // suppressed, we need to keep track of this value for future decisions.
+        boolean suppressedByDND = false;
 
         // Never show FSI when suppressed by DND
         if (entry.shouldSuppressFullScreenIntent()) {
-            mLogger.logNoFullscreen(entry, "Suppressed by DND");
-            return false;
+            suppressedByDND = true;
         }
 
         // Never show FSI if importance is not HIGH
         if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
-            mLogger.logNoFullscreen(entry, "Not important enough");
-            return false;
+            return getDecisionGivenSuppression(FullScreenIntentDecision.NO_FSI_NOT_IMPORTANT_ENOUGH,
+                    suppressedByDND);
         }
 
         // If the notification has suppressive GroupAlertBehavior, block FSI and warn.
@@ -228,36 +257,35 @@
         if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
             // b/231322873: Detect and report an event when a notification has both an FSI and a
             // suppressive groupAlertBehavior, and now correctly block the FSI from firing.
-            final int uid = entry.getSbn().getUid();
-            final String packageName = entry.getSbn().getPackageName();
-            android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "groupAlertBehavior");
-            mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR, uid, packageName);
-            mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
-            return false;
+            return getDecisionGivenSuppression(
+                    FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR,
+                    suppressedByDND);
         }
 
         // If the screen is off, then launch the FullScreenIntent
         if (!mPowerManager.isInteractive()) {
-            mLogger.logFullscreen(entry, "Device is not interactive");
-            return true;
+            return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE,
+                    suppressedByDND);
         }
 
         // If the device is currently dreaming, then launch the FullScreenIntent
         if (isDreaming()) {
-            mLogger.logFullscreen(entry, "Device is dreaming");
-            return true;
+            return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_DEVICE_IS_DREAMING,
+                    suppressedByDND);
         }
 
         // If the keyguard is showing, then launch the FullScreenIntent
         if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
-            mLogger.logFullscreen(entry, "Keyguard is showing");
-            return true;
+            return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_KEYGUARD_SHOWING,
+                    suppressedByDND);
         }
 
         // If the notification should HUN, then we don't need FSI
-        if (shouldHeadsUp(entry)) {
-            mLogger.logNoFullscreen(entry, "Expected to HUN");
-            return false;
+        // Because this is not the heads-up decision-making point, and checking whether it would
+        // HUN, don't log this specific check.
+        if (checkHeadsUp(entry, /* log= */ false)) {
+            return getDecisionGivenSuppression(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN,
+                    suppressedByDND);
         }
 
         // Check whether FSI requires the keyguard to be showing.
@@ -266,27 +294,77 @@
             // If notification won't HUN and keyguard is showing, launch the FSI.
             if (mKeyguardStateController.isShowing()) {
                 if (mKeyguardStateController.isOccluded()) {
-                    mLogger.logFullscreen(entry, "Expected not to HUN while keyguard occluded");
+                    return getDecisionGivenSuppression(
+                            FullScreenIntentDecision.FSI_KEYGUARD_OCCLUDED,
+                            suppressedByDND);
                 } else {
                     // Likely LOCKED_SHADE, but launch FSI anyway
-                    mLogger.logFullscreen(entry, "Keyguard is showing and not occluded");
+                    return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_LOCKED_SHADE,
+                            suppressedByDND);
                 }
-                return true;
             }
 
             // Detect the case determined by b/231322873 to launch FSI while device is in use,
             // as blocked by the correct implementation, and report the event.
-            final int uid = entry.getSbn().getUid();
-            final String packageName = entry.getSbn().getPackageName();
-            android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "no hun or keyguard");
-            mUiEventLogger.log(FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD, uid, packageName);
-            mLogger.logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
-            return false;
+            return getDecisionGivenSuppression(FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD,
+                    suppressedByDND);
         }
 
         // If the notification won't HUN for some other reason (DND/snooze/etc), launch FSI.
-        mLogger.logFullscreen(entry, "Expected not to HUN");
-        return true;
+        return getDecisionGivenSuppression(FullScreenIntentDecision.FSI_EXPECTED_NOT_TO_HUN,
+                suppressedByDND);
+    }
+
+    @Override
+    public void logFullScreenIntentDecision(NotificationEntry entry,
+            FullScreenIntentDecision decision) {
+        final int uid = entry.getSbn().getUid();
+        final String packageName = entry.getSbn().getPackageName();
+        switch (decision) {
+            case NO_FULL_SCREEN_INTENT:
+                return;
+            case NO_FSI_SUPPRESSED_BY_DND:
+            case NO_FSI_SUPPRESSED_ONLY_BY_DND:
+                mLogger.logNoFullscreen(entry, "Suppressed by DND");
+                return;
+            case NO_FSI_NOT_IMPORTANT_ENOUGH:
+                mLogger.logNoFullscreen(entry, "Not important enough");
+                return;
+            case NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR:
+                android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
+                        "groupAlertBehavior");
+                mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR, uid,
+                        packageName);
+                mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
+                return;
+            case FSI_DEVICE_NOT_INTERACTIVE:
+                mLogger.logFullscreen(entry, "Device is not interactive");
+                return;
+            case FSI_DEVICE_IS_DREAMING:
+                mLogger.logFullscreen(entry, "Device is dreaming");
+                return;
+            case FSI_KEYGUARD_SHOWING:
+                mLogger.logFullscreen(entry, "Keyguard is showing");
+                return;
+            case NO_FSI_EXPECTED_TO_HUN:
+                mLogger.logNoFullscreen(entry, "Expected to HUN");
+                return;
+            case FSI_KEYGUARD_OCCLUDED:
+                mLogger.logFullscreen(entry,
+                        "Expected not to HUN while keyguard occluded");
+                return;
+            case FSI_LOCKED_SHADE:
+                mLogger.logFullscreen(entry, "Keyguard is showing and not occluded");
+                return;
+            case NO_FSI_NO_HUN_OR_KEYGUARD:
+                android.util.EventLog.writeEvent(0x534e4554, "231322873", uid,
+                        "no hun or keyguard");
+                mUiEventLogger.log(FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD, uid, packageName);
+                mLogger.logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
+                return;
+            case FSI_EXPECTED_NOT_TO_HUN:
+                mLogger.logFullscreen(entry, "Expected not to HUN");
+        }
     }
 
     private boolean isDreaming() {
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 ea311da..f04de85 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
@@ -22,6 +22,7 @@
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 
 import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
@@ -58,6 +59,7 @@
 import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider.FullScreenIntentDecision;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -403,6 +405,8 @@
         when(mDreamManager.isDreaming()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(SHADE);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FULL_SCREEN_INTENT);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
         verify(mLogger, never()).logNoFullscreen(any(), any());
@@ -411,6 +415,44 @@
     }
 
     @Test
+    public void testShouldNotFullScreen_suppressedOnlyByDND() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+        modifyRanking(entry)
+                .setSuppressedVisualEffects(SUPPRESSED_EFFECT_FULL_SCREEN_INTENT)
+                .build();
+        when(mPowerManager.isInteractive()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FSI_SUPPRESSED_ONLY_BY_DND);
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isFalse();
+        verify(mLogger, never()).logFullscreen(any(), any());
+        verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+        verify(mLogger).logNoFullscreen(entry, "Suppressed by DND");
+    }
+
+    @Test
+    public void testShouldNotFullScreen_suppressedByDNDAndOther() throws RemoteException {
+        NotificationEntry entry = createFsiNotification(IMPORTANCE_LOW, /* silenced */ false);
+        modifyRanking(entry)
+                .setSuppressedVisualEffects(SUPPRESSED_EFFECT_FULL_SCREEN_INTENT)
+                .build();
+        when(mPowerManager.isInteractive()).thenReturn(false);
+        when(mDreamManager.isDreaming()).thenReturn(false);
+        when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FSI_SUPPRESSED_BY_DND);
+        assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+                .isFalse();
+        verify(mLogger, never()).logFullscreen(any(), any());
+        verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+        verify(mLogger).logNoFullscreen(entry, "Suppressed by DND");
+    }
+
+    @Test
     public void testShouldNotFullScreen_notHighImportance_withStrictFlag() throws Exception {
         when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
         testShouldNotFullScreen_notHighImportance();
@@ -423,6 +465,8 @@
         when(mDreamManager.isDreaming()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(SHADE);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FSI_NOT_IMPORTANT_ENOUGH);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
         verify(mLogger).logNoFullscreen(entry, "Not important enough");
@@ -443,6 +487,8 @@
         when(mDreamManager.isDreaming()).thenReturn(true);
         when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
         verify(mLogger, never()).logNoFullscreen(any(), any());
@@ -470,6 +516,8 @@
         when(mDreamManager.isDreaming()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(SHADE);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.FSI_DEVICE_NOT_INTERACTIVE);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
@@ -490,6 +538,8 @@
         when(mDreamManager.isDreaming()).thenReturn(true);
         when(mStatusBarStateController.getState()).thenReturn(SHADE);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.FSI_DEVICE_IS_DREAMING);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
@@ -510,6 +560,8 @@
         when(mDreamManager.isDreaming()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.FSI_KEYGUARD_SHOWING);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isTrue();
         verify(mLogger, never()).logNoFullscreen(any(), any());
@@ -531,6 +583,8 @@
         when(mDreamManager.isDreaming()).thenReturn(false);
         when(mStatusBarStateController.getState()).thenReturn(SHADE);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FSI_EXPECTED_TO_HUN);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
         verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
@@ -547,9 +601,10 @@
         when(mStatusBarStateController.getState()).thenReturn(SHADE);
         when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.FSI_EXPECTED_NOT_TO_HUN);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isTrue();
-        verify(mLogger).logNoHeadsUpPackageSnoozed(entry);
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger).logFullscreen(entry, "Expected not to HUN");
@@ -567,9 +622,10 @@
         when(mKeyguardStateController.isShowing()).thenReturn(true);
         when(mKeyguardStateController.isOccluded()).thenReturn(true);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.FSI_KEYGUARD_OCCLUDED);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isTrue();
-        verify(mLogger).logNoHeadsUpPackageSnoozed(entry);
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger).logFullscreen(entry, "Expected not to HUN while keyguard occluded");
@@ -587,9 +643,10 @@
         when(mKeyguardStateController.isShowing()).thenReturn(true);
         when(mKeyguardStateController.isOccluded()).thenReturn(false);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.FSI_LOCKED_SHADE);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isTrue();
-        verify(mLogger).logNoHeadsUpPackageSnoozed(entry);
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger, never()).logNoFullscreenWarning(any(), any());
         verify(mLogger).logFullscreen(entry, "Keyguard is showing and not occluded");
@@ -607,9 +664,10 @@
         when(mKeyguardStateController.isShowing()).thenReturn(false);
         when(mKeyguardStateController.isOccluded()).thenReturn(false);
 
+        assertThat(mNotifInterruptionStateProvider.getFullScreenIntentDecision(entry))
+                .isEqualTo(FullScreenIntentDecision.NO_FSI_NO_HUN_OR_KEYGUARD);
         assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
                 .isFalse();
-        verify(mLogger).logNoHeadsUpPackageSnoozed(entry);
         verify(mLogger, never()).logNoFullscreen(any(), any());
         verify(mLogger).logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
         verify(mLogger, never()).logFullscreen(any(), any());