diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java index bd2209b0d2920..0424382a1b88a 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java @@ -52,13 +52,6 @@ public interface QS extends FragmentBase { void setListening(boolean listening); boolean isShowingDetail(); void closeDetail(); - - /** - * Set that we're currently pulse expanding - * - * @param pulseExpanding if we're currently expanding during pulsing - */ - default void setPulseExpanding(boolean pulseExpanding) {} void animateHeaderSlidingOut(); void setQsExpansion(float qsExpansionFraction, float headerTranslation); void setHeaderListening(boolean listening); diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 5fec796669aa1..06e448310a137 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1462,7 +1462,7 @@ 24dp - 16dp + 32dp 28dp 20dp diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index d56fe481c3ca8..dd81b65723b9f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -48,6 +48,7 @@ import com.android.systemui.qs.dagger.QSFragmentComponent; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; +import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.util.InjectionInflationController; @@ -69,6 +70,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca private final Rect mQsBounds = new Rect(); private final StatusBarStateController mStatusBarStateController; private final FalsingManager mFalsingManager; + private final KeyguardBypassController mBypassController; private boolean mQsExpanded; private boolean mHeaderAnimating; private boolean mStackScrollerOverscrolling; @@ -135,6 +137,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca StatusBarStateController statusBarStateController, CommandQueue commandQueue, QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost, @Named(QUICK_QS_PANEL) MediaHost qqsMediaHost, + KeyguardBypassController keyguardBypassController, QSFragmentComponent.Factory qsComponentFactory, FalsingManager falsingManager) { mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler; @@ -147,6 +150,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca commandQueue.observe(getLifecycle(), this); mHost = qsTileHost; mFalsingManager = falsingManager; + mBypassController = keyguardBypassController; mStatusBarStateController = statusBarStateController; } @@ -385,16 +389,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca return mStatusBarStateController.getState() == StatusBarState.KEYGUARD; } - @Override - public void setPulseExpanding(boolean pulseExpanding) { - if (pulseExpanding != mPulseExpanding) { - mPulseExpanding = pulseExpanding; - updateShowCollapsedOnKeyguard(); - } - } - private void updateShowCollapsedOnKeyguard() { - boolean showCollapsed = mPulseExpanding || mTransitioningToFullShade; + boolean showCollapsed = mBypassController.getBypassEnabled() || mTransitioningToFullShade; if (showCollapsed != mShowCollapsedOnKeyguard) { mShowCollapsedOnKeyguard = showCollapsed; updateQsState(); @@ -724,5 +720,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca public void onStateChanged(int newState) { mState = newState; setKeyguardShowing(newState == StatusBarState.KEYGUARD); + updateShowCollapsedOnKeyguard(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index f0da70273507c..ca18b076b1e95 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -64,6 +64,7 @@ class LockscreenShadeTransitionController @Inject constructor( configurationController: ConfigurationController, falsingManager: FalsingManager ) { + private var pulseHeight: Float = 0f private var useSplitShade: Boolean = false private lateinit var nsslController: NotificationStackScrollLayoutController lateinit var notificationPanelController: NotificationPanelViewController @@ -86,6 +87,12 @@ class LockscreenShadeTransitionController @Inject constructor( @VisibleForTesting internal var dragDownAnimator: ValueAnimator? = null + /** + * The current pulse height animator if any + */ + @VisibleForTesting + internal var pulseHeightAnimator: ValueAnimator? = null + /** * Distance that the full shade transition takes in order for scrim to fully transition to * the shade (in alpha) @@ -108,6 +115,12 @@ class LockscreenShadeTransitionController @Inject constructor( */ private var nextHideKeyguardNeedsNoAnimation = false + /** + * The distance until we're showing the notifications when pulsing + */ + val distanceUntilShowingPulsingNotifications + get() = scrimTransitionDistance + /** * The udfpsKeyguardViewController if it exists. */ @@ -285,22 +298,26 @@ class LockscreenShadeTransitionController @Inject constructor( nsslController.setTransitionToFullShadeAmount(field) notificationPanelController.setTransitionToFullShadeAmount(field, false /* animate */, 0 /* delay */) - val scrimProgress = MathUtils.saturate(field / scrimTransitionDistance) - scrimController.setTransitionToFullShadeProgress(scrimProgress) // TODO: appear qs also in split shade val qsAmount = if (useSplitShade) 0f else field qS.setTransitionToFullShadeAmount(qsAmount, false /* animate */) // TODO: appear media also in split shade val mediaAmount = if (useSplitShade) 0f else field mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount) - // Fade out all content only visible on the lockscreen - notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress) - depthController.transitionToFullShadeProgress = scrimProgress - udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress) + transitionToShadeAmountCommon(field) } } } + private fun transitionToShadeAmountCommon(dragDownAmount: Float) { + val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance) + scrimController.setTransitionToFullShadeProgress(scrimProgress) + // Fade out all content only visible on the lockscreen + notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress) + depthController.transitionToFullShadeProgress = scrimProgress + udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress) + } + private fun setDragDownAmountAnimated( target: Float, delay: Long = 0, @@ -452,15 +469,19 @@ class LockscreenShadeTransitionController @Inject constructor( /** * Notify this handler that the keyguard was just dismissed and that a animation to * the full shade should happen. + * + * @param delay the delay to do the animation with + * @param previousState which state were we in when we hid the keyguard? */ - fun onHideKeyguard(delay: Long) { + fun onHideKeyguard(delay: Long, previousState: Int) { if (animationHandlerOnKeyguardDismiss != null) { animationHandlerOnKeyguardDismiss!!.invoke(delay) animationHandlerOnKeyguardDismiss = null } else { if (nextHideKeyguardNeedsNoAnimation) { nextHideKeyguardNeedsNoAnimation = false - } else { + } else if (previousState != StatusBarState.SHADE_LOCKED) { + // No animation necessary if we already were in the shade locked! performDefaultGoToFullShadeAnimation(delay) } } @@ -478,6 +499,53 @@ class LockscreenShadeTransitionController @Inject constructor( notificationPanelController.animateToFullShade(delay) animateAppear(delay) } + + // + // PULSE EXPANSION + // + + /** + * Set the height how tall notifications are pulsing. This is only set whenever we are expanding + * from a pulse and determines how much the notifications are expanded. + */ + fun setPulseHeight(height: Float, animate: Boolean = false) { + if (animate) { + val pulseHeightAnimator = ValueAnimator.ofFloat(pulseHeight, height) + pulseHeightAnimator.interpolator = Interpolators.FAST_OUT_SLOW_IN + pulseHeightAnimator.duration = SPRING_BACK_ANIMATION_LENGTH_MS + pulseHeightAnimator.addUpdateListener { animation: ValueAnimator -> + setPulseHeight(animation.animatedValue as Float) + } + pulseHeightAnimator.start() + this.pulseHeightAnimator = pulseHeightAnimator + } else { + pulseHeight = height + val overflow = nsslController.setPulseHeight(height) + notificationPanelController.setOverStrechAmount(overflow) + val transitionHeight = if (keyguardBypassController.bypassEnabled) height else 0.0f + transitionToShadeAmountCommon(transitionHeight) + } + } + + /** + * Finish the pulse animation when the touch interaction finishes + * @param cancelled was the interaction cancelled and this is a reset? + */ + fun finishPulseAnimation(cancelled: Boolean) { + if (cancelled) { + setPulseHeight(0f, animate = true) + } else { + notificationPanelController.onPulseExpansionFinished() + setPulseHeight(0f, animate = false) + } + } + + /** + * Notify this class that a pulse expansion is starting + */ + fun onPulseExpansionStarted() { + pulseHeightAnimator?.cancel() + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt index b34bfad499f87..761a20326200b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt @@ -19,8 +19,8 @@ package com.android.systemui.statusbar import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ObjectAnimator -import android.animation.ValueAnimator import android.content.Context +import android.content.res.Configuration import android.os.PowerManager import android.os.PowerManager.WAKE_REASON_GESTURE import android.os.SystemClock @@ -42,6 +42,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationRoundnessMa import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.HeadsUpManagerPhone import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.statusbar.policy.ConfigurationController import javax.inject.Inject import kotlin.math.max @@ -56,18 +57,17 @@ constructor( private val bypassController: KeyguardBypassController, private val headsUpManager: HeadsUpManagerPhone, private val roundnessManager: NotificationRoundnessManager, + private val configurationController: ConfigurationController, private val statusBarStateController: StatusBarStateController, private val falsingManager: FalsingManager, private val lockscreenShadeTransitionController: LockscreenShadeTransitionController, private val falsingCollector: FalsingCollector ) : Gefingerpoken { companion object { - private val RUBBERBAND_FACTOR_STATIC = 0.25f private val SPRING_BACK_ANIMATION_LENGTH_MS = 375 } private val mPowerManager: PowerManager? - private val mMinDragDistance: Int private var mInitialTouchX: Float = 0.0f private var mInitialTouchY: Float = 0.0f var isExpanding: Boolean = false @@ -81,6 +81,7 @@ constructor( topEntry?.let { roundnessManager.setTrackingHeadsUp(it.row) } + lockscreenShadeTransitionController.onPulseExpansionStarted() } else { roundnessManager.setTrackingHeadsUp(null) if (!leavingLockscreen) { @@ -93,8 +94,8 @@ constructor( } var leavingLockscreen: Boolean = false private set - private val mTouchSlop: Float - private lateinit var overStretchHandler: OverStretchHandler + private var touchSlop = 0f + private var minDragDistance = 0 private lateinit var stackScrollerController: NotificationStackScrollLayoutController private val mTemp2 = IntArray(2) private var mDraggedFarEnough: Boolean = false @@ -102,9 +103,7 @@ constructor( private var mPulsing: Boolean = false var isWakingToShadeLocked: Boolean = false private set - private var overStretchAmount: Float = 0.0f - private var mWakeUpHeight: Float = 0.0f - private var mReachedWakeUpHeight: Boolean = false + private var velocityTracker: VelocityTracker? = null private val isFalseTouch: Boolean @@ -114,12 +113,21 @@ constructor( var bouncerShowing: Boolean = false init { - mMinDragDistance = context.resources.getDimensionPixelSize( - R.dimen.keyguard_drag_down_min_distance) - mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat() + initResources(context) + configurationController.addCallback(object : ConfigurationController.ConfigurationListener { + override fun onConfigChanged(newConfig: Configuration?) { + initResources(context) + } + }) mPowerManager = context.getSystemService(PowerManager::class.java) } + private fun initResources(context: Context) { + minDragDistance = context.resources.getDimensionPixelSize( + R.dimen.keyguard_drag_down_min_distance) + touchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat() + } + override fun onInterceptTouchEvent(event: MotionEvent): Boolean { return canHandleMotionEvent() && startExpansion(event) } @@ -148,14 +156,12 @@ constructor( MotionEvent.ACTION_MOVE -> { val h = y - mInitialTouchY - if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) { + if (h > touchSlop && h > Math.abs(x - mInitialTouchX)) { falsingCollector.onStartExpandingFromPulse() isExpanding = true captureStartingChild(mInitialTouchX, mInitialTouchY) mInitialTouchY = y mInitialTouchX = x - mWakeUpHeight = wakeUpCoordinator.getWakeUpHeight() - mReachedWakeUpHeight = false return true } } @@ -216,7 +222,6 @@ constructor( } private fun finishExpansion() { - resetClock() val startingChild = mStartingChild if (mStartingChild != null) { setUserLocked(mStartingChild!!, false) @@ -230,6 +235,7 @@ constructor( } lockscreenShadeTransitionController.goToLockedShade(startingChild, needsQSAnimation = false) + lockscreenShadeTransitionController.finishPulseAnimation(cancelled = false) leavingLockscreen = true isExpanding = false if (mStartingChild is ExpandableNotificationRow) { @@ -240,24 +246,19 @@ constructor( private fun updateExpansionHeight(height: Float) { var expansionHeight = max(height, 0.0f) - if (!mReachedWakeUpHeight && height > mWakeUpHeight) { - mReachedWakeUpHeight = true - } if (mStartingChild != null) { val child = mStartingChild!! val newHeight = Math.min((child.collapsedHeight + expansionHeight).toInt(), child.maxContentHeight) child.actualHeight = newHeight - expansionHeight = max(newHeight.toFloat(), expansionHeight) } else { - val target = if (mReachedWakeUpHeight) mWakeUpHeight else 0.0f - wakeUpCoordinator.setNotificationsVisibleForExpansion(height > target, - true /* animate */, - true /* increaseSpeed */) - expansionHeight = max(mWakeUpHeight, expansionHeight) + wakeUpCoordinator.setNotificationsVisibleForExpansion( + height + > lockscreenShadeTransitionController.distanceUntilShowingPulsingNotifications, + true /* animate */, + true /* increaseSpeed */) } - val dragDownAmount = wakeUpCoordinator.setPulseHeight(expansionHeight) - setOverStretchAmount(dragDownAmount) + lockscreenShadeTransitionController.setPulseHeight(expansionHeight, animate = false) } private fun captureStartingChild(x: Float, y: Float) { @@ -269,11 +270,6 @@ constructor( } } - private fun setOverStretchAmount(amount: Float) { - overStretchAmount = amount - overStretchHandler.setOverStretchAmount(amount) - } - private fun reset(child: ExpandableView) { if (child.actualHeight == child.collapsedHeight) { setUserLocked(child, false) @@ -297,25 +293,14 @@ constructor( } } - private fun resetClock() { - val anim = ValueAnimator.ofFloat(overStretchAmount, 0f) - anim.interpolator = Interpolators.FAST_OUT_SLOW_IN - anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong() - anim.addUpdateListener { - animation -> setOverStretchAmount(animation.animatedValue as Float) - } - anim.start() - } - private fun cancelExpansion() { isExpanding = false falsingCollector.onExpansionFromPulseStopped() if (mStartingChild != null) { reset(mStartingChild!!) mStartingChild = null - } else { - resetClock() } + lockscreenShadeTransitionController.finishPulseAnimation(cancelled = true) wakeUpCoordinator.setNotificationsVisibleForExpansion(false /* visible */, true /* animate */, false /* increaseSpeed */) @@ -333,11 +318,7 @@ constructor( } else null } - fun setUp( - stackScrollerController: NotificationStackScrollLayoutController, - overStrechHandler: OverStretchHandler - ) { - this.overStretchHandler = overStrechHandler + fun setUp(stackScrollerController: NotificationStackScrollLayoutController) { this.stackScrollerController = stackScrollerController } @@ -348,12 +329,4 @@ constructor( fun onStartedWakingUp() { isWakingToShadeLocked = false } - - interface OverStretchHandler { - - /** - * Set the overstretch amount in pixels This will be rubberbanded later - */ - fun setOverStretchAmount(amount: Float) - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index b0a7767accfc1..a2c9ffc6bdc4b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -374,10 +374,6 @@ class NotificationWakeUpCoordinator @Inject constructor( } } - fun getWakeUpHeight(): Float { - return mStackScrollerController.wakeUpHeight - } - private fun updateHideAmount() { val linearAmount = min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount) val amount = min(1.0f - mVisibilityAmount, mDozeAmount) @@ -395,16 +391,6 @@ class NotificationWakeUpCoordinator @Inject constructor( } } - /** - * Set the height how tall notifications are pulsing. This is only set whenever we are expanding - * from a pulse and determines how much the notifications are expanded. - */ - fun setPulseHeight(height: Float): Float { - val overflow = mStackScrollerController.setPulseHeight(height) - // no overflow for the bypass experience - return if (bypassController.bypassEnabled) 0.0f else overflow - } - override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) { var animate = shouldAnimateVisibility() if (!isHeadsUp) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 2cf0a7ea18506..2033adf353d6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -5144,12 +5144,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * @return the overflow how much the height is further than he lowest notification */ public float setPulseHeight(float height) { + float overflow; mAmbientState.setPulseHeight(height); if (mKeyguardBypassEnabled) { notifyAppearChangedListeners(); + overflow = Math.max(0, height - getIntrinsicPadding()); + } else { + overflow = Math.max(0, height + - mAmbientState.getInnerHeight(true /* ignorePulseHeight */)); } requestChildrenUpdate(); - return Math.max(0, height - mAmbientState.getInnerHeight(true /* ignorePulseHeight */)); + return overflow; } public float getPulseHeight() { @@ -5209,12 +5214,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable public float calculateAppearFractionBypass() { float pulseHeight = getPulseHeight(); - float wakeUpHeight = getWakeUpHeight(); - float dragDownAmount = pulseHeight - wakeUpHeight; - // The total distance required to fully reveal the header float totalDistance = getIntrinsicPadding(); - return MathUtils.smoothStep(0, totalDistance, dragDownAmount); + return MathUtils.smoothStep(0, totalDistance, pulseHeight); } public void setController( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 75ea27289c4ea..a160e1099dfd5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -903,10 +903,6 @@ public class NotificationStackScrollLayoutController { mView.setDozeAmount(amount); } - public float getWakeUpHeight() { - return mView.getWakeUpHeight(); - } - public int getSpeedBumpIndex() { return mView.getSpeedBumpIndex(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index ad4213d212a0b..f77c0520cdb1b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -211,7 +211,7 @@ public class KeyguardClockPositionAlgorithm { private int getStackScrollerPadding(int clockYPosition) { if (mBypassEnabled) { - return mUnlockedStackScrollerPadding; + return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount); } else if (mIsSplitShade) { return clockYPosition; } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java index cfe95e06fb61f..6516abd143edf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -165,14 +165,14 @@ public class NotificationIconAreaController implements * Called by the Keyguard*ViewController whose view contains the aod icons. */ public void setupAodIcons(@NonNull NotificationIconContainer aodIcons) { - boolean changed = mAodIcons != null; + boolean changed = mAodIcons != null && aodIcons != mAodIcons; if (changed) { mAodIcons.setAnimationsEnabled(false); mAodIcons.removeAllViews(); } mAodIcons = aodIcons; mAodIcons.setOnLockScreen(true); - updateAodIconsVisibility(false /* animate */); + updateAodIconsVisibility(false /* animate */, changed); updateAnimations(); if (changed) { updateAodNotificationIcons(); @@ -587,7 +587,7 @@ public class NotificationIconAreaController implements @Override public void onStateChanged(int newState) { - updateAodIconsVisibility(false /* animate */); + updateAodIconsVisibility(false /* animate */, false /* force */); updateAnimations(); } @@ -663,18 +663,18 @@ public class NotificationIconAreaController implements // since otherwise the unhide animation overlaps animate &= fullyHidden; } - updateAodIconsVisibility(animate); + updateAodIconsVisibility(animate, false /* force */); updateAodNotificationIcons(); } @Override public void onPulseExpansionChanged(boolean expandingChanged) { if (expandingChanged) { - updateAodIconsVisibility(true /* animate */); + updateAodIconsVisibility(true /* animate */, false /* force */); } } - private void updateAodIconsVisibility(boolean animate) { + private void updateAodIconsVisibility(boolean animate, boolean forceUpdate) { if (mAodIcons == null) { return; } @@ -688,10 +688,11 @@ public class NotificationIconAreaController implements && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) { visible = false; } - if (visible && mWakeUpCoordinator.isPulseExpanding()) { + if (visible && mWakeUpCoordinator.isPulseExpanding() + && !mBypassController.getBypassEnabled()) { visible = false; } - if (mAodIconsVisible != visible) { + if (mAodIconsVisible != visible || forceUpdate) { mAodIconsVisible = visible; mAodIcons.animate().cancel(); if (animate) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 277059356ffb7..1e918b43804d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -612,6 +612,11 @@ public class NotificationPanelViewController extends PanelViewController { * Is the current animator resetting the qs translation. */ private boolean mIsQsTranslationResetAnimator; + + /** + * Is the current animator resetting the pulse expansion after a drag down + */ + private boolean mIsPulseExpansionResetAnimator; private final Rect mKeyguardStatusAreaClipBounds = new Rect(); private final Region mQsInterceptRegion = new Region(); @@ -888,14 +893,7 @@ public class NotificationPanelViewController extends PanelViewController { mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController); mQsFrame = mView.findViewById(R.id.qs_frame); - mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController, - amount -> { - float progress = amount / mView.getHeight(); - float overstretch = Interpolators.getOvershootInterpolation(progress, - (float) mMaxOverscrollAmountForPulse / mView.getHeight(), - 0.2f); - setOverStrechAmount(overstretch); - }); + mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController); mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() { @Override public void onFullyHiddenChanged(boolean isFullyHidden) { @@ -907,7 +905,6 @@ public class NotificationPanelViewController extends PanelViewController { if (mKeyguardBypassController.getBypassEnabled()) { // Position the notifications while dragging down while pulsing requestScrollerTopPaddingUpdate(false /* animate */); - updateQSPulseExpansion(); } } }); @@ -2280,7 +2277,7 @@ public class NotificationPanelViewController extends PanelViewController { } } - protected void updateQsExpansion() { + private void updateQsExpansion() { if (mQs == null) return; float qsExpansionFraction = computeQsExpansionFraction(); mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation()); @@ -2340,9 +2337,20 @@ public class NotificationPanelViewController extends PanelViewController { top = mTransitionToFullShadeQSPosition; } else { final float notificationTop = getQSEdgePosition(); - top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop) - : notificationTop); + if (isOnKeyguard()) { + if (mKeyguardBypassController.getBypassEnabled()) { + // When bypassing on the keyguard, let's use the panel bottom. + // this should go away once we unify the stackY position and don't have + // to do this min anymore below. + top = qsPanelBottomY; + } else { + top = (int) Math.min(qsPanelBottomY, notificationTop); + } + } else { + top = (int) notificationTop; + } } + top += mOverStretchAmount; bottom = getView().getBottom(); // notification bounds should take full screen width regardless of insets left = 0; @@ -2395,6 +2403,7 @@ public class NotificationPanelViewController extends PanelViewController { public void onAnimationEnd(Animator animation) { mQsClippingAnimation = null; mIsQsTranslationResetAnimator = false; + mIsPulseExpansionResetAnimator = false; } }); mQsClippingAnimation.start(); @@ -2420,9 +2429,17 @@ public class NotificationPanelViewController extends PanelViewController { } if (mQs != null) { float qsTranslation = 0; - if (mTransitioningToFullShadeProgress > 0.0f || (mQsClippingAnimation != null - && mIsQsTranslationResetAnimator)) { - qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT; + boolean pulseExpanding = mPulseExpansionHandler.isExpanding(); + if (mTransitioningToFullShadeProgress > 0.0f || pulseExpanding + || (mQsClippingAnimation != null + && (mIsQsTranslationResetAnimator || mIsPulseExpansionResetAnimator))) { + if (pulseExpanding || mIsPulseExpansionResetAnimator) { + // qsTranslation should only be positive during pulse expansion because it's + // already translating in from the top + qsTranslation = Math.max(0, (top - mQs.getHeader().getHeight()) / 2.0f); + } else { + qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT; + } } mQsTranslationForFullShadeTransition = qsTranslation; updateQsFrameTranslation(); @@ -2551,14 +2568,6 @@ public class NotificationPanelViewController extends PanelViewController { } } - private void updateQSPulseExpansion() { - if (mQs != null) { - mQs.setPulseExpanding( - mKeyguardShowing && mKeyguardBypassController.getBypassEnabled() - && mNotificationStackScrollLayoutController.isPulseExpanding()); - } - } - /** * Set the amount of pixels we have currently dragged down if we're transitioning to the full * shade. 0.0f means we're not transitioning yet. @@ -2609,6 +2618,15 @@ public class NotificationPanelViewController extends PanelViewController { updateQsExpansion(); } + /** + * Notify the panel that the pulse expansion has finished and that we're going to the full + * shade + */ + public void onPulseExpansionFinished() { + animateNextNotificationBounds(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE, 0); + mIsPulseExpansionResetAnimator = true; + } + /** * Set the alpha of the keyguard elements which only show on the lockscreen, but not in * shade locked / shade. This is used when dragging down to the full shade. @@ -2966,19 +2984,7 @@ public class NotificationPanelViewController extends PanelViewController { startHeight = -mQsExpansionHeight * QS_PARALLAX_AMOUNT; } if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) { - if (mNotificationStackScrollLayoutController.isPulseExpanding()) { - if (!mPulseExpansionHandler.isExpanding() - && !mPulseExpansionHandler.getLeavingLockscreen()) { - // If we aborted the expansion we need to make sure the header doesn't reappear - // again after the header has animated away - appearAmount = 0; - } else { - appearAmount = mNotificationStackScrollLayoutController - .calculateAppearFractionBypass(); - } - } else { - appearAmount = 0.0f; - } + appearAmount = mNotificationStackScrollLayoutController.calculateAppearFractionBypass(); startHeight = -mQs.getQsMinExpansionHeight(); } float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount)); @@ -3581,7 +3587,6 @@ public class NotificationPanelViewController extends PanelViewController { mQs.setPanelView(mHeightListener); mQs.setExpandClickListener(mOnClickListener); mQs.setHeaderClickable(isQsExpansionEnabled()); - updateQSPulseExpansion(); mQs.setOverscrolling(mStackScrollerOverscrolling); mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade); @@ -4462,7 +4467,6 @@ public class NotificationPanelViewController extends PanelViewController { updateMaxDisplayedNotifications(false); // The update needs to happen after the headerSlide in above, otherwise the translation // would reset - updateQSPulseExpansion(); maybeAnimateBottomAreaAlpha(); resetHorizontalPanelPosition(); updateQsState(); @@ -4499,7 +4503,9 @@ public class NotificationPanelViewController extends PanelViewController { * Sets the overstretch amount in raw pixels when dragging down. */ public void setOverStrechAmount(float amount) { - mOverStretchAmount = amount; + float progress = amount / mView.getHeight(); + float overstretch = Interpolators.getOvershootInterpolation(progress); + mOverStretchAmount = overstretch * mMaxOverscrollAmountForPulse; positionClockAndNotifications(true /* forceUpdate */); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 8023d5956faad..10d5d571ef50c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3615,6 +3615,7 @@ public class StatusBar extends SystemUI implements DemoMode, mIsKeyguard = false; Trace.beginSection("StatusBar#hideKeyguard"); boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); + int previousState = mStatusBarStateController.getState(); if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) { //TODO: StatusBarStateController should probably know about hiding the keyguard and // notify listeners. @@ -3627,7 +3628,7 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); } long delay = mKeyguardStateController.calculateGoingToFullShadeDelay(); - mLockscreenShadeTransitionController.onHideKeyguard(delay); + mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState); // Disable layout transitions in navbar for this transition because the load is just // too heavy for the CPU and GPU on any device. diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index 8c530914f7e80..ad16e9deb9235 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -54,6 +54,7 @@ import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoTileManager; +import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.Clock; @@ -91,6 +92,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { @Mock private MediaHost mQQSMediaHost; @Mock + private KeyguardBypassController mBypassController; + @Mock private FalsingManager mFalsingManager; public QSFragmentTest() { @@ -181,6 +184,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { new QSDetailDisplayer(), mQSMediaHost, mQQSMediaHost, + mBypassController, mQsComponentFactory, mFalsingManager); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index a6958b9398485..d2f87ec63d01c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -369,16 +369,17 @@ public class NotificationPanelViewTest extends SysuiTestCase { mKeyguardBypassController, mDozeParameters, mUnlockedScreenOffAnimationController); + mConfigurationController = new ConfigurationControllerImpl(mContext); PulseExpansionHandler expansionHandler = new PulseExpansionHandler( mContext, coordinator, mKeyguardBypassController, mHeadsUpManager, mock(NotificationRoundnessManager.class), + mConfigurationController, mStatusBarStateController, mFalsingManager, mLockscreenShadeTransitionController, new FalsingCollectorFake()); - mConfigurationController = new ConfigurationControllerImpl(mContext); when(mKeyguardStatusViewComponentFactory.build(any())) .thenReturn(mKeyguardStatusViewComponent); when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())