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

Commit 975ca323 authored by Kevin Chyn's avatar Kevin Chyn Committed by Automerger Merge Worker
Browse files

Merge "Fix condition where FP would require confirmation" into sc-dev am: c52f2f06

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15413720

Change-Id: I93d3280186a6bac6705b74f54bde5338022425f3
parents 1e204f1f c52f2f06
Loading
Loading
Loading
Loading
+24 −25
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
    @Nullable private ModalityListener mModalityListener;
    @Nullable private FingerprintSensorPropertiesInternal mFingerprintSensorProps;
    @Nullable private UdfpsDialogMeasureAdapter mUdfpsMeasureAdapter;
    @Nullable @VisibleForTesting UdfpsIconController mUdfpsIconController;


    public AuthBiometricFaceToFingerprintView(Context context) {
        super(context);
@@ -107,6 +109,12 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
        super(context, attrs, injector);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mUdfpsIconController = new UdfpsIconController(mContext, mIconView, mIndicatorView);
    }

    @Modality
    int getActiveSensorType() {
        return mActiveSensorType;
@@ -167,36 +175,27 @@ public class AuthBiometricFaceToFingerprintView extends AuthBiometricFaceView {
        return super.getStateForAfterError();
    }

    @Override
    @NonNull
    protected IconController getIconController() {
        if (mActiveSensorType == TYPE_FINGERPRINT) {
            if (!(mIconController instanceof UdfpsIconController)) {
                mIconController = createUdfpsIconController();
            }
            return mIconController;
        }
        return super.getIconController();
    }

    @NonNull
    protected IconController createUdfpsIconController() {
        return new UdfpsIconController(getContext(), mIconView, mIndicatorView);
    }

    @Override
    public void updateState(@BiometricState int newState) {
        if (mState == STATE_HELP || mState == STATE_ERROR) {
            @Modality final int currentType = mActiveSensorType;
        if (mActiveSensorType == TYPE_FACE) {
            if (newState == STATE_HELP || newState == STATE_ERROR) {
                mActiveSensorType = TYPE_FINGERPRINT;

                setRequireConfirmation(false);
                mConfirmButton.setEnabled(false);
                mConfirmButton.setVisibility(View.GONE);

            if (mModalityListener != null && currentType != mActiveSensorType) {
                mModalityListener.onModalitySwitched(currentType, mActiveSensorType);
                if (mModalityListener != null) {
                    mModalityListener.onModalitySwitched(TYPE_FACE, mActiveSensorType);
                }

                // Deactivate the face icon controller so it stops drawing to the view
                mFaceIconController.deactivate();
                // Then, activate this icon controller. We need to start in the "error" state
                mUdfpsIconController.updateState(mState, newState);
            }
        } else { // Fingerprint
            mUdfpsIconController.updateState(mState, newState);
        }

        super.updateState(newState);
+28 −10
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ public class AuthBiometricFaceView extends AuthBiometricView {
        protected Handler mHandler;
        protected boolean mLastPulseLightToDark; // false = dark to light, true = light to dark
        protected @BiometricState int mState;
        protected boolean mDeactivated;

        protected IconController(Context context, ImageView iconView, TextView textView) {
            mContext = context;
@@ -67,6 +68,11 @@ public class AuthBiometricFaceView extends AuthBiometricView {
        }

        protected void animateIcon(int iconRes, boolean repeat) {
            Log.d(TAG, "animateIcon, state: " + mState + ", deactivated: " + mDeactivated);
            if (mDeactivated) {
                return;
            }

            final AnimatedVectorDrawable icon =
                    (AnimatedVectorDrawable) mContext.getDrawable(iconRes);
            mIconView.setImageDrawable(icon);
@@ -92,12 +98,26 @@ public class AuthBiometricFaceView extends AuthBiometricView {
        @Override
        public void onAnimationEnd(Drawable drawable) {
            super.onAnimationEnd(drawable);
            Log.d(TAG, "onAnimationEnd, mState: " + mState + ", deactivated: " + mDeactivated);
            if (mDeactivated) {
                return;
            }

            if (mState == STATE_AUTHENTICATING || mState == STATE_HELP) {
                pulseInNextDirection();
            }
        }

        protected void deactivate() {
            mDeactivated = true;
        }

        protected void updateState(int lastState, int newState) {
            if (mDeactivated) {
                Log.w(TAG, "Ignoring updateState when deactivated: " + newState);
                return;
            }

            final boolean lastStateIsErrorIcon =
                    lastState == STATE_ERROR || lastState == STATE_HELP;

@@ -142,7 +162,7 @@ public class AuthBiometricFaceView extends AuthBiometricView {
        }
    }

    protected IconController mIconController;
    @Nullable @VisibleForTesting IconController mFaceIconController;

    public AuthBiometricFaceView(Context context) {
        this(context, null);
@@ -157,6 +177,12 @@ public class AuthBiometricFaceView extends AuthBiometricView {
        super(context, attrs, injector);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mFaceIconController = new IconController(mContext, mIconView, mIndicatorView);
    }

    @Override
    protected int getDelayAfterAuthenticatedDurationMs() {
        return HIDE_DELAY_MS;
@@ -187,17 +213,9 @@ public class AuthBiometricFaceView extends AuthBiometricView {
        return true;
    }

    @NonNull
    protected IconController getIconController() {
        if (mIconController == null) {
            mIconController = new IconController(mContext, mIconView, mIndicatorView);
        }
        return mIconController;
    }

    @Override
    public void updateState(@BiometricState int newState) {
        getIconController().updateState(mState, newState);
        mFaceIconController.updateState(mState, newState);

        if (newState == STATE_AUTHENTICATING_ANIMATING_IN ||
                (newState == STATE_AUTHENTICATING && getSize() == AuthDialog.SIZE_MEDIUM)) {
+27 −22
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -50,7 +49,6 @@ import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@@ -78,14 +76,16 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
    @Mock private TextView mIndicatorView;
    @Mock private ImageView mIconView;
    @Mock private View mIconHolderView;
    @Mock private AuthBiometricFaceView.IconController mIconController;
    @Mock private AuthBiometricFaceView.IconController mFaceIconController;
    @Mock private AuthBiometricFaceToFingerprintView.UdfpsIconController mUdfpsIconController;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);

        mFaceToFpView = new TestableView(mContext);
        mFaceToFpView.mIconController = mIconController;
        mFaceToFpView.mFaceIconController = mFaceIconController;
        mFaceToFpView.mUdfpsIconController = mUdfpsIconController;
        mFaceToFpView.setCallback(mCallback);

        mFaceToFpView.mNegativeButton = mNegativeButton;
@@ -99,20 +99,23 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
    @Test
    public void testStateUpdated_whenDialogAnimatedIn() {
        mFaceToFpView.onDialogAnimatedIn();
        verify(mFaceToFpView.mIconController)
        verify(mFaceToFpView.mFaceIconController)
                .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
        verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt());
    }

    @Test
    public void testIconUpdatesState_whenDialogStateUpdated() {
        mFaceToFpView.onDialogAnimatedIn();
        verify(mFaceToFpView.mIconController)
        verify(mFaceToFpView.mFaceIconController)
                .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));
        verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt());

        mFaceToFpView.updateState(AuthBiometricFaceView.STATE_AUTHENTICATED);
        verify(mFaceToFpView.mIconController).updateState(
        verify(mFaceToFpView.mFaceIconController).updateState(
                eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING),
                eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATED));
        verify(mFaceToFpView.mUdfpsIconController, never()).updateState(anyInt(), anyInt());

        assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATED, mFaceToFpView.mState);
    }
@@ -120,21 +123,22 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
    @Test
    public void testStateUpdated_whenSwitchToFingerprint() {
        mFaceToFpView.onDialogAnimatedIn();
        verify(mFaceToFpView.mIconController)
        verify(mFaceToFpView.mFaceIconController)
                .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));

        mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_ERROR);
        mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);

        InOrder order = inOrder(mFaceToFpView.mIconController);
        order.verify(mFaceToFpView.mIconController).updateState(
        verify(mFaceToFpView.mFaceIconController).deactivate();
        verify(mFaceToFpView.mUdfpsIconController).updateState(
                eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING),
                eq(AuthBiometricFaceToFingerprintView.STATE_ERROR));
        order.verify(mFaceToFpView.mIconController).updateState(
        verify(mConfirmButton).setVisibility(eq(View.GONE));

        mFaceToFpView.updateState(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING);

        verify(mFaceToFpView.mUdfpsIconController).updateState(
                eq(AuthBiometricFaceToFingerprintView.STATE_ERROR),
                eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));

        verify(mConfirmButton).setVisibility(eq(View.GONE));
    }

    @Test
@@ -172,7 +176,10 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
                eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
        verify(mCallback).onAction(
                eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
        assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);

        // First we enter the error state, since we need to show the error animation/text. The
        // error state is later cleared based on a timer, and we enter STATE_AUTHENTICATING.
        assertEquals(AuthBiometricFaceToFingerprintView.STATE_ERROR, mFaceToFpView.mState);
    }

    @Test
