diff options
| author | 2024-09-06 20:04:31 +0000 | |
|---|---|---|
| committer | 2024-09-06 20:04:31 +0000 | |
| commit | ceb129e971821fc56da0d16c7bb60c2cef2e1662 (patch) | |
| tree | 50fbf34db02014bd3798e8efb8dc2523bafe147b | |
| parent | 11721d019dc711b5af082b228ac604edb49141e4 (diff) | |
| parent | e1c367ebf2c67863502c19265940856a623cbf24 (diff) | |
Merge "Skip falsing on non-touchscreen device sources" into main
| -rw-r--r-- | packages/SystemUI/aconfig/systemui.aconfig | 6 | ||||
| -rw-r--r-- | packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java | 8 | ||||
| -rw-r--r-- | packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java) | 90 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java | 3 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java | 22 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java | 24 | ||||
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java | 1 |
7 files changed, 149 insertions, 5 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index d1a59af1c471..892f778ff8c0 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1396,3 +1396,9 @@ flag { } } +flag { + name: "non_touchscreen_devices_bypass_falsing" + namespace: "systemui" + description: "Allow non-touchscreen devices to bypass falsing" + bug: "319809270" +}
\ No newline at end of file diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java index 53d82d7b2a07..956c12916c98 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java @@ -95,6 +95,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); when(mKeyguardStateController.isShowing()).thenReturn(true); when(mFalsingDataProvider.isUnfolded()).thenReturn(false); + when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(true); mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier, mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController, @@ -193,6 +194,13 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { } @Test + public void testSkipNonTouchscreenDevices() { + assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue(); + when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(false); + assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse(); + } + + @Test public void testTrackpadGesture() { assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue(); when(mFalsingDataProvider.isFromTrackpad()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java index 49c6239d2541..df4b0480f5c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java @@ -18,6 +18,7 @@ package com.android.systemui.classifier; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -25,13 +26,20 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.devicestate.DeviceStateManager.FoldStateListener; +import android.hardware.input.IInputManager; +import android.hardware.input.InputManagerGlobal; +import android.os.RemoteException; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.util.DisplayMetrics; +import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.systemui.Flags; import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener; import com.android.systemui.dock.DockManagerFake; import com.android.systemui.statusbar.policy.BatteryController; @@ -56,11 +64,15 @@ public class FalsingDataProviderTest extends ClassifierTest { private FoldStateListener mFoldStateListener; private final DockManagerFake mDockManager = new DockManagerFake(); private DisplayMetrics mDisplayMetrics; + private IInputManager mIInputManager; + private InputManagerGlobal.TestSession inputManagerGlobalTestSession; @Before public void setup() { super.setup(); MockitoAnnotations.initMocks(this); + mIInputManager = mock(IInputManager.Stub.class); + inputManagerGlobalTestSession = InputManagerGlobal.createTestSession(mIInputManager); mDisplayMetrics = new DisplayMetrics(); mDisplayMetrics.xdpi = 100; mDisplayMetrics.ydpi = 100; @@ -73,6 +85,7 @@ public class FalsingDataProviderTest extends ClassifierTest { public void tearDown() { super.tearDown(); mDataProvider.onSessionEnd(); + inputManagerGlobalTestSession.close(); } @Test @@ -378,6 +391,79 @@ public class FalsingDataProviderTest extends ClassifierTest { } @Test + @DisableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) + public void test_isTouchscreenSource_flagOff_alwaysTrue() { + assertThat(mDataProvider.isTouchScreenSource()).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) + public void test_isTouchscreenSource_recentEventsEmpty_true() { + //send no events into the data provider + assertThat(mDataProvider.isTouchScreenSource()).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) + public void test_isTouchscreenSource_latestDeviceTouchscreen_true() throws RemoteException { + int deviceId = 999; + + InputDevice device = new InputDevice.Builder() + .setSources(InputDevice.SOURCE_CLASS_TRACKBALL | InputDevice.SOURCE_TOUCHSCREEN) + .setId(deviceId) + .build(); + when(mIInputManager.getInputDeviceIds()).thenReturn(new int[]{deviceId}); + when(mIInputManager.getInputDevice(anyInt())).thenReturn(device); + + MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1, + MotionEvent.PointerProperties.createArray(1), + MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, deviceId, 0, + InputDevice.SOURCE_CLASS_NONE, 0, 0, 0); + + mDataProvider.onMotionEvent(event); + boolean result = mDataProvider.isTouchScreenSource(); + assertThat(result).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) + public void test_isTouchscreenSource_latestDeviceNonTouchscreen_false() throws RemoteException { + int deviceId = 9999; + + InputDevice device = new InputDevice.Builder() + .setSources(InputDevice.SOURCE_CLASS_TRACKBALL) + .setId(deviceId) + .build(); + when(mIInputManager.getInputDeviceIds()).thenReturn(new int[]{deviceId}); + when(mIInputManager.getInputDevice(anyInt())).thenReturn(device); + + MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1, + MotionEvent.PointerProperties.createArray(1), + MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, deviceId, 0, + InputDevice.SOURCE_CLASS_NONE, 0, 0, 0); + + mDataProvider.onMotionEvent(event); + boolean result = mDataProvider.isTouchScreenSource(); + assertThat(result).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING) + public void test_isTouchscreenSource_latestDeviceNull_true() { + // Do not mock InputManager for this test + inputManagerGlobalTestSession.close(); + + int nonExistentDeviceId = 9997; + MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1, + MotionEvent.PointerProperties.createArray(1), + MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, nonExistentDeviceId, 0, + InputDevice.SOURCE_CLASS_NONE, 0, 0, 0); + + mDataProvider.onMotionEvent(event); + assertThat(mDataProvider.isTouchScreenSource()).isTrue(); + } + + @Test public void test_UnfoldedState_Folded() { FalsingDataProvider falsingDataProvider = createWithFoldCapability(true); when(mFoldStateListener.getFolded()).thenReturn(true); @@ -413,7 +499,7 @@ public class FalsingDataProviderTest extends ClassifierTest { } private FalsingDataProvider createWithFoldCapability(boolean foldable) { - return new FalsingDataProvider( - mDisplayMetrics, mBatteryController, mFoldStateListener, mDockManager, foldable); + return new FalsingDataProvider(mDisplayMetrics, mBatteryController, mFoldStateListener, + mDockManager, foldable); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index e1ba93c75aad..83d4091802d7 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -34,8 +34,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.systemui.classifier.FalsingDataProvider.SessionListener; import com.android.systemui.classifier.HistoryTracker.BeliefListener; import com.android.systemui.dagger.qualifiers.TestHarness; -import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -396,6 +394,7 @@ public class BrightLineFalsingManager implements FalsingManager { || mDataProvider.isA11yAction() || mDataProvider.isFromTrackpad() || mDataProvider.isFromKeyboard() + || !mDataProvider.isTouchScreenSource() || mDataProvider.isUnfolded(); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 2eca02c2b0d1..962ab998ddb1 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -21,6 +21,7 @@ import static com.android.systemui.dock.DockManager.DockEventListener; import android.hardware.SensorManager; import android.hardware.biometrics.BiometricSourceType; import android.util.Log; +import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; @@ -28,6 +29,7 @@ import androidx.annotation.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.Flags; import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -343,7 +345,9 @@ class FalsingCollectorImpl implements FalsingCollector { // will be ignored by the collector until another MotionEvent.ACTION_DOWN is passed in. // avoidGesture must be called immediately following the MotionEvent.ACTION_DOWN, before // any other events are processed, otherwise the whole gesture will be recorded. - if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { + // + // We should only delay processing of these events for touchscreen sources + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN && isTouchscreenSource(ev)) { // Make a copy of ev, since it will be recycled after we exit this method. mPendingDownEvent = MotionEvent.obtain(ev); mAvoidGesture = false; @@ -410,6 +414,22 @@ class FalsingCollectorImpl implements FalsingCollector { mFalsingDataProvider.onA11yAction(); } + /** + * returns {@code true} if the device supports Touchscreen, {@code false} otherwise. Defaults to + * {@code true} if the device is {@code null} + */ + private boolean isTouchscreenSource(MotionEvent ev) { + if (!Flags.nonTouchscreenDevicesBypassFalsing()) { + return true; + } + InputDevice device = ev.getDevice(); + if (device != null) { + return device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN); + } else { + return true; + } + } + private boolean shouldSessionBeActive() { return mScreenOn && (mState == StatusBarState.KEYGUARD) diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index 15017011134b..769976ef5058 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -20,11 +20,13 @@ import static com.android.systemui.classifier.FalsingModule.IS_FOLDABLE_DEVICE; import android.hardware.devicestate.DeviceStateManager.FoldStateListener; import android.util.DisplayMetrics; +import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; +import com.android.systemui.Flags; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.policy.BatteryController; @@ -281,6 +283,9 @@ public class FalsingDataProvider { } public boolean isFromTrackpad() { + if (Flags.nonTouchscreenDevicesBypassFalsing()) { + return false; + } if (mRecentMotionEvents.isEmpty()) { return false; } @@ -290,6 +295,25 @@ public class FalsingDataProvider { || classification == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE; } + /** + * returns {@code true} if the device supports Touchscreen, {@code false} otherwise. Defaults to + * {@code true} if the device is {@code null} + */ + public boolean isTouchScreenSource() { + if (!Flags.nonTouchscreenDevicesBypassFalsing()) { + return true; + } + if (mRecentMotionEvents.isEmpty()) { + return true; + } + InputDevice device = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1).getDevice(); + if (device != null) { + return device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN); + } else { + return true; + } + } + private void recalculateData() { if (!mDirty) { return; diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java index a1bea0620528..637771790b28 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java @@ -104,6 +104,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); when(mKeyguardStateController.isShowing()).thenReturn(true); when(mFalsingDataProvider.isUnfolded()).thenReturn(false); + when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(true); mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier, mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController, |