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

Commit 87df068a authored by Kevin Chyn's avatar Kevin Chyn
Browse files

Fix FingerprintDialogView when show is called before animation is complete

If handleShowDialog is called before the animation is finished, the window
will still be attached despite the mDialogShowing variable == false. We
need a new variable to track the dismiss animation state; if the dialog
is dismissing and handleShowDialog is called again, cancel the animation
and remove the window. Then show the dialog without an entry animation.
This lets us show the dialog without a "bouncy" animation when the device
rotates, etc..

Fixes: 77877888

Test: Manual test with modified settings APK
Change-Id: Iae878ca10099d9755c27284d6df04a73fd5a37f7
parent a4596f3e
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -134,8 +134,11 @@ public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Call
    }

    private void handleShowDialog(SomeArgs args) {
        if (DEBUG) Log.d(TAG, "handleShowDialog");
        if (mDialogShowing) {
        if (DEBUG) Log.d(TAG, "handleShowDialog, isAnimatingAway: "
                + mDialogView.isAnimatingAway());
        if (mDialogView.isAnimatingAway()) {
            mDialogView.forceRemove();
        } else if (mDialogShowing) {
            Log.w(TAG, "Dialog already showing");
            return;
        }
@@ -168,7 +171,7 @@ public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Call
    }

    private void handleHideDialog(boolean userCanceled) {
        if (DEBUG) Log.d(TAG, "handleHideDialog");
        if (DEBUG) Log.d(TAG, "handleHideDialog, userCanceled: " + userCanceled);
        if (!mDialogShowing) {
            // This can happen if there's a race and we get called from both
            // onAuthenticated and onError, etc.
+54 −21
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.fingerprint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricPrompt;
@@ -76,9 +75,29 @@ public class FingerprintDialogView extends LinearLayout {
    private Bundle mBundle;
    private final LinearLayout mDialog;
    private int mLastState;
    private boolean mAnimatingAway;
    private boolean mWasForceRemoved;

    private final float mDisplayWidth;

    private final Runnable mShowAnimationRunnable = new Runnable() {
        @Override
        public void run() {
            mLayout.animate()
                    .alpha(1f)
                    .setDuration(ANIMATION_DURATION_SHOW)
                    .setInterpolator(mLinearOutSlowIn)
                    .withLayer()
                    .start();
            mDialog.animate()
                    .translationY(0)
                    .setDuration(ANIMATION_DURATION_SHOW)
                    .setInterpolator(mLinearOutSlowIn)
                    .withLayer()
                    .start();
        }
    };

    public FingerprintDialogView(Context context, Handler handler) {
        super(context);
        mHandler = handler;
@@ -192,26 +211,20 @@ public class FingerprintDialogView extends LinearLayout {
            positive.setVisibility(View.GONE);
        }

        if (!mWasForceRemoved) {
            // Dim the background and slide the dialog up
            mDialog.setTranslationY(mAnimationTranslationOffset);
            mLayout.setAlpha(0f);
        postOnAnimation(new Runnable() {
            @Override
            public void run() {
                mLayout.animate()
                        .alpha(1f)
                        .setDuration(ANIMATION_DURATION_SHOW)
                        .setInterpolator(mLinearOutSlowIn)
                        .withLayer()
                        .start();
                mDialog.animate()
                        .translationY(0)
                        .setDuration(ANIMATION_DURATION_SHOW)
                        .setInterpolator(mLinearOutSlowIn)
                        .withLayer()
                        .start();
            postOnAnimation(mShowAnimationRunnable);
        } else {
            // Show the dialog immediately
            mLayout.animate().cancel();
            mDialog.animate().cancel();
            mDialog.setAlpha(1.0f);
            mDialog.setTranslationY(0);
            mLayout.setAlpha(1.0f);
        }
        });
        mWasForceRemoved = false;
    }

    private void setDismissesDialog(View v) {
@@ -224,10 +237,13 @@ public class FingerprintDialogView extends LinearLayout {
    }

    public void startDismiss() {
        mAnimatingAway = true;

        final Runnable endActionRunnable = new Runnable() {
            @Override
            public void run() {
                mWindowManager.removeView(FingerprintDialogView.this);
                mAnimatingAway = false;
            }
        };

@@ -251,6 +267,23 @@ public class FingerprintDialogView extends LinearLayout {
        });
    }

    /**
     * Force remove the window, cancelling any animation that's happening. This should only be
     * called if we want to quickly show the dialog again (e.g. on rotation). Calling this method
     * will cause the dialog to show without an animation the next time it's attached.
     */
    public void forceRemove() {
        mLayout.animate().cancel();
        mDialog.animate().cancel();
        mWindowManager.removeView(FingerprintDialogView.this);
        mAnimatingAway = false;
        mWasForceRemoved = true;
    }

    public boolean isAnimatingAway() {
        return mAnimatingAway;
    }

    public void setBundle(Bundle bundle) {
        mBundle = bundle;
    }