Loading packages/SystemUI/src/com/android/systemui/Interpolators.java +14 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,13 @@ import com.android.systemui.statusbar.stack.HeadsUpAppearInterpolator; */ */ public class Interpolators { public class Interpolators { public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); /** * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t * goes from 1 to 0 instead of 0 to 1). */ public static final Interpolator FAST_OUT_SLOW_IN_REVERSE = new PathInterpolator(0.8f, 0f, 0.6f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); Loading @@ -51,4 +58,11 @@ public class Interpolators { */ */ public static final Interpolator TOUCH_RESPONSE = public static final Interpolator TOUCH_RESPONSE = new PathInterpolator(0.3f, 0f, 0.1f, 1f); new PathInterpolator(0.3f, 0f, 0.1f, 1f); /** * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t * goes from 1 to 0 instead of 0 to 1). */ public static final Interpolator TOUCH_RESPONSE_REVERSE = new PathInterpolator(0.9f, 0f, 0.7f, 1f); } } packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +38 −15 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowInsets; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.FrameLayout; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -109,17 +110,20 @@ public class NotificationPanelView extends PanelView implements private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties() private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties() .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY = private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY = new FloatProperty<NotificationPanelView>("mDarkAmount") { new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") { @Override @Override public void setValue(NotificationPanelView object, float value) { public void setValue(NotificationPanelView object, float value) { object.setDarkAmount(value); object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value)); } } @Override @Override public Float get(NotificationPanelView object) { public Float get(NotificationPanelView object) { return object.mDarkAmount; return object.mLinearDarkAmount; } } }; }; private Interpolator mDarkInterpolator; private final PowerManager mPowerManager; private final PowerManager mPowerManager; private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager mAccessibilityManager; Loading Loading @@ -239,7 +243,18 @@ public class NotificationPanelView extends PanelView implements private int mIndicationBottomPadding; private int mIndicationBottomPadding; private int mAmbientIndicationBottomPadding; private int mAmbientIndicationBottomPadding; private boolean mIsFullWidth; private boolean mIsFullWidth; private float mDarkAmount; /** * Current dark amount that follows regular interpolation curve of animation. */ private float mInterpolatedDarkAmount; /** * Dark amount that animates from 0 to 1 or vice-versa in linear manner, even if the * interpolation curve is different. */ private float mLinearDarkAmount; private float mDarkAmountTarget; private float mDarkAmountTarget; private boolean mPulsing; private boolean mPulsing; private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); Loading Loading @@ -394,7 +409,7 @@ public class NotificationPanelView extends PanelView implements false); false); addView(mKeyguardBottomArea, index); addView(mKeyguardBottomArea, index); initBottomArea(); initBottomArea(); setDarkAmount(mDarkAmount); setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount); setKeyguardStatusViewVisibility(mStatusBarState, false, false); setKeyguardStatusViewVisibility(mStatusBarState, false, false); setKeyguardBottomAreaVisibility(mStatusBarState, false); setKeyguardBottomAreaVisibility(mStatusBarState, false); Loading Loading @@ -508,7 +523,7 @@ public class NotificationPanelView extends PanelView implements getExpandedFraction(), getExpandedFraction(), totalHeight, totalHeight, mKeyguardStatusView.getHeight(), mKeyguardStatusView.getHeight(), mDarkAmount, mInterpolatedDarkAmount, mStatusBar.isKeyguardCurrentlySecure(), mStatusBar.isKeyguardCurrentlySecure(), mPulsing, mPulsing, mBouncerTop); mBouncerTop); Loading Loading @@ -1919,7 +1934,7 @@ public class NotificationPanelView extends PanelView implements if (view == null && mQsExpanded) { if (view == null && mQsExpanded) { return; return; } } if (needsAnimation && mDarkAmount == 0) { if (needsAnimation && mInterpolatedDarkAmount == 0) { mAnimateNextPositionUpdate = true; mAnimateNextPositionUpdate = true; } } ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone(); ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone(); Loading Loading @@ -2729,20 +2744,28 @@ public class NotificationPanelView extends PanelView implements } } mDarkAmountTarget = darkAmount; mDarkAmountTarget = darkAmount; if (animate) { if (animate) { if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) { mDarkInterpolator = dozing ? Interpolators.FAST_OUT_SLOW_IN : Interpolators.TOUCH_RESPONSE_REVERSE; } mNotificationStackScroller.notifyDarkAnimationStart(dozing); mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount); mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount); mDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); mDarkAnimator.setInterpolator(Interpolators.LINEAR); mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP); mDarkAnimator.setDuration(mNotificationStackScroller.getDarkAnimationDuration(dozing)); mDarkAnimator.start(); mDarkAnimator.start(); } else { } else { setDarkAmount(darkAmount); setDarkAmount(darkAmount, darkAmount); } } } } private void setDarkAmount(float amount) { private void setDarkAmount(float linearAmount, float amount) { mDarkAmount = amount; mInterpolatedDarkAmount = amount; mKeyguardStatusView.setDarkAmount(mDarkAmount); mLinearDarkAmount = linearAmount; mKeyguardBottomArea.setDarkAmount(mDarkAmount); mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount); mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount); positionClockAndNotifications(); positionClockAndNotifications(); mNotificationStackScroller.setDarkAmount(linearAmount, mInterpolatedDarkAmount); } } public void setPulsing(boolean pulsing) { public void setPulsing(boolean pulsing) { Loading @@ -2767,7 +2790,7 @@ public class NotificationPanelView extends PanelView implements public void dozeTimeTick() { public void dozeTimeTick() { mKeyguardStatusView.dozeTimeTick(); mKeyguardStatusView.dozeTimeTick(); mKeyguardBottomArea.dozeTimeTick(); mKeyguardBottomArea.dozeTimeTick(); if (mDarkAmount > 0) { if (mInterpolatedDarkAmount > 0) { positionClockAndNotifications(); positionClockAndNotifications(); } } } } Loading packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +51 −62 Original line number Original line Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode; Loading @@ -46,11 +45,9 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils; import android.util.AttributeSet; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; import android.util.Log; import android.util.MathUtils; import android.util.MathUtils; import android.util.Pair; import android.util.Pair; import android.util.Property; import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper; import android.view.InputDevice; import android.view.InputDevice; import android.view.MotionEvent; import android.view.MotionEvent; Loading Loading @@ -375,25 +372,22 @@ public class NotificationStackScrollLayout extends ViewGroup private boolean mScrollable; private boolean mScrollable; private View mForcedScroll; private View mForcedScroll; private View mNeedingPulseAnimation; private View mNeedingPulseAnimation; private float mDarkAmount = 0f; /** * @see #setDarkAmount(float, float) */ private float mInterpolatedDarkAmount = 0f; /** * @see #setDarkAmount(float, float) */ private float mLinearDarkAmount = 0f; /** /** * How fast the background scales in the X direction as a factor of the Y expansion. * How fast the background scales in the X direction as a factor of the Y expansion. */ */ private float mBackgroundXFactor = 1f; private float mBackgroundXFactor = 1f; private static final Property<NotificationStackScrollLayout, Float> DARK_AMOUNT = new FloatProperty<NotificationStackScrollLayout>("darkAmount") { @Override public void setValue(NotificationStackScrollLayout object, float value) { object.setDarkAmount(value); } @Override public Float get(NotificationStackScrollLayout object) { return object.getDarkAmount(); } }; private ObjectAnimator mDarkAmountAnimator; private boolean mUsingLightTheme; private boolean mUsingLightTheme; private boolean mQsExpanded; private boolean mQsExpanded; private boolean mForwardScrollable; private boolean mForwardScrollable; Loading Loading @@ -424,6 +418,8 @@ public class NotificationStackScrollLayout extends ViewGroup private NotificationIconAreaController mIconAreaController; private NotificationIconAreaController mIconAreaController; private float mVerticalPanelTranslation; private float mVerticalPanelTranslation; private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN; public NotificationStackScrollLayout(Context context) { public NotificationStackScrollLayout(Context context) { this(context, null); this(context, null); } } Loading Loading @@ -558,16 +554,16 @@ public class NotificationStackScrollLayout extends ViewGroup canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint); canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint); } } } else { } else { float inverseDark = 1 - mDarkAmount; float yProgress = 1 - mInterpolatedDarkAmount; float yProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(inverseDark); float xProgress = mDarkXInterpolator.getInterpolation( float xProgress = Interpolators.FAST_OUT_SLOW_IN (1 - mLinearDarkAmount) * mBackgroundXFactor); .getInterpolation(inverseDark * mBackgroundXFactor); mBackgroundAnimationRect.set( mBackgroundAnimationRect.set( (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress), (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress), (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress), (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress), (int) MathUtils.lerp(darkRight, lockScreenRight, xProgress), (int) MathUtils.lerp(darkRight, lockScreenRight, xProgress), (int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress)); (int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress)); if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) { if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) { canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top, canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top, mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom, mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom, Loading @@ -585,14 +581,15 @@ public class NotificationStackScrollLayout extends ViewGroup float alpha = float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount); BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount); alpha *= 1f - mDarkAmount; alpha *= 1f - mInterpolatedDarkAmount; // We need to manually blend in the background color. // We need to manually blend in the background color. int scrimColor = mScrimController.getBackgroundColor(); int scrimColor = mScrimController.getBackgroundColor(); int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha); int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha); // Interpolate between semi-transparent notification panel background color // Interpolate between semi-transparent notification panel background color // and white AOD separator. // and white AOD separator. float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation(mDarkAmount); float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation( mInterpolatedDarkAmount); int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation); int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation); if (mCachedBackgroundColor != color) { if (mCachedBackgroundColor != color) { Loading Loading @@ -740,7 +737,8 @@ public class NotificationStackScrollLayout extends ViewGroup } } private void updateAlgorithmHeightAndPadding() { private void updateAlgorithmHeightAndPadding() { mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, mDarkAmount); mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, mInterpolatedDarkAmount); mAmbientState.setLayoutHeight(getLayoutHeight()); mAmbientState.setLayoutHeight(getLayoutHeight()); updateAlgorithmLayoutMinHeight(); updateAlgorithmLayoutMinHeight(); mAmbientState.setTopPadding(mTopPadding); mAmbientState.setTopPadding(mTopPadding); Loading Loading @@ -965,7 +963,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } public void updateClipping() { public void updateClipping() { boolean animatingClipping = mDarkAmount > 0 && mDarkAmount < 1; boolean animatingClipping = mInterpolatedDarkAmount > 0 && mInterpolatedDarkAmount < 1; boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode && !mHeadsUpAnimatingAway; && !mHeadsUpAnimatingAway; if (mIsClipped != clipped) { if (mIsClipped != clipped) { Loading Loading @@ -2425,7 +2423,7 @@ public class NotificationStackScrollLayout extends ViewGroup return; return; } } final boolean awake = mDarkAmount != 0 || mAmbientState.isDark(); final boolean awake = mInterpolatedDarkAmount != 0 || mAmbientState.isDark(); mScrimController.setExcludedBackgroundArea( mScrimController.setExcludedBackgroundArea( mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null : mCurrentBounds); : mCurrentBounds); Loading Loading @@ -3417,7 +3415,6 @@ public class NotificationStackScrollLayout extends ViewGroup .animateY(mShelf)); .animateY(mShelf)); ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex; ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex; mAnimationEvents.add(ev); mAnimationEvents.add(ev); startDarkAmountAnimation(); } } mDarkNeedsAnimation = false; mDarkNeedsAnimation = false; } } Loading Loading @@ -3995,9 +3992,6 @@ public class NotificationStackScrollLayout extends ViewGroup mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation); mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation); mNeedsAnimation = true; mNeedsAnimation = true; } else { } else { if (mDarkAmountAnimator != null) { mDarkAmountAnimator.cancel(); } setDarkAmount(dark ? 1f : 0f); setDarkAmount(dark ? 1f : 0f); updateBackground(); updateBackground(); } } Loading @@ -4008,7 +4002,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } private void updatePanelTranslation() { private void updatePanelTranslation() { setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mDarkAmount); setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mInterpolatedDarkAmount); } } public void setVerticalPanelTranslation(float verticalPanelTranslation) { public void setVerticalPanelTranslation(float verticalPanelTranslation) { Loading @@ -4027,9 +4021,22 @@ public class NotificationStackScrollLayout extends ViewGroup } } private void setDarkAmount(float darkAmount) { private void setDarkAmount(float darkAmount) { mDarkAmount = darkAmount; setDarkAmount(darkAmount, darkAmount); } /** * Sets the current dark amount. * * @param linearDarkAmount The dark amount that follows linear interpoloation in the animation, * i.e. animates from 0 to 1 or vice-versa in a linear manner. * @param interpolatedDarkAmount The dark amount that follows the actual interpolation of the * animation curve. */ public void setDarkAmount(float linearDarkAmount, float interpolatedDarkAmount) { mLinearDarkAmount = linearDarkAmount; mInterpolatedDarkAmount = interpolatedDarkAmount; boolean wasFullyDark = mAmbientState.isFullyDark(); boolean wasFullyDark = mAmbientState.isFullyDark(); mAmbientState.setDarkAmount(darkAmount); mAmbientState.setDarkAmount(interpolatedDarkAmount); boolean nowFullyDark = mAmbientState.isFullyDark(); boolean nowFullyDark = mAmbientState.isFullyDark(); if (nowFullyDark != wasFullyDark) { if (nowFullyDark != wasFullyDark) { updateContentHeight(); updateContentHeight(); Loading @@ -4047,42 +4054,24 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); requestChildrenUpdate(); } } public float getDarkAmount() { public void notifyDarkAnimationStart(boolean dark) { return mDarkAmount; // We only swap the scaling factor if we're fully dark or fully awake to avoid // interpolation issues when playing with the power button. if (mInterpolatedDarkAmount == 0 || mInterpolatedDarkAmount == 1) { mBackgroundXFactor = dark ? 1.8f : 1.5f; mDarkXInterpolator = dark ? Interpolators.FAST_OUT_SLOW_IN_REVERSE : Interpolators.FAST_OUT_SLOW_IN; } } /** * Cancel any previous dark animations - to avoid race conditions - and creates a new one. * This function also sets {@code mBackgroundXFactor} based on the current {@code mDarkAmount}. */ private void startDarkAmountAnimation() { boolean dark = mAmbientState.isDark(); if (mDarkAmountAnimator != null) { mDarkAmountAnimator.cancel(); } } public long getDarkAnimationDuration(boolean dark) { long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP; long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP; // Longer animation when sleeping with more than 1 notification // Longer animation when sleeping with more than 1 notification if (dark && getNotGoneChildCount() > 2) { if (dark && getNotGoneChildCount() > 2) { duration *= 1.2f; duration *= 1.2f; } } return duration; mDarkAmountAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount, dark ? 1f : 0); // We only swap the scaling factor if we're fully dark or fully awake to avoid // interpolation issues when playing with the power button. if (mDarkAmount == 0 || mDarkAmount == 1) { mBackgroundXFactor = dark ? 2.5f : 1.5f; } mDarkAmountAnimator.setDuration(duration); mDarkAmountAnimator.setInterpolator(Interpolators.LINEAR); mDarkAmountAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mDarkAmountAnimator = null; } }); mDarkAmountAnimator.start(); } } private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) { private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) { Loading Loading
packages/SystemUI/src/com/android/systemui/Interpolators.java +14 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,13 @@ import com.android.systemui.statusbar.stack.HeadsUpAppearInterpolator; */ */ public class Interpolators { public class Interpolators { public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); /** * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t * goes from 1 to 0 instead of 0 to 1). */ public static final Interpolator FAST_OUT_SLOW_IN_REVERSE = new PathInterpolator(0.8f, 0f, 0.6f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); Loading @@ -51,4 +58,11 @@ public class Interpolators { */ */ public static final Interpolator TOUCH_RESPONSE = public static final Interpolator TOUCH_RESPONSE = new PathInterpolator(0.3f, 0f, 0.1f, 1f); new PathInterpolator(0.3f, 0f, 0.1f, 1f); /** * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t * goes from 1 to 0 instead of 0 to 1). */ public static final Interpolator TOUCH_RESPONSE_REVERSE = new PathInterpolator(0.9f, 0f, 0.7f, 1f); } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +38 −15 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowInsets; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.FrameLayout; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -109,17 +110,20 @@ public class NotificationPanelView extends PanelView implements private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties() private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties() .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY = private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY = new FloatProperty<NotificationPanelView>("mDarkAmount") { new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") { @Override @Override public void setValue(NotificationPanelView object, float value) { public void setValue(NotificationPanelView object, float value) { object.setDarkAmount(value); object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value)); } } @Override @Override public Float get(NotificationPanelView object) { public Float get(NotificationPanelView object) { return object.mDarkAmount; return object.mLinearDarkAmount; } } }; }; private Interpolator mDarkInterpolator; private final PowerManager mPowerManager; private final PowerManager mPowerManager; private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager mAccessibilityManager; Loading Loading @@ -239,7 +243,18 @@ public class NotificationPanelView extends PanelView implements private int mIndicationBottomPadding; private int mIndicationBottomPadding; private int mAmbientIndicationBottomPadding; private int mAmbientIndicationBottomPadding; private boolean mIsFullWidth; private boolean mIsFullWidth; private float mDarkAmount; /** * Current dark amount that follows regular interpolation curve of animation. */ private float mInterpolatedDarkAmount; /** * Dark amount that animates from 0 to 1 or vice-versa in linear manner, even if the * interpolation curve is different. */ private float mLinearDarkAmount; private float mDarkAmountTarget; private float mDarkAmountTarget; private boolean mPulsing; private boolean mPulsing; private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); Loading Loading @@ -394,7 +409,7 @@ public class NotificationPanelView extends PanelView implements false); false); addView(mKeyguardBottomArea, index); addView(mKeyguardBottomArea, index); initBottomArea(); initBottomArea(); setDarkAmount(mDarkAmount); setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount); setKeyguardStatusViewVisibility(mStatusBarState, false, false); setKeyguardStatusViewVisibility(mStatusBarState, false, false); setKeyguardBottomAreaVisibility(mStatusBarState, false); setKeyguardBottomAreaVisibility(mStatusBarState, false); Loading Loading @@ -508,7 +523,7 @@ public class NotificationPanelView extends PanelView implements getExpandedFraction(), getExpandedFraction(), totalHeight, totalHeight, mKeyguardStatusView.getHeight(), mKeyguardStatusView.getHeight(), mDarkAmount, mInterpolatedDarkAmount, mStatusBar.isKeyguardCurrentlySecure(), mStatusBar.isKeyguardCurrentlySecure(), mPulsing, mPulsing, mBouncerTop); mBouncerTop); Loading Loading @@ -1919,7 +1934,7 @@ public class NotificationPanelView extends PanelView implements if (view == null && mQsExpanded) { if (view == null && mQsExpanded) { return; return; } } if (needsAnimation && mDarkAmount == 0) { if (needsAnimation && mInterpolatedDarkAmount == 0) { mAnimateNextPositionUpdate = true; mAnimateNextPositionUpdate = true; } } ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone(); ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone(); Loading Loading @@ -2729,20 +2744,28 @@ public class NotificationPanelView extends PanelView implements } } mDarkAmountTarget = darkAmount; mDarkAmountTarget = darkAmount; if (animate) { if (animate) { if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) { mDarkInterpolator = dozing ? Interpolators.FAST_OUT_SLOW_IN : Interpolators.TOUCH_RESPONSE_REVERSE; } mNotificationStackScroller.notifyDarkAnimationStart(dozing); mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount); mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount); mDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); mDarkAnimator.setInterpolator(Interpolators.LINEAR); mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP); mDarkAnimator.setDuration(mNotificationStackScroller.getDarkAnimationDuration(dozing)); mDarkAnimator.start(); mDarkAnimator.start(); } else { } else { setDarkAmount(darkAmount); setDarkAmount(darkAmount, darkAmount); } } } } private void setDarkAmount(float amount) { private void setDarkAmount(float linearAmount, float amount) { mDarkAmount = amount; mInterpolatedDarkAmount = amount; mKeyguardStatusView.setDarkAmount(mDarkAmount); mLinearDarkAmount = linearAmount; mKeyguardBottomArea.setDarkAmount(mDarkAmount); mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount); mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount); positionClockAndNotifications(); positionClockAndNotifications(); mNotificationStackScroller.setDarkAmount(linearAmount, mInterpolatedDarkAmount); } } public void setPulsing(boolean pulsing) { public void setPulsing(boolean pulsing) { Loading @@ -2767,7 +2790,7 @@ public class NotificationPanelView extends PanelView implements public void dozeTimeTick() { public void dozeTimeTick() { mKeyguardStatusView.dozeTimeTick(); mKeyguardStatusView.dozeTimeTick(); mKeyguardBottomArea.dozeTimeTick(); mKeyguardBottomArea.dozeTimeTick(); if (mDarkAmount > 0) { if (mInterpolatedDarkAmount > 0) { positionClockAndNotifications(); positionClockAndNotifications(); } } } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +51 −62 Original line number Original line Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.PorterDuffXfermode; Loading @@ -46,11 +45,9 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils; import android.util.AttributeSet; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; import android.util.Log; import android.util.MathUtils; import android.util.MathUtils; import android.util.Pair; import android.util.Pair; import android.util.Property; import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper; import android.view.InputDevice; import android.view.InputDevice; import android.view.MotionEvent; import android.view.MotionEvent; Loading Loading @@ -375,25 +372,22 @@ public class NotificationStackScrollLayout extends ViewGroup private boolean mScrollable; private boolean mScrollable; private View mForcedScroll; private View mForcedScroll; private View mNeedingPulseAnimation; private View mNeedingPulseAnimation; private float mDarkAmount = 0f; /** * @see #setDarkAmount(float, float) */ private float mInterpolatedDarkAmount = 0f; /** * @see #setDarkAmount(float, float) */ private float mLinearDarkAmount = 0f; /** /** * How fast the background scales in the X direction as a factor of the Y expansion. * How fast the background scales in the X direction as a factor of the Y expansion. */ */ private float mBackgroundXFactor = 1f; private float mBackgroundXFactor = 1f; private static final Property<NotificationStackScrollLayout, Float> DARK_AMOUNT = new FloatProperty<NotificationStackScrollLayout>("darkAmount") { @Override public void setValue(NotificationStackScrollLayout object, float value) { object.setDarkAmount(value); } @Override public Float get(NotificationStackScrollLayout object) { return object.getDarkAmount(); } }; private ObjectAnimator mDarkAmountAnimator; private boolean mUsingLightTheme; private boolean mUsingLightTheme; private boolean mQsExpanded; private boolean mQsExpanded; private boolean mForwardScrollable; private boolean mForwardScrollable; Loading Loading @@ -424,6 +418,8 @@ public class NotificationStackScrollLayout extends ViewGroup private NotificationIconAreaController mIconAreaController; private NotificationIconAreaController mIconAreaController; private float mVerticalPanelTranslation; private float mVerticalPanelTranslation; private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN; public NotificationStackScrollLayout(Context context) { public NotificationStackScrollLayout(Context context) { this(context, null); this(context, null); } } Loading Loading @@ -558,16 +554,16 @@ public class NotificationStackScrollLayout extends ViewGroup canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint); canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint); } } } else { } else { float inverseDark = 1 - mDarkAmount; float yProgress = 1 - mInterpolatedDarkAmount; float yProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(inverseDark); float xProgress = mDarkXInterpolator.getInterpolation( float xProgress = Interpolators.FAST_OUT_SLOW_IN (1 - mLinearDarkAmount) * mBackgroundXFactor); .getInterpolation(inverseDark * mBackgroundXFactor); mBackgroundAnimationRect.set( mBackgroundAnimationRect.set( (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress), (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress), (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress), (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress), (int) MathUtils.lerp(darkRight, lockScreenRight, xProgress), (int) MathUtils.lerp(darkRight, lockScreenRight, xProgress), (int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress)); (int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress)); if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) { if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) { canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top, canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top, mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom, mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom, Loading @@ -585,14 +581,15 @@ public class NotificationStackScrollLayout extends ViewGroup float alpha = float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount); BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount); alpha *= 1f - mDarkAmount; alpha *= 1f - mInterpolatedDarkAmount; // We need to manually blend in the background color. // We need to manually blend in the background color. int scrimColor = mScrimController.getBackgroundColor(); int scrimColor = mScrimController.getBackgroundColor(); int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha); int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha); // Interpolate between semi-transparent notification panel background color // Interpolate between semi-transparent notification panel background color // and white AOD separator. // and white AOD separator. float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation(mDarkAmount); float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation( mInterpolatedDarkAmount); int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation); int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation); if (mCachedBackgroundColor != color) { if (mCachedBackgroundColor != color) { Loading Loading @@ -740,7 +737,8 @@ public class NotificationStackScrollLayout extends ViewGroup } } private void updateAlgorithmHeightAndPadding() { private void updateAlgorithmHeightAndPadding() { mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, mDarkAmount); mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, mInterpolatedDarkAmount); mAmbientState.setLayoutHeight(getLayoutHeight()); mAmbientState.setLayoutHeight(getLayoutHeight()); updateAlgorithmLayoutMinHeight(); updateAlgorithmLayoutMinHeight(); mAmbientState.setTopPadding(mTopPadding); mAmbientState.setTopPadding(mTopPadding); Loading Loading @@ -965,7 +963,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } public void updateClipping() { public void updateClipping() { boolean animatingClipping = mDarkAmount > 0 && mDarkAmount < 1; boolean animatingClipping = mInterpolatedDarkAmount > 0 && mInterpolatedDarkAmount < 1; boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode && !mHeadsUpAnimatingAway; && !mHeadsUpAnimatingAway; if (mIsClipped != clipped) { if (mIsClipped != clipped) { Loading Loading @@ -2425,7 +2423,7 @@ public class NotificationStackScrollLayout extends ViewGroup return; return; } } final boolean awake = mDarkAmount != 0 || mAmbientState.isDark(); final boolean awake = mInterpolatedDarkAmount != 0 || mAmbientState.isDark(); mScrimController.setExcludedBackgroundArea( mScrimController.setExcludedBackgroundArea( mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null : mCurrentBounds); : mCurrentBounds); Loading Loading @@ -3417,7 +3415,6 @@ public class NotificationStackScrollLayout extends ViewGroup .animateY(mShelf)); .animateY(mShelf)); ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex; ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex; mAnimationEvents.add(ev); mAnimationEvents.add(ev); startDarkAmountAnimation(); } } mDarkNeedsAnimation = false; mDarkNeedsAnimation = false; } } Loading Loading @@ -3995,9 +3992,6 @@ public class NotificationStackScrollLayout extends ViewGroup mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation); mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation); mNeedsAnimation = true; mNeedsAnimation = true; } else { } else { if (mDarkAmountAnimator != null) { mDarkAmountAnimator.cancel(); } setDarkAmount(dark ? 1f : 0f); setDarkAmount(dark ? 1f : 0f); updateBackground(); updateBackground(); } } Loading @@ -4008,7 +4002,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } private void updatePanelTranslation() { private void updatePanelTranslation() { setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mDarkAmount); setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mInterpolatedDarkAmount); } } public void setVerticalPanelTranslation(float verticalPanelTranslation) { public void setVerticalPanelTranslation(float verticalPanelTranslation) { Loading @@ -4027,9 +4021,22 @@ public class NotificationStackScrollLayout extends ViewGroup } } private void setDarkAmount(float darkAmount) { private void setDarkAmount(float darkAmount) { mDarkAmount = darkAmount; setDarkAmount(darkAmount, darkAmount); } /** * Sets the current dark amount. * * @param linearDarkAmount The dark amount that follows linear interpoloation in the animation, * i.e. animates from 0 to 1 or vice-versa in a linear manner. * @param interpolatedDarkAmount The dark amount that follows the actual interpolation of the * animation curve. */ public void setDarkAmount(float linearDarkAmount, float interpolatedDarkAmount) { mLinearDarkAmount = linearDarkAmount; mInterpolatedDarkAmount = interpolatedDarkAmount; boolean wasFullyDark = mAmbientState.isFullyDark(); boolean wasFullyDark = mAmbientState.isFullyDark(); mAmbientState.setDarkAmount(darkAmount); mAmbientState.setDarkAmount(interpolatedDarkAmount); boolean nowFullyDark = mAmbientState.isFullyDark(); boolean nowFullyDark = mAmbientState.isFullyDark(); if (nowFullyDark != wasFullyDark) { if (nowFullyDark != wasFullyDark) { updateContentHeight(); updateContentHeight(); Loading @@ -4047,42 +4054,24 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); requestChildrenUpdate(); } } public float getDarkAmount() { public void notifyDarkAnimationStart(boolean dark) { return mDarkAmount; // We only swap the scaling factor if we're fully dark or fully awake to avoid // interpolation issues when playing with the power button. if (mInterpolatedDarkAmount == 0 || mInterpolatedDarkAmount == 1) { mBackgroundXFactor = dark ? 1.8f : 1.5f; mDarkXInterpolator = dark ? Interpolators.FAST_OUT_SLOW_IN_REVERSE : Interpolators.FAST_OUT_SLOW_IN; } } /** * Cancel any previous dark animations - to avoid race conditions - and creates a new one. * This function also sets {@code mBackgroundXFactor} based on the current {@code mDarkAmount}. */ private void startDarkAmountAnimation() { boolean dark = mAmbientState.isDark(); if (mDarkAmountAnimator != null) { mDarkAmountAnimator.cancel(); } } public long getDarkAnimationDuration(boolean dark) { long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP; long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP; // Longer animation when sleeping with more than 1 notification // Longer animation when sleeping with more than 1 notification if (dark && getNotGoneChildCount() > 2) { if (dark && getNotGoneChildCount() > 2) { duration *= 1.2f; duration *= 1.2f; } } return duration; mDarkAmountAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount, dark ? 1f : 0); // We only swap the scaling factor if we're fully dark or fully awake to avoid // interpolation issues when playing with the power button. if (mDarkAmount == 0 || mDarkAmount == 1) { mBackgroundXFactor = dark ? 2.5f : 1.5f; } mDarkAmountAnimator.setDuration(duration); mDarkAmountAnimator.setInterpolator(Interpolators.LINEAR); mDarkAmountAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mDarkAmountAnimator = null; } }); mDarkAmountAnimator.start(); } } private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) { private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) { Loading