From 87df068ac1184449879b595fe4986ff7e664aa16 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 10 Apr 2018 19:29:23 -0700 Subject: [PATCH] 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 --- .../fingerprint/FingerprintDialogImpl.java | 9 ++- .../fingerprint/FingerprintDialogView.java | 75 +++++++++++++------ 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java index c238e54e7cc96..a81043e22fe53 100644 --- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java @@ -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. diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java index d1d66097d48d7..8013a9e29dfd2 100644 --- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java @@ -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); } - // 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(); - } - }); + if (!mWasForceRemoved) { + // Dim the background and slide the dialog up + mDialog.setTranslationY(mAnimationTranslationOffset); + mLayout.setAlpha(0f); + 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; }