Fix drag down animation when bypassing

The drag down animation didn't do the transition
to the full shade visually, so things would look
out of place.

Fixes: 191282610
Test: drag down while bypassing
Change-Id: Icdd62155f3762621c1046ed5271476ec0b4e2635
This commit is contained in:
Selim Cinek
2021-06-25 14:52:12 +02:00
committed by Beth Thibodeau
parent aff5acf765
commit d879f8802c
14 changed files with 182 additions and 154 deletions

View File

@@ -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);

View File

@@ -1462,7 +1462,7 @@
<dimen name="lockscreen_shade_notification_movement">24dp</dimen>
<!-- Maximum overshoot for the pulse expansion -->
<dimen name="pulse_expansion_max_top_overshoot">16dp</dimen>
<dimen name="pulse_expansion_max_top_overshoot">32dp</dimen>
<dimen name="people_space_widget_radius">28dp</dimen>
<dimen name="people_space_image_radius">20dp</dimen>

View File

@@ -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();
}
}

View File

@@ -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()
}
}
/**

View File

@@ -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)
}
}

View File

@@ -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) {

View File

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

View File

@@ -903,10 +903,6 @@ public class NotificationStackScrollLayoutController {
mView.setDozeAmount(amount);
}
public float getWakeUpHeight() {
return mView.getWakeUpHeight();
}
public int getSpeedBumpIndex() {
return mView.getSpeedBumpIndex();
}

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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 */);
}

View File

@@ -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.

View File

@@ -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);
}

View File

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