Merge "Add overscroll effect to top of split shade" into tm-qpr-dev
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 5db95d7..ca1e397 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -146,7 +146,8 @@
private static final int DELAY_BEFORE_SHADE_CLOSE = 200;
private boolean mShadeNeedsToClose = false;
- private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
+ @VisibleForTesting
+ static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
private static final float RUBBER_BAND_FACTOR_ON_PANEL_EXPAND = 0.21f;
/**
@@ -1326,8 +1327,11 @@
* @param listenerNeedsAnimation does the listener need to animate?
*/
private void updateStackPosition(boolean listenerNeedsAnimation) {
+ float topOverscrollAmount = mShouldUseSplitNotificationShade
+ ? getCurrentOverScrollAmount(true /* top */) : 0f;
final float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition
+ mAmbientState.getOverExpansion()
+ + topOverscrollAmount
- getCurrentOverScrollAmount(false /* top */);
float fraction = mAmbientState.getExpansionFraction();
// If we are on quick settings, we need to quickly hide it to show the bouncer to avoid an
@@ -2613,8 +2617,10 @@
float bottomAmount = getCurrentOverScrollAmount(false);
if (velocityY < 0 && topAmount > 0) {
setOwnScrollY(mOwnScrollY - (int) topAmount);
- mDontReportNextOverScroll = true;
- setOverScrollAmount(0, true, false);
+ if (!mShouldUseSplitNotificationShade) {
+ mDontReportNextOverScroll = true;
+ setOverScrollAmount(0, true, false);
+ }
mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */)
* mOverflingDistance + topAmount;
} else if (velocityY > 0 && bottomAmount > 0) {
@@ -2648,6 +2654,7 @@
float topOverScroll = getCurrentOverScrollAmount(true);
return mScrolledToTopOnFirstDown
&& !mExpandedInThisMotion
+ && !mShouldUseSplitNotificationShade
&& (initialVelocity > mMinimumVelocity
|| (topOverScroll > mMinTopOverScrollToEscape && initialVelocity > 0));
}
@@ -2713,7 +2720,7 @@
return RUBBER_BAND_FACTOR_AFTER_EXPAND;
} else if (mIsExpansionChanging || mPanelTracking) {
return RUBBER_BAND_FACTOR_ON_PANEL_EXPAND;
- } else if (mScrolledToTopOnFirstDown) {
+ } else if (mScrolledToTopOnFirstDown && !mShouldUseSplitNotificationShade) {
return 1.0f;
}
return RUBBER_BAND_FACTOR_NORMAL;
@@ -5705,7 +5712,8 @@
}
}
- private void updateSplitNotificationShade() {
+ @VisibleForTesting
+ void updateSplitNotificationShade() {
boolean split = LargeScreenUtils.shouldUseSplitNotificationShade(getResources());
if (split != mShouldUseSplitNotificationShade) {
mShouldUseSplitNotificationShade = split;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 07ea630..7622549 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -20,6 +20,7 @@
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.RUBBER_BAND_FACTOR_NORMAL;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -47,6 +48,7 @@
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.testing.TestableResources;
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
@@ -99,6 +101,7 @@
private NotificationStackScrollLayout mStackScroller; // Normally test this
private NotificationStackScrollLayout mStackScrollerInternal; // See explanation below
private AmbientState mAmbientState;
+ private TestableResources mTestableResources;
@Rule public MockitoRule mockito = MockitoJUnit.rule();
@Mock private CentralSurfaces mCentralSurfaces;
@@ -123,6 +126,7 @@
@UiThreadTest
public void setUp() throws Exception {
allowTestableLooperAsMainThread();
+ mTestableResources = mContext.getOrCreateTestableResources();
// Interact with real instance of AmbientState.
mAmbientState = spy(new AmbientState(
@@ -394,7 +398,7 @@
@Test
@UiThreadTest
public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() {
- mContext.getOrCreateTestableResources()
+ mTestableResources
.addOverride(R.bool.config_use_split_notification_shade, /* value= */ true);
final int[] expectedStackHeight = {0};
@@ -405,12 +409,12 @@
.isEqualTo(expectedStackHeight[0]);
});
- mContext.getOrCreateTestableResources()
+ mTestableResources
.addOverride(R.bool.config_use_split_notification_shade, /* value= */ false);
expectedStackHeight[0] = 0;
mStackScroller.setExpandedHeight(100f);
- mContext.getOrCreateTestableResources()
+ mTestableResources
.addOverride(R.bool.config_use_split_notification_shade, /* value= */ true);
expectedStackHeight[0] = 100;
mStackScroller.setExpandedHeight(100f);
@@ -781,6 +785,39 @@
assertEquals(mAmbientState.getScrollY(), 0);
}
+ @Test
+ public void testSplitShade_hasTopOverscroll() {
+ mTestableResources
+ .addOverride(R.bool.config_use_split_notification_shade, /* value= */ true);
+ mStackScroller.updateSplitNotificationShade();
+ mAmbientState.setExpansionFraction(1f);
+
+ int topOverscrollPixels = 100;
+ mStackScroller.setOverScrolledPixels(topOverscrollPixels, true, false);
+
+ float expectedTopOverscrollAmount = topOverscrollPixels * RUBBER_BAND_FACTOR_NORMAL;
+ assertEquals(expectedTopOverscrollAmount, mStackScroller.getCurrentOverScrollAmount(true));
+ assertEquals(expectedTopOverscrollAmount, mAmbientState.getStackY());
+ }
+
+ @Test
+ public void testNormalShade_hasNoTopOverscroll() {
+ mTestableResources
+ .addOverride(R.bool.config_use_split_notification_shade, /* value= */ false);
+ mStackScroller.updateSplitNotificationShade();
+ mAmbientState.setExpansionFraction(1f);
+
+ int topOverscrollPixels = 100;
+ mStackScroller.setOverScrolledPixels(topOverscrollPixels, true, false);
+
+ float expectedTopOverscrollAmount = topOverscrollPixels * RUBBER_BAND_FACTOR_NORMAL;
+ assertEquals(expectedTopOverscrollAmount, mStackScroller.getCurrentOverScrollAmount(true));
+ // When not in split shade mode, then the overscroll effect is handled in
+ // NotificationPanelViewController and not in NotificationStackScrollLayout. Therefore
+ // mAmbientState must have stackY set to 0
+ assertEquals(0f, mAmbientState.getStackY());
+ }
+
private void setBarStateForTest(int state) {
// Can't inject this through the listener or we end up on the actual implementation
// rather than the mock because the spy just coppied the anonymous inner /shruggie.