From 9ce60a5ab86d443ebe71b3e8681df7de004d729b Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Wed, 30 Nov 2022 09:47:28 -0800 Subject: [PATCH] [Bouncer] hide/show keyboard when focus is... regained. For the bonuncer, often times the UDFPS overlay, or AOD can take the window focus. This will prevent the window of the bouncer from sending signals to the input manager to hide/show the keyboard. Add an override method for the password view to show or hide the keyboard contingent upon the visibility of the view. Also refocus edit text when changing orientation of device. Fixes: 259552291 Test: Open scrimmed bouncer from AOD. Test: Open bouncer and hide bouncer a bunch. Test: Open bouncer from udfps overlay. Test: Unit test. Test: change view mode from landscape to portrait when on bouncer on tablet. Change-Id: Ic30099408086f6dcc63506cac6ca2fb015504d17 --- .../keyguard/KeyguardPasswordView.java | 47 +++++++++++++++++++ .../KeyguardPasswordViewController.java | 18 ++----- .../KeyguardPasswordViewControllerTest.kt | 20 +++++++- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index 2cc5ccdc3fa13..c985fd7bef828 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -34,6 +34,7 @@ import android.graphics.Insets; import android.graphics.Rect; import android.os.Trace; import android.util.AttributeSet; +import android.view.WindowInsets; import android.view.WindowInsetsAnimationControlListener; import android.view.WindowInsetsAnimationController; import android.view.animation.AnimationUtils; @@ -236,4 +237,50 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { return getResources().getString( com.android.internal.R.string.keyguard_accessibility_password_unlock); } + + @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + if (!mPasswordEntry.isFocused() && isVisibleToUser()) { + mPasswordEntry.requestFocus(); + } + return super.onApplyWindowInsets(insets); + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + if (hasWindowFocus) { + if (isVisibleToUser()) { + showKeyboard(); + } else { + hideKeyboard(); + } + } + } + + /** + * Sends signal to the focused window to show the keyboard. + */ + public void showKeyboard() { + post(() -> { + if (mPasswordEntry.isAttachedToWindow() + && !mPasswordEntry.getRootWindowInsets().isVisible(WindowInsets.Type.ime())) { + mPasswordEntry.requestFocus(); + mPasswordEntry.getWindowInsetsController().show(WindowInsets.Type.ime()); + } + }); + } + + /** + * Sends signal to the focused window to hide the keyboard. + */ + public void hideKeyboard() { + post(() -> { + if (mPasswordEntry.isAttachedToWindow() + && mPasswordEntry.getRootWindowInsets().isVisible(WindowInsets.Type.ime())) { + mPasswordEntry.clearFocus(); + mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime()); + } + }); + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java index 0025986c0e5c3..4d1afed5dbd21 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java @@ -27,7 +27,6 @@ import android.text.method.TextKeyListener; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; -import android.view.WindowInsets; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -214,12 +213,9 @@ public class KeyguardPasswordViewController return; } - mView.post(() -> { - if (mView.isShown()) { - mPasswordEntry.requestFocus(); - mPasswordEntry.getWindowInsetsController().show(WindowInsets.Type.ime()); - } - }); + if (mView.isShown()) { + mView.showKeyboard(); + } } @Override @@ -241,16 +237,12 @@ public class KeyguardPasswordViewController super.onPause(); }); } - if (mPasswordEntry.isAttachedToWindow()) { - mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime()); - } + mView.hideKeyboard(); } @Override public void onStartingToHide() { - if (mPasswordEntry.isAttachedToWindow()) { - mPasswordEntry.getWindowInsetsController().hide(WindowInsets.Type.ime()); - } + mView.hideKeyboard(); } private void updateSwitchImeButton() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt index ffd95f4041f96..d20be56d6c6b3 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt @@ -19,6 +19,7 @@ package com.android.keyguard import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.inputmethod.InputMethodManager +import android.widget.EditText import androidx.test.filters.SmallTest import com.android.internal.util.LatencyTracker import com.android.internal.widget.LockPatternUtils @@ -43,6 +44,8 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { @Mock private lateinit var keyguardPasswordView: KeyguardPasswordView @Mock + private lateinit var passwordEntry: EditText + @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Mock lateinit var securityMode: KeyguardSecurityModel.SecurityMode @@ -81,6 +84,9 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { ).thenReturn(mKeyguardMessageArea) Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea)) .thenReturn(mKeyguardMessageAreaController) + Mockito.`when`(keyguardPasswordView.passwordTextViewId).thenReturn(R.id.passwordEntry) + Mockito.`when`(keyguardPasswordView.findViewById(R.id.passwordEntry) + ).thenReturn(passwordEntry) keyguardPasswordViewController = KeyguardPasswordViewController( keyguardPasswordView, keyguardUpdateMonitor, @@ -103,7 +109,10 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(true) Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true) keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED) - keyguardPasswordView.post { verify(keyguardPasswordView).requestFocus() } + keyguardPasswordView.post { + verify(keyguardPasswordView).requestFocus() + verify(keyguardPasswordView).showKeyboard() + } } @Test @@ -114,6 +123,15 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { verify(keyguardPasswordView, never()).requestFocus() } + @Test + fun testHideKeyboardWhenOnPause() { + keyguardPasswordViewController.onPause() + keyguardPasswordView.post { + verify(keyguardPasswordView).clearFocus() + verify(keyguardPasswordView).hideKeyboard() + } + } + @Test fun startAppearAnimation() { keyguardPasswordViewController.startAppearAnimation()