Fix fingerprint listening delay when locking phone

Currently, when the user presses the power button to lock their phone,
there's a delay before the device starts listening for fingerprint to
unclock the phone again. This commit resets the keyguard going away
state earlier when the phone is going to sleep in order to remove this
delay. It also adds a new unit test to exercise this behavior.

Test: atest KeyguardViewMediatorTest
Test: Lock screen, quickly tap fingerprint, verify there is no delay

Fixes: 141445468
Change-Id: Ib2f7d956122eec39e5164e865001a08fa70f47cc
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e0270de..5e38f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -68,6 +68,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
@@ -685,16 +686,22 @@
             Context context,
             FalsingManager falsingManager,
             LockPatternUtils lockPatternUtils) {
+        this(context, falsingManager, lockPatternUtils, SystemUIFactory.getInstance());
+    }
+
+    @VisibleForTesting
+    KeyguardViewMediator(
+            Context context,
+            FalsingManager falsingManager,
+            LockPatternUtils lockPatternUtils,
+            SystemUIFactory systemUIFactory) {
         super(context);
-
         mFalsingManager = falsingManager;
-
         mLockPatternUtils = lockPatternUtils;
-        mStatusBarKeyguardViewManager =
-                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(
-                        mContext,
-                        mViewMediatorCallback,
-                        mLockPatternUtils);
+        mStatusBarKeyguardViewManager = systemUIFactory.createStatusBarKeyguardViewManager(
+                mContext,
+                mViewMediatorCallback,
+                mLockPatternUtils);
     }
 
     public void userActivity() {
@@ -826,6 +833,9 @@
             mDeviceInteractive = false;
             mGoingToSleep = true;
 
+            // Reset keyguard going away state so we can start listening for biometric auth
+            setKeyguardGoingAway(false);
+
             // Lock immediately based on setting if secure (user has a pin/pattern/password).
             // This also "locks" the device when not secure to provide easy access to the
             // camera while preventing unwanted input.
@@ -1572,12 +1582,14 @@
                     handleNotifyFinishedGoingToSleep();
                     break;
                 case NOTIFY_SCREEN_TURNING_ON:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
                     handleNotifyScreenTurningOn((IKeyguardDrawnCallback) msg.obj);
                     Trace.endSection();
                     break;
                 case NOTIFY_SCREEN_TURNED_ON:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
                     handleNotifyScreenTurnedOn();
                     Trace.endSection();
                     break;
@@ -1585,7 +1597,8 @@
                     handleNotifyScreenTurnedOff();
                     break;
                 case NOTIFY_STARTED_WAKING_UP:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
                     handleNotifyStartedWakingUp();
                     Trace.endSection();
                     break;
@@ -1614,14 +1627,16 @@
                     handleDismiss(message.getCallback(), message.getMessage());
                     break;
                 case START_KEYGUARD_EXIT_ANIM:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
                     StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
                     handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
                     mFalsingManager.onSucccessfulUnlock();
                     Trace.endSection();
                     break;
                 case KEYGUARD_DONE_PENDING_TIMEOUT:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE_PENDING_TIMEOUT");
+                    Trace.beginSection("KeyguardViewMediator#handleMessage"
+                            + " KEYGUARD_DONE_PENDING_TIMEOUT");
                     Log.w(TAG, "Timeout while waiting for activity drawn!");
                     Trace.endSection();
                     break;
@@ -1799,8 +1814,7 @@
             mHideAnimationRun = false;
             adjustStatusBarLocked();
             userActivity();
-            mUpdateMonitor.setKeyguardGoingAway(false /* away */);
-            mStatusBarWindowController.setKeyguardGoingAway(false /* goingAway */);
+            setKeyguardGoingAway(false);
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
@@ -1832,8 +1846,7 @@
                         .KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
             }
 
-            mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
-            mStatusBarWindowController.setKeyguardGoingAway(true /* goingAway */);
+            setKeyguardGoingAway(true);
 
             // Don't actually hide the Keyguard at the moment, wait for window
             // manager until it tells us it's safe to do so with
@@ -2068,6 +2081,11 @@
         mHandler.removeMessages(KEYGUARD_DONE_PENDING_TIMEOUT);
     }
 
+    private void setKeyguardGoingAway(boolean goingAway) {
+        mUpdateMonitor.setKeyguardGoingAway(goingAway);
+        mStatusBarWindowController.setKeyguardGoingAway(goingAway);
+    }
+
     @Override
     public void onBootCompleted() {
         mUpdateMonitor.dispatchBootCompleted();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
new file mode 100644
index 0000000..c385e8f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard;
+
+import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class KeyguardViewMediatorTest extends SysuiTestCase {
+    private KeyguardViewMediator mViewMediator;
+
+    private @Mock DevicePolicyManager mDevicePolicyManager;
+    private @Mock LockPatternUtils mLockPatternUtils;
+    private @Mock KeyguardUpdateMonitor mUpdateMonitor;
+    private @Mock StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private @Mock StatusBarWindowController mStatusBarWindowController;
+    private @Mock SystemUIFactory mSystemUIFactory;
+
+    private FalsingManagerFake mFalsingManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mFalsingManager = new FalsingManagerFake();
+
+        mDependency.injectTestDependency(FalsingManager.class, mFalsingManager);
+        mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
+        mDependency.injectTestDependency(StatusBarWindowController.class,
+                mStatusBarWindowController);
+
+        when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+        when(mSystemUIFactory.createStatusBarKeyguardViewManager(
+                any(Context.class),
+                any(ViewMediatorCallback.class),
+                any(LockPatternUtils.class))).thenReturn(mStatusBarKeyguardViewManager);
+
+        TestableLooper.get(this).runWithLooper(() -> {
+            mViewMediator = new KeyguardViewMediator(
+                    mContext, mFalsingManager, mLockPatternUtils, mSystemUIFactory);
+        });
+    }
+
+    @Test
+    public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
+        mViewMediator.start();
+        mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
+        verify(mUpdateMonitor).setKeyguardGoingAway(false);
+        verify(mStatusBarWindowController).setKeyguardGoingAway(false);
+    }
+}