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

Commit 2eb242bc authored by Julia Tuttle's avatar Julia Tuttle Committed by Android (Google) Code Review
Browse files

Merge "Register new suppressors in StatusBarNotificationPresenter" into main

parents ee7eea32 fb5aa9ca
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));
    }
    }
}
}