Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9744e40 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

8/n: Ensure accessibility works on new implementation

Bug: 123378871
Test: manual test with talkback enabled

Change-Id: I7f4da76ef7ebcbb74f1984b2859b85aa72e8d946
parent 27da718e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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"
+3 −1
Original line number Diff line number Diff line
@@ -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>
+6 −0
Original line number Diff line number Diff line
@@ -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);
            }
+32 −8
Original line number Diff line number Diff line
@@ -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);
        });
    }

+17 −0
Original line number Diff line number Diff line
@@ -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);
    }
}