8/n: Ensure accessibility works on new implementation
Bug: 123378871 Test: manual test with talkback enabled Change-Id: I7f4da76ef7ebcbb74f1984b2859b85aa72e8d946
This commit is contained in:
@@ -23,7 +23,8 @@
|
||||
android:id="@+id/background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/biometric_dialog_dim_color"/>
|
||||
android:background="@color/biometric_dialog_dim_color"
|
||||
android:contentDescription="@string/biometric_dialog_empty_space_description"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/panel"
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
<!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR LIMIT=30] -->
|
||||
<string name="biometric_dialog_try_again">Try again</string>
|
||||
<!-- Content description for empty spaces that are not taken by the biometric dialog. Clicking on these areas will cancel authentication and dismiss the biometric dialog [CHAR LIMIT=NONE] -->
|
||||
<string name="biometric_dialog_empty_space_description">Empty region, tap to cancel authentication</string>
|
||||
<string name="biometric_dialog_empty_space_description">Tap to cancel authentication</string>
|
||||
<!-- Content description for the face icon when the device is not authenticating anymore [CHAR LIMIT=NONE] -->
|
||||
<string name="biometric_dialog_face_icon_description_idle">Please try again</string>
|
||||
<!-- Content description for the face icon when the device is authenticating [CHAR LIMIT=NONE] -->
|
||||
@@ -305,6 +305,8 @@
|
||||
<string name="biometric_dialog_face_icon_description_confirmed">Confirmed</string>
|
||||
<!-- Message shown when a biometric is authenticated, waiting for the user to confirm authentication [CHAR LIMIT=40]-->
|
||||
<string name="biometric_dialog_tap_confirm">Tap Confirm to complete</string>
|
||||
<!-- Talkback string when a biometric is authenticated [CHAR LIMIT=NONE] -->
|
||||
<string name="biometric_dialog_authenticated">Authenticated</string>
|
||||
|
||||
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
|
||||
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
|
||||
|
||||
@@ -111,8 +111,12 @@ public class AuthBiometricFaceView extends AuthBiometricView {
|
||||
R.string.biometric_dialog_face_icon_description_confirmed));
|
||||
} else if (lastStateIsErrorIcon && newState == STATE_IDLE) {
|
||||
animateOnce(R.drawable.face_dialog_error_to_idle);
|
||||
mIconView.setContentDescription(mContext.getString(
|
||||
R.string.biometric_dialog_face_icon_description_idle));
|
||||
} else if (lastStateIsErrorIcon && newState == STATE_AUTHENTICATED) {
|
||||
animateOnce(R.drawable.face_dialog_dark_to_checkmark);
|
||||
mIconView.setContentDescription(mContext.getString(
|
||||
R.string.biometric_dialog_face_icon_description_authenticated));
|
||||
} else if (newState == STATE_ERROR && lastState != STATE_ERROR) {
|
||||
animateOnce(R.drawable.face_dialog_dark_to_error);
|
||||
} else if (lastState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
|
||||
@@ -125,6 +129,8 @@ public class AuthBiometricFaceView extends AuthBiometricView {
|
||||
R.string.biometric_dialog_face_icon_description_authenticated));
|
||||
} else if (newState == STATE_IDLE) {
|
||||
showStaticDrawable(R.drawable.face_dialog_idle_static);
|
||||
mIconView.setContentDescription(mContext.getString(
|
||||
R.string.biometric_dialog_face_icon_description_idle));
|
||||
} else {
|
||||
Log.w(TAG, "Unhandled state: " + newState);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
@@ -32,6 +34,8 @@ import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
@@ -145,6 +149,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
|
||||
private final Injector mInjector;
|
||||
private final Handler mHandler;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
private final int mTextColorError;
|
||||
private final int mTextColorHint;
|
||||
|
||||
@@ -196,15 +201,9 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
*/
|
||||
protected abstract boolean supportsSmallDialog();
|
||||
|
||||
private final Runnable mResetErrorRunnable = () -> {
|
||||
updateState(getStateForAfterError());
|
||||
handleResetAfterError();
|
||||
};
|
||||
private final Runnable mResetErrorRunnable;
|
||||
|
||||
private final Runnable mResetHelpRunnable = () -> {
|
||||
updateState(STATE_AUTHENTICATING);
|
||||
handleResetAfterHelp();
|
||||
};
|
||||
private final Runnable mResetHelpRunnable;
|
||||
|
||||
private final OnClickListener mBackgroundClickListener = (view) -> {
|
||||
if (mState == STATE_AUTHENTICATED) {
|
||||
@@ -236,6 +235,20 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
|
||||
mInjector = injector;
|
||||
mInjector.mBiometricView = this;
|
||||
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
|
||||
mResetErrorRunnable = () -> {
|
||||
updateState(getStateForAfterError());
|
||||
handleResetAfterError();
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
};
|
||||
|
||||
mResetHelpRunnable = () -> {
|
||||
updateState(STATE_AUTHENTICATING);
|
||||
handleResetAfterHelp();
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
};
|
||||
}
|
||||
|
||||
public void setPanelController(AuthPanelController panelController) {
|
||||
@@ -333,6 +346,8 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
super.onAnimationEnd(animation);
|
||||
mSize = newSize;
|
||||
mDialogSizeAnimating = false;
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager,
|
||||
AuthBiometricView.this);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -348,6 +363,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
} else {
|
||||
Log.e(TAG, "Unknown transition from: " + mSize + " to: " + newSize);
|
||||
}
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
}
|
||||
|
||||
public void updateState(@BiometricState int newState) {
|
||||
@@ -369,6 +385,8 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
mNegativeButton.setVisibility(View.GONE);
|
||||
mIndicatorView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
announceForAccessibility(getResources()
|
||||
.getString(R.string.biometric_dialog_authenticated));
|
||||
mHandler.postDelayed(() -> mCallback.onAction(Callback.ACTION_AUTHENTICATED),
|
||||
getDelayAfterAuthenticatedDurationMs());
|
||||
break;
|
||||
@@ -395,6 +413,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
break;
|
||||
}
|
||||
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
mState = newState;
|
||||
}
|
||||
|
||||
@@ -461,6 +480,8 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
} else {
|
||||
view.setText(string);
|
||||
}
|
||||
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
}
|
||||
|
||||
private void setText(TextView view, String string) {
|
||||
@@ -479,6 +500,8 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
mIndicatorView.setTextColor(mTextColorError);
|
||||
mIndicatorView.setVisibility(View.VISIBLE);
|
||||
mHandler.postDelayed(resetMessageRunnable, BiometricPrompt.HIDE_DIALOG_DELAY);
|
||||
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -517,6 +540,7 @@ public abstract class AuthBiometricView extends LinearLayout {
|
||||
updateState(STATE_AUTHENTICATING);
|
||||
mCallback.onAction(Callback.ACTION_BUTTON_TRY_AGAIN);
|
||||
mTryAgainButton.setVisibility(View.GONE);
|
||||
Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,14 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
public class Utils {
|
||||
static float dpToPixels(Context context, float dp) {
|
||||
@@ -29,4 +35,15 @@ public class Utils {
|
||||
return pixels / ((float) context.getResources().getDisplayMetrics().densityDpi
|
||||
/ DisplayMetrics.DENSITY_DEFAULT);
|
||||
}
|
||||
|
||||
static void notifyAccessibilityContentChanged(AccessibilityManager am, ViewGroup view) {
|
||||
if (!am.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
AccessibilityEvent event = AccessibilityEvent.obtain();
|
||||
event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||
event.setContentChangeTypes(CONTENT_CHANGE_TYPE_SUBTREE);
|
||||
view.sendAccessibilityEventUnchecked(event);
|
||||
view.notifySubtreeAccessibilityStateChanged(view, view, CONTENT_CHANGE_TYPE_SUBTREE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user