Request focus when pin is visible

Change-Id: Idfa7f0ea7f989de95030ed9dbd0ac4b45abc8155
Fixes: 77963692
Fixes: 78187153
Fixes: 78235570
Fixes: 78887466
Test: atest tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
Test: atest tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
Test: atest android.server.am.ActivityManagerDisplayLockedKeyguardTests#testDismissKeyguard_whileOccluded_secondaryDisplay
Test: atest -dt android.server.am.KeyguardLockedTests#testEnterPipOverKeyguard
Test: go/sysui-bouncer-tests
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 7cc37c4..81cf3ae 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -140,12 +140,6 @@
         mImm.hideSoftInputFromWindow(getWindowToken(), 0);
     }
 
-    @Override
-    public void reset() {
-        super.reset();
-        mPasswordEntry.requestFocus();
-    }
-
     private void updateSwitchImeButton() {
         // If there's more than one IME, enable the IME switcher button
         final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE;
@@ -193,8 +187,6 @@
         // Set selected property on so the view can send accessibility events.
         mPasswordEntry.setSelected(true);
 
-        mPasswordEntry.requestFocus();
-
         mSwitchImeButton = findViewById(R.id.switch_ime_button);
         mSwitchImeButton.setOnClickListener(new OnClickListener() {
             @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 1d3f9a1..a2befef 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,13 +23,16 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * A Pin based Keyguard input view
  */
 public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
         implements View.OnKeyListener, View.OnTouchListener {
 
-    protected PasswordTextView mPasswordEntry;
+    @VisibleForTesting
+    PasswordTextView mPasswordEntry;
     private View mOkButton;
     private View mDeleteButton;
     private View mButton0;
@@ -52,12 +55,6 @@
     }
 
     @Override
-    public void reset() {
-        mPasswordEntry.requestFocus();
-        super.reset();
-    }
-
-    @Override
     protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
         // send focus to the password field
         return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
@@ -238,6 +235,12 @@
     }
 
     @Override
+    public void onResume(int reason) {
+        super.onResume(reason);
+        mPasswordEntry.requestFocus();
+    }
+
+    @Override
     public boolean onTouch(View v, MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
             doHapticKeyClick();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3e01aec..f134151 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -54,6 +54,8 @@
 
     private static final String TAG = "KeyguardBouncer";
     static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
+    private static final float EXPANSION_HIDDEN = 1f;
+    private static final float EXPANSION_VISIBLE = 0f;
 
     protected final Context mContext;
     protected final ViewMediatorCallback mCallback;
@@ -71,10 +73,15 @@
                 }
             };
     private final Runnable mRemoveViewRunnable = this::removeView;
+    protected KeyguardHostView mKeyguardView;
+    private final Runnable mResetRunnable = ()-> {
+        if (mKeyguardView != null) {
+            mKeyguardView.reset();
+        }
+    };
 
     private int mStatusBarHeight;
-    private float mExpansion;
-    protected KeyguardHostView mKeyguardView;
+    private float mExpansion = EXPANSION_HIDDEN;
     protected ViewGroup mRoot;
     private boolean mShowingSoon;
     private int mBouncerPromptReason;
@@ -96,7 +103,7 @@
     }
 
     public void show(boolean resetSecuritySelection) {
-        show(resetSecuritySelection, true /* notifyFalsing */);
+        show(resetSecuritySelection, true /* animated */);
     }
 
     /**
@@ -120,8 +127,7 @@
         // Later, at the end of the animation, when the bouncer is at the top of the screen,
         // onFullyShown() will be called and FalsingManager will stop recording touches.
         if (animated) {
-            mFalsingManager.onBouncerShown();
-            setExpansion(0);
+            setExpansion(EXPANSION_VISIBLE);
         }
 
         if (resetSecuritySelection) {
@@ -152,6 +158,7 @@
         mShowingSoon = true;
 
         // Split up the work over multiple frames.
+        DejankUtils.removeCallbacks(mResetRunnable);
         DejankUtils.postAfterTraversal(mShowRunnable);
 
         mCallback.onBouncerVisiblityChanged(true /* shown */);
@@ -181,6 +188,7 @@
                 mRoot.setVisibility(View.INVISIBLE);
             }
             mFalsingManager.onBouncerHidden();
+            DejankUtils.postAfterTraversal(mResetRunnable);
         }
     }
 
@@ -210,6 +218,9 @@
                 mKeyguardView.requestLayout();
             }
             mShowingSoon = false;
+            if (mExpansion == EXPANSION_VISIBLE) {
+                mKeyguardView.onResume();
+            }
             StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
                 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
         }
@@ -303,7 +314,7 @@
 
     public boolean isShowing() {
         return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
-                && mExpansion == 0 && !isAnimatingAway();
+                && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
     }
 
     /**
@@ -337,10 +348,10 @@
             mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
         }
 
-        if (fraction == 0 && oldExpansion != 0) {
+        if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
             onFullyShown();
             mExpansionCallback.onFullyShown();
-        } else if (fraction == 1 && oldExpansion != 0) {
+        } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
             onFullyHidden();
             mExpansionCallback.onFullyHidden();
         }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
new file mode 100644
index 0000000..e79c9d0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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.keyguard;
+
+import static org.mockito.Mockito.verify;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+public class KeyguardPinBasedInputViewTest extends SysuiTestCase {
+
+    @Mock
+    private PasswordTextView mPasswordTextView;
+    private KeyguardPinBasedInputView mKeyguardPinView;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        LayoutInflater inflater = LayoutInflater.from(getContext());
+        mKeyguardPinView =
+                (KeyguardPinBasedInputView) inflater.inflate(R.layout.keyguard_pin_view, null);
+        mKeyguardPinView.mPasswordEntry = mPasswordTextView;
+    }
+
+    @Test
+    public void onResume_requestsFocus() {
+        mKeyguardPinView.onResume(KeyguardSecurityView.SCREEN_ON);
+        verify(mPasswordTextView).requestFocus();
+    }
+}