Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt +14 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { // THEN the magnetic and roundable targets are defined and the state is TARGETS_SET assertThat(underTest.currentState).isEqualTo(State.TARGETS_SET) assertThat(underTest.currentMagneticListeners.isNotEmpty()).isTrue() assertThat(underTest.currentRoundableTargets).isNotNull() assertThat(underTest.isSwipedViewRoundableSet).isTrue() } @Test Loading Loading @@ -281,6 +281,19 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { assertThat(magneticAnimationsCancelled[neighborIndex]).isTrue() } @Test fun onResetRoundness_swipedRoundableGetsCleared() = kosmos.testScope.runTest { // GIVEN targets are set setTargets() // WHEN we reset the roundness underTest.resetRoundness() // THEN the swiped roundable gets cleared assertThat(underTest.isSwipedViewRoundableSet).isFalse() } @After fun tearDown() { // We reset the manager so that all MagneticRowListener can cancel all animations Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManager.kt +5 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ interface MagneticNotificationRowManager { */ fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float? = null) /* Reset any roundness that magnetic targets may have */ fun resetRoundness() /** * Reset any magnetic and roundable targets set, as well as any internal state. * Loading Loading @@ -124,6 +127,8 @@ interface MagneticNotificationRowManager { velocity: Float?, ) {} override fun resetRoundness() {} override fun reset() {} } } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt +33 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.google.android.msdl.domain.MSDLPlayer import javax.inject.Inject import kotlin.math.abs import kotlin.math.pow import org.jetbrains.annotations.TestOnly @SysUISingleton class MagneticNotificationRowManagerImpl Loading @@ -41,15 +42,16 @@ constructor( var currentState = State.IDLE private set // Magnetic and roundable targets // Magnetic targets var currentMagneticListeners = listOf<MagneticRowListener?>() private set var currentRoundableTargets: RoundableTargets? = null private set private var magneticDetachThreshold = Float.POSITIVE_INFINITY // Has the roundable target been set for the magnetic view that is being swiped. val isSwipedViewRoundableSet: Boolean @TestOnly get() = notificationRoundnessManager.isSwipedViewSet // Animation spring forces private val detachForce = SpringForce().setStiffness(DETACH_STIFFNESS).setDampingRatio(DETACH_DAMPING_RATIO) Loading Loading @@ -83,12 +85,14 @@ constructor( sectionsManager: NotificationSectionsManager, ) { // Update roundable targets currentRoundableTargets = notificationRoundnessManager.clear() val currentRoundableTargets = notificationTargetsHelper.findRoundableTargets( expandableNotificationRow, stackScrollLayout, sectionsManager, ) notificationRoundnessManager.setRoundableTargets(currentRoundableTargets) // Update magnetic targets val newListeners = Loading Loading @@ -127,6 +131,7 @@ constructor( currentState = State.PULLING } State.PULLING -> { updateRoundness(translation) if (canTargetBeDismissed) { pullDismissibleRow(translation) } else { Loading @@ -141,6 +146,14 @@ constructor( return true } private fun updateRoundness(translation: Float) { val normalizedTranslation = abs(swipedRowMultiplier * translation) / magneticDetachThreshold notificationRoundnessManager.setRoundnessForAffectedViews( /* roundness */ normalizedTranslation.coerceIn(0f, MAX_PRE_DETACH_ROUNDNESS), /* animate */ false, ) } private fun pullDismissibleRow(translation: Float) { val targetTranslation = swipedRowMultiplier * translation val crossedThreshold = abs(targetTranslation) >= magneticDetachThreshold Loading Loading @@ -203,9 +216,10 @@ constructor( private fun detach(listener: MagneticRowListener, toPosition: Float) { listener.cancelMagneticAnimations() listener.triggerMagneticForce(toPosition, detachForce) currentRoundableTargets?.let { notificationRoundnessManager.setViewsAffectedBySwipe(it.before, it.swiped, it.after) } notificationRoundnessManager.setRoundnessForAffectedViews( /* roundness */ 1f, /* animate */ true, ) msdlPlayer.playToken(MSDLToken.SWIPE_THRESHOLD_INDICATOR) } Loading Loading @@ -240,6 +254,8 @@ constructor( } } override fun resetRoundness() = notificationRoundnessManager.clear() override fun reset() { currentMagneticListeners.forEach { it?.cancelMagneticAnimations() Loading @@ -247,7 +263,7 @@ constructor( } currentState = State.IDLE currentMagneticListeners = listOf() currentRoundableTargets = null notificationRoundnessManager.clear() } private fun List<MagneticRowListener?>.swipedListener(): MagneticRowListener? = Loading @@ -256,6 +272,11 @@ constructor( private fun ExpandableNotificationRow.isSwipedTarget(): Boolean = magneticRowListener == currentMagneticListeners.swipedListener() private fun NotificationRoundnessManager.clear() = setViewsAffectedBySwipe(null, null, null) private fun NotificationRoundnessManager.setRoundableTargets(targets: RoundableTargets) = setViewsAffectedBySwipe(targets.before, targets.swiped, targets.after) enum class State { IDLE, TARGETS_SET, Loading @@ -280,6 +301,9 @@ constructor( private const val SNAP_BACK_STIFFNESS = 550f private const val SNAP_BACK_DAMPING_RATIO = 0.52f // Maximum value of corner roundness that gets applied during the pre-detach dragging private const val MAX_PRE_DETACH_ROUNDNESS = 0.8f private val VIBRATION_ATTRIBUTES_PIPELINING = VibrationAttributes.Builder() .setUsage(VibrationAttributes.USAGE_TOUCH) Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +34 −7 Original line number Diff line number Diff line Loading @@ -71,10 +71,8 @@ public class NotificationRoundnessManager implements Dumpable { Roundable viewBefore, ExpandableView viewSwiped, Roundable viewAfter) { // This method requires you to change the roundness of the current View targets and reset // the roundness of the old View targets (if any) to 0f. // To avoid conflicts, it generates a set of old Views and removes the current Views // from this set. // This method caches a new set of current View targets and reset the roundness of the old // View targets (if any) to 0f. HashSet<Roundable> oldViews = new HashSet<>(); if (mViewBeforeSwipedView != null) oldViews.add(mViewBeforeSwipedView); if (mSwipedView != null) oldViews.add(mSwipedView); Loading @@ -83,19 +81,16 @@ public class NotificationRoundnessManager implements Dumpable { mViewBeforeSwipedView = viewBefore; if (viewBefore != null) { oldViews.remove(viewBefore); viewBefore.requestRoundness(/* top = */ 0f, /* bottom = */ 1f, DISMISS_ANIMATION); } mSwipedView = viewSwiped; if (viewSwiped != null) { oldViews.remove(viewSwiped); viewSwiped.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, DISMISS_ANIMATION); } mViewAfterSwipedView = viewAfter; if (viewAfter != null) { oldViews.remove(viewAfter); viewAfter.requestRoundness(/* top = */ 1f, /* bottom = */ 0f, DISMISS_ANIMATION); } // After setting the current Views, reset the views that are still present in the set. Loading @@ -104,6 +99,34 @@ public class NotificationRoundnessManager implements Dumpable { } } void setRoundnessForAffectedViews(float roundness) { if (mViewBeforeSwipedView != null) { mViewBeforeSwipedView.requestBottomRoundness(roundness, DISMISS_ANIMATION); } if (mSwipedView != null) { mSwipedView.requestRoundness(roundness, roundness, DISMISS_ANIMATION); } if (mViewAfterSwipedView != null) { mViewAfterSwipedView.requestTopRoundness(roundness, DISMISS_ANIMATION); } } void setRoundnessForAffectedViews(float roundness, boolean animate) { if (mViewBeforeSwipedView != null) { mViewBeforeSwipedView.requestBottomRoundness(roundness, DISMISS_ANIMATION, animate); } if (mSwipedView != null) { mSwipedView.requestRoundness(roundness, roundness, DISMISS_ANIMATION, animate); } if (mViewAfterSwipedView != null) { mViewAfterSwipedView.requestTopRoundness(roundness, DISMISS_ANIMATION, animate); } } void setClearAllInProgress(boolean isClearingAll) { mIsClearAllInProgress = isClearingAll; } Loading Loading @@ -138,4 +161,8 @@ public class NotificationRoundnessManager implements Dumpable { public void setShouldRoundPulsingViews(boolean shouldRoundPulsingViews) { mRoundForPulsingViews = shouldRoundPulsingViews; } public boolean isSwipedViewSet() { return mSwipedView != null; } } packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +6 −3 Original line number Diff line number Diff line Loading @@ -5840,7 +5840,8 @@ public class NotificationStackScrollLayout targets.getBefore(), targets.getSwiped(), targets.getAfter()); mController.getNotificationRoundnessManager() .setRoundnessForAffectedViews(/* roundness */ 1f); } updateFirstAndLastBackgroundViews(); Loading @@ -5851,8 +5852,10 @@ public class NotificationStackScrollLayout void onSwipeEnd() { updateFirstAndLastBackgroundViews(); if (!magneticNotificationSwipes()) { mController.getNotificationRoundnessManager() .setViewsAffectedBySwipe(null, null, null); } // Round bottom corners for notification right before shelf. mShelf.updateAppearance(); } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImplTest.kt +14 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,7 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { // THEN the magnetic and roundable targets are defined and the state is TARGETS_SET assertThat(underTest.currentState).isEqualTo(State.TARGETS_SET) assertThat(underTest.currentMagneticListeners.isNotEmpty()).isTrue() assertThat(underTest.currentRoundableTargets).isNotNull() assertThat(underTest.isSwipedViewRoundableSet).isTrue() } @Test Loading Loading @@ -281,6 +281,19 @@ class MagneticNotificationRowManagerImplTest : SysuiTestCase() { assertThat(magneticAnimationsCancelled[neighborIndex]).isTrue() } @Test fun onResetRoundness_swipedRoundableGetsCleared() = kosmos.testScope.runTest { // GIVEN targets are set setTargets() // WHEN we reset the roundness underTest.resetRoundness() // THEN the swiped roundable gets cleared assertThat(underTest.isSwipedViewRoundableSet).isFalse() } @After fun tearDown() { // We reset the manager so that all MagneticRowListener can cancel all animations Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManager.kt +5 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ interface MagneticNotificationRowManager { */ fun onMagneticInteractionEnd(row: ExpandableNotificationRow, velocity: Float? = null) /* Reset any roundness that magnetic targets may have */ fun resetRoundness() /** * Reset any magnetic and roundable targets set, as well as any internal state. * Loading Loading @@ -124,6 +127,8 @@ interface MagneticNotificationRowManager { velocity: Float?, ) {} override fun resetRoundness() {} override fun reset() {} } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MagneticNotificationRowManagerImpl.kt +33 −9 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.google.android.msdl.domain.MSDLPlayer import javax.inject.Inject import kotlin.math.abs import kotlin.math.pow import org.jetbrains.annotations.TestOnly @SysUISingleton class MagneticNotificationRowManagerImpl Loading @@ -41,15 +42,16 @@ constructor( var currentState = State.IDLE private set // Magnetic and roundable targets // Magnetic targets var currentMagneticListeners = listOf<MagneticRowListener?>() private set var currentRoundableTargets: RoundableTargets? = null private set private var magneticDetachThreshold = Float.POSITIVE_INFINITY // Has the roundable target been set for the magnetic view that is being swiped. val isSwipedViewRoundableSet: Boolean @TestOnly get() = notificationRoundnessManager.isSwipedViewSet // Animation spring forces private val detachForce = SpringForce().setStiffness(DETACH_STIFFNESS).setDampingRatio(DETACH_DAMPING_RATIO) Loading Loading @@ -83,12 +85,14 @@ constructor( sectionsManager: NotificationSectionsManager, ) { // Update roundable targets currentRoundableTargets = notificationRoundnessManager.clear() val currentRoundableTargets = notificationTargetsHelper.findRoundableTargets( expandableNotificationRow, stackScrollLayout, sectionsManager, ) notificationRoundnessManager.setRoundableTargets(currentRoundableTargets) // Update magnetic targets val newListeners = Loading Loading @@ -127,6 +131,7 @@ constructor( currentState = State.PULLING } State.PULLING -> { updateRoundness(translation) if (canTargetBeDismissed) { pullDismissibleRow(translation) } else { Loading @@ -141,6 +146,14 @@ constructor( return true } private fun updateRoundness(translation: Float) { val normalizedTranslation = abs(swipedRowMultiplier * translation) / magneticDetachThreshold notificationRoundnessManager.setRoundnessForAffectedViews( /* roundness */ normalizedTranslation.coerceIn(0f, MAX_PRE_DETACH_ROUNDNESS), /* animate */ false, ) } private fun pullDismissibleRow(translation: Float) { val targetTranslation = swipedRowMultiplier * translation val crossedThreshold = abs(targetTranslation) >= magneticDetachThreshold Loading Loading @@ -203,9 +216,10 @@ constructor( private fun detach(listener: MagneticRowListener, toPosition: Float) { listener.cancelMagneticAnimations() listener.triggerMagneticForce(toPosition, detachForce) currentRoundableTargets?.let { notificationRoundnessManager.setViewsAffectedBySwipe(it.before, it.swiped, it.after) } notificationRoundnessManager.setRoundnessForAffectedViews( /* roundness */ 1f, /* animate */ true, ) msdlPlayer.playToken(MSDLToken.SWIPE_THRESHOLD_INDICATOR) } Loading Loading @@ -240,6 +254,8 @@ constructor( } } override fun resetRoundness() = notificationRoundnessManager.clear() override fun reset() { currentMagneticListeners.forEach { it?.cancelMagneticAnimations() Loading @@ -247,7 +263,7 @@ constructor( } currentState = State.IDLE currentMagneticListeners = listOf() currentRoundableTargets = null notificationRoundnessManager.clear() } private fun List<MagneticRowListener?>.swipedListener(): MagneticRowListener? = Loading @@ -256,6 +272,11 @@ constructor( private fun ExpandableNotificationRow.isSwipedTarget(): Boolean = magneticRowListener == currentMagneticListeners.swipedListener() private fun NotificationRoundnessManager.clear() = setViewsAffectedBySwipe(null, null, null) private fun NotificationRoundnessManager.setRoundableTargets(targets: RoundableTargets) = setViewsAffectedBySwipe(targets.before, targets.swiped, targets.after) enum class State { IDLE, TARGETS_SET, Loading @@ -280,6 +301,9 @@ constructor( private const val SNAP_BACK_STIFFNESS = 550f private const val SNAP_BACK_DAMPING_RATIO = 0.52f // Maximum value of corner roundness that gets applied during the pre-detach dragging private const val MAX_PRE_DETACH_ROUNDNESS = 0.8f private val VIBRATION_ATTRIBUTES_PIPELINING = VibrationAttributes.Builder() .setUsage(VibrationAttributes.USAGE_TOUCH) Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +34 −7 Original line number Diff line number Diff line Loading @@ -71,10 +71,8 @@ public class NotificationRoundnessManager implements Dumpable { Roundable viewBefore, ExpandableView viewSwiped, Roundable viewAfter) { // This method requires you to change the roundness of the current View targets and reset // the roundness of the old View targets (if any) to 0f. // To avoid conflicts, it generates a set of old Views and removes the current Views // from this set. // This method caches a new set of current View targets and reset the roundness of the old // View targets (if any) to 0f. HashSet<Roundable> oldViews = new HashSet<>(); if (mViewBeforeSwipedView != null) oldViews.add(mViewBeforeSwipedView); if (mSwipedView != null) oldViews.add(mSwipedView); Loading @@ -83,19 +81,16 @@ public class NotificationRoundnessManager implements Dumpable { mViewBeforeSwipedView = viewBefore; if (viewBefore != null) { oldViews.remove(viewBefore); viewBefore.requestRoundness(/* top = */ 0f, /* bottom = */ 1f, DISMISS_ANIMATION); } mSwipedView = viewSwiped; if (viewSwiped != null) { oldViews.remove(viewSwiped); viewSwiped.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, DISMISS_ANIMATION); } mViewAfterSwipedView = viewAfter; if (viewAfter != null) { oldViews.remove(viewAfter); viewAfter.requestRoundness(/* top = */ 1f, /* bottom = */ 0f, DISMISS_ANIMATION); } // After setting the current Views, reset the views that are still present in the set. Loading @@ -104,6 +99,34 @@ public class NotificationRoundnessManager implements Dumpable { } } void setRoundnessForAffectedViews(float roundness) { if (mViewBeforeSwipedView != null) { mViewBeforeSwipedView.requestBottomRoundness(roundness, DISMISS_ANIMATION); } if (mSwipedView != null) { mSwipedView.requestRoundness(roundness, roundness, DISMISS_ANIMATION); } if (mViewAfterSwipedView != null) { mViewAfterSwipedView.requestTopRoundness(roundness, DISMISS_ANIMATION); } } void setRoundnessForAffectedViews(float roundness, boolean animate) { if (mViewBeforeSwipedView != null) { mViewBeforeSwipedView.requestBottomRoundness(roundness, DISMISS_ANIMATION, animate); } if (mSwipedView != null) { mSwipedView.requestRoundness(roundness, roundness, DISMISS_ANIMATION, animate); } if (mViewAfterSwipedView != null) { mViewAfterSwipedView.requestTopRoundness(roundness, DISMISS_ANIMATION, animate); } } void setClearAllInProgress(boolean isClearingAll) { mIsClearAllInProgress = isClearingAll; } Loading Loading @@ -138,4 +161,8 @@ public class NotificationRoundnessManager implements Dumpable { public void setShouldRoundPulsingViews(boolean shouldRoundPulsingViews) { mRoundForPulsingViews = shouldRoundPulsingViews; } public boolean isSwipedViewSet() { return mSwipedView != null; } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +6 −3 Original line number Diff line number Diff line Loading @@ -5840,7 +5840,8 @@ public class NotificationStackScrollLayout targets.getBefore(), targets.getSwiped(), targets.getAfter()); mController.getNotificationRoundnessManager() .setRoundnessForAffectedViews(/* roundness */ 1f); } updateFirstAndLastBackgroundViews(); Loading @@ -5851,8 +5852,10 @@ public class NotificationStackScrollLayout void onSwipeEnd() { updateFirstAndLastBackgroundViews(); if (!magneticNotificationSwipes()) { mController.getNotificationRoundnessManager() .setViewsAffectedBySwipe(null, null, null); } // Round bottom corners for notification right before shelf. mShelf.updateAppearance(); } Loading