summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lyn Han <lynhan@google.com> 2022-01-28 22:01:40 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-28 22:01:40 +0000
commit63075cc39a35fa86f23c15c3f616e2daac81a625 (patch)
tree0e68431f2131daaaec62d6fede2d3a1ef603a54c
parentcb6178a280d7c35dd4671616923b46743e558a51 (diff)
parent9a52b474d67c76c4d1c1bf59dd4e62b4cd2a3b3c (diff)
Merge "Short shelf on lockscreen that animates width with transition to shade"
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt153
9 files changed, 358 insertions, 33 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index c136d9cc7272..b312ce20b313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -337,11 +337,11 @@ class LockscreenShadeTransitionController @Inject constructor(
if (field != value || forceApplyAmount) {
field = value
if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
- nsslController.setTransitionToFullShadeAmount(field)
- notificationPanelController.setTransitionToFullShadeAmount(field,
- false /* animate */, 0 /* delay */)
qSDragProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
+ nsslController.setTransitionToFullShadeAmount(field, qSDragProgress)
qS.setTransitionToFullShadeAmount(field, qSDragProgress)
+ notificationPanelController.setTransitionToFullShadeAmount(field,
+ false /* animate */, 0 /* delay */)
// TODO: appear media also in split shade
val mediaAmount = if (useSplitShade) 0f else field
mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 51a66aad39fb..3411eab23d63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.statusbar.phone.NotificationIconContainer.MAX_ICONS_ON_LOCKSCREEN;
+
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -32,6 +34,7 @@ import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -45,6 +48,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import com.android.systemui.util.Utils;
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
@@ -81,6 +85,11 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mIndexOfFirstViewInShelf = -1;
private float mCornerAnimationDistance;
private NotificationShelfController mController;
+ private int mActualWidth = -1;
+ private boolean mUseSplitShade;
+
+ /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */
+ private float mFractionToShade;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -122,13 +131,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
setLayoutParams(layoutParams);
- int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
+ final int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
mShelfIcons.setPadding(padding, 0, padding, 0);
mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
mCornerAnimationDistance = res.getDimensionPixelSize(
R.dimen.notification_corner_animation_distance);
+ // TODO(b/213480466) enable short shelf on split shade
+ mUseSplitShade = Utils.shouldUseSplitNotificationShade(mContext.getResources());
+
mShelfIcons.setInNotificationIconShelf(true);
if (!mShowNotificationShelf) {
setVisibility(GONE);
@@ -203,6 +215,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
final float stackEnd = ambientState.getStackY() + ambientState.getStackHeight();
viewState.yTranslation = stackEnd - viewState.height;
+
+ final int shortestWidth = mShelfIcons.calculateWidthFor(MAX_ICONS_ON_LOCKSCREEN);
+ final float fraction = Interpolators.STANDARD.getInterpolation(mFractionToShade);
+ updateStateWidth(viewState, fraction, shortestWidth);
} else {
viewState.hidden = true;
viewState.location = ExpandableViewState.LOCATION_GONE;
@@ -211,6 +227,77 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
/**
+ * @param shelfState View state for NotificationShelf
+ * @param fraction Fraction of lockscreen to shade transition
+ * @param shortestWidth Shortest width to use for lockscreen shelf
+ */
+ @VisibleForTesting
+ public void updateStateWidth(ShelfState shelfState, float fraction, int shortestWidth) {
+ shelfState.actualWidth = !mUseSplitShade && mAmbientState.isOnKeyguard()
+ ? (int) MathUtils.lerp(shortestWidth, getWidth(), fraction)
+ : getWidth();
+ }
+
+ /**
+ * @param fractionToShade Fraction of lockscreen to shade transition
+ */
+ public void setFractionToShade(float fractionToShade) {
+ mFractionToShade = fractionToShade;
+ }
+
+ /**
+ * @return Actual width of shelf, accounting for possible ongoing width animation
+ */
+ public int getActualWidth() {
+ return mActualWidth > -1 ? mActualWidth : getWidth();
+ }
+
+ /**
+ * @param localX Click x from left of screen
+ * @param slop Margin of error within which we count x for valid click
+ * @param left Left of shelf, from left of screen
+ * @param right Right of shelf, from left of screen
+ * @return Whether click x was in view
+ */
+ @VisibleForTesting
+ public boolean isXInView(float localX, float slop, float left, float right) {
+ return (left - slop) <= localX && localX < (right + slop);
+ }
+
+ /**
+ * @param localY Click y from top of shelf
+ * @param slop Margin of error within which we count y for valid click
+ * @param top Top of shelf
+ * @param bottom Height of shelf
+ * @return Whether click y was in view
+ */
+ @VisibleForTesting
+ public boolean isYInView(float localY, float slop, float top, float bottom) {
+ return (top - slop) <= localY && localY < (bottom + slop);
+ }
+
+ /**
+ * @param localX Click x
+ * @param localY Click y
+ * @param slop Margin of error for valid click
+ * @return Whether this click was on the visible (non-clipped) part of the shelf
+ */
+ @Override
+ public boolean pointInView(float localX, float localY, float slop) {
+ final float containerWidth = getWidth();
+ final float shelfWidth = getActualWidth();
+
+ final float left = isLayoutRtl() ? containerWidth - shelfWidth : 0;
+ final float right = isLayoutRtl() ? containerWidth : shelfWidth;
+
+ final float top = mClipTopAmount;
+ final float bottom = getActualHeight();
+
+ return isXInView(localX, slop, left, right)
+ && isYInView(localY, slop, top, bottom);
+ }
+
+ /**
* Update the shelf appearance based on the other notifications around it. This transforms
* the icons from the notification area into the shelf.
*/
@@ -732,11 +819,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
// we always want to clip to our sides, such that nothing can draw outside of these bounds
int height = getResources().getDisplayMetrics().heightPixels;
mClipRect.set(0, -height, getWidth(), height);
- mShelfIcons.setClipBounds(mClipRect);
+ if (mShelfIcons != null) {
+ mShelfIcons.setClipBounds(mClipRect);
+ }
}
private void updateRelativeOffset() {
- mCollapsedIcons.getLocationOnScreen(mTmp);
+ if (mCollapsedIcons != null) {
+ mCollapsedIcons.getLocationOnScreen(mTmp);
+ }
getLocationOnScreen(mTmp);
}
@@ -831,9 +922,20 @@ public class NotificationShelf extends ActivatableNotificationView implements
mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf);
}
- private class ShelfState extends ExpandableViewState {
+ public class ShelfState extends ExpandableViewState {
private boolean hasItemsInStableShelf;
private ExpandableView firstViewInShelf;
+ public int actualWidth = -1;
+
+ private void updateShelfWidth(View view) {
+ if (actualWidth < 0) {
+ return;
+ }
+ mActualWidth = actualWidth;
+ ActivatableNotificationView anv = (ActivatableNotificationView) view;
+ anv.getBackgroundNormal().setActualWidth(actualWidth);
+ mShelfIcons.setActualLayoutWidth(actualWidth);
+ }
@Override
public void applyToView(View view) {
@@ -846,19 +948,21 @@ public class NotificationShelf extends ActivatableNotificationView implements
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
+ updateShelfWidth(view);
}
@Override
- public void animateTo(View child, AnimationProperties properties) {
+ public void animateTo(View view, AnimationProperties properties) {
if (!mShowNotificationShelf) {
return;
}
- super.animateTo(child, properties);
+ super.animateTo(view, properties);
setIndexOfFirstViewInShelf(firstViewInShelf);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
+ updateShelfWidth(view);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 5d6d0f701f12..fca2aa167e37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -162,6 +162,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
updateBackgroundTint();
}
+ /**
+ * @return The background of this view.
+ */
+ public NotificationBackgroundView getBackgroundNormal() {
+ return mBackgroundNormal;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 0f615aa9356f..c640ab6c3a90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -29,6 +29,7 @@ import android.view.View;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.R;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
/**
@@ -39,15 +40,17 @@ public class NotificationBackgroundView extends View {
private final boolean mDontModifyCorners;
private Drawable mBackground;
private int mClipTopAmount;
- private int mActualHeight;
private int mClipBottomAmount;
private int mTintColor;
private final float[] mCornerRadii = new float[8];
private boolean mBottomIsRounded;
private int mBackgroundTop;
private boolean mBottomAmountClips = true;
+ private int mActualHeight = -1;
+ private int mActualWidth = -1;
private boolean mExpandAnimationRunning;
- private float mActualWidth;
+ private int mExpandAnimationWidth = -1;
+ private int mExpandAnimationHeight = -1;
private int mDrawableAlpha = 255;
private boolean mIsPressedAllowed;
@@ -59,11 +62,12 @@ public class NotificationBackgroundView extends View {
@Override
protected void onDraw(Canvas canvas) {
- if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop
+ if (mClipTopAmount + mClipBottomAmount < getActualHeight() - mBackgroundTop
|| mExpandAnimationRunning) {
canvas.save();
if (!mExpandAnimationRunning) {
- canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
+ canvas.clipRect(0, mClipTopAmount, getWidth(),
+ getActualHeight() - mClipBottomAmount);
}
draw(canvas, mBackground);
canvas.restore();
@@ -73,17 +77,23 @@ public class NotificationBackgroundView extends View {
private void draw(Canvas canvas, Drawable drawable) {
if (drawable != null) {
int top = mBackgroundTop;
- int bottom = mActualHeight;
+ int bottom = getActualHeight();
if (mBottomIsRounded
&& mBottomAmountClips
&& !mExpandAnimationRunning) {
bottom -= mClipBottomAmount;
}
- int left = 0;
- int right = getWidth();
+ final boolean isRtl = isLayoutRtl();
+ final int width = getWidth();
+ final int actualWidth = getActualWidth();
+
+ int left = isRtl ? width - actualWidth : 0;
+ int right = isRtl ? width : actualWidth;
+
if (mExpandAnimationRunning) {
- left = (int) ((getWidth() - mActualWidth) / 2.0f);
- right = (int) (left + mActualWidth);
+ // Horizontally center this background view inside of the container
+ left = (int) ((width - actualWidth) / 2.0f);
+ right = (int) (left + actualWidth);
}
drawable.setBounds(left, top, right, bottom);
drawable.draw(canvas);
@@ -152,8 +162,26 @@ public class NotificationBackgroundView extends View {
invalidate();
}
- public int getActualHeight() {
- return mActualHeight;
+ private int getActualHeight() {
+ if (mExpandAnimationRunning && mExpandAnimationHeight > -1) {
+ return mExpandAnimationHeight;
+ } else if (mActualHeight > -1) {
+ return mActualHeight;
+ }
+ return getHeight();
+ }
+
+ public void setActualWidth(int actualWidth) {
+ mActualWidth = actualWidth;
+ }
+
+ private int getActualWidth() {
+ if (mExpandAnimationRunning && mExpandAnimationWidth > -1) {
+ return mExpandAnimationWidth;
+ } else if (mActualWidth > -1) {
+ return mActualWidth;
+ }
+ return getWidth();
}
public void setClipTopAmount(int clipTopAmount) {
@@ -241,9 +269,9 @@ public class NotificationBackgroundView extends View {
}
/** Set the current expand animation size. */
- public void setExpandAnimationSize(int actualWidth, int actualHeight) {
- mActualHeight = actualHeight;
- mActualWidth = actualWidth;
+ public void setExpandAnimationSize(int width, int height) {
+ mExpandAnimationHeight = width;
+ mExpandAnimationWidth = height;
invalidate();
}
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 9655a9ce5e45..9f6a81d3a9ee 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
@@ -5497,6 +5497,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
/**
+ * @param fraction Fraction of the lockscreen to shade transition. 0f for all other states.
+ * Once the lockscreen to shade transition completes and the shade is 100% open
+ * LockscreenShadeTransitionController resets fraction to 0
+ * where it remains until the next lockscreen-to-shade transition.
+ */
+ public void setFractionToShade(float fraction) {
+ mShelf.setFractionToShade(fraction);
+ requestChildrenUpdate();
+ }
+
+ /**
* Set a listener to when scrolling changes.
*/
public void setOnScrollListener(Consumer<Integer> listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 0d0e5e850523..334128a2b4ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -1515,10 +1515,18 @@ public class NotificationStackScrollLayoutController {
}
/**
- * 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.
+ * @param amount The amount of pixels we have currently dragged down
+ * for the lockscreen to shade transition. 0f for all other states.
+ * @param fraction The fraction of lockscreen to shade transition.
+ * 0f for all other states.
+ *
+ * Once the lockscreen to shade transition completes and the shade is 100% open,
+ * LockscreenShadeTransitionController resets amount and fraction to 0, where they remain
+ * until the next lockscreen-to-shade transition.
*/
- public void setTransitionToFullShadeAmount(float amount) {
+ public void setTransitionToFullShadeAmount(float amount, float fraction) {
+ mView.setFractionToShade(fraction);
+
float extraTopInset = 0.0f;
if (mStatusBarStateController.getState() == KEYGUARD) {
float overallProgress = MathUtils.saturate(amount / mView.getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index c09c48540901..febf2b5b5f24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -135,7 +135,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
}.setDuration(CONTENT_FADE_DURATION);
- private static final int MAX_VISIBLE_ICONS_ON_LOCK = 5;
+ private static final int MAX_ICONS_ON_AOD = 5;
+ public static final int MAX_ICONS_ON_LOCKSCREEN = 3;
public static final int MAX_STATIC_ICONS = 4;
private static final int MAX_DOTS = 1;
@@ -386,6 +387,19 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
/**
+ * @return Width of shelf for the given number of icons and overflow dot
+ */
+ public int calculateWidthFor(int numMaxIcons) {
+ if (getChildCount() == 0) {
+ return 0;
+ }
+ return (int) (getActualPaddingStart()
+ + numMaxIcons * mIconSize
+ + mOverflowWidth
+ + getActualPaddingEnd());
+ }
+
+ /**
* Calculate the horizontal translations for each notification based on how much the icons
* are inserted into the notification container.
* If this is not a whole number, the fraction means by how much the icon is appearing.
@@ -394,7 +408,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
float translationX = getActualPaddingStart();
int firstOverflowIndex = -1;
int childCount = getChildCount();
- int maxVisibleIcons = mOnLockScreen ? MAX_VISIBLE_ICONS_ON_LOCK :
+ int maxVisibleIcons = mOnLockScreen ? MAX_ICONS_ON_AOD :
mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
float layoutEnd = getLayoutEnd();
float overflowStart = getMaxOverflowStart();
@@ -414,7 +428,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
boolean forceOverflow = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex
&& iconState.iconAppearAmount > 0.0f || i >= maxVisibleIcons;
- boolean noOverflowAfter = i == childCount - 1;
+ boolean isLastChild = i == childCount - 1;
float drawingScale = mOnLockScreen && view instanceof StatusBarIconView
? ((StatusBarIconView) view).getIconScaleIncreased()
: 1f;
@@ -423,10 +437,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
: StatusBarIconView.STATE_ICON;
boolean isOverflowing =
- (translationX > (noOverflowAfter ? layoutEnd - mIconSize
+ (translationX > (isLastChild ? layoutEnd - mIconSize
: overflowStart - mIconSize));
if (firstOverflowIndex == -1 && (forceOverflow || isOverflowing)) {
- firstOverflowIndex = noOverflowAfter && !forceOverflow ? i - 1 : i;
+ firstOverflowIndex = isLastChild && !forceOverflow ? i - 1 : i;
mVisualOverflowStart = layoutEnd - mOverflowWidth;
if (forceOverflow || mIsStaticLayout) {
mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 42647f7b026a..d51d370eecb9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -227,7 +227,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
fun testDragDownAmountDoesntCallOutInLockedDownShade() {
whenever(nsslController.isInLockedDownShade).thenReturn(true)
transitionController.dragDownAmount = 10f
- verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
+ verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat())
verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
@@ -238,7 +238,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Test
fun testDragDownAmountCallsOut() {
transitionController.dragDownAmount = 10f
- verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
+ verify(nsslController).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
verify(scrimController).setTransitionToFullShadeProgress(anyFloat())
verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
new file mode 100644
index 000000000000..d280f54e32f2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
@@ -0,0 +1,153 @@
+package com.android.systemui.statusbar.notification.stack
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.NotificationShelf
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.*
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Tests for {@link NotificationShelf}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotificationShelfTest : SysuiTestCase() {
+
+ private val shelf = NotificationShelf(context, /* attrs */ null)
+ private val shelfState = shelf.viewState as NotificationShelf.ShelfState
+ private val ambientState = mock(AmbientState::class.java)
+
+ @Before
+ fun setUp() {
+ shelf.bind(ambientState, /* hostLayoutController */ null)
+ shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5)
+ }
+
+ @Test
+ fun testShadeWidth_BasedOnFractionToShade() {
+ setFractionToShade(0f)
+ setOnLockscreen(true)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 0f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 10)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 0.5f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 20)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 1f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 30)
+ }
+
+ @Test
+ fun testShelfIsLong_WhenNotOnLockscreen() {
+ setFractionToShade(0f)
+ setOnLockscreen(false)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 0f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 30)
+ }
+
+ @Test
+ fun testX_inViewForClick() {
+ val isXInView = shelf.isXInView(
+ /* localX */ 5f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertTrue(isXInView)
+ }
+
+ @Test
+ fun testXSlop_inViewForClick() {
+ val isLeftXSlopInView = shelf.isXInView(
+ /* localX */ -3f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertTrue(isLeftXSlopInView)
+
+ val isRightXSlopInView = shelf.isXInView(
+ /* localX */ 13f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertTrue(isRightXSlopInView)
+ }
+
+ @Test
+ fun testX_notInViewForClick() {
+ val isXLeftOfShelfInView = shelf.isXInView(
+ /* localX */ -10f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertFalse(isXLeftOfShelfInView)
+
+ val isXRightOfShelfInView = shelf.isXInView(
+ /* localX */ 20f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertFalse(isXRightOfShelfInView)
+ }
+
+ @Test
+ fun testY_inViewForClick() {
+ val isYInView = shelf.isYInView(
+ /* localY */ 5f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 10f)
+ assertTrue(isYInView)
+ }
+
+ @Test
+ fun testYSlop_inViewForClick() {
+ val isTopYSlopInView = shelf.isYInView(
+ /* localY */ -3f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 10f)
+ assertTrue(isTopYSlopInView)
+
+ val isBottomYSlopInView = shelf.isYInView(
+ /* localY */ 13f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 10f)
+ assertTrue(isBottomYSlopInView)
+ }
+
+ @Test
+ fun testY_notInViewForClick() {
+ val isYAboveShelfInView = shelf.isYInView(
+ /* localY */ -10f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 5f)
+ assertFalse(isYAboveShelfInView)
+
+ val isYBelowShelfInView = shelf.isYInView(
+ /* localY */ 15f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 5f)
+ assertFalse(isYBelowShelfInView)
+ }
+
+ private fun setFractionToShade(fraction: Float) {
+ shelf.setFractionToShade(fraction)
+ }
+
+ private fun setOnLockscreen(isOnLockscreen: Boolean) {
+ whenever(ambientState.isOnKeyguard).thenReturn(isOnLockscreen)
+ }
+} \ No newline at end of file