OnScroll roundness type should be reset to 0f when the View is removed from the Shelf

The steps to reproduce the bug in my case are:

- Connect the device in debug mode to a computer.
- A Heads Up notification should compare with the text "USB debugging connected"
- That notification after a few seconds (less than 5s) becomes a normal notification
- By opening the notification shader you can see the "Android System" group
- Once the "Android System" group has been extended, the "USB debugging connected" notification has all rounded edges

Note: There should be a second notification in the group "Charging this device via USB"

Test: manual test, atest NotificationShelfTest, atest NotificationChildrenContainerTest
Bug: 255946140
Change-Id: I66f3d40422143ce90f57801a4dfe9334c7e26a97
This commit is contained in:
omarmt
2022-10-28 14:40:18 +00:00
parent 46ee767267
commit fbcddedc57
5 changed files with 125 additions and 10 deletions

View File

@@ -496,9 +496,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
return;
}
final float smallCornerRadius =
getResources().getDimension(R.dimen.notification_corner_radius_small)
/ getResources().getDimension(R.dimen.notification_corner_radius);
final float viewEnd = viewStart + anv.getActualHeight();
final float cornerAnimationDistance = mCornerAnimationDistance
* mAmbientState.getExpansionFraction();
@@ -509,7 +506,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
final float changeFraction = MathUtils.saturate(
(viewEnd - cornerAnimationTop) / cornerAnimationDistance);
anv.requestBottomRoundness(
anv.isLastInSection() ? 1f : changeFraction,
/* value = */ anv.isLastInSection() ? 1f : changeFraction,
/* animate = */ false,
SourceType.OnScroll);
@@ -517,7 +514,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
// Fast scroll skips frames and leaves corners with unfinished rounding.
// Reset top and bottom corners outside of animation bounds.
anv.requestBottomRoundness(
anv.isLastInSection() ? 1f : smallCornerRadius,
/* value = */ anv.isLastInSection() ? 1f : 0f,
/* animate = */ false,
SourceType.OnScroll);
}
@@ -527,16 +524,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
final float changeFraction = MathUtils.saturate(
(viewStart - cornerAnimationTop) / cornerAnimationDistance);
anv.requestTopRoundness(
anv.isFirstInSection() ? 1f : changeFraction,
false,
/* value = */ anv.isFirstInSection() ? 1f : changeFraction,
/* animate = */ false,
SourceType.OnScroll);
} else if (viewStart < cornerAnimationTop) {
// Fast scroll skips frames and leaves corners with unfinished rounding.
// Reset top and bottom corners outside of animation bounds.
anv.requestTopRoundness(
anv.isFirstInSection() ? 1f : smallCornerRadius,
false,
/* value = */ anv.isFirstInSection() ? 1f : 0f,
/* animate = */ false,
SourceType.OnScroll);
}
}
@@ -976,6 +973,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf);
}
/**
* This method resets the OnScroll roundness of a view to 0f
*
* Note: This should be the only class that handles roundness {@code SourceType.OnScroll}
*/
public static void resetOnScrollRoundness(ExpandableView expandableView) {
expandableView.requestTopRoundness(0f, false, SourceType.OnScroll);
expandableView.requestBottomRoundness(0f, false, SourceType.OnScroll);
}
public class ShelfState extends ExpandableViewState {
private boolean hasItemsInStableShelf;
private ExpandableView firstViewInShelf;

View File

@@ -44,6 +44,7 @@ import com.android.internal.widget.NotificationExpandButton;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.NotificationGroupingUtil;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -308,6 +309,11 @@ public class NotificationChildrenContainer extends ViewGroup
row.setContentTransformationAmount(0, false /* isLastChild */);
row.setNotificationFaded(mContainingNotificationIsFaded);
// This is a workaround, the NotificationShelf should be the owner of `OnScroll` roundness.
// Here we should reset the `OnScroll` roundness only on top-level rows.
NotificationShelf.resetOnScrollRoundness(row);
// It doesn't make sense to keep old animations around, lets cancel them!
ExpandableViewState viewState = row.getViewState();
if (viewState != null) {
@@ -1377,8 +1383,12 @@ public class NotificationChildrenContainer extends ViewGroup
if (child.getVisibility() == View.GONE) {
continue;
}
child.requestTopRoundness(
/* value = */ 0f,
/* animate = */ isShown(),
SourceType.DefaultValue);
child.requestBottomRoundness(
last ? getBottomRoundness() : 0f,
/* value = */ last ? getBottomRoundness() : 0f,
/* animate = */ isShown(),
SourceType.DefaultValue);
last = false;

View File

@@ -22,6 +22,7 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -60,6 +61,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -193,6 +195,25 @@ public class NotificationTestHelper {
mDefaultInflationFlags = defaultInflationFlags;
}
/**
* Creates a generic row with rounded border.
*
* @return a generic row with the set roundness.
* @throws Exception
*/
public ExpandableNotificationRow createRowWithRoundness(
float topRoundness,
float bottomRoundness,
SourceType sourceType
) throws Exception {
ExpandableNotificationRow row = createRow();
row.requestTopRoundness(topRoundness, false, sourceType);
row.requestBottomRoundness(bottomRoundness, /*animate = */ false, sourceType);
assertEquals(topRoundness, row.getTopRoundness(), /* delta = */ 0f);
assertEquals(bottomRoundness, row.getBottomRoundness(), /* delta = */ 0f);
return row;
}
/**
* Creates a generic row.
*

View File

@@ -25,6 +25,7 @@ import android.view.View;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -151,4 +152,37 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
Assert.assertNotNull("Children container must have a header after recreation",
mChildrenContainer.getCurrentHeaderView());
}
@Test
public void addNotification_shouldResetOnScrollRoundness() throws Exception {
ExpandableNotificationRow row = mNotificationTestHelper.createRowWithRoundness(
/* topRoundness = */ 1f,
/* bottomRoundness = */ 1f,
/* sourceType = */ SourceType.OnScroll);
mChildrenContainer.addNotification(row, 0);
Assert.assertEquals(0f, row.getTopRoundness(), /* delta = */ 0f);
Assert.assertEquals(0f, row.getBottomRoundness(), /* delta = */ 0f);
}
@Test
public void addNotification_shouldNotResetOtherRoundness() throws Exception {
ExpandableNotificationRow row1 = mNotificationTestHelper.createRowWithRoundness(
/* topRoundness = */ 1f,
/* bottomRoundness = */ 1f,
/* sourceType = */ SourceType.DefaultValue);
ExpandableNotificationRow row2 = mNotificationTestHelper.createRowWithRoundness(
/* topRoundness = */ 1f,
/* bottomRoundness = */ 1f,
/* sourceType = */ SourceType.OnDismissAnimation);
mChildrenContainer.addNotification(row1, 0);
mChildrenContainer.addNotification(row2, 0);
Assert.assertEquals(1f, row1.getTopRoundness(), /* delta = */ 0f);
Assert.assertEquals(1f, row1.getBottomRoundness(), /* delta = */ 0f);
Assert.assertEquals(1f, row2.getTopRoundness(), /* delta = */ 0f);
Assert.assertEquals(1f, row2.getBottomRoundness(), /* delta = */ 0f);
}
}

