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

Commit 96fbb06f authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Use doze amount to ensure notification stability when going to sleep

Test: atest VisualStabilityCoordinatorTest
Fixes: 233396394
Change-Id: Ic6c6dfe428054bfdae8ed53ab6d6e9d599f238db
parent d7ffdd77
Loading
Loading
Loading
Loading
+42 −16
Original line number Diff line number Diff line
@@ -16,8 +16,9 @@

package com.android.systemui.statusbar.notification.collection.coordinator;

import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;

import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -35,6 +36,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.phone.NotifPanelEvents;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.Compile;
import com.android.systemui.util.concurrency.DelayableExecutor;

import java.io.PrintWriter;
@@ -54,6 +56,8 @@ import javax.inject.Inject;
@SysUISingleton
public class VisualStabilityCoordinator implements Coordinator, Dumpable,
        NotifPanelEvents.Listener {
    public static final String TAG = "VisualStability";
    public static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
    private final DelayableExecutor mDelayableExecutor;
    private final HeadsUpManager mHeadsUpManager;
    private final NotifPanelEvents mNotifPanelEvents;
@@ -61,7 +65,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
    private final VisualStabilityProvider mVisualStabilityProvider;
    private final WakefulnessLifecycle mWakefulnessLifecycle;

    private boolean mScreenOn;
    private boolean mSleepy = true;
    private boolean mFullyDozed;
    private boolean mPanelExpanded;
    private boolean mPulsing;
    private boolean mNotifPanelCollapsing;
@@ -104,8 +109,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
    @Override
    public void attach(NotifPipeline pipeline) {
        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
        mScreenOn = mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
                || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING;
        mSleepy = mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP;
        mFullyDozed = mStatusBarStateController.getDozeAmount() == 1f;

        mStatusBarStateController.addCallback(mStatusBarStateControllerListener);
        mPulsing = mStatusBarStateController.isPulsing();
@@ -113,6 +118,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,

        pipeline.setVisualStabilityManager(mNotifStabilityManager);
    }

    // TODO(b/203826051): Ensure stability manager can allow reordering off-screen
    //  HUNs to the top of the shade
    private final NotifStabilityManager mNotifStabilityManager =
@@ -174,9 +180,18 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
                }
            };

    private void updateAllowedStates() {
    private void updateAllowedStates(String field, boolean value) {
        boolean wasPipelineRunAllowed = mPipelineRunAllowed;
        boolean wasReorderingAllowed = mReorderingAllowed;
        mPipelineRunAllowed = !isPanelCollapsingOrLaunchingActivity();
        mReorderingAllowed = isReorderingAllowed();
        if (DEBUG && (wasPipelineRunAllowed != mPipelineRunAllowed
                || wasReorderingAllowed != mReorderingAllowed)) {
            Log.d(TAG, "Stability allowances changed:"
                    + "  pipelineRunAllowed " + wasPipelineRunAllowed + "->" + mPipelineRunAllowed
                    + "  reorderingAllowed " + wasReorderingAllowed + "->" + mReorderingAllowed
                    + "  when setting " + field + "=" + value);
        }
        if ((mPipelineRunAllowed && mIsSuppressingPipelineRun)
                || (mReorderingAllowed && (mIsSuppressingGroupChange
                        || isSuppressingSectionChange()
@@ -195,7 +210,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
    }

    private boolean isReorderingAllowed() {
        return (!mScreenOn || !mPanelExpanded) && !mPulsing;
        return ((mFullyDozed && mSleepy) || !mPanelExpanded) && !mPulsing;
    }

    /**
@@ -235,27 +250,37 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
                @Override
                public void onPulsingChanged(boolean pulsing) {
                    mPulsing = pulsing;
                    updateAllowedStates();
                    updateAllowedStates("pulsing", pulsing);
                }

                @Override
                public void onExpandedChanged(boolean expanded) {
                    mPanelExpanded = expanded;
                    updateAllowedStates();
                    updateAllowedStates("panelExpanded", expanded);
                }

                @Override
                public void onDozeAmountChanged(float linear, float eased) {
                    final boolean fullyDozed = linear == 1f;
                    mFullyDozed = fullyDozed;
                    updateAllowedStates("fullyDozed", fullyDozed);
                }
            };

    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
        @Override
        public void onFinishedGoingToSleep() {
            mScreenOn = false;
            updateAllowedStates();
            // NOTE: this method is called much earlier than what we consider "finished" going to
            // sleep (the animation isn't done), so we also need to check the doze amount is not 1
            // and use the combo to determine that the locked shade is not visible.
            mSleepy = true;
            updateAllowedStates("sleepy", true);
        }

        @Override
        public void onStartedWakingUp() {
            mScreenOn = true;
            updateAllowedStates();
            mSleepy = false;
            updateAllowedStates("sleepy", false);
        }
    };

@@ -265,7 +290,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
        pw.println("  notifPanelCollapsing: " + mNotifPanelCollapsing);
        pw.println("  launchingNotifActivity: " + mNotifPanelLaunchingActivity);
        pw.println("reorderingAllowed: " + mReorderingAllowed);
        pw.println("  screenOn: " + mScreenOn);
        pw.println("  sleepy: " + mSleepy);
        pw.println("  fullyDozed: " + mFullyDozed);
        pw.println("  panelExpanded: " + mPanelExpanded);
        pw.println("  pulsing: " + mPulsing);
        pw.println("isSuppressingPipelineRun: " + mIsSuppressingPipelineRun);
@@ -285,12 +311,12 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
    @Override
    public void onPanelCollapsingChanged(boolean isCollapsing) {
        mNotifPanelCollapsing = isCollapsing;
        updateAllowedStates();
        updateAllowedStates("notifPanelCollapsing", isCollapsing);
    }

    @Override
    public void onLaunchingActivityChanged(boolean isLaunchingActivity) {
        mNotifPanelLaunchingActivity = isLaunchingActivity;
        updateAllowedStates();
        updateAllowedStates("notifPanelLaunchingActivity", isLaunchingActivity);
    }
}
+74 −20
Original line number Diff line number Diff line
@@ -136,7 +136,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testScreenOff_groupAndSectionChangesAllowed() {
        // GIVEN screen is off, panel isn't expanded and device isn't pulsing
        setScreenOn(false);
        setFullyDozed(true);
        setSleepy(true);
        setPanelExpanded(false);
        setPulsing(false);

@@ -148,10 +149,43 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
        assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
    }

    @Test
    public void testScreenTurningOff_groupAndSectionChangesNotAllowed() {
        // GIVEN the screen is turning off (sleepy but partially dozed)
        setFullyDozed(false);
        setSleepy(true);
        setPanelExpanded(true);
        setPulsing(false);

        // THEN group changes are NOT allowed
        assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
        assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));

        // THEN section changes are NOT allowed
        assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
    }

    @Test
    public void testScreenTurningOn_groupAndSectionChangesNotAllowed() {
        // GIVEN the screen is turning on (still fully dozed, not sleepy)
        setFullyDozed(true);
        setSleepy(false);
        setPanelExpanded(true);
        setPulsing(false);

        // THEN group changes are NOT allowed
        assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
        assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));

        // THEN section changes are NOT allowed
        assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
    }

    @Test
    public void testPanelNotExpanded_groupAndSectionChangesAllowed() {
        // GIVEN screen is on but the panel isn't expanded and device isn't pulsing
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(false);
        setPulsing(false);

@@ -166,7 +200,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testPanelExpanded_groupAndSectionChangesNotAllowed() {
        // GIVEN the panel true expanded and device isn't pulsing
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);
        setPulsing(false);

@@ -181,7 +216,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testPulsing_screenOff_groupAndSectionChangesNotAllowed() {
        // GIVEN the device is pulsing and screen is off
        setScreenOn(false);
        setFullyDozed(true);
        setSleepy(true);
        setPulsing(true);

        // THEN group changes are NOT allowed
@@ -195,7 +231,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testPulsing_panelNotExpanded_groupAndSectionChangesNotAllowed() {
        // GIVEN the device is pulsing and screen is off with the panel not expanded
        setScreenOn(false);
        setFullyDozed(true);
        setSleepy(true);
        setPanelExpanded(false);
        setPulsing(true);

@@ -211,7 +248,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    public void testOverrideReorderingSuppression_onlySectionChangesAllowed() {
        // GIVEN section changes typically wouldn't be allowed because the panel is expanded and
        // we're not pulsing
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);
        setPulsing(true);

@@ -233,7 +271,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testTemporarilyAllowSectionChanges_callsInvalidate() {
        // GIVEN section changes typically wouldn't be allowed because the panel is expanded
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);
        setPulsing(false);

@@ -247,7 +286,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testTemporarilyAllowSectionChanges_noInvalidationCalled() {
        // GIVEN section changes typically WOULD be allowed
        setScreenOn(false);
        setFullyDozed(true);
        setSleepy(true);
        setPanelExpanded(false);
        setPulsing(false);

@@ -261,7 +301,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testTemporarilyAllowSectionChangesTimeout() {
        // GIVEN section changes typically WOULD be allowed
        setScreenOn(false);
        setFullyDozed(true);
        setSleepy(true);
        setPanelExpanded(false);
        setPulsing(false);
        assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
@@ -292,7 +333,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testTemporarilyAllowSectionChanges_isPulsingChangeBeforeTimeout() {
        // GIVEN section changes typically wouldn't be allowed because the device is pulsing
        setScreenOn(false);
        setFullyDozed(true);
        setSleepy(true);
        setPanelExpanded(false);
        setPulsing(true);

@@ -315,8 +357,11 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
        // WHEN device isn't pulsing anymore
        setPulsing(false);

        // WHEN screen isn't on
        setScreenOn(false);
        // WHEN fully dozed
        setFullyDozed(true);

        // WHEN sleepy
        setSleepy(true);

        // WHEN panel isn't expanded
        setPanelExpanded(false);
@@ -330,7 +375,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    public void testNotSuppressingGroupChangesAnymore_invalidationCalled() {
        // GIVEN visual stability is being maintained b/c panel is expanded
        setPulsing(false);
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);

        assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
@@ -399,7 +445,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    public void testNotSuppressingEntryReorderingAnymoreWillInvalidate() {
        // GIVEN visual stability is being maintained b/c panel is expanded
        setPulsing(false);
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);

        assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
@@ -417,7 +464,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    public void testQueryingEntryReorderingButNotReportingReorderSuppressedDoesNotInvalidate() {
        // GIVEN visual stability is being maintained b/c panel is expanded
        setPulsing(false);
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);

        assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
@@ -432,7 +480,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
    @Test
    public void testHeadsUp_allowedToChangeGroupAndSection() {
        // GIVEN group + section changes disallowed
        setScreenOn(true);
        setFullyDozed(false);
        setSleepy(false);
        setPanelExpanded(true);
        setPulsing(true);
        assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
@@ -462,11 +511,16 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
        mStatusBarStateListener.onPulsingChanged(pulsing);
    }

    private void setScreenOn(boolean screenOn) {
        if (screenOn) {
            mWakefulnessObserver.onStartedWakingUp();
        } else {
    private void setFullyDozed(boolean fullyDozed) {
        float dozeAmount = fullyDozed ? 1 : 0;
        mStatusBarStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
    }

    private void setSleepy(boolean sleepy) {
        if (sleepy) {
            mWakefulnessObserver.onFinishedGoingToSleep();
        } else {
            mWakefulnessObserver.onStartedWakingUp();
        }
    }