Fix drag down animation when bypassing am: 286825f60c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15114537

Change-Id: I9b24c716adcb2128bb6d1edd44f43e1063596fdf
This commit is contained in:
Selim Cinek
2021-07-23 22:48:16 +00:00
committed by Automerger Merge Worker
14 changed files with 182 additions and 154 deletions

View File

@@ -52,13 +52,6 @@ public interface QS extends FragmentBase {
void setListening(boolean listening); void setListening(boolean listening);
boolean isShowingDetail(); boolean isShowingDetail();
void closeDetail(); 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 animateHeaderSlidingOut();
void setQsExpansion(float qsExpansionFraction, float headerTranslation); void setQsExpansion(float qsExpansionFraction, float headerTranslation);
void setHeaderListening(boolean listening); void setHeaderListening(boolean listening);

View File

@@ -1456,7 +1456,7 @@
<dimen name="lockscreen_shade_notification_movement">24dp</dimen> <dimen name="lockscreen_shade_notification_movement">24dp</dimen>
<!-- Maximum overshoot for the pulse expansion --> <!-- 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_widget_radius">28dp</dimen>
<dimen name="people_space_image_radius">20dp</dimen> <dimen name="people_space_image_radius">20dp</dimen>

View File

@@ -48,6 +48,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator; 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.phone.NotificationsQuickSettingsContainer;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.util.InjectionInflationController; 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 Rect mQsBounds = new Rect();
private final StatusBarStateController mStatusBarStateController; private final StatusBarStateController mStatusBarStateController;
private final FalsingManager mFalsingManager; private final FalsingManager mFalsingManager;
private final KeyguardBypassController mBypassController;
private boolean mQsExpanded; private boolean mQsExpanded;
private boolean mHeaderAnimating; private boolean mHeaderAnimating;
private boolean mStackScrollerOverscrolling; private boolean mStackScrollerOverscrolling;
@@ -135,6 +137,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
StatusBarStateController statusBarStateController, CommandQueue commandQueue, StatusBarStateController statusBarStateController, CommandQueue commandQueue,
QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost, QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QUICK_QS_PANEL) MediaHost qqsMediaHost, @Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
KeyguardBypassController keyguardBypassController,
QSFragmentComponent.Factory qsComponentFactory, FeatureFlags featureFlags, QSFragmentComponent.Factory qsComponentFactory, FeatureFlags featureFlags,
FalsingManager falsingManager) { FalsingManager falsingManager) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler; mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
@@ -148,6 +151,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mHost = qsTileHost; mHost = qsTileHost;
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
mFalsingManager = falsingManager; mFalsingManager = falsingManager;
mBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController; mStatusBarStateController = statusBarStateController;
} }
@@ -380,16 +384,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
return mStatusBarStateController.getState() == StatusBarState.KEYGUARD; return mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
} }
@Override
public void setPulseExpanding(boolean pulseExpanding) {
if (pulseExpanding != mPulseExpanding) {
mPulseExpanding = pulseExpanding;
updateShowCollapsedOnKeyguard();
}
}
private void updateShowCollapsedOnKeyguard() { private void updateShowCollapsedOnKeyguard() {
boolean showCollapsed = mPulseExpanding || mTransitioningToFullShade; boolean showCollapsed = mBypassController.getBypassEnabled() || mTransitioningToFullShade;
if (showCollapsed != mShowCollapsedOnKeyguard) { if (showCollapsed != mShowCollapsedOnKeyguard) {
mShowCollapsedOnKeyguard = showCollapsed; mShowCollapsedOnKeyguard = showCollapsed;
updateQsState(); updateQsState();
@@ -719,5 +715,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
public void onStateChanged(int newState) { public void onStateChanged(int newState) {
mState = newState; mState = newState;
setKeyguardShowing(newState == StatusBarState.KEYGUARD); setKeyguardShowing(newState == StatusBarState.KEYGUARD);
updateShowCollapsedOnKeyguard();
} }
} }

View File

@@ -65,6 +65,7 @@ class LockscreenShadeTransitionController @Inject constructor(
configurationController: ConfigurationController, configurationController: ConfigurationController,
falsingManager: FalsingManager falsingManager: FalsingManager
) { ) {
private var pulseHeight: Float = 0f
private var useSplitShade: Boolean = false private var useSplitShade: Boolean = false
private lateinit var nsslController: NotificationStackScrollLayoutController private lateinit var nsslController: NotificationStackScrollLayoutController
lateinit var notificationPanelController: NotificationPanelViewController lateinit var notificationPanelController: NotificationPanelViewController
@@ -87,6 +88,12 @@ class LockscreenShadeTransitionController @Inject constructor(
@VisibleForTesting @VisibleForTesting
internal var dragDownAnimator: ValueAnimator? = null 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 * Distance that the full shade transition takes in order for scrim to fully transition to
* the shade (in alpha) * the shade (in alpha)
@@ -109,6 +116,12 @@ class LockscreenShadeTransitionController @Inject constructor(
*/ */
private var nextHideKeyguardNeedsNoAnimation = false private var nextHideKeyguardNeedsNoAnimation = false
/**
* The distance until we're showing the notifications when pulsing
*/
val distanceUntilShowingPulsingNotifications
get() = scrimTransitionDistance
/** /**
* The udfpsKeyguardViewController if it exists. * The udfpsKeyguardViewController if it exists.
*/ */
@@ -286,22 +299,26 @@ class LockscreenShadeTransitionController @Inject constructor(
nsslController.setTransitionToFullShadeAmount(field) nsslController.setTransitionToFullShadeAmount(field)
notificationPanelController.setTransitionToFullShadeAmount(field, notificationPanelController.setTransitionToFullShadeAmount(field,
false /* animate */, 0 /* delay */) false /* animate */, 0 /* delay */)
val scrimProgress = MathUtils.saturate(field / scrimTransitionDistance)
scrimController.setTransitionToFullShadeProgress(scrimProgress)
// TODO: appear qs also in split shade // TODO: appear qs also in split shade
val qsAmount = if (useSplitShade) 0f else field val qsAmount = if (useSplitShade) 0f else field
qS.setTransitionToFullShadeAmount(qsAmount, false /* animate */) qS.setTransitionToFullShadeAmount(qsAmount, false /* animate */)
// TODO: appear media also in split shade // TODO: appear media also in split shade
val mediaAmount = if (useSplitShade) 0f else field val mediaAmount = if (useSplitShade) 0f else field
mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount) mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount)
// Fade out all content only visible on the lockscreen transitionToShadeAmountCommon(field)
notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress)
depthController.transitionToFullShadeProgress = scrimProgress
udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress)
} }
} }
} }
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( private fun setDragDownAmountAnimated(
target: Float, target: Float,
delay: Long = 0, delay: Long = 0,
@@ -453,15 +470,19 @@ class LockscreenShadeTransitionController @Inject constructor(
/** /**
* Notify this handler that the keyguard was just dismissed and that a animation to * Notify this handler that the keyguard was just dismissed and that a animation to
* the full shade should happen. * 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) { if (animationHandlerOnKeyguardDismiss != null) {
animationHandlerOnKeyguardDismiss!!.invoke(delay) animationHandlerOnKeyguardDismiss!!.invoke(delay)
animationHandlerOnKeyguardDismiss = null animationHandlerOnKeyguardDismiss = null
} else { } else {
if (nextHideKeyguardNeedsNoAnimation) { if (nextHideKeyguardNeedsNoAnimation) {
nextHideKeyguardNeedsNoAnimation = false nextHideKeyguardNeedsNoAnimation = false
} else { } else if (previousState != StatusBarState.SHADE_LOCKED) {
// No animation necessary if we already were in the shade locked!
performDefaultGoToFullShadeAnimation(delay) performDefaultGoToFullShadeAnimation(delay)
} }
} }
@@ -479,6 +500,53 @@ class LockscreenShadeTransitionController @Inject constructor(
notificationPanelController.animateToFullShade(delay) notificationPanelController.animateToFullShade(delay)
animateAppear(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.Animator
import android.animation.AnimatorListenerAdapter import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.content.res.Configuration
import android.os.PowerManager import android.os.PowerManager
import android.os.PowerManager.WAKE_REASON_GESTURE import android.os.PowerManager.WAKE_REASON_GESTURE
import android.os.SystemClock 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.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
@@ -56,18 +57,17 @@ constructor(
private val bypassController: KeyguardBypassController, private val bypassController: KeyguardBypassController,
private val headsUpManager: HeadsUpManagerPhone, private val headsUpManager: HeadsUpManagerPhone,
private val roundnessManager: NotificationRoundnessManager, private val roundnessManager: NotificationRoundnessManager,
private val configurationController: ConfigurationController,
private val statusBarStateController: StatusBarStateController, private val statusBarStateController: StatusBarStateController,
private val falsingManager: FalsingManager, private val falsingManager: FalsingManager,
private val lockscreenShadeTransitionController: LockscreenShadeTransitionController, private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
private val falsingCollector: FalsingCollector private val falsingCollector: FalsingCollector
) : Gefingerpoken { ) : Gefingerpoken {
companion object { companion object {
private val RUBBERBAND_FACTOR_STATIC = 0.25f
private val SPRING_BACK_ANIMATION_LENGTH_MS = 375 private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
} }
private val mPowerManager: PowerManager? private val mPowerManager: PowerManager?
private val mMinDragDistance: Int
private var mInitialTouchX: Float = 0.0f private var mInitialTouchX: Float = 0.0f
private var mInitialTouchY: Float = 0.0f private var mInitialTouchY: Float = 0.0f
var isExpanding: Boolean = false var isExpanding: Boolean = false
@@ -81,6 +81,7 @@ constructor(
topEntry?.let { topEntry?.let {
roundnessManager.setTrackingHeadsUp(it.row) roundnessManager.setTrackingHeadsUp(it.row)
} }
lockscreenShadeTransitionController.onPulseExpansionStarted()
} else { } else {
roundnessManager.setTrackingHeadsUp(null) roundnessManager.setTrackingHeadsUp(null)
if (!leavingLockscreen) { if (!leavingLockscreen) {
@@ -93,8 +94,8 @@ constructor(
} }
var leavingLockscreen: Boolean = false var leavingLockscreen: Boolean = false
private set private set
private val mTouchSlop: Float private var touchSlop = 0f
private lateinit var overStretchHandler: OverStretchHandler private var minDragDistance = 0
private lateinit var stackScrollerController: NotificationStackScrollLayoutController private lateinit var stackScrollerController: NotificationStackScrollLayoutController
private val mTemp2 = IntArray(2) private val mTemp2 = IntArray(2)
private var mDraggedFarEnough: Boolean = false private var mDraggedFarEnough: Boolean = false
@@ -102,9 +103,7 @@ constructor(
private var mPulsing: Boolean = false private var mPulsing: Boolean = false
var isWakingToShadeLocked: Boolean = false var isWakingToShadeLocked: Boolean = false
private set 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 var velocityTracker: VelocityTracker? = null
private val isFalseTouch: Boolean private val isFalseTouch: Boolean
@@ -114,12 +113,21 @@ constructor(
var bouncerShowing: Boolean = false var bouncerShowing: Boolean = false
init { init {
mMinDragDistance = context.resources.getDimensionPixelSize( initResources(context)
R.dimen.keyguard_drag_down_min_distance) configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat() override fun onConfigChanged(newConfig: Configuration?) {
initResources(context)
}
})
mPowerManager = context.getSystemService(PowerManager::class.java) 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 { override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
return canHandleMotionEvent() && startExpansion(event) return canHandleMotionEvent() && startExpansion(event)
} }
@@ -148,14 +156,12 @@ constructor(
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
val h = y - mInitialTouchY val h = y - mInitialTouchY
if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) { if (h > touchSlop && h > Math.abs(x - mInitialTouchX)) {
falsingCollector.onStartExpandingFromPulse() falsingCollector.onStartExpandingFromPulse()
isExpanding = true isExpanding = true
captureStartingChild(mInitialTouchX, mInitialTouchY) captureStartingChild(mInitialTouchX, mInitialTouchY)
mInitialTouchY = y mInitialTouchY = y
mInitialTouchX = x mInitialTouchX = x
mWakeUpHeight = wakeUpCoordinator.getWakeUpHeight()
mReachedWakeUpHeight = false
return true return true
} }
} }
@@ -216,7 +222,6 @@ constructor(
} }
private fun finishExpansion() { private fun finishExpansion() {
resetClock()
val startingChild = mStartingChild val startingChild = mStartingChild
if (mStartingChild != null) { if (mStartingChild != null) {
setUserLocked(mStartingChild!!, false) setUserLocked(mStartingChild!!, false)
@@ -230,6 +235,7 @@ constructor(
} }
lockscreenShadeTransitionController.goToLockedShade(startingChild, lockscreenShadeTransitionController.goToLockedShade(startingChild,
needsQSAnimation = false) needsQSAnimation = false)
lockscreenShadeTransitionController.finishPulseAnimation(cancelled = false)
leavingLockscreen = true leavingLockscreen = true
isExpanding = false isExpanding = false
if (mStartingChild is ExpandableNotificationRow) { if (mStartingChild is ExpandableNotificationRow) {
@@ -240,24 +246,19 @@ constructor(
private fun updateExpansionHeight(height: Float) { private fun updateExpansionHeight(height: Float) {
var expansionHeight = max(height, 0.0f) var expansionHeight = max(height, 0.0f)
if (!mReachedWakeUpHeight && height > mWakeUpHeight) {
mReachedWakeUpHeight = true
}
if (mStartingChild != null) { if (mStartingChild != null) {
val child = mStartingChild!! val child = mStartingChild!!
val newHeight = Math.min((child.collapsedHeight + expansionHeight).toInt(), val newHeight = Math.min((child.collapsedHeight + expansionHeight).toInt(),
child.maxContentHeight) child.maxContentHeight)
child.actualHeight = newHeight child.actualHeight = newHeight
expansionHeight = max(newHeight.toFloat(), expansionHeight)
} else { } else {
val target = if (mReachedWakeUpHeight) mWakeUpHeight else 0.0f wakeUpCoordinator.setNotificationsVisibleForExpansion(
wakeUpCoordinator.setNotificationsVisibleForExpansion(height > target, height
true /* animate */, > lockscreenShadeTransitionController.distanceUntilShowingPulsingNotifications,
true /* increaseSpeed */) true /* animate */,
expansionHeight = max(mWakeUpHeight, expansionHeight) true /* increaseSpeed */)
} }
val dragDownAmount = wakeUpCoordinator.setPulseHeight(expansionHeight) lockscreenShadeTransitionController.setPulseHeight(expansionHeight, animate = false)
setOverStretchAmount(dragDownAmount)
} }
private fun captureStartingChild(x: Float, y: Float) { 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) { private fun reset(child: ExpandableView) {
if (child.actualHeight == child.collapsedHeight) { if (child.actualHeight == child.collapsedHeight) {
setUserLocked(child, false) 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() { private fun cancelExpansion() {
isExpanding = false isExpanding = false
falsingCollector.onExpansionFromPulseStopped() falsingCollector.onExpansionFromPulseStopped()
if (mStartingChild != null) { if (mStartingChild != null) {
reset(mStartingChild!!) reset(mStartingChild!!)
mStartingChild = null mStartingChild = null
} else {
resetClock()
} }
lockscreenShadeTransitionController.finishPulseAnimation(cancelled = true)
wakeUpCoordinator.setNotificationsVisibleForExpansion(false /* visible */, wakeUpCoordinator.setNotificationsVisibleForExpansion(false /* visible */,
true /* animate */, true /* animate */,
false /* increaseSpeed */) false /* increaseSpeed */)
@@ -333,11 +318,7 @@ constructor(
} else null } else null
} }
fun setUp( fun setUp(stackScrollerController: NotificationStackScrollLayoutController) {
stackScrollerController: NotificationStackScrollLayoutController,
overStrechHandler: OverStretchHandler
) {
this.overStretchHandler = overStrechHandler
this.stackScrollerController = stackScrollerController this.stackScrollerController = stackScrollerController
} }
@@ -348,12 +329,4 @@ constructor(
fun onStartedWakingUp() { fun onStartedWakingUp() {
isWakingToShadeLocked = false 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() { private fun updateHideAmount() {
val linearAmount = min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount) val linearAmount = min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount)
val amount = min(1.0f - mVisibilityAmount, mDozeAmount) 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) { override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) {
var animate = shouldAnimateVisibility() var animate = shouldAnimateVisibility()
if (!isHeadsUp) { if (!isHeadsUp) {

View File

@@ -5138,12 +5138,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
* @return the overflow how much the height is further than he lowest notification * @return the overflow how much the height is further than he lowest notification
*/ */
public float setPulseHeight(float height) { public float setPulseHeight(float height) {
float overflow;
mAmbientState.setPulseHeight(height); mAmbientState.setPulseHeight(height);
if (mKeyguardBypassEnabledProvider.getBypassEnabled()) { if (mKeyguardBypassEnabledProvider.getBypassEnabled()) {
notifyAppearChangedListeners(); notifyAppearChangedListeners();
overflow = Math.max(0, height - getIntrinsicPadding());
} else {
overflow = Math.max(0, height
- mAmbientState.getInnerHeight(true /* ignorePulseHeight */));
} }
requestChildrenUpdate(); requestChildrenUpdate();
return Math.max(0, height - mAmbientState.getInnerHeight(true /* ignorePulseHeight */)); return overflow;
} }
public float getPulseHeight() { public float getPulseHeight() {
@@ -5203,12 +5208,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
public float calculateAppearFractionBypass() { public float calculateAppearFractionBypass() {
float pulseHeight = getPulseHeight(); float pulseHeight = getPulseHeight();
float wakeUpHeight = getWakeUpHeight();
float dragDownAmount = pulseHeight - wakeUpHeight;
// The total distance required to fully reveal the header // The total distance required to fully reveal the header
float totalDistance = getIntrinsicPadding(); float totalDistance = getIntrinsicPadding();
return MathUtils.smoothStep(0, totalDistance, dragDownAmount); return MathUtils.smoothStep(0, totalDistance, pulseHeight);
} }
public void setController( public void setController(

View File

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

View File

@@ -211,7 +211,7 @@ public class KeyguardClockPositionAlgorithm {
private int getStackScrollerPadding(int clockYPosition) { private int getStackScrollerPadding(int clockYPosition) {
if (mBypassEnabled) { if (mBypassEnabled) {
return mUnlockedStackScrollerPadding; return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
} else if (mIsSplitShade) { } else if (mIsSplitShade) {
return clockYPosition; return clockYPosition;
} else { } else {

View File

@@ -165,14 +165,14 @@ public class NotificationIconAreaController implements
* Called by the Keyguard*ViewController whose view contains the aod icons. * Called by the Keyguard*ViewController whose view contains the aod icons.
*/ */
public void setupAodIcons(@NonNull NotificationIconContainer aodIcons) { public void setupAodIcons(@NonNull NotificationIconContainer aodIcons) {
boolean changed = mAodIcons != null; boolean changed = mAodIcons != null && aodIcons != mAodIcons;
if (changed) { if (changed) {
mAodIcons.setAnimationsEnabled(false); mAodIcons.setAnimationsEnabled(false);
mAodIcons.removeAllViews(); mAodIcons.removeAllViews();
} }
mAodIcons = aodIcons; mAodIcons = aodIcons;
mAodIcons.setOnLockScreen(true); mAodIcons.setOnLockScreen(true);
updateAodIconsVisibility(false /* animate */); updateAodIconsVisibility(false /* animate */, changed);
updateAnimations(); updateAnimations();
if (changed) { if (changed) {
updateAodNotificationIcons(); updateAodNotificationIcons();
@@ -587,7 +587,7 @@ public class NotificationIconAreaController implements
@Override @Override
public void onStateChanged(int newState) { public void onStateChanged(int newState) {
updateAodIconsVisibility(false /* animate */); updateAodIconsVisibility(false /* animate */, false /* force */);
updateAnimations(); updateAnimations();
} }
@@ -663,18 +663,18 @@ public class NotificationIconAreaController implements
// since otherwise the unhide animation overlaps // since otherwise the unhide animation overlaps
animate &= fullyHidden; animate &= fullyHidden;
} }
updateAodIconsVisibility(animate); updateAodIconsVisibility(animate, false /* force */);
updateAodNotificationIcons(); updateAodNotificationIcons();
} }
@Override @Override
public void onPulseExpansionChanged(boolean expandingChanged) { public void onPulseExpansionChanged(boolean expandingChanged) {
if (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) { if (mAodIcons == null) {
return; return;
} }
@@ -688,10 +688,11 @@ public class NotificationIconAreaController implements
&& !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) { && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()) {
visible = false; visible = false;
} }
if (visible && mWakeUpCoordinator.isPulseExpanding()) { if (visible && mWakeUpCoordinator.isPulseExpanding()
&& !mBypassController.getBypassEnabled()) {
visible = false; visible = false;
} }
if (mAodIconsVisible != visible) { if (mAodIconsVisible != visible || forceUpdate) {
mAodIconsVisible = visible; mAodIconsVisible = visible;
mAodIcons.animate().cancel(); mAodIcons.animate().cancel();
if (animate) { if (animate) {

View File

@@ -608,6 +608,11 @@ public class NotificationPanelViewController extends PanelViewController {
* Is the current animator resetting the qs translation. * Is the current animator resetting the qs translation.
*/ */
private boolean mIsQsTranslationResetAnimator; 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 Rect mKeyguardStatusAreaClipBounds = new Rect();
private final Region mQsInterceptRegion = new Region(); private final Region mQsInterceptRegion = new Region();
@@ -884,14 +889,7 @@ public class NotificationPanelViewController extends PanelViewController {
mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController); mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
mQsFrame = mView.findViewById(R.id.qs_frame); mQsFrame = mView.findViewById(R.id.qs_frame);
mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController, mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController);
amount -> {
float progress = amount / mView.getHeight();
float overstretch = Interpolators.getOvershootInterpolation(progress,
(float) mMaxOverscrollAmountForPulse / mView.getHeight(),
0.2f);
setOverStrechAmount(overstretch);
});
mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() { mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
@Override @Override
public void onFullyHiddenChanged(boolean isFullyHidden) { public void onFullyHiddenChanged(boolean isFullyHidden) {
@@ -903,7 +901,6 @@ public class NotificationPanelViewController extends PanelViewController {
if (mKeyguardBypassController.getBypassEnabled()) { if (mKeyguardBypassController.getBypassEnabled()) {
// Position the notifications while dragging down while pulsing // Position the notifications while dragging down while pulsing
requestScrollerTopPaddingUpdate(false /* animate */); requestScrollerTopPaddingUpdate(false /* animate */);
updateQSPulseExpansion();
} }
} }
}); });
@@ -2239,7 +2236,7 @@ public class NotificationPanelViewController extends PanelViewController {
} }
} }
protected void updateQsExpansion() { private void updateQsExpansion() {
if (mQs == null) return; if (mQs == null) return;
float qsExpansionFraction = computeQsExpansionFraction(); float qsExpansionFraction = computeQsExpansionFraction();
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation()); mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
@@ -2298,9 +2295,20 @@ public class NotificationPanelViewController extends PanelViewController {
top = mTransitionToFullShadeQSPosition; top = mTransitionToFullShadeQSPosition;
} else { } else {
final float notificationTop = getQSEdgePosition(); final float notificationTop = getQSEdgePosition();
top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop) if (isOnKeyguard()) {
: notificationTop); 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(); bottom = getView().getBottom();
// notification bounds should take full screen width regardless of insets // notification bounds should take full screen width regardless of insets
left = 0; left = 0;
@@ -2353,6 +2361,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
mQsClippingAnimation = null; mQsClippingAnimation = null;
mIsQsTranslationResetAnimator = false; mIsQsTranslationResetAnimator = false;
mIsPulseExpansionResetAnimator = false;
} }
}); });
mQsClippingAnimation.start(); mQsClippingAnimation.start();
@@ -2378,9 +2387,17 @@ public class NotificationPanelViewController extends PanelViewController {
} }
if (mQs != null) { if (mQs != null) {
float qsTranslation = 0; float qsTranslation = 0;
if (mTransitioningToFullShadeProgress > 0.0f || (mQsClippingAnimation != null boolean pulseExpanding = mPulseExpansionHandler.isExpanding();
&& mIsQsTranslationResetAnimator)) { if (mTransitioningToFullShadeProgress > 0.0f || pulseExpanding
qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT; || (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; mQsTranslationForFullShadeTransition = qsTranslation;
updateQsFrameTranslation(); updateQsFrameTranslation();
@@ -2509,14 +2526,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 * 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. * shade. 0.0f means we're not transitioning yet.
@@ -2567,6 +2576,15 @@ public class NotificationPanelViewController extends PanelViewController {
updateQsExpansion(); 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 * 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. * shade locked / shade. This is used when dragging down to the full shade.
@@ -2928,19 +2946,7 @@ public class NotificationPanelViewController extends PanelViewController {
startHeight = -mQsExpansionHeight * QS_PARALLAX_AMOUNT; startHeight = -mQsExpansionHeight * QS_PARALLAX_AMOUNT;
} }
if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) { if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
if (mNotificationStackScrollLayoutController.isPulseExpanding()) { appearAmount = mNotificationStackScrollLayoutController.calculateAppearFractionBypass();
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;
}
startHeight = -mQs.getQsMinExpansionHeight(); startHeight = -mQs.getQsMinExpansionHeight();
} }
float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount)); float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount));
@@ -3543,7 +3549,6 @@ public class NotificationPanelViewController extends PanelViewController {
mQs.setPanelView(mHeightListener); mQs.setPanelView(mHeightListener);
mQs.setExpandClickListener(mOnClickListener); mQs.setExpandClickListener(mOnClickListener);
mQs.setHeaderClickable(isQsExpansionEnabled()); mQs.setHeaderClickable(isQsExpansionEnabled());
updateQSPulseExpansion();
mQs.setOverscrolling(mStackScrollerOverscrolling); mQs.setOverscrolling(mStackScrollerOverscrolling);
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade); mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
@@ -4423,7 +4428,6 @@ public class NotificationPanelViewController extends PanelViewController {
updateMaxDisplayedNotifications(false); updateMaxDisplayedNotifications(false);
// The update needs to happen after the headerSlide in above, otherwise the translation // The update needs to happen after the headerSlide in above, otherwise the translation
// would reset // would reset
updateQSPulseExpansion();
maybeAnimateBottomAreaAlpha(); maybeAnimateBottomAreaAlpha();
resetHorizontalPanelPosition(); resetHorizontalPanelPosition();
updateQsState(); updateQsState();
@@ -4458,7 +4462,9 @@ public class NotificationPanelViewController extends PanelViewController {
* Sets the overstretch amount in raw pixels when dragging down. * Sets the overstretch amount in raw pixels when dragging down.
*/ */
public void setOverStrechAmount(float amount) { public void setOverStrechAmount(float amount) {
mOverStretchAmount = amount; float progress = amount / mView.getHeight();
float overstretch = Interpolators.getOvershootInterpolation(progress);
mOverStretchAmount = overstretch * mMaxOverscrollAmountForPulse;
positionClockAndNotifications(true /* forceUpdate */); positionClockAndNotifications(true /* forceUpdate */);
} }

View File

@@ -3616,6 +3616,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mIsKeyguard = false; mIsKeyguard = false;
Trace.beginSection("StatusBar#hideKeyguard"); Trace.beginSection("StatusBar#hideKeyguard");
boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
int previousState = mStatusBarStateController.getState();
if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) { if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) {
//TODO: StatusBarStateController should probably know about hiding the keyguard and //TODO: StatusBarStateController should probably know about hiding the keyguard and
// notify listeners. // notify listeners.
@@ -3628,7 +3629,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
} }
long delay = mKeyguardStateController.calculateGoingToFullShadeDelay(); long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
mLockscreenShadeTransitionController.onHideKeyguard(delay); mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
// Disable layout transitions in navbar for this transition because the load is just // Disable layout transitions in navbar for this transition because the load is just
// too heavy for the CPU and GPU on any device. // too heavy for the CPU and GPU on any device.

View File

@@ -55,6 +55,7 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.phone.AutoTileManager; 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.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.policy.Clock;
@@ -92,6 +93,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Mock @Mock
private MediaHost mQQSMediaHost; private MediaHost mQQSMediaHost;
@Mock @Mock
private KeyguardBypassController mBypassController;
@Mock
private FeatureFlags mFeatureFlags; private FeatureFlags mFeatureFlags;
@Mock @Mock
private FalsingManager mFalsingManager; private FalsingManager mFalsingManager;
@@ -184,6 +187,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
new QSDetailDisplayer(), new QSDetailDisplayer(),
mQSMediaHost, mQSMediaHost,
mQQSMediaHost, mQQSMediaHost,
mBypassController,
mQsComponentFactory, mQsComponentFactory,
mFeatureFlags, mFeatureFlags,
mFalsingManager); mFalsingManager);

View File

@@ -372,16 +372,17 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mKeyguardBypassController, mKeyguardBypassController,
mDozeParameters, mDozeParameters,
mUnlockedScreenOffAnimationController); mUnlockedScreenOffAnimationController);
mConfigurationController = new ConfigurationControllerImpl(mContext);
PulseExpansionHandler expansionHandler = new PulseExpansionHandler( PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
mContext, mContext,
coordinator, coordinator,
mKeyguardBypassController, mHeadsUpManager, mKeyguardBypassController, mHeadsUpManager,
mock(NotificationRoundnessManager.class), mock(NotificationRoundnessManager.class),
mConfigurationController,
mStatusBarStateController, mStatusBarStateController,
mFalsingManager, mFalsingManager,
mLockscreenShadeTransitionController, mLockscreenShadeTransitionController,
new FalsingCollectorFake()); new FalsingCollectorFake());
mConfigurationController = new ConfigurationControllerImpl(mContext);
when(mKeyguardStatusViewComponentFactory.build(any())) when(mKeyguardStatusViewComponentFactory.build(any()))
.thenReturn(mKeyguardStatusViewComponent); .thenReturn(mKeyguardStatusViewComponent);
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController()) when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())