@@ -185,13 +192,16 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
                eq(mContext.getString(R.string.fingerprint_dialog_use_fingerprint_instead)));
        verify(mCallback).onAction(
                eq(AuthBiometricView.Callback.ACTION_START_DELAYED_FINGERPRINT_SENSOR));
        assertEquals(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING, mFaceToFpView.mState);

        // First we enter the error state, since we need to show the error animation/text. The
        // error state is later cleared based on a timer, and we enter STATE_AUTHENTICATING.
        assertEquals(AuthBiometricFaceToFingerprintView.STATE_ERROR, mFaceToFpView.mState);
    }

    @Test
    public void testFingerprintOnlyStartsOnFirstError() {
        mFaceToFpView.onDialogAnimatedIn();
        verify(mFaceToFpView.mIconController)
        verify(mFaceToFpView.mFaceIconController)
                .updateState(anyInt(), eq(AuthBiometricFaceToFingerprintView.STATE_AUTHENTICATING));

        mFaceToFpView.onDialogAnimatedIn();
@@ -260,11 +270,6 @@ public class AuthBiometricFaceToFingerprintViewTest extends SysuiTestCase {
        protected int getDelayAfterAuthenticatedDurationMs() {
            return 0;
        }

        @Override
        protected IconController createUdfpsIconController() {
            return AuthBiometricFaceToFingerprintViewTest.this.mIconController;
        }
    }

    private class MockInjector extends AuthBiometricView.Injector {
+4 −4
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ public class AuthBiometricFaceViewTest extends SysuiTestCase {
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mFaceView = new TestableFaceView(mContext);
        mFaceView.mIconController = mock(TestableFaceView.TestableIconController.class);
        mFaceView.mFaceIconController = mock(TestableFaceView.TestableIconController.class);
        mFaceView.setCallback(mCallback);

        mFaceView.mNegativeButton = mNegativeButton;
@@ -78,18 +78,18 @@ public class AuthBiometricFaceViewTest extends SysuiTestCase {
    @Test
    public void testStateUpdated_whenDialogAnimatedIn() {
        mFaceView.onDialogAnimatedIn();
        verify(mFaceView.mIconController)
        verify(mFaceView.mFaceIconController)
                .updateState(anyInt(), eq(AuthBiometricFaceView.STATE_AUTHENTICATING));
    }

    @Test
    public void testIconUpdatesState_whenDialogStateUpdated() {
        mFaceView.updateState(AuthBiometricFaceView.STATE_AUTHENTICATING);
        verify(mFaceView.mIconController)
        verify(mFaceView.mFaceIconController)
                .updateState(anyInt(), eq(AuthBiometricFaceView.STATE_AUTHENTICATING));

        mFaceView.updateState(AuthBiometricFaceView.STATE_AUTHENTICATED);
        verify(mFaceView.mIconController).updateState(
        verify(mFaceView.mFaceIconController).updateState(
                eq(AuthBiometricFaceView.STATE_AUTHENTICATING),
                eq(AuthBiometricFaceView.STATE_AUTHENTICATED));
    }