Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java +3 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.platform.test.annotations.DisableFlags; import android.provider.Settings; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; Loading @@ -38,6 +39,7 @@ import android.view.ViewGroup; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.Flags; import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.collection.EntryAdapter; Loading Loading @@ -418,6 +420,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest { assertTrue("when alpha is .5, menu is visible", row.isMenuVisible()); } @DisableFlags(Flags.FLAG_MAGNETIC_NOTIFICATION_SWIPES) @Test public void testOnTouchMove() { NotificationMenuRow row = Mockito.spy( Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt +40 −7 Original line number Diff line number Diff line Loading @@ -130,7 +130,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled setTargets() Loading @@ -150,7 +152,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled canRowBeDismissed = false Loading @@ -172,7 +176,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled setTargets() Loading @@ -192,7 +198,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled canRowBeDismissed = false Loading Loading @@ -294,6 +302,29 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { assertThat(underTest.isSwipedViewRoundableSet).isFalse() } @Test fun isMagneticRowDismissible_isDismissibleWhenDetached() = kosmos.testScope.runTest { setDetachedState() val isDismissible = underTest.isMagneticRowSwipeDetached(swipedRow) assertThat(isDismissible).isTrue() } @Test fun setMagneticRowTranslation_whenDetached_belowAttachThreshold_reattaches() = kosmos.testScope.runTest { // GIVEN that the swiped view has been detached setDetachedState() // WHEN setting a new translation above the attach threshold val translation = 50f underTest.setMagneticRowTranslation(swipedRow, translation) // THEN the swiped view reattaches magnetically and the state becomes PULLING assertThat(underTest.currentState).isEqualTo(State.PULLING) } @After fun tearDown() { // We reset the manager so that all MagneticRowListener can cancel all animations Loading @@ -302,7 +333,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { private fun setDetachedState() { val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // Set the pulling state setTargets() Loading @@ -327,8 +360,8 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { private fun MagneticRowListener.asTestableListener(rowIndex: Int): MagneticRowListener { val delegate = this return object : MagneticRowListener { override fun setMagneticTranslation(translation: Float) { delegate.setMagneticTranslation(translation) override fun setMagneticTranslation(translation: Float, trackEagerly: Boolean) { delegate.setMagneticTranslation(translation, trackEagerly) } override fun triggerMagneticForce( Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java +16 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.view.ViewConfiguration; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.flags.FakeFeatureFlags; Loading Loading @@ -362,6 +363,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { verify(mSwipeHelper, times(1)).isFalseGesture(); } @DisableFlags(Flags.FLAG_MAGNETIC_NOTIFICATION_SWIPES) @Test public void testIsDismissGesture_farEnough() { doReturn(false).when(mSwipeHelper).isFalseGesture(); Loading @@ -374,6 +376,20 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { verify(mSwipeHelper, times(1)).isFalseGesture(); } @EnableFlags(Flags.FLAG_MAGNETIC_NOTIFICATION_SWIPES) @Test public void testIsDismissGesture_magneticSwipeIsDismissible() { doReturn(false).when(mSwipeHelper).isFalseGesture(); doReturn(false).when(mSwipeHelper).swipedFarEnough(); doReturn(false).when(mSwipeHelper).swipedFastEnough(); doReturn(true).when(mCallback).isMagneticViewDetached(any()); when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true); when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP); assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent)); verify(mSwipeHelper, times(1)).isFalseGesture(); } @Test public void testIsDismissGesture_notFarOrFastEnough() { doReturn(false).when(mSwipeHelper).isFalseGesture(); Loading packages/SystemUI/src/com/android/systemui/SwipeHelper.java +18 −3 Original line number Diff line number Diff line Loading @@ -778,18 +778,26 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { protected boolean swipedFarEnough() { float translation = getTranslation(mTouchedView); return Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize( mTouchedView); return Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(mTouchedView); } public boolean isDismissGesture(MotionEvent ev) { float translation = getTranslation(mTouchedView); return ev.getActionMasked() == MotionEvent.ACTION_UP && !mFalsingManager.isUnlockingDisabled() && !isFalseGesture() && (swipedFastEnough() || swipedFarEnough()) && !isFalseGesture() && isSwipeDismissible() && mCallback.canChildBeDismissedInDirection(mTouchedView, translation > 0); } /** Can the swipe gesture on the touched view be considered as a dismiss intention */ public boolean isSwipeDismissible() { if (magneticNotificationSwipes()) { return mCallback.isMagneticViewDetached(mTouchedView) || swipedFastEnough(); } else { return swipedFastEnough() || swipedFarEnough(); } } /** Returns true if the gesture should be rejected. */ public boolean isFalseGesture() { boolean falsingDetected = mCallback.isAntiFalsingNeeded(); Loading Loading @@ -969,6 +977,13 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { */ void onMagneticInteractionEnd(View view, float velocity); /** * Determine if a view managed by magnetic interactions is magnetically detached * @param view The magnetic view * @return if the view is detached according to its magnetic state. */ boolean isMagneticViewDetached(View view); /** * Called when the child is long pressed and available to start drag and drop. * Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +21 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.Flags.notificationColorUpdateLogger; import static com.android.systemui.Flags.physicalNotificationMovement; import static java.lang.Math.abs; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.res.Configuration; Loading @@ -29,6 +31,7 @@ import android.util.FloatProperty; import android.util.IndentingPrintWriter; import android.util.Log; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.FrameLayout; Loading Loading @@ -110,15 +113,28 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro protected SpringAnimation mMagneticAnimator = new SpringAnimation( this /* object */, DynamicAnimation.TRANSLATION_X); private int mTouchSlop; protected MagneticRowListener mMagneticRowListener = new MagneticRowListener() { @Override public void setMagneticTranslation(float translation) { if (mMagneticAnimator.isRunning()) { public void setMagneticTranslation(float translation, boolean trackEagerly) { if (!mMagneticAnimator.isRunning()) { setTranslation(translation); return; } if (trackEagerly) { float delta = abs(getTranslation() - translation); if (delta > mTouchSlop) { mMagneticAnimator.animateToFinalPosition(translation); } else { mMagneticAnimator.cancel(); setTranslation(translation); } } else { mMagneticAnimator.animateToFinalPosition(translation); } } @Override Loading Loading @@ -183,6 +199,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro private void initDimens() { mContentShift = getResources().getDimensionPixelSize( R.dimen.shelf_transform_content_shift); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } @Override Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java +3 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.platform.test.annotations.DisableFlags; import android.provider.Settings; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; Loading @@ -38,6 +39,7 @@ import android.view.ViewGroup; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.Flags; import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.collection.EntryAdapter; Loading Loading @@ -418,6 +420,7 @@ public class NotificationMenuRowTest extends LeakCheckedTest { assertTrue("when alpha is .5, menu is visible", row.isMenuVisible()); } @DisableFlags(Flags.FLAG_MAGNETIC_NOTIFICATION_SWIPES) @Test public void testOnTouchMove() { NotificationMenuRow row = Mockito.spy( Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt +40 −7 Original line number Diff line number Diff line Loading @@ -130,7 +130,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled setTargets() Loading @@ -150,7 +152,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled canRowBeDismissed = false Loading @@ -172,7 +176,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled setTargets() Loading @@ -192,7 +198,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { kosmos.testScope.runTest { // GIVEN a threshold of 100 px val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // GIVEN that targets are set and the rows are being pulled canRowBeDismissed = false Loading Loading @@ -294,6 +302,29 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { assertThat(underTest.isSwipedViewRoundableSet).isFalse() } @Test fun isMagneticRowDismissible_isDismissibleWhenDetached() = kosmos.testScope.runTest { setDetachedState() val isDismissible = underTest.isMagneticRowSwipeDetached(swipedRow) assertThat(isDismissible).isTrue() } @Test fun setMagneticRowTranslation_whenDetached_belowAttachThreshold_reattaches() = kosmos.testScope.runTest { // GIVEN that the swiped view has been detached setDetachedState() // WHEN setting a new translation above the attach threshold val translation = 50f underTest.setMagneticRowTranslation(swipedRow, translation) // THEN the swiped view reattaches magnetically and the state becomes PULLING assertThat(underTest.currentState).isEqualTo(State.PULLING) } @After fun tearDown() { // We reset the manager so that all MagneticRowListener can cancel all animations Loading @@ -302,7 +333,9 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { private fun setDetachedState() { val threshold = 100f underTest.setSwipeThresholdPx(threshold) underTest.onDensityChange( threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP ) // Set the pulling state setTargets() Loading @@ -327,8 +360,8 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { private fun MagneticRowListener.asTestableListener(rowIndex: Int): MagneticRowListener { val delegate = this return object : MagneticRowListener { override fun setMagneticTranslation(translation: Float) { delegate.setMagneticTranslation(translation) override fun setMagneticTranslation(translation: Float, trackEagerly: Boolean) { delegate.setMagneticTranslation(translation, trackEagerly) } override fun triggerMagneticForce( Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java +16 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.view.ViewConfiguration; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.flags.FakeFeatureFlags; Loading Loading @@ -362,6 +363,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { verify(mSwipeHelper, times(1)).isFalseGesture(); } @DisableFlags(Flags.FLAG_MAGNETIC_NOTIFICATION_SWIPES) @Test public void testIsDismissGesture_farEnough() { doReturn(false).when(mSwipeHelper).isFalseGesture(); Loading @@ -374,6 +376,20 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { verify(mSwipeHelper, times(1)).isFalseGesture(); } @EnableFlags(Flags.FLAG_MAGNETIC_NOTIFICATION_SWIPES) @Test public void testIsDismissGesture_magneticSwipeIsDismissible() { doReturn(false).when(mSwipeHelper).isFalseGesture(); doReturn(false).when(mSwipeHelper).swipedFarEnough(); doReturn(false).when(mSwipeHelper).swipedFastEnough(); doReturn(true).when(mCallback).isMagneticViewDetached(any()); when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true); when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP); assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent)); verify(mSwipeHelper, times(1)).isFalseGesture(); } @Test public void testIsDismissGesture_notFarOrFastEnough() { doReturn(false).when(mSwipeHelper).isFalseGesture(); Loading
packages/SystemUI/src/com/android/systemui/SwipeHelper.java +18 −3 Original line number Diff line number Diff line Loading @@ -778,18 +778,26 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { protected boolean swipedFarEnough() { float translation = getTranslation(mTouchedView); return Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize( mTouchedView); return Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(mTouchedView); } public boolean isDismissGesture(MotionEvent ev) { float translation = getTranslation(mTouchedView); return ev.getActionMasked() == MotionEvent.ACTION_UP && !mFalsingManager.isUnlockingDisabled() && !isFalseGesture() && (swipedFastEnough() || swipedFarEnough()) && !isFalseGesture() && isSwipeDismissible() && mCallback.canChildBeDismissedInDirection(mTouchedView, translation > 0); } /** Can the swipe gesture on the touched view be considered as a dismiss intention */ public boolean isSwipeDismissible() { if (magneticNotificationSwipes()) { return mCallback.isMagneticViewDetached(mTouchedView) || swipedFastEnough(); } else { return swipedFastEnough() || swipedFarEnough(); } } /** Returns true if the gesture should be rejected. */ public boolean isFalseGesture() { boolean falsingDetected = mCallback.isAntiFalsingNeeded(); Loading Loading @@ -969,6 +977,13 @@ public class SwipeHelper implements Gefingerpoken, Dumpable { */ void onMagneticInteractionEnd(View view, float velocity); /** * Determine if a view managed by magnetic interactions is magnetically detached * @param view The magnetic view * @return if the view is detached according to its magnetic state. */ boolean isMagneticViewDetached(View view); /** * Called when the child is long pressed and available to start drag and drop. * Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +21 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.notification.row; import static com.android.systemui.Flags.notificationColorUpdateLogger; import static com.android.systemui.Flags.physicalNotificationMovement; import static java.lang.Math.abs; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.res.Configuration; Loading @@ -29,6 +31,7 @@ import android.util.FloatProperty; import android.util.IndentingPrintWriter; import android.util.Log; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.FrameLayout; Loading Loading @@ -110,15 +113,28 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro protected SpringAnimation mMagneticAnimator = new SpringAnimation( this /* object */, DynamicAnimation.TRANSLATION_X); private int mTouchSlop; protected MagneticRowListener mMagneticRowListener = new MagneticRowListener() { @Override public void setMagneticTranslation(float translation) { if (mMagneticAnimator.isRunning()) { public void setMagneticTranslation(float translation, boolean trackEagerly) { if (!mMagneticAnimator.isRunning()) { setTranslation(translation); return; } if (trackEagerly) { float delta = abs(getTranslation() - translation); if (delta > mTouchSlop) { mMagneticAnimator.animateToFinalPosition(translation); } else { mMagneticAnimator.cancel(); setTranslation(translation); } } else { mMagneticAnimator.animateToFinalPosition(translation); } } @Override Loading Loading @@ -183,6 +199,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro private void initDimens() { mContentShift = getResources().getDimensionPixelSize( R.dimen.shelf_transform_content_shift); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } @Override Loading