Merge "Fix "No Notification" text not gradually showing on LockScreen" into tm-qpr-dev am: 0162aec6c8

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

Change-Id: Ic4df6c6b4ba0e40c656250527a3b9af0f639b99b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Marcello Galhardo
2022-08-30 20:27:23 +00:00
committed by Automerger Merge Worker
9 changed files with 252 additions and 65 deletions

View File

@@ -24,6 +24,8 @@ import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView; import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState; import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
@@ -73,6 +75,7 @@ public class EmptyShadeView extends StackScrollerDecorView {
} }
@Override @Override
@NonNull
public ExpandableViewState createExpandableViewState() { public ExpandableViewState createExpandableViewState() {
return new EmptyShadeViewState(); return new EmptyShadeViewState();
} }

View File

@@ -29,6 +29,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator; import android.view.animation.PathInterpolator;
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils; import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R; import com.android.systemui.R;
@@ -153,6 +155,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
} }
@Override @Override
@NonNull
public ExpandableViewState createExpandableViewState() { public ExpandableViewState createExpandableViewState() {
return new ShelfState(); return new ShelfState();
} }

View File

@@ -25,8 +25,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener; import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
@@ -68,6 +66,9 @@ import android.widget.Chronometer;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -3247,6 +3248,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
} }
@Override @Override
@NonNull
public ExpandableViewState createExpandableViewState() { public ExpandableViewState createExpandableViewState() {
return new NotificationViewState(); return new NotificationViewState();
} }

View File

@@ -29,6 +29,7 @@ import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.systemui.Dumpable; import com.android.systemui.Dumpable;
@@ -66,7 +67,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
protected float mContentTransformationAmount; protected float mContentTransformationAmount;
protected boolean mIsLastChild; protected boolean mIsLastChild;
protected int mContentShift; protected int mContentShift;
private final ExpandableViewState mViewState; @NonNull private final ExpandableViewState mViewState;
private float mContentTranslation; private float mContentTranslation;
protected boolean mLastInSection; protected boolean mLastInSection;
protected boolean mFirstInSection; protected boolean mFirstInSection;
@@ -610,6 +611,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
public void setActualHeightAnimating(boolean animating) {} public void setActualHeightAnimating(boolean animating) {}
@NonNull
protected ExpandableViewState createExpandableViewState() { protected ExpandableViewState createExpandableViewState() {
return new ExpandableViewState(); return new ExpandableViewState();
} }
@@ -642,7 +644,12 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
return mViewState; return mViewState;
} }
@Nullable public ExpandableViewState getViewState() { /**
* Get the {@link ExpandableViewState} associated with the view.
*
* @return the ExpandableView's view state.
*/
@NonNull public ExpandableViewState getViewState() {
return mViewState; return mViewState;
} }

View File

@@ -23,6 +23,8 @@ import android.util.AttributeSet;
import android.util.IndentingPrintWriter; import android.util.IndentingPrintWriter;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState; import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.ViewState; import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -142,6 +144,7 @@ public class FooterView extends StackScrollerDecorView {
} }
@Override @Override
@NonNull
public ExpandableViewState createExpandableViewState() { public ExpandableViewState createExpandableViewState() {
return new FooterViewState(); return new FooterViewState();
} }

View File

