Merge "First part of Fixing heads-up notification motion in split shade" into tm-qpr-dev am: 12520fff05 am: 74d88a0b79

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

Change-Id: I96e37e8d00a427b2015e207a1b7bb68a0201fb0b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Michał Brzeziński
2022-09-14 20:48:00 +00:00
committed by Automerger Merge Worker
7 changed files with 121 additions and 58 deletions

View File

@@ -443,6 +443,8 @@ public final class NotificationPanelViewController extends PanelViewController {
private boolean mQsTouchAboveFalsingThreshold;
private int mQsFalsingThreshold;
/** Indicates drag starting height when swiping down or up on heads-up notifications */
private int mHeadsUpStartHeight;
private HeadsUpTouchHelper mHeadsUpTouchHelper;
private boolean mListenForHeadsUp;
private int mNavigationBarBottomHeight;
@@ -645,6 +647,8 @@ public final class NotificationPanelViewController extends PanelViewController {
/** The drag distance required to fully expand the split shade. */
private int mSplitShadeFullTransitionDistance;
/** The drag distance required to fully transition scrims. */
private int mSplitShadeScrimTransitionDistance;
private final NotificationListContainer mNotificationListContainer;
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
@@ -1052,6 +1056,8 @@ public final class NotificationPanelViewController extends PanelViewController {
mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
R.dimen.notification_side_paddings);
mUdfpsMaxYBurnInOffset = mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
mSplitShadeScrimTransitionDistance = mResources.getDimensionPixelSize(
R.dimen.split_shade_scrim_transition_distance);
}
private void updateViewControllers(KeyguardStatusView keyguardStatusView,
@@ -1335,7 +1341,7 @@ public final class NotificationPanelViewController extends PanelViewController {
mQsSizeChangeAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mQsSizeChangeAnimator.addUpdateListener(animation -> {
requestScrollerTopPaddingUpdate(false /* animate */);
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
int height = (int) mQsSizeChangeAnimator.getAnimatedValue();
mQs.setHeightOverride(height);
});
@@ -2114,7 +2120,7 @@ public final class NotificationPanelViewController extends PanelViewController {
mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1);
setQsExpandImmediate(true);
setShowShelfOnly(true);
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
// Normally, we start listening when the panel is expanded, but here we need to start
// earlier so the state is already up to date when dragging down.
@@ -2326,7 +2332,7 @@ public final class NotificationPanelViewController extends PanelViewController {
// Reset scroll position and apply that position to the expanded height.
float height = mQsExpansionHeight;
setQsExpansion(height);
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
mNotificationStackScrollLayoutController.checkSnoozeLeavebehind();
// When expanding QS, let's authenticate the user if possible,
@@ -2342,7 +2348,7 @@ public final class NotificationPanelViewController extends PanelViewController {
if (changed) {
mQsExpanded = expanded;
updateQsState();
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
mFalsingCollector.setQsExpanded(expanded);
mCentralSurfaces.setQsExpanded(expanded);
mNotificationsQSContainerController.setQsExpanded(expanded);
@@ -3066,16 +3072,7 @@ public final class NotificationPanelViewController extends PanelViewController {
int maxHeight;
if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted
|| mPulsing || mSplitShadeEnabled) {
if (mSplitShadeEnabled && mBarState == SHADE) {
// Max panel height is used to calculate the fraction of the shade expansion.
// Traditionally the value is based on the number of notifications.
// On split-shade, we want the required distance to be a specific and constant
// value, to make sure the expansion motion has the expected speed.
// We also only want this on non-lockscreen for now.
maxHeight = mSplitShadeFullTransitionDistance;
} else {
maxHeight = calculatePanelHeightQsExpanded();
}
maxHeight = calculatePanelHeightQsExpanded();
} else {
maxHeight = calculatePanelHeightShade();
}
@@ -3433,6 +3430,31 @@ public final class NotificationPanelViewController extends PanelViewController {
|| !isTracking());
}
@Override
public int getMaxPanelTransitionDistance() {
// Traditionally the value is based on the number of notifications. On split-shade, we want
// the required distance to be a specific and constant value, to make sure the expansion
// motion has the expected speed. We also only want this on non-lockscreen for now.
if (mSplitShadeEnabled && mBarState == SHADE) {
boolean transitionFromHeadsUp =
mHeadsUpManager.isTrackingHeadsUp() || mExpandingFromHeadsUp;
// heads-up starting height is too close to mSplitShadeFullTransitionDistance and
// when dragging HUN transition is already 90% complete. It makes shade become
// immediately visible when starting to drag. We want to set distance so that
// nothing is immediately visible when dragging (important for HUN swipe up motion) -
// 0.4 expansion fraction is a good starting point.
if (transitionFromHeadsUp) {
double maxDistance = Math.max(mSplitShadeFullTransitionDistance,
mHeadsUpStartHeight * 2.5);
return (int) Math.min(getMaxPanelHeight(), maxDistance);
} else {
return mSplitShadeFullTransitionDistance;
}
} else {
return getMaxPanelHeight();
}
}
@Override
protected boolean isTrackingBlocked() {
return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
@@ -3631,11 +3653,36 @@ public final class NotificationPanelViewController extends PanelViewController {
return mBarState == KEYGUARD;
}
/**
* Called when heads-up notification is being dragged up or down to indicate what's the starting
* height for shade motion
*/
public void setHeadsUpDraggingStartingHeight(int startHeight) {
mHeadsUpStartHeight = startHeight;
float scrimMinFraction;
if (mSplitShadeEnabled) {
boolean highHun = mHeadsUpStartHeight * 2.5 > mSplitShadeScrimTransitionDistance;
// if HUN height is higher than 40% of predefined transition distance, it means HUN
// is too high for regular transition. In that case we need to calculate transition
// distance - here we take scrim transition distance as equal to shade transition
// distance. It doesn't result in perfect motion - usually scrim transition distance
// should be longer - but it's good enough for HUN case.
float transitionDistance =
highHun ? getMaxPanelTransitionDistance() : mSplitShadeFullTransitionDistance;
scrimMinFraction = mHeadsUpStartHeight / transitionDistance;
} else {
int transitionDistance = getMaxPanelHeight();
scrimMinFraction = transitionDistance > 0f
? (float) mHeadsUpStartHeight / transitionDistance : 0f;
}
setPanelScrimMinFraction(scrimMinFraction);
}
/**
* Sets the minimum fraction for the panel expansion offset. This may be non-zero in certain
* cases, such as if there's a heads-up notification.
*/
public void setPanelScrimMinFraction(float minFraction) {
private void setPanelScrimMinFraction(float minFraction) {
mMinFraction = minFraction;
mDepthController.setPanelPullDownMinFraction(mMinFraction);
mScrimController.setPanelScrimMinFraction(mMinFraction);
@@ -4368,7 +4415,7 @@ public final class NotificationPanelViewController extends PanelViewController {
if (mKeyguardShowing) {
updateMaxDisplayedNotifications(true);
}
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
}
@Override
@@ -4501,7 +4548,7 @@ public final class NotificationPanelViewController extends PanelViewController {
if (mQsExpanded && mQsFullyExpanded) {
mQsExpansionHeight = mQsMaxExpansionHeight;
requestScrollerTopPaddingUpdate(false /* animate */);
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
}
if (mAccessibilityManager.isEnabled()) {
mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
@@ -4770,7 +4817,7 @@ public final class NotificationPanelViewController extends PanelViewController {
if (mQsExpanded && mQsFullyExpanded) {
mQsExpansionHeight = mQsMaxExpansionHeight;
requestScrollerTopPaddingUpdate(false /* animate */);
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
// Size has changed, start an animation.
if (mQsMaxExpansionHeight != oldMaxHeight) {

View File

@@ -248,7 +248,7 @@ public abstract class PanelViewController {
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onKeyguardFadingAwayChanged() {
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
}
});
mAmbientState = ambientState;
@@ -730,7 +730,7 @@ public abstract class PanelViewController {
setExpandedHeightInternal(height);
}
protected void requestPanelHeightUpdate() {
void updateExpandedHeightToMaxHeight() {
float currentMaxPanelHeight = getMaxPanelHeight();
if (isFullyCollapsed()) {
@@ -753,6 +753,13 @@ public abstract class PanelViewController {
setExpandedHeight(currentMaxPanelHeight);
}
/**
* Returns drag down distance after which panel should be fully expanded. Usually it's the
* same as max panel height but for large screen devices (especially split shade) we might
* want to return different value to shorten drag distance
*/
public abstract int getMaxPanelTransitionDistance();
public void setExpandedHeightInternal(float h) {
if (isNaN(h)) {
Log.wtf(TAG, "ExpandedHeight set to NaN");
@@ -763,18 +770,15 @@ public abstract class PanelViewController {
() -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
mExpandLatencyTracking = false;
}
float maxPanelHeight = getMaxPanelHeight();
float maxPanelHeight = getMaxPanelTransitionDistance();
if (mHeightAnimator == null) {
// Split shade has its own overscroll logic
if (mTracking && !mInSplitShade) {
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
}
mExpandedHeight = Math.min(h, maxPanelHeight);
} else {
mExpandedHeight = h;
}
mExpandedHeight = Math.min(h, maxPanelHeight);
// If we are closing the panel and we are almost there due to a slow decelerating
// interpolator, abort the animation.
if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
@@ -832,7 +836,7 @@ public abstract class PanelViewController {
protected abstract int getMaxPanelHeight();
public void setExpandedFraction(float frac) {
setExpandedHeight(getMaxPanelHeight() * frac);
setExpandedHeight(getMaxPanelTransitionDistance() * frac);
}
public float getExpandedHeight() {
@@ -1029,7 +1033,7 @@ public abstract class PanelViewController {
mHeightAnimator = animator;
if (animator == null && mPanelUpdateWhenAnimatorEnds) {
mPanelUpdateWhenAnimatorEnds = false;
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
}
}
@@ -1421,7 +1425,7 @@ public abstract class PanelViewController {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
requestPanelHeightUpdate();
updateExpandedHeightToMaxHeight();
mHasLayoutedSinceDown = true;
if (mUpdateFlingOnLayout) {
abortAnimations();

View File

@@ -14,6 +14,7 @@ import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent
import com.android.systemui.statusbar.phone.panelstate.PanelState
import com.android.systemui.statusbar.phone.panelstate.STATE_OPENING
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.util.LargeScreenUtils
import java.io.PrintWriter
import javax.inject.Inject
@@ -28,6 +29,7 @@ constructor(
private val scrimController: ScrimController,
@Main private val resources: Resources,
private val statusBarStateController: SysuiStatusBarStateController,
private val headsUpManager: HeadsUpManager
) {
private var inSplitShade = false
@@ -84,7 +86,11 @@ constructor(
}
private fun canUseCustomFraction(panelState: Int?) =
inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING
inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING &&
// in case of HUN we can't always use predefined distances to manage scrim
// transition because dragDownPxAmount can start from value bigger than
// splitShadeScrimTransitionDistance
!headsUpManager.isTrackingHeadsUp
private fun isScreenUnlocked() =
statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE

View File

@@ -115,9 +115,7 @@ public class HeadsUpTouchHelper implements Gefingerpoken {
mInitialTouchY = y;
int startHeight = (int) (mPickedChild.getActualHeight()
+ mPickedChild.getTranslationY());
float maxPanelHeight = mPanel.getMaxPanelHeight();
mPanel.setPanelScrimMinFraction(maxPanelHeight > 0f
? (float) startHeight / maxPanelHeight : 0f);
mPanel.setHeadsUpDraggingStartingHeight(startHeight);
mPanel.startExpandMotion(x, y, true /* startTracking */, startHeight);
// This call needs to be after the expansion start otherwise we will get a
// flicker of one frame as it's not expanded yet.

View File

@@ -114,8 +114,8 @@ class PanelExpansionStateManager @Inject constructor() {
"end state=${state.panelStateToString()} " +
"f=$fraction " +
"expanded=$expanded " +
"tracking=$tracking" +
"drawDownPxAmount=$dragDownPxAmount " +
"tracking=$tracking " +
"dragDownPxAmount=$dragDownPxAmount " +
"${if (fullyOpened) " fullyOpened" else ""} " +
if (fullyClosed) " fullyClosed" else ""
)

View File

@@ -183,6 +183,7 @@ import java.util.Optional;
@TestableLooper.RunWithLooper
public class NotificationPanelViewControllerTest extends SysuiTestCase {
private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
private static final int PANEL_WIDTH = 500; // Random value just for the test.
@@ -321,6 +322,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
.thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
.thenReturn(10);
when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
.thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
when(mView.getContext()).thenReturn(getContext());
when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
@@ -666,8 +669,9 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
public void testSetPanelScrimMinFraction() {
mNotificationPanelViewController.setPanelScrimMinFraction(0.5f);
public void testSetPanelScrimMinFractionWhenHeadsUpIsDragged() {
mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
mNotificationPanelViewController.getMaxPanelHeight() / 2);
verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f));
}
@@ -1363,40 +1367,47 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
public void getMaxPanelHeight_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
int splitShadeFullTransitionDistance = 123456;
public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
enableSplitShade(true);
setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance);
mNotificationPanelViewController.expandWithQs();
int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight();
int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
assertThat(maxPanelHeight).isEqualTo(splitShadeFullTransitionDistance);
assertThat(maxDistance).isEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
}
@Test
public void getMaxPanelHeight_expandingSplitShade_keyguard_returnsNonSplitShadeValue() {
public void getMaxPanelTransitionDistance_inSplitShade_withHeadsUp_returnsBiggerValue() {
enableSplitShade(true);
mNotificationPanelViewController.expandWithQs();
when(mHeadsUpManager.isTrackingHeadsUp()).thenReturn(true);
mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
assertThat(maxDistance).isGreaterThan(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
}
@Test
public void getMaxPanelTransitionDistance_expandingSplitShade_keyguard_returnsNonSplitShadeValue() {
mStatusBarStateController.setState(KEYGUARD);
int splitShadeFullTransitionDistance = 123456;
enableSplitShade(true);
setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance);
mNotificationPanelViewController.expandWithQs();
int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight();
int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance);
assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
}
@Test
public void getMaxPanelHeight_expanding_notSplitShade_returnsNonSplitShadeValue() {
int splitShadeFullTransitionDistance = 123456;
public void getMaxPanelTransitionDistance_expanding_notSplitShade_returnsNonSplitShadeValue() {
enableSplitShade(false);
setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance);
mNotificationPanelViewController.expandWithQs();
int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight();
int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance);
assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
}
@Test
@@ -1543,12 +1554,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mTouchHandler.onTouch(mView, ev);
}
private void setSplitShadeFullTransitionDistance(int splitShadeFullTransitionDistance) {
when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
.thenReturn(splitShadeFullTransitionDistance);
mNotificationPanelViewController.updateResources();
}
private void setDozing(boolean dozing, boolean dozingAlwaysOn) {
when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
mNotificationPanelViewController.setDozing(

View File

@@ -13,6 +13,7 @@ import com.android.systemui.statusbar.phone.panelstate.STATE_CLOSED
import com.android.systemui.statusbar.phone.panelstate.STATE_OPEN
import com.android.systemui.statusbar.phone.panelstate.STATE_OPENING
import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.android.systemui.statusbar.policy.HeadsUpManager
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -28,6 +29,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
@Mock private lateinit var scrimController: ScrimController
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock private lateinit var headsUpManager: HeadsUpManager
private val configurationController = FakeConfigurationController()
private lateinit var controller: ScrimShadeTransitionController
@@ -42,7 +44,8 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() {
dumpManager,
scrimController,
context.resources,
statusBarStateController)
statusBarStateController,
headsUpManager)
controller.onPanelStateChanged(STATE_OPENING)
}