Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1b8107a authored by Jeff DeCew's avatar Jeff DeCew
Browse files

FullScreenIntent cannot launch unless Keyguard is showing.

This feature is currently guarded behind a teamfood flag.

Bug: 231322873
Test: atest NotificationInterruptStateProviderImplTest StatusBarNotificationPresenterTest CentralSurfacesImplTest BubblesTest
Change-Id: Icd10387c20d5d49699e2794334fe03e9514d1e0b
parent 55a6021f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -63,6 +63,9 @@ public class Flags {
    public static final BooleanFlag REMOVE_UNRANKED_NOTIFICATIONS =
            new BooleanFlag(109, false);

    public static final BooleanFlag FSI_REQUIRES_KEYGUARD =
            new BooleanFlag(110, false, true);

    /***************************************/
    // 200 - keyguard/lockscreen

+3 −0
Original line number Diff line number Diff line
@@ -59,4 +59,7 @@ class NotifPipelineFlags @Inject constructor(

    fun removeUnrankedNotifs(): Boolean =
        featureFlags.isEnabled(Flags.REMOVE_UNRANKED_NOTIFICATIONS)

    fun fullScreenIntentRequiresKeyguard(): Boolean =
        featureFlags.isEnabled(Flags.FSI_REQUIRES_KEYGUARD)
}
+26 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;

import java.util.ArrayList;
import java.util.List;
@@ -58,6 +59,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter

    private final List<NotificationInterruptSuppressor> mSuppressors = new ArrayList<>();
    private final StatusBarStateController mStatusBarStateController;
    private final KeyguardStateController mKeyguardStateController;
    private final NotificationFilter mNotificationFilter;
    private final ContentResolver mContentResolver;
    private final PowerManager mPowerManager;
@@ -82,6 +84,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
            NotificationFilter notificationFilter,
            BatteryController batteryController,
            StatusBarStateController statusBarStateController,
            KeyguardStateController keyguardStateController,
            HeadsUpManager headsUpManager,
            NotificationInterruptLogger logger,
            @Main Handler mainHandler,
@@ -94,6 +97,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
        mAmbientDisplayConfiguration = ambientDisplayConfiguration;
        mNotificationFilter = notificationFilter;
        mStatusBarStateController = statusBarStateController;
        mKeyguardStateController = keyguardStateController;
        mHeadsUpManager = headsUpManager;
        mLogger = logger;
        mFlags = flags;
@@ -228,6 +232,28 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
            return false;
        }

        // Check whether FSI requires the keyguard to be showing.
        if (mFlags.fullScreenIntentRequiresKeyguard()) {

            // 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");
                } else {
                    // Likely LOCKED_SHADE, but launch FSI anyway
                    mLogger.logFullscreen(entry, "Keyguard is showing and not occluded");
                }
                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();
            android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "no hun or keyguard");
            mLogger.logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard");
            return false;
        }

        // If the notification won't HUN for some other reason (DND/snooze/etc), launch FSI.
        mLogger.logFullscreen(entry, "Expected not to HUN");
        return true;
+2 −1
Original line number Diff line number Diff line
@@ -399,7 +399,8 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
                return true;
            }

            if (sbn.getNotification().fullScreenIntent != null) {
            if (sbn.getNotification().fullScreenIntent != null
                    && !mNotifPipelineFlags.fullScreenIntentRequiresKeyguard()) {
                // we don't allow head-up on the lockscreen (unless there's a
                // "showWhenLocked" activity currently showing)  if
                // the potential HUN has a fullscreen intent
+108 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;

import static com.google.common.truth.Truth.assertThat;

@@ -61,6 +62,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;

import org.junit.Before;
import org.junit.Test;
@@ -87,6 +89,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
    @Mock
    StatusBarStateController mStatusBarStateController;
    @Mock
    KeyguardStateController mKeyguardStateController;
    @Mock
    HeadsUpManager mHeadsUpManager;
    @Mock
    NotificationInterruptLogger mLogger;
@@ -106,6 +110,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(false);

        mNotifInterruptionStateProvider =
                new NotificationInterruptStateProviderImpl(
@@ -116,6 +121,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
                        mNotificationFilter,
                        mBatteryController,
                        mStatusBarStateController,
                        mKeyguardStateController,
                        mHeadsUpManager,
                        mLogger,
                        mMockHandler,
@@ -426,6 +432,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
    }

    @Test
    public void testShouldNotFullScreen_notPendingIntent_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldNotFullScreen_notPendingIntent();
    }

    @Test
    public void testShouldNotFullScreen_notPendingIntent() throws RemoteException {
        NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
@@ -440,6 +452,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger, never()).logFullscreen(any(), any());
    }

    @Test
    public void testShouldNotFullScreen_notHighImportance_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldNotFullScreen_notHighImportance();
    }

    @Test
    public void testShouldNotFullScreen_notHighImportance() throws RemoteException {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_DEFAULT, /* silenced */ false);
@@ -454,6 +472,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger, never()).logFullscreen(any(), any());
    }

    @Test
    public void testShouldNotFullScreen_isGroupAlertSilenced_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldNotFullScreen_isGroupAlertSilenced();
    }

    @Test
    public void testShouldNotFullScreen_isGroupAlertSilenced() throws RemoteException {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ true);
@@ -468,6 +492,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger, never()).logFullscreen(any(), any());
    }

    @Test
    public void testShouldFullScreen_notInteractive_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldFullScreen_notInteractive();
    }

    @Test
    public void testShouldFullScreen_notInteractive() throws RemoteException {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
@@ -482,6 +512,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger).logFullscreen(entry, "Device is not interactive");
    }

    @Test
    public void testShouldFullScreen_isDreaming_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldFullScreen_isDreaming();
    }

    @Test
    public void testShouldFullScreen_isDreaming() throws RemoteException {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
@@ -496,6 +532,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger).logFullscreen(entry, "Device is dreaming");
    }

    @Test
    public void testShouldFullScreen_onKeyguard_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldFullScreen_onKeyguard();
    }

    @Test
    public void testShouldFullScreen_onKeyguard() throws RemoteException {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
@@ -510,6 +552,12 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger).logFullscreen(entry, "Keyguard is showing");
    }

    @Test
    public void testShouldNotFullScreen_willHun_withStrictFlag() throws Exception {
        when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(true);
        testShouldNotFullScreen_willHun();
    }

    @Test
    public void testShouldNotFullScreen_willHun() throws RemoteException {
        NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
@@ -542,6 +590,66 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
        verify(mLogger).logFullscreen(entry, "Expected not to HUN");
    }

    @Test
    public void testShouldFullScreen_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.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");
    }

    @Test
    public void testShouldFullScreen_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.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");
    }

    @Test
    public void testShouldNotFullScreen_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.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());
    }

    /**
     * Bubbles can happen.
     */
Loading