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

Commit 473e877d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Playing dismiss haptics when flinging to dismiss but without detaching." into main

parents 311d9066 68b0b534
Loading
Loading
Loading
Loading
+58 −5
Original line number Diff line number Diff line
@@ -16,12 +16,18 @@

package com.android.systemui.statusbar.notification.stack

import android.os.VibrationEffect
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import androidx.dynamicanimation.animation.SpringForce
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.haptics.fakeVibratorHelper
import com.android.systemui.haptics.msdl.fakeMSDLPlayer
import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.createRowGroup
@@ -46,6 +52,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
    private val stackScrollLayout = mock<NotificationStackScrollLayout>()
    private val sectionsManager = mock<NotificationSectionsManager>()
    private val msdlPlayer = kosmos.fakeMSDLPlayer
    private val vibratorHelper = kosmos.fakeVibratorHelper
    private var canRowBeDismissed = true
    private var magneticAnimationsCancelled = MutableList(childrenNumber) { false }

@@ -235,7 +242,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            underTest.setMagneticRowTranslation(swipedRow, translation = 100f)

            // WHEN the interaction ends on the row
            underTest.onMagneticInteractionEnd(swipedRow, velocity = null)
            underTest.onMagneticInteractionEnd(swipedRow, dismissing = false, velocity = null)

            // THEN the state resets
            assertThat(underTest.currentState).isEqualTo(State.IDLE)
@@ -248,7 +255,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            setTargets()

            // WHEN the interaction ends on the row
            underTest.onMagneticInteractionEnd(swipedRow, velocity = null)
            underTest.onMagneticInteractionEnd(swipedRow, dismissing = false, velocity = null)

            // THEN the state resets
            assertThat(underTest.currentState).isEqualTo(State.IDLE)
@@ -261,7 +268,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            setDetachedState()

            // WHEN the interaction ends on the row
            underTest.onMagneticInteractionEnd(swipedRow, velocity = null)
            underTest.onMagneticInteractionEnd(swipedRow, dismissing = false, velocity = null)

            // THEN the state resets
            assertThat(underTest.currentState).isEqualTo(State.IDLE)
@@ -274,7 +281,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            setDetachedState()

            // WHEN the interaction ends on the row
            underTest.onMagneticInteractionEnd(swipedRow, velocity = null)
            underTest.onMagneticInteractionEnd(swipedRow, dismissing = false, velocity = null)

            // THEN magnetic animations are cancelled
            assertThat(magneticAnimationsCancelled[childrenNumber / 2]).isTrue()
@@ -290,12 +297,58 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() {
            setTargets()

            // WHEN the interactionEnd is called on a target different from the swiped row
            underTest.onMagneticInteractionEnd(neighborRow, null)
            underTest.onMagneticInteractionEnd(neighborRow, dismissing = false, velocity = null)

            // THEN magnetic animations are cancelled
            assertThat(magneticAnimationsCancelled[neighborIndex]).isTrue()
        }

    @Test
    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
    fun onMagneticInteractionEnd_whenPulling_fromDismiss_playsMSDLThresholdHaptics() =
        kosmos.testScope.runTest {
            // GIVEN a threshold of 100 px
            val threshold = 100f
            underTest.onDensityChange(
                threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP
            )

            // GIVEN that targets are set and the swiped row is being pulled
            setTargets()
            underTest.setMagneticRowTranslation(swipedRow, translation = 100f)

            // WHEN the interaction ends on the row because it was dismissed
            underTest.onMagneticInteractionEnd(swipedRow, dismissing = true, velocity = null)

            // THEN threshold haptics play to indicate the dismissal
            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.SWIPE_THRESHOLD_INDICATOR)
        }

    @Test
    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
    fun onMagneticInteractionEnd_whenPulling_fromDismiss_playsThresholdVibration() =
        kosmos.testScope.runTest {
            // GIVEN a threshold of 100 px
            val threshold = 100f
            underTest.onDensityChange(
                threshold / MagneticNotificationRowManager.MAGNETIC_DETACH_THRESHOLD_DP
            )

            // GIVEN that targets are set and the swiped row is being pulled
            setTargets()
            underTest.setMagneticRowTranslation(swipedRow, translation = 100f)

            // WHEN the interaction ends on the row because it was dismissed
            underTest.onMagneticInteractionEnd(swipedRow, dismissing = true, velocity = null)

            // THEN threshold haptics play to indicate the dismissal
            val composition =
                VibrationEffect.startComposition()
                    .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.7f)
                    .compose()
            assertThat(vibratorHelper.hasVibratedWithEffects(composition)).isTrue()
        }

    @Test
    fun onResetRoundness_swipedRoundableGetsCleared() =
        kosmos.testScope.runTest {
+5 −3
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
        };

        Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
        mCallback.onMagneticInteractionEnd(animView, velocity);
        mCallback.onMagneticInteractionEnd(animView, /* dismissing = */ true, velocity);
        if (anim == null) {
            onDismissChildWithAnimationFinished();
            return;
@@ -754,7 +754,8 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
                        dismissChild(mTouchedView, velocity,
                                !swipedFastEnough() /* useAccelerateInterpolator */);
                    } else {
                        mCallback.onMagneticInteractionEnd(mTouchedView, velocity);
                        mCallback.onMagneticInteractionEnd(mTouchedView, /* dismissing = */ false,
                                velocity);
                        mCallback.onDragCancelled(mTouchedView);
                        snapChild(mTouchedView, 0 /* leftTarget */, velocity);
                    }
