diff options
| author | 2024-10-17 16:49:43 +0000 | |
|---|---|---|
| committer | 2024-10-17 19:38:20 +0000 | |
| commit | bff27edb33096142a76fed89dbf0cc4f91df969c (patch) | |
| tree | 92853e5fa2a72a104e70c91b9fff2458675d95cd | |
| parent | 3b56cb92823921178a7b8544e82c60f5ba6fb77b (diff) | |
Do not handle touches next to shelf Take #2
NSSL would return true for all touches below the last notification,
and to the right of the shelf. This is essentially empty space.
The reason for this is the SwipeHelper is always returning true,
since it is looking at the full width of the NotificationShelf. By
using getActualWidth() instead, the touches are more accurately
handled.
This fixes an issue where the shelf is vertically overlapping
the unlock icon, and taking touches from it.
Fixes: 358424256
Test: atest NotificationSwipeHelperTest
Test: manual - horizontal swipe notifications
Test: manual - vertically swipe notifications
Test: manual - all touch interactions with notifs
Test: manual - tap on shelf to expand shade
Test: manual - face auth without bypass, add notifications next
to unlock icon, use unlock
Flag: com.android.systemui.ignore_touches_next_to_notification_shelf
Change-Id: Idf22d6e72e7d618ed98e869142b5cc5dc785985e
4 files changed, 86 insertions, 1 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 651244a9e52a..b854964eb252 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1489,6 +1489,16 @@ flag { } flag { + name: "ignore_touches_next_to_notification_shelf" + namespace: "systemui" + description: "The shelf can vertically overlap the unlock icon. Ignore touches if so." + bug: "358424256" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "media_projection_request_attribution_fix" namespace: "systemui" description: "Ensure MediaProjection consent requests are properly attributed" diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java index 95db95cd288b..789701f5e4b0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java @@ -13,6 +13,8 @@ package com.android.systemui.statusbar.notification.stack; +import static com.android.systemui.Flags.FLAG_IGNORE_TOUCHES_NEXT_TO_NOTIFICATION_SHELF; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -36,6 +38,7 @@ import static org.mockito.Mockito.when; import android.animation.Animator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.os.Handler; +import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.service.notification.StatusBarNotification; import android.testing.TestableLooper; @@ -52,6 +55,7 @@ import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption; +import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization; @@ -85,6 +89,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { private NotificationMenuRowPlugin mMenuRow; private Handler mHandler; private ExpandableNotificationRow mNotificationRow; + private NotificationShelf mShelf; private Runnable mFalsingCheck; private final FeatureFlags mFeatureFlags = new FakeFeatureFlags(); @@ -111,6 +116,7 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { mEvent = mock(MotionEvent.class); mMenuRow = mock(NotificationMenuRowPlugin.class); mNotificationRow = mock(ExpandableNotificationRow.class); + mShelf = mock(NotificationShelf.class); mHandler = mock(Handler.class); mFalsingCheck = mock(Runnable.class); } @@ -665,6 +671,54 @@ public class NotificationSwipeHelperTest extends SysuiTestCase { } @Test + @EnableFlags(FLAG_IGNORE_TOUCHES_NEXT_TO_NOTIFICATION_SHELF) + public void testIsTouchInView_notificationShelf_flagEnabled() { + doReturn(500).when(mShelf).getWidth(); + doReturn(FAKE_ROW_WIDTH).when(mShelf).getActualWidth(); + doReturn(FAKE_ROW_HEIGHT).when(mShelf).getHeight(); + doReturn(FAKE_ROW_HEIGHT).when(mShelf).getActualHeight(); + + Answer answer = (Answer) invocation -> { + int[] arr = invocation.getArgument(0); + arr[0] = 0; + arr[1] = 0; + return null; + }; + + doReturn(5f).when(mEvent).getRawX(); + doReturn(10f).when(mEvent).getRawY(); + doAnswer(answer).when(mShelf).getLocationOnScreen(any()); + assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mShelf)); + + doReturn(50f).when(mEvent).getRawX(); + assertFalse("Touch is not within the view", mSwipeHelper.isTouchInView(mEvent, mShelf)); + } + + @Test + @DisableFlags(FLAG_IGNORE_TOUCHES_NEXT_TO_NOTIFICATION_SHELF) + public void testIsTouchInView_notificationShelf_flagDisabled() { + doReturn(500).when(mShelf).getWidth(); + doReturn(FAKE_ROW_WIDTH).when(mShelf).getActualWidth(); + doReturn(FAKE_ROW_HEIGHT).when(mShelf).getHeight(); + doReturn(FAKE_ROW_HEIGHT).when(mShelf).getActualHeight(); + + Answer answer = (Answer) invocation -> { + int[] arr = invocation.getArgument(0); + arr[0] = 0; + arr[1] = 0; + return null; + }; + + doReturn(5f).when(mEvent).getRawX(); + doReturn(10f).when(mEvent).getRawY(); + doAnswer(answer).when(mShelf).getLocationOnScreen(any()); + assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mShelf)); + + doReturn(50f).when(mEvent).getRawX(); + assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mShelf)); + } + + @Test public void testContentAlphaRemainsUnchangedWhenNotificationIsNotDismissible() { doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth(); 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 379a67ed3942..04974b4353f4 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 @@ -24,6 +24,7 @@ import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_ import static com.android.server.notification.Flags.screenshareNotificationHiding; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import static com.android.systemui.Flags.confineNotificationTouchToViewWidth; +import static com.android.systemui.Flags.ignoreTouchesNextToNotificationShelf; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener; @@ -607,6 +608,16 @@ public class NotificationStackScrollLayoutController implements Dumpable { true /* requireMinHeight */, false /* ignoreDecors */, !confineNotificationTouchToViewWidth() /* ignoreWidth */); + + // Verify the MotionEvent x,y are actually inside the touch area of the shelf, + // since the shelf may be animated down to a collapsed size on keyguard. + if (ignoreTouchesNextToNotificationShelf()) { + if (child instanceof NotificationShelf shelf) { + if (!NotificationSwipeHelper.isTouchInView(ev, shelf)) { + return null; + } + } + } if (child instanceof ExpandableNotificationRow row) { ExpandableNotificationRow parent = row.getNotificationParent(); if (parent != null && parent.areChildrenExpanded() 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 7e327e66982c..0e94ca351835 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 @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_SWIPE; +import static com.android.systemui.Flags.ignoreTouchesNextToNotificationShelf; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -39,6 +40,7 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; +import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.notification.SourceType; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; @@ -503,13 +505,21 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc final int height = (view instanceof ExpandableView) ? ((ExpandableView) view).getActualHeight() : view.getHeight(); + final int width; + if (ignoreTouchesNextToNotificationShelf()) { + width = (view instanceof NotificationShelf) + ? ((NotificationShelf) view).getActualWidth() + : view.getWidth(); + } else { + width = view.getWidth(); + } final int rx = (int) ev.getRawX(); final int ry = (int) ev.getRawY(); int[] temp = new int[2]; view.getLocationOnScreen(temp); final int x = temp[0]; final int y = temp[1]; - Rect rect = new Rect(x, y, x + view.getWidth(), y + height); + Rect rect = new Rect(x, y, x + width, y + height); boolean ret = rect.contains(rx, ry); return ret; } |