View File

@@ -1,6 +1,7 @@
package com.android.systemui.statusbar.notification.stack
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
@@ -8,8 +9,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.notification.SourceType
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.StackScrollAlgorithmState
import com.android.systemui.util.mockito.mock
import junit.framework.Assert.assertEquals
@@ -37,6 +40,13 @@ class NotificationShelfTest : SysuiTestCase() {
private val shelfState = shelf.viewState as NotificationShelf.ShelfState
private val ambientState = mock(AmbientState::class.java)
private val hostLayoutController: NotificationStackScrollLayoutController = mock()
private val notificationTestHelper by lazy {
allowTestableLooperAsMainThread()
NotificationTestHelper(
mContext,
mDependency,
TestableLooper.get(this))
}
@Before
fun setUp() {
@@ -299,6 +309,39 @@ class NotificationShelfTest : SysuiTestCase() {
)
}
@Test
fun resetOnScrollRoundness_shouldSetOnScrollTo0() {
val row: ExpandableNotificationRow = notificationTestHelper.createRowWithRoundness(
/* topRoundness = */ 1f,
/* bottomRoundness = */ 1f,
/* sourceType = */ SourceType.OnScroll)
NotificationShelf.resetOnScrollRoundness(row)
assertEquals(0f, row.topRoundness)
assertEquals(0f, row.bottomRoundness)
}
@Test
fun resetOnScrollRoundness_shouldNotResetOtherRoundness() {
val row1: ExpandableNotificationRow = notificationTestHelper.createRowWithRoundness(
/* topRoundness = */ 1f,
/* bottomRoundness = */ 1f,
/* sourceType = */ SourceType.DefaultValue)
val row2: ExpandableNotificationRow = notificationTestHelper.createRowWithRoundness(
/* topRoundness = */ 1f,
/* bottomRoundness = */ 1f,
/* sourceType = */ SourceType.OnDismissAnimation)
NotificationShelf.resetOnScrollRoundness(row1)
NotificationShelf.resetOnScrollRoundness(row2)
assertEquals(1f, row1.topRoundness)
assertEquals(1f, row1.bottomRoundness)
assertEquals(1f, row2.topRoundness)
assertEquals(1f, row2.bottomRoundness)
}
private fun setFractionToShade(fraction: Float) {
whenever(ambientState.fractionToShade).thenReturn(fraction)
}