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

Commit 56e6a327 authored by Selim Cinek's avatar Selim Cinek
Browse files

Dismissed keyguard gone runnables when aborting

Previously those actions could linger around
and lead to a variety of bugs.
Also fixed an issue when gutsManager calls were overlapping
to protect against these issues

Fixes: 130885521
Test: atest SystemUITests
Test: see bug description
Change-Id: Iffe37e6d48bbc9c26ba92f362d7b67bf743c7c28
parent d1b1f6fc
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -421,7 +421,7 @@ public class NotificationGuts extends FrameLayout {
    }

    /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
    private static class AnimateCloseListener extends AnimatorListenerAdapter {
    private class AnimateCloseListener extends AnimatorListenerAdapter {
        final View mView;
        private final GutsContent mGutsContent;

@@ -433,8 +433,10 @@ public class NotificationGuts extends FrameLayout {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            if (!isExposed()) {
                mView.setVisibility(View.GONE);
                mGutsContent.onFinishedClosing();
            }
        }
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
    protected String mKeyToRemoveOnGutsClosed;

    private StatusBar mStatusBar;
    private Runnable mOpenRunnable;

    @Inject
    public NotificationGutsManager(
@@ -343,6 +344,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
    public void closeAndSaveGuts(boolean removeLeavebehinds, boolean force, boolean removeControls,
            int x, int y, boolean resetMenu) {
        if (mNotificationGutsExposed != null) {
            mNotificationGutsExposed.removeCallbacks(mOpenRunnable);
            mNotificationGutsExposed.closeControls(removeLeavebehinds, removeControls, x, y, force);
        }
        if (resetMenu) {
@@ -445,7 +447,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
        // ensure that it's laid but not visible until actually laid out
        guts.setVisibility(View.INVISIBLE);
        // Post to ensure the the guts are properly laid out.
        guts.post(new Runnable() {
        mOpenRunnable = new Runnable() {
            @Override
            public void run() {
                if (row.getWindowToken() == null) {
@@ -470,7 +472,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
                mListContainer.onHeightChanged(row, true /* needsAnimation */);
                mGutsMenuItem = menuItem;
            }
        });
        };
        guts.post(mOpenRunnable);
        return true;
    }

+16 −1
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter;
import java.util.ArrayList;

import androidx.annotation.VisibleForTesting;

/**
 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
@@ -160,6 +162,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
    private boolean mLastLockVisible;

    private OnDismissAction mAfterKeyguardGoneAction;
    private Runnable mKeyguardGoneCancelAction;
    private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();

    // Dismiss action to be launched when we stop dozing or the keyguard is gone.
@@ -329,10 +332,20 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
        return false;
    }

    private void hideBouncer(boolean destroyView) {
    @VisibleForTesting
    void hideBouncer(boolean destroyView) {
        if (mBouncer == null) {
            return;
        }
        if (mShowing) {
            // If we were showing the bouncer and then aborting, we need to also clear out any
            // potential actions unless we actually unlocked.
            mAfterKeyguardGoneAction = null;
            if (mKeyguardGoneCancelAction != null) {
                mKeyguardGoneCancelAction.run();
                mKeyguardGoneCancelAction = null;
            }
        }
        mBouncer.hide(destroyView);
        cancelPendingWakeupAction();
    }
@@ -365,6 +378,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
                mBouncer.showWithDismissAction(r, cancelAction);
            } else {
                mAfterKeyguardGoneAction = r;
                mKeyguardGoneCancelAction = cancelAction;
                mBouncer.show(false /* resetSecuritySelection */);
            }
        }
@@ -672,6 +686,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
            mAfterKeyguardGoneAction.onDismiss();
            mAfterKeyguardGoneAction = null;
        }
        mKeyguardGoneCancelAction = null;
        for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
            mAfterKeyguardGoneRunnables.get(i).run();
        }
+25 −0
Original line number Diff line number Diff line
@@ -227,6 +227,31 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
        verify(mStatusBar, never()).animateKeyguardUnoccluding();
    }

    @Test
    public void testHiding_cancelsGoneRunnable() {
        OnDismissAction action = mock(OnDismissAction.class);
        Runnable cancelAction = mock(Runnable.class);
        mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
                true /* afterKeyguardGone */);

        mStatusBarKeyguardViewManager.hideBouncer(true);
        mStatusBarKeyguardViewManager.hide(0, 30);
        verify(action, never()).onDismiss();
        verify(cancelAction).run();
    }

    @Test
    public void testHiding_doesntCancelWhenShowing() {
        OnDismissAction action = mock(OnDismissAction.class);
        Runnable cancelAction = mock(Runnable.class);
        mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
                true /* afterKeyguardGone */);

        mStatusBarKeyguardViewManager.hide(0, 30);
        verify(action).onDismiss();
        verify(cancelAction, never()).run();
    }

    private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {

        public TestableStatusBarKeyguardViewManager(Context context,