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

Commit 6aeb1399 authored by Bryce Lee's avatar Bryce Lee
Browse files

Check for non-interactive dreams when wake and unlocking.

BiometricUnlockController coordinates with KeyguardViewMediator for
ordering the wake and unlock actions, necessary for non-doze/aod dreams.
Currently, the StatusBarStateController is consulted for the doze state.
However, this value can be out of sync with the current state. This
change instead checks the dream interactivity through PowerManager,
which provides a consistent signal for this state. This change also
ensures BiometricUnlockController and KeyguardViewMediator are in sync
on this state with biometricUnlockController informing
KeyguardViewMediator of the dream state in onWakingAndUnlocking, rather
than KeyguardViewMediator calculating this later in handleHide(). This
prevents inconsistencies from state changes between these two method
invocations.

This changelist also improves the logging around wake and unlock in
KeyguardViewMediator.

Test: atest KeyguardViewMediatorTest#testWakeAndUnlockingOverNonInteractiveDream_noWakeByKeyguardViewMediator
Fixes: 293159518
Fixes: 293464892
Change-Id: Iaffbb53b29578c0575a7737c8aacdc8ca547b426
Merged-In: Iaffbb53b29578c0575a7737c8aacdc8ca547b426
parent 134966d7
Loading
Loading
Loading
Loading
+77 −5
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ import android.view.WindowManagerPolicyConstants;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -173,6 +174,8 @@ import com.android.wm.shell.keyguard.KeyguardTransitions;
import dagger.Lazy;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
@@ -257,6 +260,22 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
    private static final int SYSTEM_READY = 18;
    private static final int CANCEL_KEYGUARD_EXIT_ANIM = 19;

    /** Enum for reasons behind updating wakeAndUnlock state. */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(
            value = {
                    WakeAndUnlockUpdateReason.HIDE,
                    WakeAndUnlockUpdateReason.SHOW,
                    WakeAndUnlockUpdateReason.FULFILL,
                    WakeAndUnlockUpdateReason.WAKE_AND_UNLOCK,
            })
    @interface WakeAndUnlockUpdateReason {
        int HIDE = 0;
        int SHOW = 1;
        int FULFILL = 2;
        int WAKE_AND_UNLOCK = 3;
    }

    /**
     * The default amount of time we stay awake (used for all key input)
     */
@@ -808,7 +827,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
            // dreaming. It's time to wake up.
            if (mUnlockingAndWakingFromDream) {
                Log.d(TAG, "waking from dream after unlock");
                mUnlockingAndWakingFromDream = false;
                setUnlockAndWakeFromDream(false, WakeAndUnlockUpdateReason.FULFILL);

                if (mKeyguardStateController.isShowing()) {
                    Log.d(TAG, "keyguard showing after keyguardGone, dismiss");
@@ -2693,7 +2712,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,

            mKeyguardExitAnimationRunner = null;
            mWakeAndUnlocking = false;
            mUnlockingAndWakingFromDream = false;
            setUnlockAndWakeFromDream(false, WakeAndUnlockUpdateReason.SHOW);
            setPendingLock(false);

            // Force if we we're showing in the middle of hiding, to ensure we end up in the correct
@@ -2799,6 +2818,51 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
        tryKeyguardDone();
    };

    private void setUnlockAndWakeFromDream(boolean updatedValue,
            @WakeAndUnlockUpdateReason int reason) {
        if (updatedValue == mUnlockingAndWakingFromDream) {
            return;
        }

        final String reasonDescription;

        switch(reason) {
            case WakeAndUnlockUpdateReason.FULFILL:
                reasonDescription = "fulfilling existing request";
                break;
            case WakeAndUnlockUpdateReason.HIDE:
                reasonDescription = "hiding keyguard";
                break;
            case WakeAndUnlockUpdateReason.SHOW:
                reasonDescription = "showing keyguard";
                break;
            case WakeAndUnlockUpdateReason.WAKE_AND_UNLOCK:
                reasonDescription = "waking to unlock";
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + reason);
        }

        final boolean unsetUnfulfilled = !updatedValue
                && reason != WakeAndUnlockUpdateReason.FULFILL;

        mUnlockingAndWakingFromDream = updatedValue;

        final String description;

        if (unsetUnfulfilled) {
            description = "Interrupting request to wake and unlock";
        } else if (mUnlockingAndWakingFromDream) {
            description = "Initiating request to wake and unlock";
        } else {
            description = "Fulfilling request to wake and unlock";
        }

        Log.d(TAG, String.format(
                "Updating waking and unlocking request to %b. description:[%s]. reason:[%s]",
                mUnlockingAndWakingFromDream,  description, reasonDescription));
    }

    /**
     * Handle message sent by {@link #hideLocked()}
     * @see #HIDE
@@ -2816,8 +2880,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
        synchronized (KeyguardViewMediator.this) {
            if (DEBUG) Log.d(TAG, "handleHide");

            mUnlockingAndWakingFromDream = mStatusBarStateController.isDreaming()
                && !mStatusBarStateController.isDozing();
            // If waking and unlocking, waking from dream has been set properly.
            if (!mWakeAndUnlocking) {
                setUnlockAndWakeFromDream(mStatusBarStateController.isDreaming()
                        && mPM.isInteractive(), WakeAndUnlockUpdateReason.HIDE);
            }

            if ((mShowing && !mOccluded) || mUnlockingAndWakingFromDream) {
                if (mUnlockingAndWakingFromDream) {
@@ -3319,9 +3386,14 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
        }
    }

    public void onWakeAndUnlocking() {
    /**
     * Informs the keyguard view mediator that the device is waking and unlocking.
     * @param fromDream Whether waking and unlocking is happening over an interactive dream.
     */
    public void onWakeAndUnlocking(boolean fromDream) {
        Trace.beginSection("KeyguardViewMediator#onWakeAndUnlocking");
        mWakeAndUnlocking = true;
        setUnlockAndWakeFromDream(fromDream, WakeAndUnlockUpdateReason.WAKE_AND_UNLOCK);

        mKeyguardViewControllerLazy.get().notifyKeyguardAuthenticated(/* primaryAuth */ false);
        userActivity();
+2 −2
Original line number Diff line number Diff line
@@ -471,7 +471,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        };

        final boolean wakingFromDream = mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM
                && !mStatusBarStateController.isDozing();
                && mPowerManager.isInteractive();

        if (mMode != MODE_NONE && !wakingFromDream) {
            wakeUp.run();
@@ -509,7 +509,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
                    // later to awaken.
                }
                mNotificationShadeWindowController.setNotificationShadeFocusable(false);
                mKeyguardViewMediator.onWakeAndUnlocking();
                mKeyguardViewMediator.onWakeAndUnlocking(wakingFromDream);
                Trace.endSection();
                break;
            case MODE_ONLY_WAKE:
