Ensure keyboard is hidden when bouncer is...

not showing. There are still cases where the keyboard will show. The
most common case that I have observed is that when the falsing manager
closes the bouncer after detecting a potential false touch. This can be
done by clicking on a notification, and double tapping the alternate
boucner overlay twice very quickly. The issue is that when we send a
signal to show the keyboard, there is no way to stop that signal before
the keyboard shows (from my understanding).

The solution here is to listen to onApplyWindowInsets, which is called
when the keyboard shows, and hide the keyboard if the bouncer is not
showing.

Fixes: 266816405
Test: Test as described above.
Change-Id: I71419781ab91d8a1404d3571cd7e7d16b2a3afc9
This commit is contained in:
Aaron Liu
2023-02-23 15:49:35 -08:00
parent feb16cb218
commit 8d0f687b31
2 changed files with 29 additions and 1 deletions

View File

@@ -26,6 +26,7 @@ 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;
@@ -156,6 +157,15 @@ public class KeyguardPasswordViewController
// TODO: Remove this workaround by ensuring such a race condition never happens.
mMainExecutor.executeDelayed(
this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
mView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
if (!mKeyguardViewController.isBouncerShowing()) {
mView.hideKeyboard();
}
return insets;
}
});
}
@Override

View File

@@ -18,8 +18,10 @@ package com.android.keyguard
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
@@ -30,6 +32,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
@@ -37,6 +40,7 @@ import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
@@ -76,7 +80,9 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
.thenReturn(passwordEntry)
`when`(keyguardPasswordView.resources).thenReturn(context.resources)
keyguardPasswordViewController =
`when`(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
.thenReturn(mock(ImageView::class.java))
keyguardPasswordViewController =
KeyguardPasswordViewController(
keyguardPasswordView,
keyguardUpdateMonitor,
@@ -112,6 +118,18 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
verify(keyguardPasswordView, never()).requestFocus()
}
@Test
fun onApplyWindowInsetsListener_onApplyWindowInsets() {
`when`(keyguardViewController.isBouncerShowing).thenReturn(false)
val argumentCaptor = ArgumentCaptor.forClass(View.OnApplyWindowInsetsListener::class.java)
keyguardPasswordViewController.onViewAttached()
verify(keyguardPasswordView).setOnApplyWindowInsetsListener(argumentCaptor.capture())
argumentCaptor.value.onApplyWindowInsets(keyguardPasswordView, null)
verify(keyguardPasswordView).hideKeyboard()
}
@Test
fun testHideKeyboardWhenOnPause() {
keyguardPasswordViewController.onPause()