Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b11d6bc authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez
Browse files

Consolidating magnetic detachment with dismissibility.

The condition that determines if a notification has been swiped far
enough and fast enought to be dismissed now depends on whether the
swiped notification has magnetically detached or not. We also flag the
conflicting previous haptic feedback when the notification is swiped
past the previous length threshold.

Test: MagneticNotificationRowManagerImplTest
Test: NotificationSwipeHelperTest
Flag: com.android.systemui.magnetic_notification_swipes
Bug: 397418669
Change-Id: I9b12c8a90176b6bc27c370ed463e713a33cbb292
parent 14cb9b41
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -413,6 +415,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(
+24 −5
Original line number Diff line number Diff line
@@ -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()
@@ -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
@@ -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()
@@ -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
@@ -294,6 +302,15 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            assertThat(underTest.isSwipedViewRoundableSet).isFalse()
        }

    @Test
    fun isMagneticRowDismissible_isDismissibleWhenDetached() =
        kosmos.testScope.runTest {
            setDetachedState()

            val isDismissible = underTest.isMagneticRowSwipeDetached(swipedRow)
            assertThat(isDismissible).isTrue()
        }

    @After
    fun tearDown() {
        // We reset the manager so that all MagneticRowListener can cancel all animations
@@ -302,7 +319,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()
+16 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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();
+18 −3
Original line number Diff line number Diff line
@@ -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();
@@ -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.
         *
+3 −2
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
@@ -358,8 +357,10 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
            final float dismissThreshold = getDismissThreshold();
            final boolean snappingToDismiss = delta < -dismissThreshold || delta > dismissThreshold;
            if (mSnappingToDismiss != snappingToDismiss) {
                if (!Flags.magneticNotificationSwipes()) {
                    getMenuView().performHapticFeedback(CLOCK_TICK);
                }
            }
            mSnappingToDismiss = snappingToDismiss;
        }
    }
Loading