@@ -4460,8 +4460,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
} }
private void updateVisibility() { private void updateVisibility() {
boolean shouldShow = !mAmbientState.isFullyHidden() || !onKeyguard(); mController.updateVisibility(!mAmbientState.isFullyHidden() || !onKeyguard());
setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
} }
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -4526,17 +4525,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
} }
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
void updateEmptyShadeView(boolean visible, boolean notifVisibleInShade) { void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled); mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
int oldTextRes = mEmptyShadeView.getTextResource(); int oldTextRes = mEmptyShadeView.getTextResource();
int newTextRes = notifVisibleInShade int newTextRes = areNotificationsHiddenInShade
? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text; ? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
if (oldTextRes != newTextRes) { if (oldTextRes != newTextRes) {
mEmptyShadeView.setText(newTextRes); mEmptyShadeView.setText(newTextRes);
} }
} }
public boolean isEmptyShadeViewVisible() {
return mEmptyShadeView.isVisible();
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) { public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) {
if (mFooterView == null) { if (mFooterView == null) {

View File

@@ -177,7 +177,6 @@ public class NotificationStackScrollLayoutController {
private NotificationStackScrollLayout mView; private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss; private boolean mFadeNotificationsOnDismiss;
private NotificationSwipeHelper mSwipeHelper; private NotificationSwipeHelper mSwipeHelper;
private boolean mShowEmptyShadeView;
@Nullable private Boolean mHistoryEnabled; @Nullable private Boolean mHistoryEnabled;
private int mBarState; private int mBarState;
private HeadsUpAppearanceController mHeadsUpAppearanceController; private HeadsUpAppearanceController mHeadsUpAppearanceController;
@@ -1173,8 +1172,21 @@ public class NotificationStackScrollLayoutController {
} }
/** /**
* Update whether we should show the empty shade view (no notifications in the shade). * Set the visibility of the view, and propagate it to specific children.
* If so, send the update to our view. *
* @param visible either the view is visible or not.
*/
public void updateVisibility(boolean visible) {
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
if (mView.getVisibility() == View.VISIBLE) {
// Synchronize EmptyShadeView visibility with the parent container.
updateShowEmptyShadeView();
}
}
/**
* Update whether we should show the empty shade view ("no notifications" in the shade).
* *
* When in split mode, notifications are always visible regardless of the state of the * When in split mode, notifications are always visible regardless of the state of the
* QuickSettings panel. That being the case, empty view is always shown if the other conditions * QuickSettings panel. That being the case, empty view is always shown if the other conditions
@@ -1182,18 +1194,31 @@ public class NotificationStackScrollLayoutController {
*/ */
public void updateShowEmptyShadeView() { public void updateShowEmptyShadeView() {
Trace.beginSection("NSSLC.updateShowEmptyShadeView"); Trace.beginSection("NSSLC.updateShowEmptyShadeView");
mShowEmptyShadeView = mStatusBarStateController.getCurrentOrUpcomingState() != KEYGUARD
&& !mView.isQsFullScreen()
&& getVisibleNotificationCount() == 0;
mView.updateEmptyShadeView( final boolean shouldShow = getVisibleNotificationCount() == 0
mShowEmptyShadeView, && !mView.isQsFullScreen()
mZenModeController.areNotificationsHiddenInShade()); // Hide empty shade view when in transition to Keyguard.
// That avoids "No Notifications" to blink when transitioning to AOD.
// For more details, see: b/228790482
&& !isInTransitionToKeyguard();
mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
Trace.endSection(); Trace.endSection();
} }
/**
* @return true if {@link StatusBarStateController} is in transition to the KEYGUARD
* and false otherwise.
*/
private boolean isInTransitionToKeyguard() {
final int currentState = mStatusBarStateController.getState();
final int upcomingState = mStatusBarStateController.getCurrentOrUpcomingState();
return (currentState != upcomingState && upcomingState == KEYGUARD);
}
public boolean isShowingEmptyShadeView() { public boolean isShowingEmptyShadeView() {
return mShowEmptyShadeView; return mView.isEmptyShadeViewVisible();
} }
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) { public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {

View File

@@ -120,11 +120,64 @@ public class StackScrollAlgorithm {
updateClipping(algorithmState, ambientState); updateClipping(algorithmState, ambientState);
updateSpeedBumpState(algorithmState, speedBumpIndex); updateSpeedBumpState(algorithmState, speedBumpIndex);
updateShelfState(algorithmState, ambientState); updateShelfState(algorithmState, ambientState);
updateAlphaState(algorithmState, ambientState);
getNotificationChildrenStates(algorithmState, ambientState); getNotificationChildrenStates(algorithmState, ambientState);
} }
private void updateAlphaState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
for (ExpandableView view : algorithmState.visibleChildren) {
final ViewState viewState = view.getViewState();
final boolean isHunGoingToShade = ambientState.isShadeExpanded()
&& view == ambientState.getTrackedHeadsUpRow();
if (isHunGoingToShade) {
// Keep 100% opacity for heads up notification going to shade.
viewState.alpha = 1f;
} else if (ambientState.isOnKeyguard()) {
// Adjust alpha for wakeup to lockscreen.
viewState.alpha = 1f - ambientState.getHideAmount();
} else if (ambientState.isExpansionChanging()) {
// Adjust alpha for shade open & close.
float expansion = ambientState.getExpansionFraction();
viewState.alpha = ambientState.isBouncerInTransit()
? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
: ShadeInterpolation.getContentAlpha(expansion);
}
// For EmptyShadeView if on keyguard, we need to control the alpha to create
// a nice transition when the user is dragging down the notification panel.
if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
final float fractionToShade = ambientState.getFractionToShade();
viewState.alpha = ShadeInterpolation.getContentAlpha(fractionToShade);
}
NotificationShelf shelf = ambientState.getShelf();
if (shelf != null) {
final ViewState shelfState = shelf.getViewState();
// After the shelf has updated its yTranslation, explicitly set alpha=0 for view
// below shelf to skip rendering them in the hardware layer. We do not set them
// invisible because that runs invalidate & onDraw when these views return onscreen,
// which is more expensive.
if (shelfState.hidden) {
// When the shelf is hidden, it won't clip views, so we don't hide rows
return;
}
final float shelfTop = shelfState.yTranslation;
final float viewTop = viewState.yTranslation;
if (viewTop >= shelfTop) {
viewState.alpha = 0;
}
}
}
}
/** /**
* How expanded or collapsed notifications are when pulling down the shade. * How expanded or collapsed notifications are when pulling down the shade.
*
* @param ambientState Current ambient state. * @param ambientState Current ambient state.
* @return 0 when fully collapsed, 1 when expanded. * @return 0 when fully collapsed, 1 when expanded.
*/ */
@@ -208,22 +261,6 @@ public class StackScrollAlgorithm {
} }
shelf.updateState(algorithmState, ambientState); shelf.updateState(algorithmState, ambientState);
// After the shelf has updated its yTranslation, explicitly set alpha=0 for view below shelf
// to skip rendering them in the hardware layer. We do not set them invisible because that
// runs invalidate & onDraw when these views return onscreen, which is more expensive.
if (shelf.getViewState().hidden) {
// When the shelf is hidden, it won't clip views, so we don't hide rows
return;
}
final float shelfTop = shelf.getViewState().yTranslation;
for (ExpandableView view : algorithmState.visibleChildren) {
final float viewTop = view.getViewState().yTranslation;
if (viewTop >= shelfTop) {
view.getViewState().alpha = 0;
}
}
} }
private void updateClipping(StackScrollAlgorithmState algorithmState, private void updateClipping(StackScrollAlgorithmState algorithmState,
@@ -473,21 +510,6 @@ public class StackScrollAlgorithm {
ExpandableViewState viewState = view.getViewState(); ExpandableViewState viewState = view.getViewState();
viewState.location = ExpandableViewState.LOCATION_UNKNOWN; viewState.location = ExpandableViewState.LOCATION_UNKNOWN;
final boolean isHunGoingToShade = ambientState.isShadeExpanded()
&& view == ambientState.getTrackedHeadsUpRow();
if (isHunGoingToShade) {
// Keep 100% opacity for heads up notification going to shade.
} else if (ambientState.isOnKeyguard()) {
// Adjust alpha for wakeup to lockscreen.
viewState.alpha = 1f - ambientState.getHideAmount();
} else if (ambientState.isExpansionChanging()) {
// Adjust alpha for shade open & close.
float expansion = ambientState.getExpansionFraction();
viewState.alpha = ambientState.isBouncerInTransit()
? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
: ShadeInterpolation.getContentAlpha(expansion);
}
final float expansionFraction = getExpansionFractionWithoutShelf( final float expansionFraction = getExpansionFractionWithoutShelf(
algorithmState, ambientState); algorithmState, ambientState);

View File

@@ -3,19 +3,21 @@ package com.android.systemui.statusbar.notification.stack
import android.annotation.DimenRes import android.annotation.DimenRes
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
import com.android.systemui.dump.DumpManager import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.EmptyShadeView import com.android.systemui.statusbar.EmptyShadeView
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue import junit.framework.Assert.assertTrue
import junit.framework.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
@@ -26,17 +28,20 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
private val hostView = FrameLayout(context) private val hostView = FrameLayout(context)
private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView) private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
private val expandableViewState = ExpandableViewState()
private val notificationRow = mock(ExpandableNotificationRow::class.java) private val notificationRow = mock(ExpandableNotificationRow::class.java)
private val dumpManager = mock(DumpManager::class.java) private val dumpManager = mock(DumpManager::class.java)
private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java) private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java)
private val notificationShelf = mock(NotificationShelf::class.java)
private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
}
private val ambientState = AmbientState( private val ambientState = AmbientState(
context, context,
dumpManager, dumpManager,
SectionProvider { _, _ -> false }, /* sectionProvider */ { _, _ -> false },
BypassController { false }, /* bypassController */ { false },
mStatusBarKeyguardViewManager mStatusBarKeyguardViewManager
) )
private val testableResources = mContext.orCreateTestableResources private val testableResources = mContext.orCreateTestableResources
@@ -49,7 +54,9 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
@Before @Before
fun setUp() { fun setUp() {
whenever(notificationRow.viewState).thenReturn(expandableViewState) whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
hostView.addView(notificationRow) hostView.addView(notificationRow)
} }
@@ -60,7 +67,8 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
stackScrollAlgorithm.resetViewStates(ambientState, 0) stackScrollAlgorithm.resetViewStates(ambientState, 0)
assertThat(expandableViewState.yTranslation).isEqualTo(stackScrollAlgorithm.mHeadsUpInset) assertThat(notificationRow.viewState.yTranslation)
.isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
} }
@Test @Test
@@ -75,15 +83,12 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
stackScrollAlgorithm.resetViewStates(ambientState, 0) stackScrollAlgorithm.resetViewStates(ambientState, 0)
// top margin presence should decrease heads up translation up to minHeadsUpTranslation // top margin presence should decrease heads up translation up to minHeadsUpTranslation
assertThat(expandableViewState.yTranslation).isEqualTo(minHeadsUpTranslation) assertThat(notificationRow.viewState.yTranslation).isEqualTo(minHeadsUpTranslation)
} }
@Test @Test
fun resetViewStates_emptyShadeView_isCenteredVertically() { fun resetViewStates_emptyShadeView_isCenteredVertically() {
stackScrollAlgorithm.initView(context) stackScrollAlgorithm.initView(context)
val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
}
hostView.removeAllViews() hostView.removeAllViews()
hostView.addView(emptyShadeView) hostView.addView(emptyShadeView)
ambientState.layoutMaxHeight = 1280 ambientState.layoutMaxHeight = 1280
@@ -97,6 +102,121 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
assertThat(emptyShadeView.viewState?.yTranslation).isEqualTo(centeredY) assertThat(emptyShadeView.viewState?.yTranslation).isEqualTo(centeredY)
} }
@Test
fun resetViewStates_hunGoingToShade_viewBecomesOpaque() {
whenever(notificationRow.isAboveShelf).thenReturn(true)
ambientState.isShadeExpanded = true
ambientState.trackedHeadsUpRow = notificationRow
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
assertThat(notificationRow.viewState.alpha).isEqualTo(1f)
}
@Test
fun resetViewStates_isExpansionChanging_viewBecomesTransparent() {
whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(false)
ambientState.isExpansionChanging = true
ambientState.expansionFraction = 0.25f
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
val expected = getContentAlpha(0.25f)
assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
}
@Test
fun resetViewStates_isExpansionChangingWhileBouncerInTransit_viewBecomesTransparent() {
whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(true)
ambientState.isExpansionChanging = true
ambientState.expansionFraction = 0.25f
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
val expected = aboutToShowBouncerProgress(0.25f)
assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
}
@Test
fun resetViewStates_isOnKeyguard_viewBecomesTransparent() {
ambientState.setStatusBarState(StatusBarState.KEYGUARD)
ambientState.hideAmount = 0.25f
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
assertThat(notificationRow.viewState.alpha).isEqualTo(1f - ambientState.hideAmount)
}
@Test
fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesTransparent() {
ambientState.setStatusBarState(StatusBarState.KEYGUARD)
ambientState.fractionToShade = 0.25f
stackScrollAlgorithm.initView(context)
hostView.removeAllViews()
hostView.addView(emptyShadeView)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
val expected = getContentAlpha(ambientState.fractionToShade)
assertThat(emptyShadeView.viewState.alpha).isEqualTo(expected)
}
@Test
fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesOpaque() {
ambientState.setStatusBarState(StatusBarState.SHADE)
ambientState.fractionToShade = 0.25f
stackScrollAlgorithm.initView(context)
hostView.removeAllViews()
hostView.addView(emptyShadeView)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
assertThat(emptyShadeView.viewState.alpha).isEqualTo(1f)
}
@Test
fun resetViewStates_hiddenShelf_viewAlphaDoesNotChange() {
val expected = notificationShelf.viewState.alpha
notificationShelf.viewState.hidden = true
ambientState.shelf = notificationShelf
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
assertThat(notificationShelf.viewState.alpha).isEqualTo(expected)
}
@Test
fun resetViewStates_shelfTopLessThanViewTop_hidesView() {
notificationRow.viewState.yTranslation = 10f
notificationShelf.viewState.yTranslation = 0.9f
notificationShelf.viewState.hidden = false
ambientState.shelf = notificationShelf
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
assertThat(notificationRow.viewState.alpha).isEqualTo(0f)
}
@Test
fun resetViewStates_shelfTopGreaterOrEqualThanViewTop_viewAlphaDoesNotChange() {
val expected = notificationRow.viewState.alpha
notificationRow.viewState.yTranslation = 10f
notificationShelf.viewState.yTranslation = 10f
notificationShelf.viewState.hidden = false
ambientState.shelf = notificationShelf
stackScrollAlgorithm.initView(context)
stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
}
@Test @Test
fun getGapForLocation_onLockscreen_returnsSmallGap() { fun getGapForLocation_onLockscreen_returnsSmallGap() {
val gap = stackScrollAlgorithm.getGapForLocation( val gap = stackScrollAlgorithm.getGapForLocation(
@@ -267,7 +387,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
assertEquals(10f, expandableViewState.yTranslation) assertEquals(10f, expandableViewState.yTranslation)
} }
@Test @Test
fun clampHunToTop_viewYFarAboveVisibleStack_heightCollapsed() { fun clampHunToTop_viewYFarAboveVisibleStack_heightCollapsed() {
val expandableViewState = ExpandableViewState() val expandableViewState = ExpandableViewState()