Fade in the UDFPS icon from HOME => AOD

Animate the fade in on the first signal from onDozeAmountChanged
when the unlockedScreenOffAnimation is running.

Remove the callbacks from the UnlockedScreenOffAnimationController
progress which starts the animation much sooner than when the AOD
UI starts to come in. It was also causing a pulsing bug where
the UDFPS bouncer would be reset and be out of sync with the scrims.

Test: atest SystemUITest
Test: manually transition between the home screen
and the AOD screen with udfps enrolled
Test: manually transition between the lock screen
and AOD with udfps enrolled
Test: Tap on a pulsing notification in AOD when
udfps is enrolled
Fixes: 220219675

Change-Id: Idfe6144d1d46443db52583b165a836c69f17b259
This commit is contained in:
Beverly
2022-02-22 21:45:33 +00:00
committed by Beverly Tai
parent d62c6e6c7d
commit 99d2e63d4e
4 changed files with 65 additions and 52 deletions

View File

@@ -38,7 +38,6 @@ import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.StatusBarState;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieProperty;
@@ -68,6 +67,7 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
private float mBurnInOffsetY;
private float mBurnInProgress;
private float mInterpolatedDarkAmount;
private boolean mAnimatingBetweenAodAndLockscreen; // As opposed to Unlocked => AOD
private boolean mFullyInflated;
public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
@@ -114,23 +114,32 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
return;
}
final float darkAmountForAnimation = mAnimatingBetweenAodAndLockscreen
? mInterpolatedDarkAmount : 1f /* animating from unlocked to AOD */;
mBurnInOffsetX = MathUtils.lerp(0f,
getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
- mMaxBurnInOffsetX, mInterpolatedDarkAmount);
- mMaxBurnInOffsetX, darkAmountForAnimation);
mBurnInOffsetY = MathUtils.lerp(0f,
getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
- mMaxBurnInOffsetY, mInterpolatedDarkAmount);
mBurnInProgress = MathUtils.lerp(0f, getBurnInProgressOffset(), mInterpolatedDarkAmount);
- mMaxBurnInOffsetY, darkAmountForAnimation);
mBurnInProgress = MathUtils.lerp(0f, getBurnInProgressOffset(), darkAmountForAnimation);
if (mAnimatingBetweenAodAndLockscreen) {
mBgProtection.setAlpha(1f - mInterpolatedDarkAmount);
mLockScreenFp.setTranslationX(mBurnInOffsetX);
mLockScreenFp.setTranslationY(mBurnInOffsetY);
mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount);
mLockScreenFp.setAlpha(1f - mInterpolatedDarkAmount);
} else {
mBgProtection.setAlpha(0f);
mLockScreenFp.setAlpha(0f);
}
mAodFp.setTranslationX(mBurnInOffsetX);
mAodFp.setTranslationY(mBurnInOffsetY);
mAodFp.setProgress(mBurnInProgress);
mAodFp.setAlpha(255 * mInterpolatedDarkAmount);
mLockScreenFp.setTranslationX(mBurnInOffsetX);
mLockScreenFp.setTranslationY(mBurnInOffsetY);
mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount);
mLockScreenFp.setAlpha((1f - mInterpolatedDarkAmount) * 255);
mAodFp.setAlpha(mInterpolatedDarkAmount);
}
void requestUdfps(boolean request, int color) {
@@ -171,15 +180,14 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
protected int updateAlpha() {
int alpha = super.updateAlpha();
if (mFullyInflated) {
mLockScreenFp.setAlpha(alpha / 255f);
if (mInterpolatedDarkAmount != 0f) {
mBgProtection.setAlpha(1f - mInterpolatedDarkAmount);
} else {
if (mInterpolatedDarkAmount == 0f) {
mLockScreenFp.setAlpha(alpha / 255f);
mBgProtection.setAlpha(alpha / 255f);
} else {
updateBurnInOffsets();
}
}
return alpha;
}
@@ -191,8 +199,10 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
return mAlpha;
}
void onDozeAmountChanged(float linear, float eased) {
void onDozeAmountChanged(float linear, float eased, boolean animatingBetweenAodAndLockscreen) {
mAnimatingBetweenAodAndLockscreen = animatingBetweenAodAndLockscreen;
mInterpolatedDarkAmount = eased;
updateAlpha();
updateBurnInOffsets();
}
@@ -225,10 +235,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
mBackgroundInAnimator.start();
}
private boolean isShadeLocked() {
return mStatusBarState == StatusBarState.SHADE_LOCKED;
}
private final AsyncLayoutInflater.OnInflateFinishedListener mLayoutInflaterFinishListener =
new AsyncLayoutInflater.OnInflateFinishedListener() {
@Override

View File

@@ -18,6 +18,7 @@ package com.android.systemui.biometrics;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.res.Configuration;
import android.util.MathUtils;
@@ -30,6 +31,7 @@ import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
@@ -57,6 +59,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@NonNull private final UnlockedScreenOffAnimationController
mUnlockedScreenOffAnimationController;
@NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final ValueAnimator mUnlockedScreenOffDozeAnimator = ValueAnimator.ofFloat(0f, 1f);
private boolean mShowingUdfpsBouncer;
private boolean mUdfpsRequested;
@@ -105,6 +108,18 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mUdfpsController = udfpsController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mActivityLaunchAnimator = activityLaunchAnimator;
mUnlockedScreenOffDozeAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
mUnlockedScreenOffDozeAnimator.addUpdateListener(
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mView.onDozeAmountChanged(
animation.getAnimatedFraction(),
(float) animation.getAnimatedValue(),
/* animatingBetweenAodAndLockScreen */ false);
}
});
}
@Override
@@ -141,7 +156,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this);
mUnlockedScreenOffAnimationController.addCallback(mUnlockedScreenOffCallback);
mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
}
@@ -159,7 +173,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
}
mUnlockedScreenOffAnimationController.removeCallback(mUnlockedScreenOffCallback);
mActivityLaunchAnimator.removeListener(mActivityLaunchAnimatorListener);
}
@@ -177,6 +190,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
pw.println("mUdfpsRequested=" + mUdfpsRequested);
pw.println("mView.mUdfpsRequested=" + mView.mUdfpsRequested);
pw.println("mLaunchTransitionFadingAway=" + mLaunchTransitionFadingAway);
pw.println("mLastDozeAmount=" + mLastDozeAmount);
}
/**
@@ -237,7 +251,11 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
return true;
}
if (mStatusBarState != KEYGUARD) {
// Only pause auth if we're not on the keyguard AND we're not transitioning to doze
// (ie: dozeAmount = 0f). For the UnlockedScreenOffAnimation, the statusBarState is
// delayed. However, we still animate in the UDFPS affordance with the
// mUnlockedScreenOffDozeAnimator.
if (mStatusBarState != KEYGUARD && mLastDozeAmount == 0f) {
return true;
}
@@ -292,6 +310,10 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
updateAlpha();
}
/**
* Update alpha for the UDFPS lock screen affordance. The AoD UDFPS visual affordance's
* alpha is based on the doze amount.
*/
private void updateAlpha() {
// fade icon on transitions to showing the status bar, but if mUdfpsRequested, then
// the keyguard is occluded by some application - so instead use the input bouncer
@@ -320,7 +342,18 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
if (mLastDozeAmount < linear) {
showUdfpsBouncer(false);
}
mView.onDozeAmountChanged(linear, eased);
mUnlockedScreenOffDozeAnimator.cancel();
final boolean animatingFromUnlockedScreenOff =
mUnlockedScreenOffAnimationController.isAnimationPlaying();
if (animatingFromUnlockedScreenOff && linear != 0f) {
// we manually animate the fade in of the UDFPS icon since the unlocked
// screen off animation prevents the doze amounts to be incrementally eased in
mUnlockedScreenOffDozeAnimator.start();
} else {
mView.onDozeAmountChanged(linear, eased,
/* animatingBetweenAodAndLockScreen */ true);
}
mLastDozeAmount = linear;
updatePauseAuth();
}
@@ -439,9 +472,6 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
}
};
private final UnlockedScreenOffAnimationController.Callback mUnlockedScreenOffCallback =
(linear, eased) -> mStateListener.onDozeAmountChanged(linear, eased);
private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
new ActivityLaunchAnimator.Listener() {
@Override

View File

@@ -67,7 +67,6 @@ class UnlockedScreenOffAnimationController @Inject constructor(
private var shouldAnimateInKeyguard = false
private var lightRevealAnimationPlaying = false
private var aodUiAnimationPlaying = false
private var callbacks = HashSet<Callback>()
/**
* The result of our decision whether to play the screen off animation in
@@ -81,9 +80,6 @@ class UnlockedScreenOffAnimationController @Inject constructor(
interpolator = Interpolators.LINEAR
addUpdateListener {
lightRevealScrim.revealAmount = it.animatedValue as Float
sendUnlockedScreenOffProgressUpdate(
1f - (it.animatedFraction as Float),
1f - (it.animatedValue as Float))
if (lightRevealScrim.isScrimAlmostOccludes &&
interactionJankMonitor.isInstrumenting(CUJ_SCREEN_OFF)) {
// ends the instrument when the scrim almost occludes the screen.
@@ -95,7 +91,6 @@ class UnlockedScreenOffAnimationController @Inject constructor(
override fun onAnimationCancel(animation: Animator?) {
lightRevealScrim.revealAmount = 1f
lightRevealAnimationPlaying = false
sendUnlockedScreenOffProgressUpdate(0f, 0f)
interactionJankMonitor.cancel(CUJ_SCREEN_OFF)
}
@@ -309,20 +304,6 @@ class UnlockedScreenOffAnimationController @Inject constructor(
override fun shouldDelayDisplayDozeTransition(): Boolean =
dozeParameters.get().shouldControlUnlockedScreenOff()
fun addCallback(callback: Callback) {
callbacks.add(callback)
}
fun removeCallback(callback: Callback) {
callbacks.remove(callback)
}
private fun sendUnlockedScreenOffProgressUpdate(linear: Float, eased: Float) {
callbacks.forEach {
it.onUnlockedScreenOffProgressUpdate(linear, eased)
}
}
/**
* Whether we're doing the light reveal animation or we're done with that and animating in the
* AOD UI.
@@ -356,8 +337,4 @@ class UnlockedScreenOffAnimationController @Inject constructor(
fun isScreenOffLightRevealAnimationPlaying(): Boolean {
return lightRevealAnimationPlaying
}
interface Callback {
fun onUnlockedScreenOffProgressUpdate(linear: Float, eased: Float)
}
}

View File

@@ -166,7 +166,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
mController.onViewAttached();
verify(mView, atLeast(1)).setPauseAuth(true);
verify(mView).onDozeAmountChanged(dozeAmount, dozeAmount);
verify(mView).onDozeAmountChanged(dozeAmount, dozeAmount, true);
}
@Test
@@ -193,7 +193,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
final float eased = .65f;
mStatusBarStateListener.onDozeAmountChanged(linear, eased);
verify(mView).onDozeAmountChanged(linear, eased);
verify(mView).onDozeAmountChanged(linear, eased, true);
}
@Test