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())