+35 −4
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        TestableLooper.get(this).processAllMessages();

        mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
        mViewMediator.onWakeAndUnlocking();
        mViewMediator.onWakeAndUnlocking(false);
        mViewMediator.onStartedWakingUp(OFF_BECAUSE_OF_USER, false);
        TestableLooper.get(this).processAllMessages();

@@ -378,6 +378,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        mViewMediator.onSystemReady();
        TestableLooper.get(this).processAllMessages();

        when(mPowerManager.isInteractive()).thenReturn(true);

        // Given device is dreaming
        when(mUpdateMonitor.isDreaming()).thenReturn(true);

@@ -717,14 +719,14 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {

    @Test
    public void testWakeAndUnlocking() {
        mViewMediator.onWakeAndUnlocking();
        mViewMediator.onWakeAndUnlocking(false);
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
    }

    @Test
    public void testWakeAndUnlockingOverDream() {
        // Send signal to wake
        mViewMediator.onWakeAndUnlocking();
        mViewMediator.onWakeAndUnlocking(true);

        // Ensure not woken up yet
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
@@ -753,7 +755,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
    @Test
    public void testWakeAndUnlockingOverDream_signalAuthenticateIfStillShowing() {
        // Send signal to wake
        mViewMediator.onWakeAndUnlocking();
        mViewMediator.onWakeAndUnlocking(true);

        // Ensure not woken up yet
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
@@ -782,6 +784,35 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
    }

    @Test
    public void testWakeAndUnlockingOverNonInteractiveDream_noWakeByKeyguardViewMediator() {
        // Send signal to wake
        mViewMediator.onWakeAndUnlocking(false);

        // Ensure not woken up yet
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());

        // Verify keyguard told of authentication
        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(anyBoolean());
        mViewMediator.mViewMediatorCallback.keyguardDonePending(true,
                mUpdateMonitor.getCurrentUser());
        mViewMediator.mViewMediatorCallback.readyForKeyguardDone();
        final ArgumentCaptor<Runnable> animationRunnableCaptor =
                ArgumentCaptor.forClass(Runnable.class);
        verify(mStatusBarKeyguardViewManager).startPreHideAnimation(
                animationRunnableCaptor.capture());

        when(mStatusBarStateController.isDreaming()).thenReturn(true);
        when(mStatusBarStateController.isDozing()).thenReturn(false);
        animationRunnableCaptor.getValue().run();

        when(mKeyguardStateController.isShowing()).thenReturn(false);
        mViewMediator.mViewMediatorCallback.keyguardGone();

        // Verify not woken up.
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
    }

    @Test
    @TestableLooper.RunWithLooper(setAsMainLooper = true)
    public void testDoKeyguardWhileInteractive_resets() {
+4 −3
Original line number Diff line number Diff line
@@ -199,7 +199,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);

        verify(mKeyguardViewMediator).onWakeAndUnlocking();
        verify(mKeyguardViewMediator).onWakeAndUnlocking(false);
        assertThat(mBiometricUnlockController.getMode())
                .isEqualTo(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
    }
@@ -217,7 +217,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);

        verify(mKeyguardViewMediator).onWakeAndUnlocking();
        verify(mKeyguardViewMediator).onWakeAndUnlocking(false);
        assertThat(mBiometricUnlockController.getMode())
                .isEqualTo(MODE_WAKE_AND_UNLOCK);
    }
@@ -671,8 +671,9 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
        when(mWakefulnessLifecycle.getLastWakeReason())
                .thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
        givenDreamingLocked();
        when(mPowerManager.isInteractive()).thenReturn(true);
        mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT, true);
        verify(mKeyguardViewMediator).onWakeAndUnlocking();
        verify(mKeyguardViewMediator).onWakeAndUnlocking(true);
        // Ensure that the power hasn't been told to wake up yet.
        verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString());
    }