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

Commit fb5aa9ca authored by Julia Tuttle's avatar Julia Tuttle
Browse files

Register new suppressors in StatusBarNotificationPresenter

Bug: 261728888
Test: atest StatusBarNotificationPresenterTest
Test: atest VisualInterruptionDecisionProviderImplTest
Flag: ACONFIG com.android.systemui.visual_interruptions_refactor DEVELOPMENT
Change-Id: Ib6663ef1c87c34503f940aa6a440d8f0d5d8e793
parent c0fc00cb
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -73,6 +73,11 @@ abstract class VisualInterruptionCondition(
    override val uiEventId: UiEventEnum? = null,
    override val uiEventId: UiEventEnum? = null,
    override val eventLogData: EventLogData? = null
    override val eventLogData: EventLogData? = null
) : VisualInterruptionSuppressor {
) : VisualInterruptionSuppressor {
    constructor(
        types: Set<VisualInterruptionType>,
        reason: String
    ) : this(types, reason, /* uiEventId = */ null)

    /** @return true if these interruptions should be suppressed right now. */
    /** @return true if these interruptions should be suppressed right now. */
    abstract fun shouldSuppress(): Boolean
    abstract fun shouldSuppress(): Boolean
}
}
@@ -84,6 +89,11 @@ abstract class VisualInterruptionFilter(
    override val uiEventId: UiEventEnum? = null,
    override val uiEventId: UiEventEnum? = null,
    override val eventLogData: EventLogData? = null
    override val eventLogData: EventLogData? = null
) : VisualInterruptionSuppressor {
) : VisualInterruptionSuppressor {
    constructor(
        types: Set<VisualInterruptionType>,
        reason: String
    ) : this(types, reason, /* uiEventId = */ null)

    /**
    /**
     * @param entry the notification to consider suppressing
     * @param entry the notification to consider suppressing
     * @return true if these interruptions should be suppressed for this notification right now
     * @return true if these interruptions should be suppressed for this notification right now
+68 −1
Original line number Original line Diff line number Diff line
@@ -14,6 +14,9 @@


package com.android.systemui.statusbar.phone;
package com.android.systemui.statusbar.phone;


import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.BUBBLE;
import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PEEK;
import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE;
import static com.android.systemui.statusbar.phone.CentralSurfaces.CLOSE_PANEL_WHEN_EMPTIED;
import static com.android.systemui.statusbar.phone.CentralSurfaces.CLOSE_PANEL_WHEN_EMPTIED;
import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;
import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;


@@ -29,6 +32,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.Slog;
import android.view.View;
import android.view.View;


import androidx.annotation.NonNull;

import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.InitController;
import com.android.systemui.InitController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.SysUISingleton;
@@ -54,7 +59,10 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.domain.interactor.NotificationAlertsInteractor;
import com.android.systemui.statusbar.notification.domain.interactor.NotificationAlertsInteractor;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionCondition;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionFilter;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionRefactor;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
@@ -63,6 +71,8 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardStateController;


import java.util.Set;

import javax.inject.Inject;
import javax.inject.Inject;


@SysUISingleton
@SysUISingleton
@@ -163,7 +173,14 @@ class StatusBarNotificationPresenter implements NotificationPresenter, CommandQu
        initController.addPostInitTask(() -> {
        initController.addPostInitTask(() -> {
            mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
            mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
            mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
            mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
            if (VisualInterruptionRefactor.isEnabled()) {
                visualInterruptionDecisionProvider.addCondition(mAlertsDisabledCondition);
                visualInterruptionDecisionProvider.addCondition(mVrModeCondition);
                visualInterruptionDecisionProvider.addFilter(mNeedsRedactionFilter);
                visualInterruptionDecisionProvider.addCondition(mPanelsDisabledCondition);
            } else {
                visualInterruptionDecisionProvider.addLegacySuppressor(mInterruptSuppressor);
                visualInterruptionDecisionProvider.addLegacySuppressor(mInterruptSuppressor);
            }
            mLockscreenUserManager.setUpWithPresenter(this);
            mLockscreenUserManager.setUpWithPresenter(this);
            mGutsManager.setUpWithPresenter(
            mGutsManager.setUpWithPresenter(
                    this, mNotifListContainer, mOnSettingsClickListener);
                    this, mNotifListContainer, mOnSettingsClickListener);
@@ -306,4 +323,54 @@ class StatusBarNotificationPresenter implements NotificationPresenter, CommandQu
            return !mNotificationAlertsInteractor.areNotificationAlertsEnabled();
            return !mNotificationAlertsInteractor.areNotificationAlertsEnabled();
        }
        }
    };
    };

    private final VisualInterruptionCondition mAlertsDisabledCondition =
            new VisualInterruptionCondition(Set.of(PEEK, PULSE, BUBBLE),
                    "notification alerts disabled") {
                @Override
                public boolean shouldSuppress() {
                    return !mNotificationAlertsInteractor.areNotificationAlertsEnabled();
                }
            };

    private final VisualInterruptionCondition mVrModeCondition =
            new VisualInterruptionCondition(Set.of(PEEK, BUBBLE), "device is in VR mode") {
                @Override
                public boolean shouldSuppress() {
                    return isDeviceInVrMode();
                }
            };

    private final VisualInterruptionFilter mNeedsRedactionFilter =
            new VisualInterruptionFilter(Set.of(PEEK), "needs redaction on public lockscreen") {
                @Override
                public boolean shouldSuppress(@NonNull NotificationEntry entry) {
                    if (!mKeyguardStateController.isOccluded()) {
                        return false;
                    }

                    if (!mLockscreenUserManager.needsRedaction(entry)) {
                        return false;
                    }

                    final int currentUserId = mLockscreenUserManager.getCurrentUserId();
                    final boolean currentUserPublic = mLockscreenUserManager.isLockscreenPublicMode(
                            currentUserId);

                    final int notificationUserId = entry.getSbn().getUserId();
                    final boolean notificationUserPublic =
                            mLockscreenUserManager.isLockscreenPublicMode(notificationUserId);

                    // TODO(b/135046837): we can probably relax this with dynamic privacy
                    return currentUserPublic || notificationUserPublic;
                }
            };

    private final VisualInterruptionCondition mPanelsDisabledCondition =
            new VisualInterruptionCondition(Set.of(PEEK), "disabled panel") {
                @Override
                public boolean shouldSuppress() {
                    return !mCommandQueue.panelsEnabled();
                }
            };
}
}
+236 −85
Original line number Original line Diff line number Diff line
@@ -16,22 +16,28 @@ package com.android.systemui.statusbar.phone;


import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;


import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.BUBBLE;
import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PEEK;
import static com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;


import android.app.Notification;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.StatusBarManager;
import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.testing.TestableLooper.RunWithLooper;


import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.Flags;
import com.android.systemui.InitController;
import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter;
@@ -55,7 +61,10 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.domain.interactor.NotificationAlertsInteractor;
import com.android.systemui.statusbar.notification.domain.interactor.NotificationAlertsInteractor;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionCondition;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionFilter;
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -64,10 +73,14 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardStateController;


import org.junit.Before;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentCaptor;


import java.util.List;
import java.util.Set;

@SmallTest
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWith(AndroidTestingRunner.class)
@RunWithLooper()
@RunWithLooper()
@@ -76,18 +89,23 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
    private final VisualInterruptionDecisionProvider mVisualInterruptionDecisionProvider =
    private final VisualInterruptionDecisionProvider mVisualInterruptionDecisionProvider =
            mock(VisualInterruptionDecisionProvider.class);
            mock(VisualInterruptionDecisionProvider.class);
    private NotificationInterruptSuppressor mInterruptSuppressor;
    private NotificationInterruptSuppressor mInterruptSuppressor;
    private VisualInterruptionCondition mAlertsDisabledCondition;
    private VisualInterruptionCondition mVrModeCondition;
    private VisualInterruptionFilter mNeedsRedactionFilter;
    private VisualInterruptionCondition mPanelsDisabledCondition;
    private CommandQueue mCommandQueue;
    private CommandQueue mCommandQueue;
    private FakeMetricsLogger mMetricsLogger;
    private final ShadeController mShadeController = mock(ShadeController.class);
    private final ShadeController mShadeController = mock(ShadeController.class);
    private final NotificationAlertsInteractor mNotificationAlertsInteractor =
    private final NotificationAlertsInteractor mNotificationAlertsInteractor =
            mock(NotificationAlertsInteractor.class);
            mock(NotificationAlertsInteractor.class);
    private final KeyguardStateController mKeyguardStateController =
    private final KeyguardStateController mKeyguardStateController =
            mock(KeyguardStateController.class);
            mock(KeyguardStateController.class);
    private final InitController mInitController = new InitController();

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
            SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);


    @Before
    @Before
    public void setup() {
    public void setup() {
        mMetricsLogger = new FakeMetricsLogger();
        mCommandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext));
        mCommandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext));
        mDependency.injectTestDependency(StatusBarStateController.class,
        mDependency.injectTestDependency(StatusBarStateController.class,
                mock(SysuiStatusBarStateController.class));
                mock(SysuiStatusBarStateController.class));
@@ -95,15 +113,182 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
        mDependency.injectMockDependency(NotificationRemoteInputManager.Callback.class);
        mDependency.injectMockDependency(NotificationRemoteInputManager.Callback.class);
        mDependency.injectMockDependency(NotificationShadeWindowController.class);
        mDependency.injectMockDependency(NotificationShadeWindowController.class);


        NotificationShadeWindowView notificationShadeWindowView =
        when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(true);
    }

    @Test
    public void testInit_refactorDisabled() {
        ensureRefactorDisabledState();
    }

    @Test
    public void testInit_refactorEnabled() {
        ensureRefactorEnabledState();
    }

    @Test
    public void testNoSuppressHeadsUp_default_refactorDisabled() {
        ensureRefactorDisabledState();

        assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(createNotificationEntry()));
    }

    @Test
    public void testNoSuppressHeadsUp_default_refactorEnabled() {
        ensureRefactorEnabledState();

        assertFalse(mAlertsDisabledCondition.shouldSuppress());
        assertFalse(mVrModeCondition.shouldSuppress());
        assertFalse(mNeedsRedactionFilter.shouldSuppress(createNotificationEntry()));
        assertFalse(mAlertsDisabledCondition.shouldSuppress());
    }

    @Test
    public void testSuppressHeadsUp_disabledStatusBar_refactorDisabled() {
        ensureRefactorDisabledState();

        mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0,
                false /* animate */);
        TestableLooper.get(this).processAllMessages();

        assertTrue("The panel should suppress heads up while disabled",
                mInterruptSuppressor.suppressAwakeHeadsUp(createNotificationEntry()));
    }

    @Test
    public void testSuppressHeadsUp_disabledStatusBar_refactorEnabled() {
        ensureRefactorEnabledState();

        mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0,
                false /* animate */);
        TestableLooper.get(this).processAllMessages();

        assertTrue("The panel should suppress heads up while disabled",
                mPanelsDisabledCondition.shouldSuppress());
    }

    @Test
    public void testSuppressHeadsUp_disabledNotificationShade_refactorDisabled() {
        ensureRefactorDisabledState();

        mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
                false /* animate */);
        TestableLooper.get(this).processAllMessages();

        assertTrue("The panel should suppress interruptions while notification shade disabled",
                mInterruptSuppressor.suppressAwakeHeadsUp(createNotificationEntry()));
    }

    @Test
    public void testSuppressHeadsUp_disabledNotificationShade_refactorEnabled() {
        ensureRefactorEnabledState();

        mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
                false /* animate */);
        TestableLooper.get(this).processAllMessages();

        assertTrue("The panel should suppress interruptions while notification shade disabled",
                mPanelsDisabledCondition.shouldSuppress());
    }

    @Test
    public void testPanelsDisabledConditionSuppressesPeek() {
        ensureRefactorEnabledState();

        final Set<VisualInterruptionType> types = mPanelsDisabledCondition.getTypes();
        assertTrue(types.contains(PEEK));
        assertFalse(types.contains(PULSE));
        assertFalse(types.contains(BUBBLE));
    }

    @Test
    public void testNoSuppressHeadsUp_FSI_nonOccludedKeyguard_refactorDisabled() {
        ensureRefactorDisabledState();

        when(mKeyguardStateController.isShowing()).thenReturn(true);
        when(mKeyguardStateController.isOccluded()).thenReturn(false);

        assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(createFsiNotificationEntry()));
    }

    @Test
    public void testNoSuppressHeadsUp_FSI_nonOccludedKeyguard_refactorEnabled() {
        ensureRefactorEnabledState();

        when(mKeyguardStateController.isShowing()).thenReturn(true);
        when(mKeyguardStateController.isOccluded()).thenReturn(false);

        assertFalse(mNeedsRedactionFilter.shouldSuppress(createFsiNotificationEntry()));

        final Set<VisualInterruptionType> types = mNeedsRedactionFilter.getTypes();
        assertTrue(types.contains(PEEK));
        assertFalse(types.contains(PULSE));
        assertFalse(types.contains(BUBBLE));
    }

    @Test
    public void testSuppressInterruptions_vrMode_refactorDisabled() {
        ensureRefactorDisabledState();

        mStatusBarNotificationPresenter.mVrMode = true;

        assertTrue("Vr mode should suppress interruptions",
                mInterruptSuppressor.suppressAwakeInterruptions(createNotificationEntry()));
    }

    @Test
    public void testSuppressInterruptions_vrMode_refactorEnabled() {
        ensureRefactorEnabledState();

        mStatusBarNotificationPresenter.mVrMode = true;

        assertTrue("Vr mode should suppress interruptions", mVrModeCondition.shouldSuppress());

        final Set<VisualInterruptionType> types = mVrModeCondition.getTypes();
        assertTrue(types.contains(PEEK));
        assertFalse(types.contains(PULSE));
        assertTrue(types.contains(BUBBLE));
    }

    @Test
    public void testSuppressInterruptions_statusBarAlertsDisabled_refactorDisabled() {
        ensureRefactorDisabledState();

        when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false);

        assertTrue("When alerts aren't enabled, interruptions are suppressed",
                mInterruptSuppressor.suppressInterruptions(createNotificationEntry()));
    }

    @Test
    public void testSuppressInterruptions_statusBarAlertsDisabled_refactorEnabled() {
        ensureRefactorEnabledState();

        when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false);

        assertTrue("When alerts aren't enabled, interruptions are suppressed",
                mAlertsDisabledCondition.shouldSuppress());

        final Set<VisualInterruptionType> types = mAlertsDisabledCondition.getTypes();
        assertTrue(types.contains(PEEK));
        assertTrue(types.contains(PULSE));
        assertTrue(types.contains(BUBBLE));
    }

    private void createPresenter() {
        final ShadeViewController shadeViewController = mock(ShadeViewController.class);

        final NotificationShadeWindowView notificationShadeWindowView =
                mock(NotificationShadeWindowView.class);
                mock(NotificationShadeWindowView.class);
        when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources());

        NotificationStackScrollLayoutController stackScrollLayoutController =
        NotificationStackScrollLayoutController stackScrollLayoutController =
                mock(NotificationStackScrollLayoutController.class);
                mock(NotificationStackScrollLayoutController.class);
        when(stackScrollLayoutController.getView()).thenReturn(
        when(stackScrollLayoutController.getView()).thenReturn(
                mock(NotificationStackScrollLayout.class));
                mock(NotificationStackScrollLayout.class));
        when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources());


        ShadeViewController shadeViewController = mock(ShadeViewController.class);
        final InitController initController = new InitController();

        mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(
        mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(
                mContext,
                mContext,
                shadeViewController,
                shadeViewController,
@@ -125,110 +310,76 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
                mock(NotifShadeEventSource.class),
                mock(NotifShadeEventSource.class),
                mock(NotificationMediaManager.class),
                mock(NotificationMediaManager.class),
                mock(NotificationGutsManager.class),
                mock(NotificationGutsManager.class),
                mInitController,
                initController,
                mVisualInterruptionDecisionProvider,
                mVisualInterruptionDecisionProvider,
                mock(NotificationRemoteInputManager.class),
                mock(NotificationRemoteInputManager.class),
                mock(NotificationRemoteInputManager.Callback.class),
                mock(NotificationRemoteInputManager.Callback.class),
                mock(NotificationListContainer.class));
                mock(NotificationListContainer.class));
        mInitController.executePostInitTasks();

        ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
        initController.executePostInitTasks();
                ArgumentCaptor.forClass(NotificationInterruptSuppressor.class);
        verify(mVisualInterruptionDecisionProvider).addLegacySuppressor(suppressorCaptor.capture());
        mInterruptSuppressor = suppressorCaptor.getValue();
    }
    }


    @Test
    private void verifyAndCaptureSuppressors() {
    public void testNoSuppressHeadsUp_default() {
        mInterruptSuppressor = null;
        Notification n = new Notification.Builder(getContext(), "a").build();
        NotificationEntry entry = new NotificationEntryBuilder()
                .setPkg("a")
                .setOpPkg("a")
                .setTag("a")
                .setNotification(n)
                .build();


        assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(entry));
        final ArgumentCaptor<VisualInterruptionCondition> conditionCaptor =
                ArgumentCaptor.forClass(VisualInterruptionCondition.class);
        verify(mVisualInterruptionDecisionProvider, times(3)).addCondition(
                conditionCaptor.capture());
        final List<VisualInterruptionCondition> conditions = conditionCaptor.getAllValues();
        mAlertsDisabledCondition = conditions.get(0);
        mVrModeCondition = conditions.get(1);
        mPanelsDisabledCondition = conditions.get(2);

        final ArgumentCaptor<VisualInterruptionFilter> needsRedactionFilterCaptor =
                ArgumentCaptor.forClass(VisualInterruptionFilter.class);
        verify(mVisualInterruptionDecisionProvider).addFilter(needsRedactionFilterCaptor.capture());
        mNeedsRedactionFilter = needsRedactionFilterCaptor.getValue();
    }
    }


    @Test
    private void verifyAndCaptureLegacySuppressor() {
    public void testSuppressHeadsUp_disabledStatusBar() {
        mAlertsDisabledCondition = null;
        Notification n = new Notification.Builder(getContext(), "a").build();
        mVrModeCondition = null;
        NotificationEntry entry = new NotificationEntryBuilder()
        mNeedsRedactionFilter = null;
                .setPkg("a")
        mPanelsDisabledCondition = null;
                .setOpPkg("a")
                .setTag("a")
                .setNotification(n)
                .build();
        mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0,
                false /* animate */);
        TestableLooper.get(this).processAllMessages();


        assertTrue("The panel should suppress heads up while disabled",
        final ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
                mInterruptSuppressor.suppressAwakeHeadsUp(entry));
                ArgumentCaptor.forClass(NotificationInterruptSuppressor.class);
        verify(mVisualInterruptionDecisionProvider).addLegacySuppressor(suppressorCaptor.capture());
        mInterruptSuppressor = suppressorCaptor.getValue();
    }
    }


    @Test
    private void ensureRefactorDisabledState() {
    public void testSuppressHeadsUp_disabledNotificationShade() {
        mSetFlagsRule.disableFlags(Flags.FLAG_VISUAL_INTERRUPTIONS_REFACTOR);
        Notification n = new Notification.Builder(getContext(), "a").build();
        createPresenter();
        NotificationEntry entry = new NotificationEntryBuilder()
        verifyAndCaptureLegacySuppressor();
                .setPkg("a")
    }
                .setOpPkg("a")
                .setTag("a")
                .setNotification(n)
                .build();
        mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
                false /* animate */);
        TestableLooper.get(this).processAllMessages();


        assertTrue("The panel should suppress interruptions while notification shade "
    private void ensureRefactorEnabledState() {
                        + "disabled",
        mSetFlagsRule.enableFlags(Flags.FLAG_VISUAL_INTERRUPTIONS_REFACTOR);
                mInterruptSuppressor.suppressAwakeHeadsUp(entry));
        createPresenter();
        verifyAndCaptureSuppressors();
    }
    }


    @Test
    private NotificationEntry createNotificationEntry() {
    public void testNoSuppressHeadsUp_FSI_nonOccludedKeyguard() {
        return new NotificationEntryBuilder()
        Notification n = new Notification.Builder(getContext(), "a")
                .setFullScreenIntent(mock(PendingIntent.class), true)
                .build();
        NotificationEntry entry = new NotificationEntryBuilder()
                .setPkg("a")
                .setPkg("a")
                .setOpPkg("a")
                .setOpPkg("a")
                .setTag("a")
                .setTag("a")
                .setNotification(n)
                .setNotification(new Notification.Builder(getContext(), "a").build())
                .build();
                .build();

        when(mKeyguardStateController.isShowing()).thenReturn(true);
        when(mKeyguardStateController.isOccluded()).thenReturn(false);
        assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(entry));
    }
    }


    @Test
    private NotificationEntry createFsiNotificationEntry() {
    public void testSuppressInterruptions_vrMode() {
        final Notification notification = new Notification.Builder(getContext(), "a")
        Notification n = new Notification.Builder(getContext(), "a").build();
                .setFullScreenIntent(mock(PendingIntent.class), true)
        NotificationEntry entry = new NotificationEntryBuilder()
                .setPkg("a")
                .setOpPkg("a")
                .setTag("a")
                .setNotification(n)
                .build();
                .build();
        mStatusBarNotificationPresenter.mVrMode = true;

        assertTrue("Vr mode should suppress interruptions",
                mInterruptSuppressor.suppressAwakeInterruptions(entry));
    }


    @Test
        return new NotificationEntryBuilder()
    public void testSuppressInterruptions_statusBarAlertsDisabled() {
        Notification n = new Notification.Builder(getContext(), "a").build();
        NotificationEntry entry = new NotificationEntryBuilder()
                .setPkg("a")
                .setPkg("a")
                .setOpPkg("a")
                .setOpPkg("a")
                .setTag("a")
                .setTag("a")
                .setNotification(n)
                .setNotification(notification)
                .build();
                .build();
        when(mNotificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false);

        assertTrue("When alerts aren't enabled, interruptions are suppressed",
                mInterruptSuppressor.suppressInterruptions(entry));
    }
    }
}
}