@@ -985,9 +986,10 @@ public class SwipeHelper implements Gefingerpoken, Dumpable {
         * This method should be called when a view will snap back or be dismissed.
         *
         * @param view The {@link  View} whose magnetic interaction ended.
         * @param dismissing If the interaction ended with the view being dismissed.
         * @param velocity The velocity when the interaction ended.
         */
        void onMagneticInteractionEnd(View view, float velocity);
        void onMagneticInteractionEnd(View view, boolean dismissing, float velocity);

        /**
         * Determine if a view managed by magnetic interactions is dismissible when being swiped by
+8 −1
Original line number Diff line number Diff line
@@ -85,10 +85,16 @@ interface MagneticNotificationRowManager {
     * after calls to [setMagneticRowTranslation].
     *
     * @param[row] [ExpandableNotificationRow] that stopped whose interaction stopped.
     * @param[dismissing] If the interaction ended because the row is dismissing. If false, it is
     *   assumed that the row is snapping back instead.
     * @param[velocity] Optional velocity at the end of the interaction. Use this to trigger
     *   animations with a start velocity.
     */
    fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float? = null)
    fun onMagneticInteractionEnd(
        row: ExpandableNotificationRow,
        dismissing: Boolean,
        velocity: Float? = null,
    )

    /**
     * Determine if a magnetic row swiped is dismissible according to the end velocity of the swipe.
@@ -144,6 +150,7 @@ interface MagneticNotificationRowManager {

                    override fun onMagneticInteractionEnd(
                        row: ExpandableNotificationRow,
                        dismissing: Boolean,
                        velocity: Float?,
                    ) {}

+8 −1
Original line number Diff line number Diff line
@@ -336,12 +336,19 @@ constructor(
        detachDirectionEstimator.reset()
    }

    override fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float?) {
    override fun onMagneticInteractionEnd(
        row: ExpandableNotificationRow,
        dismissing: Boolean,
        velocity: Float?,
    ) {
        detachDirectionEstimator.reset()
        if (row.isSwipedTarget()) {
            when (currentState) {
                State.TARGETS_SET -> currentState = State.IDLE
                State.PULLING -> {
                    if (dismissing) {
                        playThresholdHaptics()
                    }
                    snapNeighborsBack(velocity)
                    currentState = State.IDLE
                }
+4 −2
Original line number Diff line number Diff line
@@ -503,9 +503,11 @@ public class NotificationStackScrollLayoutController implements Dumpable {
                }

                @Override
                public void onMagneticInteractionEnd(View view, float velocity) {
                public void onMagneticInteractionEnd(View view, boolean dismissing,
                        float velocity) {
                    if (view instanceof ExpandableNotificationRow row) {
                        mMagneticNotificationRowManager.onMagneticInteractionEnd(row, velocity);
                        mMagneticNotificationRowManager.onMagneticInteractionEnd(row, dismissing,
                                velocity);
                    }
                }

Loading