diff options
8 files changed, 121 insertions, 18 deletions
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 37549c927a90..9188ce091a3b 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -337,9 +337,6 @@ have been scrolled off-screen. --> <bool name="config_showNotificationShelf">true</bool> - <!-- Whether or not the notifications should always fade as they are dismissed. --> - <bool name="config_fadeNotificationsOnDismiss">false</bool> - <!-- Whether or not the fade on the notification is based on the amount that it has been swiped off-screen. --> <bool name="config_fadeDependingOnAmountSwiped">false</bool> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index fe6dbe5de8f0..873a695ecd93 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -38,6 +38,8 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; +import androidx.annotation.VisibleForTesting; + import com.android.systemui.animation.Interpolators; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; @@ -66,7 +68,7 @@ public class SwipeHelper implements Gefingerpoken { private static final int MAX_DISMISS_VELOCITY = 4000; // dp/sec private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 150; // ms - static final float SWIPE_PROGRESS_FADE_END = 0.5f; // fraction of thumbnail width + public static final float SWIPE_PROGRESS_FADE_END = 0.6f; // fraction of thumbnail width // beyond which swipe progress->0 public static final float SWIPED_FAR_ENOUGH_SIZE_FRACTION = 0.6f; static final float MAX_SCROLL_SIZE_FRACTION = 0.3f; @@ -235,7 +237,11 @@ public class SwipeHelper implements Gefingerpoken { return Math.min(Math.max(mMinSwipeProgress, result), mMaxSwipeProgress); } - private float getSwipeAlpha(float progress) { + /** + * Returns the alpha value depending on the progress of the swipe. + */ + @VisibleForTesting + public float getSwipeAlpha(float progress) { if (mFadeDependingOnAmountSwiped) { // The more progress has been fade, the lower the alpha value so that the view fades. return Math.max(1 - progress, 0); @@ -260,7 +266,7 @@ public class SwipeHelper implements Gefingerpoken { animView.setLayerType(View.LAYER_TYPE_NONE, null); } } - animView.setAlpha(getSwipeAlpha(swipeProgress)); + updateSwipeProgressAlpha(animView, getSwipeAlpha(swipeProgress)); } } invalidateGlobalRegion(animView); @@ -561,6 +567,14 @@ public class SwipeHelper implements Gefingerpoken { mCallback.onChildSnappedBack(animView, targetLeft); } + + /** + * Called to update the content alpha while the view is swiped + */ + protected void updateSwipeProgressAlpha(View animView, float alpha) { + animView.setAlpha(alpha); + } + /** * Give the swipe helper itself a chance to do something on snap back so NSSL doesn't have * to tell us what to do diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 978aaa081d45..c3bde34c1bef 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -71,7 +71,9 @@ public class Flags { public static final UnreleasedFlag NOTIFICATION_MEMORY_MONITOR_ENABLED = new UnreleasedFlag(112, false); - // next id: 112 + public static final UnreleasedFlag NOTIFICATION_DISMISSAL_FADE = new UnreleasedFlag(113, true); + + // next id: 114 /***************************************/ // 200 - keyguard/lockscreen diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 6138265c641d..07ed0135bf6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -1477,6 +1477,20 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } } + /** + * Sets the alpha on the content, while leaving the background of the row itself as is. + * + * @param alpha alpha value to apply to the notification content + */ + public void setContentAlpha(float alpha) { + for (NotificationContentView l : mLayouts) { + l.setAlpha(alpha); + } + if (mChildrenContainer != null) { + mChildrenContainer.setAlpha(alpha); + } + } + public void setIsLowPriority(boolean isLowPriority) { mIsLowPriority = isLowPriority; mPrivateLayout.setIsLowPriority(isLowPriority); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 843a9ff2acb5..5c09d618403d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -56,12 +56,13 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.ExpandHelper; import com.android.systemui.Gefingerpoken; -import com.android.systemui.R; import com.android.systemui.SwipeHelper; import com.android.systemui.classifier.Classifier; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; @@ -178,6 +179,7 @@ public class NotificationStackScrollLayoutController { @Nullable private Boolean mHistoryEnabled; private int mBarState; private HeadsUpAppearanceController mHeadsUpAppearanceController; + private final FeatureFlags mFeatureFlags; private View mLongPressedView; @@ -639,7 +641,8 @@ public class NotificationStackScrollLayoutController { InteractionJankMonitor jankMonitor, StackStateLogger stackLogger, NotificationStackScrollLogger logger, - NotificationStackSizeCalculator notificationStackSizeCalculator) { + NotificationStackSizeCalculator notificationStackSizeCalculator, + FeatureFlags featureFlags) { mStackStateLogger = stackLogger; mLogger = logger; mAllowLongPress = allowLongPress; @@ -675,6 +678,7 @@ public class NotificationStackScrollLayoutController { mUiEventLogger = uiEventLogger; mRemoteInputManager = remoteInputManager; mShadeController = shadeController; + mFeatureFlags = featureFlags; updateResources(); } @@ -739,9 +743,7 @@ public class NotificationStackScrollLayoutController { mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener); - mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly - mResources.getBoolean(R.bool.config_fadeNotificationsOnDismiss); - + mFadeNotificationsOnDismiss = mFeatureFlags.isEnabled(Flags.NOTIFICATION_DISMISSAL_FADE); mNotificationRoundnessManager.setOnRoundingChangedCallback(mView::invalidate); mView.addOnExpandedHeightChangedListener(mNotificationRoundnessManager::setExpanded); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java index 2d2fbe588728..ee57411cb495 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java @@ -185,6 +185,13 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc return false; } + @Override + protected void updateSwipeProgressAlpha(View animView, float alpha) { + if (animView instanceof ExpandableNotificationRow) { + ((ExpandableNotificationRow) animView).setContentAlpha(alpha); + } + } + @VisibleForTesting protected void handleMenuRowSwipe(MotionEvent ev, View animView, float velocity, NotificationMenuRowPlugin menuRow) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java index 8be9eb57aa9b..1c9b0be0185a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java @@ -45,6 +45,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener; @@ -127,6 +128,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { @Mock private NotificationStackScrollLogger mLogger; @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; @Mock private ShadeTransitionController mShadeTransitionController; + @Mock private FeatureFlags mFeatureFlags; @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor; @@ -174,7 +176,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { mJankMonitor, mStackLogger, mLogger, - mNotificationStackSizeCalculator + mNotificationStackSizeCalculator, + mFeatureFlags ); when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java index 1305d79e4648..4ea1c7100557 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java @@ -18,10 +18,13 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -51,10 +54,15 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + /** * Tests for {@link NotificationSwipeHelper}. */ @@ -74,7 +82,11 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { private Runnable mFalsingCheck; private FeatureFlags mFeatureFlags; - @Rule public MockitoRule mockito = MockitoJUnit.rule(); + private static final int FAKE_ROW_WIDTH = 20; + private static final int FAKE_ROW_HEIGHT = 20; + + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); @Before public void setUp() throws Exception { @@ -444,8 +456,8 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { doReturn(5f).when(mEvent).getRawX(); doReturn(10f).when(mEvent).getRawY(); - doReturn(20).when(mView).getWidth(); - doReturn(20).when(mView).getHeight(); + doReturn(FAKE_ROW_WIDTH).when(mView).getWidth(); + doReturn(FAKE_ROW_HEIGHT).when(mView).getHeight(); Answer answer = (Answer) invocation -> { int[] arr = invocation.getArgument(0); @@ -472,8 +484,8 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { doReturn(5f).when(mEvent).getRawX(); doReturn(10f).when(mEvent).getRawY(); - doReturn(20).when(mNotificationRow).getWidth(); - doReturn(20).when(mNotificationRow).getActualHeight(); + doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getWidth(); + doReturn(FAKE_ROW_HEIGHT).when(mNotificationRow).getActualHeight(); Answer answer = (Answer) invocation -> { int[] arr = invocation.getArgument(0); @@ -491,4 +503,56 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { assertFalse("Touch is not within the view", mSwipeHelper.isTouchInView(mEvent, mNotificationRow)); } + + @Test + public void testContentAlphaRemainsUnchangedWhenNotificationIsNotDismissible() { + doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); + + mSwipeHelper.onTranslationUpdate(mNotificationRow, 12, false); + + verify(mNotificationRow, never()).setContentAlpha(anyFloat()); + } + + @Test + public void testContentAlphaRemainsUnchangedWhenFeatureFlagIsDisabled() { + + // Returning true prevents alpha fade. In an unmocked scenario the callback is instantiated + // within NotificationStackScrollLayoutController and returns the inverted value of the + // feature flag + doReturn(true).when(mCallback).updateSwipeProgress(any(), anyBoolean(), anyFloat()); + doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); + + mSwipeHelper.onTranslationUpdate(mNotificationRow, 12, true); + + verify(mNotificationRow, never()).setContentAlpha(anyFloat()); + } + + @Test + public void testContentAlphaFadeAnimationSpecs() { + // The alpha fade should be linear from 1f to 0f as translation progresses from 0 to 60% of + // view-width, and 0f at translations higher than that. + doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); + + List<Integer> translations = Arrays.asList( + -FAKE_ROW_WIDTH * 2, + -FAKE_ROW_WIDTH, + (int) (-FAKE_ROW_WIDTH * 0.3), + 0, + (int) (FAKE_ROW_WIDTH * 0.3), + (int) (FAKE_ROW_WIDTH * 0.6), + FAKE_ROW_WIDTH, + FAKE_ROW_WIDTH * 2); + List<Float> expectedAlphas = translations.stream().map(translation -> + mSwipeHelper.getSwipeAlpha(Math.abs((float) translation / FAKE_ROW_WIDTH))) + .collect(Collectors.toList()); + + for (Integer translation : translations) { + mSwipeHelper.onTranslationUpdate(mNotificationRow, translation, true); + } + + ArgumentCaptor<Float> capturedValues = ArgumentCaptor.forClass(Float.class); + verify(mNotificationRow, times(translations.size())).setContentAlpha( + capturedValues.capture()); + assertEquals(expectedAlphas, capturedValues.getAllValues()); + } } |