Fix pin error scenario for talkback.
There were a couple of issues with the accessibility of the wrong pin scenario. 1. the user activity signal from the password view is trying to set the error message to an empty string. Move setting the error message to after resetting the password view. 2. No text is set yet while we are animating the view and this prevents the text from being announced. I remedied this by relying on a textwatcher to keep track of the textview. 3. The password view is constantly being selected, which shouldn't really be the case. This is because we set the input to be disabled as we check the password and re-enable it. While in this process, we requestfocus if focus is not on the password view. 4. For some reason we set the textview to "wrong pin" and then immediately an empty string. There is a 250ms delay to make the accessibility announcement. After 250ms, we want to ensure that the text is still displayed in the textview. Consequently, once a wrong pin in inputted, the only talkback text is now "Wrong Pin" Fixes: 281635711 Fixes: 281787557 Test: wrong pin scenario in bouncer. Test: password, simpin, and sim puk views. Change-Id: I018e067e0a3b17fbd7921f40924ced401707297c
This commit is contained in:
@@ -179,10 +179,10 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
|
||||
handleAttemptLockout(deadline);
|
||||
}
|
||||
}
|
||||
mView.resetPasswordText(true /* animate */, false /* announce deletion if no match */);
|
||||
if (timeoutMs == 0) {
|
||||
mMessageAreaController.setMessage(mView.getWrongPasswordStringId());
|
||||
}
|
||||
mView.resetPasswordText(true /* animate */, false /* announce deletion if no match */);
|
||||
startErrorAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.android.keyguard;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -45,6 +47,31 @@ public class KeyguardMessageAreaController<T extends KeyguardMessageArea>
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final ConfigurationController mConfigurationController;
|
||||
private final AnnounceRunnable mAnnounceRunnable;
|
||||
private final TextWatcher mTextWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
CharSequence msg = editable;
|
||||
if (!TextUtils.isEmpty(msg)) {
|
||||
mView.removeCallbacks(mAnnounceRunnable);
|
||||
mAnnounceRunnable.setTextToAnnounce(msg);
|
||||
mView.postDelayed(() -> {
|
||||
if (msg == mView.getText()) {
|
||||
mAnnounceRunnable.run();
|
||||
}
|
||||
}, ANNOUNCEMENT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
/* no-op */
|
||||
}
|
||||
};
|
||||
|
||||
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
|
||||
public void onFinishedGoingToSleep(int why) {
|
||||
@@ -89,12 +116,14 @@ public class KeyguardMessageAreaController<T extends KeyguardMessageArea>
|
||||
mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
|
||||
mView.setSelected(mKeyguardUpdateMonitor.isDeviceInteractive());
|
||||
mView.onThemeChanged();
|
||||
mView.addTextChangedListener(mTextWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
mConfigurationController.removeCallback(mConfigurationListener);
|
||||
mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
|
||||
mView.removeTextChangedListener(mTextWatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,12 +142,6 @@ public class KeyguardMessageAreaController<T extends KeyguardMessageArea>
|
||||
*/
|
||||
public void setMessage(CharSequence s, boolean animate) {
|
||||
mView.setMessage(s, animate);
|
||||
CharSequence msg = mView.getText();
|
||||
if (!TextUtils.isEmpty(msg)) {
|
||||
mView.removeCallbacks(mAnnounceRunnable);
|
||||
mAnnounceRunnable.setTextToAnnounce(msg);
|
||||
mView.postDelayed(mAnnounceRunnable, ANNOUNCEMENT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMessage(int resId) {
|
||||
|
||||
@@ -82,9 +82,6 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
|
||||
protected void setPasswordEntryInputEnabled(boolean enabled) {
|
||||
mPasswordEntry.setEnabled(enabled);
|
||||
mOkButton.setEnabled(enabled);
|
||||
if (enabled && !mPasswordEntry.hasFocus()) {
|
||||
mPasswordEntry.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,8 @@ import static org.mockito.Mockito.when;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
@@ -93,16 +95,16 @@ public class KeyguardMessageAreaControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessage_AnnounceForAccessibility() {
|
||||
ArgumentCaptor<Runnable> argumentCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
when(mKeyguardMessageArea.getText()).thenReturn("abc");
|
||||
mMessageAreaController.setMessage("abc");
|
||||
public void textChanged_AnnounceForAccessibility() {
|
||||
ArgumentCaptor<TextWatcher> textWatcherArgumentCaptor = ArgumentCaptor.forClass(
|
||||
TextWatcher.class);
|
||||
mMessageAreaController.onViewAttached();
|
||||
verify(mKeyguardMessageArea).addTextChangedListener(textWatcherArgumentCaptor.capture());
|
||||
|
||||
verify(mKeyguardMessageArea).setMessage("abc", /* animate= */ true);
|
||||
textWatcherArgumentCaptor.getValue().afterTextChanged(
|
||||
Editable.Factory.getInstance().newEditable("abc"));
|
||||
verify(mKeyguardMessageArea).removeCallbacks(any(Runnable.class));
|
||||
verify(mKeyguardMessageArea).postDelayed(argumentCaptor.capture(), anyLong());
|
||||
argumentCaptor.getValue().run();
|
||||
verify(mKeyguardMessageArea).announceForAccessibility("abc");
|
||||
verify(mKeyguardMessageArea).postDelayed(any(Runnable.class), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user