From 16423aa0c6d1f5a8e9abd294d876933d44361fbc Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 28 Oct 2014 11:42:58 +0100 Subject: [PATCH] Improve doze transitions This change animates the status bar and the bottom area when exiting doze mode from touch. We also prevent all animations when exiting from other means, i.e. usually when the power button is pressed, so we don't have a distracting animation there. In addition, this also optimizes the scrim animations a bit in terms of interpolation and duration to make the experience smoother and cleans up some logic. Bug: 18146441 Bug: 17717584 Change-Id: I495ce480c25de24b6433adebdfe923b637d98f66 --- packages/SystemUI/res/values/config.xml | 7 +- .../statusbar/phone/DozeParameters.java | 4 ++ .../phone/KeyguardBottomAreaView.java | 37 +++++++++- .../phone/NotificationPanelView.java | 69 ++++++++++++++----- .../statusbar/phone/PhoneStatusBar.java | 6 +- .../statusbar/phone/ScrimController.java | 41 +++++++---- 6 files changed, 127 insertions(+), 37 deletions(-) diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 4f867a0e422ad..4da54e30b9068 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -224,13 +224,16 @@ 2000 - 1000 + 900 + + + 200 3000 - 1000 + 600 222 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index b566bbc7096eb..a956151f7b50a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -72,6 +72,10 @@ public class DozeParameters { return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in); } + public int getPulseInDelay() { + return getInt("doze.pulse.delay.in", R.integer.doze_pulse_delay_in); + } + public int getPulseVisibleDuration() { return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 598a35c4acc78..fddbee2ee4008 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -39,6 +39,8 @@ import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.TextView; @@ -72,6 +74,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final Intent INSECURE_CAMERA_INTENT = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); + private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; + private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; private KeyguardAffordanceView mCameraImageView; private KeyguardAffordanceView mPhoneImageView; @@ -92,7 +96,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private PhoneStatusBar mPhoneStatusBar; private final TrustDrawable mTrustDrawable; - + private final Interpolator mLinearOutSlowInInterpolator; private int mLastUnlockIconRes = 0; public KeyguardBottomAreaView(Context context) { @@ -111,6 +115,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); mTrustDrawable = new TrustDrawable(mContext); + mLinearOutSlowInInterpolator = + AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); } private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { @@ -450,6 +456,35 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } } + public void startFinishDozeAnimation() { + long delay = 0; + if (mPhoneImageView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mPhoneImageView, delay); + delay += DOZE_ANIMATION_STAGGER_DELAY; + } + startFinishDozeAnimationElement(mLockIcon, delay); + delay += DOZE_ANIMATION_STAGGER_DELAY; + if (mCameraImageView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mCameraImageView, delay); + } + mIndicationText.setAlpha(0f); + mIndicationText.animate() + .alpha(1f) + .setInterpolator(mLinearOutSlowInInterpolator) + .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION); + } + + private void startFinishDozeAnimationElement(View element, long delay) { + element.setAlpha(0f); + element.setTranslationY(element.getHeight() / 2); + element.animate() + .alpha(1f) + .translationY(0f) + .setInterpolator(mLinearOutSlowInInterpolator) + .setStartDelay(delay) + .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); + } + private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { post(new Runnable() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index bc2196ae40bfc..0bde7efa77395 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -64,7 +64,7 @@ public class NotificationPanelView extends PanelView implements private static final int DOZE_BACKGROUND_COLOR = 0xff000000; private static final int TAG_KEY_ANIM = R.id.scrim; - private static final long DOZE_BACKGROUND_ANIM_DURATION = ScrimController.ANIMATION_DURATION; + public static final long DOZE_ANIMATION_DURATION = 700; private KeyguardAffordanceHelper mAfforanceHelper; private StatusBarHeaderView mHeader; @@ -132,6 +132,7 @@ public class NotificationPanelView extends PanelView implements private Interpolator mFastOutSlowInInterpolator; private Interpolator mFastOutLinearInterpolator; + private Interpolator mDozeAnimationInterpolator; private ObjectAnimator mClockAnimator; private int mClockAnimationTarget = -1; private int mTopPaddingAdjustment; @@ -167,6 +168,8 @@ public class NotificationPanelView extends PanelView implements private boolean mQsTouchAboveFalsingThreshold; private int mQsFalsingThreshold; + private float mKeyguardStatusBarAnimateAlpha = 1f; + public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -199,6 +202,8 @@ public class NotificationPanelView extends PanelView implements android.R.interpolator.fast_out_slow_in); mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.fast_out_linear_in); + mDozeAnimationInterpolator = AnimationUtils.loadInterpolator(getContext(), + android.R.interpolator.linear_out_slow_in); mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area); mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim); mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext()); @@ -909,6 +914,8 @@ public class NotificationPanelView extends PanelView implements @Override public void run() { mKeyguardStatusBar.setVisibility(View.INVISIBLE); + mKeyguardStatusBar.setAlpha(1f); + mKeyguardStatusBarAnimateAlpha = 1f; } }; @@ -918,10 +925,31 @@ public class NotificationPanelView extends PanelView implements .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay()) .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2) .setInterpolator(PhoneStatusBar.ALPHA_OUT) + .setUpdateListener(mStatusBarAnimateAlphaListener) .withEndAction(mAnimateKeyguardStatusBarInvisibleEndRunnable) .start(); } + private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener = + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mKeyguardStatusBarAnimateAlpha = mKeyguardStatusBar.getAlpha(); + } + }; + + private void animateKeyguardStatusBarIn() { + mKeyguardStatusBar.setVisibility(View.VISIBLE); + mKeyguardStatusBar.setAlpha(0f); + mKeyguardStatusBar.animate() + .alpha(1f) + .setStartDelay(0) + .setDuration(DOZE_ANIMATION_DURATION) + .setInterpolator(mDozeAnimationInterpolator) + .setUpdateListener(mStatusBarAnimateAlphaListener) + .start(); + } + private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() { @Override public void run() { @@ -1387,7 +1415,8 @@ public class NotificationPanelView extends PanelView implements alphaNotifications = MathUtils.constrain(alphaNotifications, 0, 1); alphaNotifications = (float) Math.pow(alphaNotifications, 0.75); float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2); - mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion)); + mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion) + * mKeyguardStatusBarAnimateAlpha); mKeyguardBottomArea.setAlpha(Math.min(1 - getQsExpansionFraction(), alphaNotifications)); setQsTranslation(mQsExpansionHeight); } @@ -1736,19 +1765,22 @@ public class NotificationPanelView extends PanelView implements return (1 - t) * start + t * end; } - private void updateKeyguardStatusBarVisibility() { - mKeyguardStatusBar.setVisibility(mKeyguardShowing && !mDozing ? VISIBLE : INVISIBLE); - } - - public void setDozing(boolean dozing) { + public void setDozing(boolean dozing, boolean animate) { if (dozing == mDozing) return; mDozing = dozing; if (mDozing) { - setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/); + setBackgroundColorAlpha(DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/); + mKeyguardStatusBar.setVisibility(View.INVISIBLE); + mKeyguardBottomArea.setVisibility(View.INVISIBLE); } else { - setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0, true /*animate*/); + setBackgroundColorAlpha(DOZE_BACKGROUND_COLOR, 0, animate); + mKeyguardBottomArea.setVisibility(View.VISIBLE); + mKeyguardStatusBar.setVisibility(View.VISIBLE); + if (animate) { + animateKeyguardStatusBarIn(); + mKeyguardBottomArea.startFinishDozeAnimation(); + } } - updateKeyguardStatusBarVisibility(); } @Override @@ -1756,21 +1788,21 @@ public class NotificationPanelView extends PanelView implements return mDozing; } - private static void setBackgroundColorAlpha(final View target, int rgb, int targetAlpha, + private void setBackgroundColorAlpha(int rgb, int targetAlpha, boolean animate) { - int currentAlpha = getBackgroundAlpha(target); + int currentAlpha = getBackgroundAlpha(this); if (currentAlpha == targetAlpha) { return; } final int r = Color.red(rgb); final int g = Color.green(rgb); final int b = Color.blue(rgb); - Object runningAnim = target.getTag(TAG_KEY_ANIM); + Object runningAnim = getTag(TAG_KEY_ANIM); if (runningAnim instanceof ValueAnimator) { ((ValueAnimator) runningAnim).cancel(); } if (!animate) { - target.setBackgroundColor(Color.argb(targetAlpha, r, g, b)); + setBackgroundColor(Color.argb(targetAlpha, r, g, b)); return; } ValueAnimator anim = ValueAnimator.ofInt(currentAlpha, targetAlpha); @@ -1778,18 +1810,19 @@ public class NotificationPanelView extends PanelView implements @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (int) animation.getAnimatedValue(); - target.setBackgroundColor(Color.argb(value, r, g, b)); + setBackgroundColor(Color.argb(value, r, g, b)); } }); - anim.setDuration(DOZE_BACKGROUND_ANIM_DURATION); + anim.setInterpolator(mDozeAnimationInterpolator); + anim.setDuration(DOZE_ANIMATION_DURATION); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - target.setTag(TAG_KEY_ANIM, null); + setTag(TAG_KEY_ANIM, null); } }); anim.start(); - target.setTag(TAG_KEY_ANIM, anim); + setTag(TAG_KEY_ANIM, anim); } private static int getBackgroundAlpha(View view) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 9a33a3697198b..eb487547f9675 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -3681,15 +3681,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mState != StatusBarState.KEYGUARD && !mNotificationPanel.isDozing()) { return; } - mNotificationPanel.setDozing(mDozing); + mNotificationPanel.setDozing(mDozing, mScrimController.isPulsing() /*animate*/); if (mDozing) { - mKeyguardBottomArea.setVisibility(View.INVISIBLE); mStackScroller.setDark(true, false /*animate*/); } else { - mKeyguardBottomArea.setVisibility(View.VISIBLE); mStackScroller.setDark(false, false /*animate*/); } - mScrimController.setDozing(mDozing); + mScrimController.setDozing(mDozing, mScrimController.isPulsing() /*animate*/); } public void updateStackScrollerState(boolean goingToFullShade) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 54adbf4825896..10d65943b9f45 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -28,6 +28,7 @@ import android.view.ViewTreeObserver; import android.view.animation.AnimationUtils; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; import com.android.systemui.R; import com.android.systemui.doze.DozeHost; @@ -70,9 +71,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private Runnable mOnAnimationFinished; private boolean mAnimationStarted; private boolean mDozing; + private boolean mPulsingOut; private DozeHost.PulseCallback mPulseCallback; private final Interpolator mInterpolator = new DecelerateInterpolator(); private final Interpolator mLinearOutSlowInInterpolator; + private final Interpolator mPulseInInterpolator = PhoneStatusBar.ALPHA_OUT; + private final Interpolator mPulseOutInterpolator = PhoneStatusBar.ALPHA_IN; private BackDropView mBackDropView; private boolean mScrimSrcEnabled; @@ -130,14 +134,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { scheduleUpdate(); } - public void setDozing(boolean dozing) { + public void setDozing(boolean dozing, boolean animate) { if (mDozing == dozing) return; mDozing = dozing; if (!mDozing) { cancelPulsing(); - mAnimateChange = true; - } else { - mAnimateChange = false; + mAnimateChange = animate; } scheduleUpdate(); } @@ -181,6 +183,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } private void pulseFinished() { + mPulsingOut = false; if (mPulseCallback != null) { mPulseCallback.onPulseFinished(); mPulseCallback = null; @@ -220,8 +223,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } else if (mBouncerShowing) { setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA); setScrimBehindColor(0f); + } else if (mDozing && isPulsing() && !mPulsingOut) { + setScrimInFrontColor(0); + setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); } else if (mDozing) { setScrimInFrontColor(1); + setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); } else { float fraction = Math.max(0, Math.min(mFraction, 1)); setScrimInFrontColor(0f); @@ -276,7 +283,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private void startScrimAnimation(final ScrimView scrim, int targetColor) { int current = Color.alpha(scrim.getScrimColor()); int target = Color.alpha(targetColor); - if (current == targetColor) { + if (current == target) { return; } ValueAnimator anim = ValueAnimator.ofInt(current, target); @@ -287,9 +294,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { scrim.setScrimColor(Color.argb(value, 0, 0, 0)); } }); - anim.setInterpolator(mAnimateKeyguardFadingOut - ? mLinearOutSlowInInterpolator - : mInterpolator); + anim.setInterpolator(getInterpolator()); anim.setStartDelay(mAnimationDelay); anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION); anim.addListener(new AnimatorListenerAdapter() { @@ -307,6 +312,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { mAnimationStarted = true; } + private Interpolator getInterpolator() { + if (mAnimateKeyguardFadingOut) { + return mLinearOutSlowInInterpolator; + } else if (isPulsing() && !mPulsingOut) { + return mPulseInInterpolator; + } else if (isPulsing()) { + return mPulseOutInterpolator; + } else { + return mInterpolator; + } + } + @Override public boolean onPreDraw() { mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this); @@ -332,10 +349,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { if (!mDozing) return; DozeLog.tracePulseStart(); mDurationOverride = mDozeParameters.getPulseInDuration(); - mAnimationDelay = 0; + mAnimationDelay = mDozeParameters.getPulseInDelay(); mAnimateChange = true; mOnAnimationFinished = mPulseInFinished; - setScrimColor(mScrimInFront, 0); + scheduleUpdate(); // Signal that the pulse is ready to turn the screen on and draw. pulseStarted(); @@ -357,10 +374,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing); if (!mDozing) return; mDurationOverride = mDozeParameters.getPulseOutDuration(); - mAnimationDelay = 0; mAnimateChange = true; mOnAnimationFinished = mPulseOutFinished; - setScrimColor(mScrimInFront, 1); + mPulsingOut = true; + scheduleUpdate(); } };