From abdc3384bc81c66c3a4c22881092093738e765e9 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Sat, 10 Jun 2023 20:29:15 -0700 Subject: [PATCH] Fix 3-finger swipe unlock not working FalsingManager is currently rejecting trackpad 3-finger events. The x and y movements in 3-finger motion events are generated from the gesture library according to the movement on the trackpad. The movement scale is bigger than events on the screen, hence considered "fake" by the falsing manager. We should skip all trackpad events in gesture falsing logic (since falsing is an on screen thing to begin with). Fixes: 277273475 Test: 3-finger swipe to bring up bouncer Change-Id: I1223129ec40c0ed0e81e5f740564172665284585 --- .../classifier/BrightLineFalsingManager.java | 1 + .../classifier/FalsingDataProvider.java | 14 ++++- .../BrightLineFalsingManagerTest.java | 7 +++ .../systemui/classifier/ClassifierTest.java | 58 +++++++++++++++++++ .../classifier/FalsingDataProviderTest.java | 16 +++++ 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index b2bcb0554b0dd..25ccc1658744a 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -396,6 +396,7 @@ public class BrightLineFalsingManager implements FalsingManager { || mDataProvider.isDocked() || mAccessibilityManager.isTouchExplorationEnabled() || mDataProvider.isA11yAction() + || mDataProvider.isFromTrackpad() || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED) && mDataProvider.isUnfolded()); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index d6c85fbaf5a9d..809d5b289caba 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -261,6 +261,16 @@ public class FalsingDataProvider { return mLastMotionEvent.getY() < mFirstRecentMotionEvent.getY(); } + public boolean isFromTrackpad() { + if (mRecentMotionEvents.isEmpty()) { + return false; + } + + int classification = mRecentMotionEvents.get(0).getClassification(); + return classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE + || classification == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE; + } + private void recalculateData() { if (!mDirty) { return; @@ -343,7 +353,9 @@ public class FalsingDataProvider { motionEvent.getDeviceId(), motionEvent.getEdgeFlags(), motionEvent.getSource(), - motionEvent.getFlags() + motionEvent.getDisplayId(), + motionEvent.getFlags(), + motionEvent.getClassification() )); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java index 292fdff0027d0..f770a3885aad7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java @@ -187,4 +187,11 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { when(mFalsingDataProvider.isUnfolded()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse(); } + + @Test + public void testTrackpadGesture() { + assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue(); + when(mFalsingDataProvider.isFromTrackpad()).thenReturn(true); + assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java index 9254617655463..4da151c3ca04b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ClassifierTest.java @@ -18,8 +18,11 @@ package com.android.systemui.classifier; import android.hardware.devicestate.DeviceStateManager.FoldStateListener; import android.util.DisplayMetrics; +import android.view.InputDevice; import android.view.MotionEvent; +import androidx.test.uiautomator.Configurator; + import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManagerFake; import com.android.systemui.statusbar.policy.BatteryController; @@ -80,6 +83,10 @@ public class ClassifierTest extends SysuiTestCase { mDataProvider.onSessionEnd(); } + protected static int getPointerAction(int actionType, int index) { + return actionType + (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT); + } + protected MotionEvent appendDownEvent(float x, float y) { return appendMotionEvent(MotionEvent.ACTION_DOWN, x, y); } @@ -124,4 +131,55 @@ public class ClassifierTest extends SysuiTestCase { return motionEvent; } + + protected MotionEvent appendTrackpadDownEvent(float x, float y) { + return appendTrackpadMotionEvent(MotionEvent.ACTION_DOWN, x, y, 1); + } + + protected MotionEvent appendTrackpadMoveEvent(float x, float y, int pointerCount) { + return appendTrackpadMotionEvent(MotionEvent.ACTION_MOVE, x, y, pointerCount); + } + + protected MotionEvent appendTrackpadPointerDownEvent(int actionType, float x, float y, + int pointerCount) { + return appendTrackpadMotionEvent(actionType, x, y, pointerCount); + } + + private MotionEvent appendTrackpadMotionEvent(int actionType, float x, float y, + int pointerCount) { + long eventTime = mMotionEvents.isEmpty() ? 1 : mMotionEvents.get( + mMotionEvents.size() - 1).getEventTime() + 1; + return appendTrackpadMotionEvent(actionType, x, y, pointerCount, eventTime); + } + + private MotionEvent appendTrackpadMotionEvent(int actionType, float x, float y, + int pointerCount, long eventTime) { + MotionEvent.PointerProperties[] pointerProperties = + new MotionEvent.PointerProperties[pointerCount]; + MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount]; + for (int i = 0; i < pointerCount; i++) { + pointerProperties[i] = getPointerProperties(i); + pointerCoords[i] = getPointerCoords(x, y); + } + return MotionEvent.obtain(1, eventTime, actionType, pointerCount, pointerProperties, + pointerCoords, 0, 0, 1.0f, 1.0f, 0, 0, + InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE, 0, 0, + MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE); + } + + private static MotionEvent.PointerProperties getPointerProperties(int pointerId) { + MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties(); + properties.id = pointerId; + properties.toolType = Configurator.getInstance().getToolType(); + return properties; + } + + private static MotionEvent.PointerCoords getPointerCoords(float x, float y) { + MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords(); + coords.pressure = 1; + coords.size = 1; + coords.x = x; + coords.y = y; + return coords; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java index 7e066808b5bde..0353f87ae9b43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java @@ -281,6 +281,22 @@ public class FalsingDataProviderTest extends ClassifierTest { mDataProvider.onSessionEnd(); } + @Test + public void test_IsFromTrackpad() { + MotionEvent motionEventOrigin = appendTrackpadDownEvent(0, 0); + + mDataProvider.onMotionEvent(motionEventOrigin); + mDataProvider.onMotionEvent( + appendTrackpadPointerDownEvent(getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 1), + 0, 0, 2)); + mDataProvider.onMotionEvent( + appendTrackpadPointerDownEvent(getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 2), + 0, 0, 3)); + mDataProvider.onMotionEvent(appendTrackpadMoveEvent(1, -1, 3)); + assertThat(mDataProvider.isFromTrackpad()).isTrue(); + mDataProvider.onSessionEnd(); + } + @Test public void test_isWirelessCharging() { assertThat(mDataProvider.isDocked()).isFalse();