diff options
11 files changed, 273 insertions, 55 deletions
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index c50340cfd247..e52a57f761c7 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -82,6 +82,18 @@ public interface FalsingManager { boolean isFalseTap(@Penalty int penalty); /** + * Returns true if the FalsingManager thinks the last gesture was not a valid long tap. + * + * Use this method to validate a long tap for launching an action, like long press on a UMO + * + * The only parameter, penalty, indicates how much this should affect future gesture + * classifications if this long tap looks like a false. + * As long taps are hard to confirm as false or otherwise, + * a low penalty value is encouraged unless context indicates otherwise. + */ + boolean isFalseLongTap(@Penalty int penalty); + + /** * Returns true if the last two gestures do not look like a double tap. * * Only works on data that has already been reported to the FalsingManager. Be sure that diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index 2245d8462c31..beaccbaf9a70 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -34,6 +34,8 @@ 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; @@ -65,6 +67,7 @@ public class BrightLineFalsingManager implements FalsingManager { private static final double FALSE_BELIEF_THRESHOLD = 0.9; private final FalsingDataProvider mDataProvider; + private final LongTapClassifier mLongTapClassifier; private final SingleTapClassifier mSingleTapClassifier; private final DoubleTapClassifier mDoubleTapClassifier; private final HistoryTracker mHistoryTracker; @@ -73,6 +76,7 @@ public class BrightLineFalsingManager implements FalsingManager { private final boolean mTestHarness; private final MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; + private FeatureFlags mFeatureFlags; private static final Queue<String> RECENT_INFO_LOG = new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1); private static final Queue<DebugSwipeRecord> RECENT_SWIPES = @@ -175,19 +179,23 @@ public class BrightLineFalsingManager implements FalsingManager { public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider, MetricsLogger metricsLogger, @Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers, - SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier, - HistoryTracker historyTracker, KeyguardStateController keyguardStateController, + SingleTapClassifier singleTapClassifier, LongTapClassifier longTapClassifier, + DoubleTapClassifier doubleTapClassifier, HistoryTracker historyTracker, + KeyguardStateController keyguardStateController, AccessibilityManager accessibilityManager, - @TestHarness boolean testHarness) { + @TestHarness boolean testHarness, + FeatureFlags featureFlags) { mDataProvider = falsingDataProvider; mMetricsLogger = metricsLogger; mClassifiers = classifiers; mSingleTapClassifier = singleTapClassifier; + mLongTapClassifier = longTapClassifier; mDoubleTapClassifier = doubleTapClassifier; mHistoryTracker = historyTracker; mKeyguardStateController = keyguardStateController; mAccessibilityManager = accessibilityManager; mTestHarness = testHarness; + mFeatureFlags = featureFlags; mDataProvider.addSessionListener(mSessionListener); mDataProvider.addGestureCompleteListener(mGestureFinalizedListener); @@ -313,6 +321,58 @@ public class BrightLineFalsingManager implements FalsingManager { } @Override + public boolean isFalseLongTap(@Penalty int penalty) { + if (!mFeatureFlags.isEnabled(Flags.FALSING_FOR_LONG_TAPS)) { + return false; + } + + checkDestroyed(); + + if (skipFalsing(GENERIC)) { + mPriorResults = getPassedResult(1); + logDebug("Skipped falsing"); + return false; + } + + double falsePenalty = 0; + switch(penalty) { + case NO_PENALTY: + falsePenalty = 0; + break; + case LOW_PENALTY: + falsePenalty = 0.1; + break; + case MODERATE_PENALTY: + falsePenalty = 0.3; + break; + case HIGH_PENALTY: + falsePenalty = 0.6; + break; + } + + FalsingClassifier.Result longTapResult = + mLongTapClassifier.isTap(mDataProvider.getRecentMotionEvents().isEmpty() + ? mDataProvider.getPriorMotionEvents() + : mDataProvider.getRecentMotionEvents(), falsePenalty); + mPriorResults = Collections.singleton(longTapResult); + + if (!longTapResult.isFalse()) { + if (mDataProvider.isJustUnlockedWithFace()) { + // Immediately pass if a face is detected. + mPriorResults = getPassedResult(1); + logDebug("False Long Tap: false (face detected)"); + } else { + mPriorResults = getPassedResult(0.1); + logDebug("False Long Tap: false (default)"); + } + return false; + } else { + logDebug("False Long Tap: " + longTapResult.isFalse() + " (simple)"); + return longTapResult.isFalse(); + } + } + + @Override public boolean isFalseDoubleTap() { checkDestroyed(); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 5d04b5f77479..c4723e895ee7 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -139,6 +139,11 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { } @Override + public boolean isFalseLongTap(int penalty) { + return mInternalFalsingManager.isFalseLongTap(penalty); + } + + @Override public boolean isFalseDoubleTap() { return mInternalFalsingManager.isFalseDoubleTap(); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java index 7b7f17e1568b..5302af9db836 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java @@ -40,6 +40,7 @@ import dagger.multibindings.ElementsIntoSet; public interface FalsingModule { String BRIGHT_LINE_GESTURE_CLASSIFERS = "bright_line_gesture_classifiers"; String SINGLE_TAP_TOUCH_SLOP = "falsing_single_tap_touch_slop"; + String LONG_TAP_TOUCH_SLOP = "falsing_long_tap_slop"; String DOUBLE_TAP_TOUCH_SLOP = "falsing_double_tap_touch_slop"; String DOUBLE_TAP_TIMEOUT_MS = "falsing_double_tap_timeout_ms"; @@ -81,4 +82,11 @@ public interface FalsingModule { static float providesSingleTapTouchSlop(ViewConfiguration viewConfiguration) { return viewConfiguration.getScaledTouchSlop(); } + + /** */ + @Provides + @Named(LONG_TAP_TOUCH_SLOP) + static float providesLongTapTouchSlop(ViewConfiguration viewConfiguration) { + return viewConfiguration.getScaledTouchSlop() * 1.25f; + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LongTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/LongTapClassifier.java new file mode 100644 index 000000000000..1963e69c1547 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/classifier/LongTapClassifier.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.classifier; + +import static com.android.systemui.classifier.FalsingModule.LONG_TAP_TOUCH_SLOP; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Falsing classifier that accepts or rejects a gesture as a long tap. + */ +public class LongTapClassifier extends TapClassifier{ + + @Inject + LongTapClassifier(FalsingDataProvider dataProvider, + @Named(LONG_TAP_TOUCH_SLOP) float touchSlop) { + super(dataProvider, touchSlop); + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java index bd6fbfbd282e..7a7401dfdd22 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java @@ -18,57 +18,17 @@ package com.android.systemui.classifier; import static com.android.systemui.classifier.FalsingModule.SINGLE_TAP_TOUCH_SLOP; -import android.view.MotionEvent; - -import java.util.List; - import javax.inject.Inject; import javax.inject.Named; /** - * Falsing classifier that accepts or rejects a single gesture as a tap. + * Falsing classifier that accepts or rejects a gesture as a single tap. */ -public class SingleTapClassifier extends FalsingClassifier { - private final float mTouchSlop; +public class SingleTapClassifier extends TapClassifier { @Inject SingleTapClassifier(FalsingDataProvider dataProvider, @Named(SINGLE_TAP_TOUCH_SLOP) float touchSlop) { - super(dataProvider); - mTouchSlop = touchSlop; - } - - @Override - Result calculateFalsingResult( - @Classifier.InteractionType int interactionType, - double historyBelief, double historyConfidence) { - return isTap(getRecentMotionEvents(), 0.5); - } - - /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */ - public Result isTap(List<MotionEvent> motionEvents, double falsePenalty) { - if (motionEvents.isEmpty()) { - return falsed(0, "no motion events"); - } - float downX = motionEvents.get(0).getX(); - float downY = motionEvents.get(0).getY(); - - for (MotionEvent event : motionEvents) { - String reason; - if (Math.abs(event.getX() - downX) >= mTouchSlop) { - reason = "dX too big for a tap: " - + Math.abs(event.getX() - downX) - + "vs " - + mTouchSlop; - return falsed(falsePenalty, reason); - } else if (Math.abs(event.getY() - downY) >= mTouchSlop) { - reason = "dY too big for a tap: " - + Math.abs(event.getY() - downY) - + " vs " - + mTouchSlop; - return falsed(falsePenalty, reason); - } - } - return Result.passed(0); + super(dataProvider, touchSlop); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TapClassifier.java new file mode 100644 index 000000000000..e24cfaa0ff8f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/classifier/TapClassifier.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.classifier; + +import android.view.MotionEvent; + +import java.util.List; + +/** + * Falsing classifier that accepts or rejects a gesture as a tap. + */ +public abstract class TapClassifier extends FalsingClassifier{ + private final float mTouchSlop; + + TapClassifier(FalsingDataProvider dataProvider, + float touchSlop) { + super(dataProvider); + mTouchSlop = touchSlop; + } + + @Override + Result calculateFalsingResult( + @Classifier.InteractionType int interactionType, + double historyBelief, double historyConfidence) { + return isTap(getRecentMotionEvents(), 0.5); + } + + /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */ + public Result isTap(List<MotionEvent> motionEvents, double falsePenalty) { + if (motionEvents.isEmpty()) { + return falsed(0, "no motion events"); + } + float downX = motionEvents.get(0).getX(); + float downY = motionEvents.get(0).getY(); + + for (MotionEvent event : motionEvents) { + String reason; + if (Math.abs(event.getX() - downX) >= mTouchSlop) { + reason = "dX too big for a tap: " + + Math.abs(event.getX() - downX) + + "vs " + + mTouchSlop; + return falsed(falsePenalty, reason); + } else if (Math.abs(event.getY() - downY) >= mTouchSlop) { + reason = "dY too big for a tap: " + + Math.abs(event.getY() - downY) + + " vs " + + mTouchSlop; + return falsed(falsePenalty, reason); + } + } + return Result.passed(0); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index f51e28196627..42f2dab1e065 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -349,6 +349,9 @@ object Flags { // 2000 - device controls @Keep val USE_APP_PANELS = UnreleasedFlag(2000, true) + // 2100 - Falsing Manager + @JvmField val FALSING_FOR_LONG_TAPS = ReleasedFlag(2100) + // Pay no attention to the reflection behind the curtain. // ========================== Curtain ========================== // | | 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 6bc7308a6a40..f8579fff488b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java @@ -39,6 +39,8 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -66,6 +68,8 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Mock private SingleTapClassifier mSingleTapClassfier; @Mock + private LongTapClassifier mLongTapClassifier; + @Mock private DoubleTapClassifier mDoubleTapClassifier; @Mock private FalsingClassifier mClassifierA; @@ -80,6 +84,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { private AccessibilityManager mAccessibilityManager; private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); + private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags(); private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), ""); @@ -94,6 +99,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { when(mClassifierB.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mPassedResult); when(mSingleTapClassfier.isTap(any(List.class), anyDouble())).thenReturn(mPassedResult); + when(mLongTapClassifier.isTap(any(List.class), anyDouble())).thenReturn(mFalsedResult); when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mPassedResult); mClassifiers.add(mClassifierA); @@ -101,9 +107,9 @@ public class BrightLineClassifierTest extends SysuiTestCase { when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); when(mKeyguardStateController.isShowing()).thenReturn(true); mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, - mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, - mHistoryTracker, mKeyguardStateController, mAccessibilityManager, - false); + mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier, + mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController, + mAccessibilityManager, false, mFakeFeatureFlags); ArgumentCaptor<GestureFinalizedListener> gestureCompleteListenerCaptor = @@ -113,6 +119,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { gestureCompleteListenerCaptor.capture()); mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue(); + mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true); } @Test @@ -212,7 +219,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { } @Test - public void testIsFalseTap_EmptyRecentEvents() { + public void testIsFalseSingleTap_EmptyRecentEvents() { // Ensure we look at prior events if recent events has already been emptied. when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(new ArrayList<>()); when(mFalsingDataProvider.getPriorMotionEvents()).thenReturn(mMotionEventList); @@ -223,7 +230,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test - public void testIsFalseTap_RobustCheck_NoFaceAuth() { + public void testIsFalseSingleTap_RobustCheck_NoFaceAuth() { when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult); when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mFalsedResult); @@ -233,13 +240,50 @@ public class BrightLineClassifierTest extends SysuiTestCase { } @Test - public void testIsFalseTap_RobustCheck_FaceAuth() { + public void testIsFalseSingleTap_RobustCheck_FaceAuth() { when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTap(NO_PENALTY)).isFalse(); } @Test + public void testIsFalseLongTap_EmptyRecentEvents() { + // Ensure we look at prior events if recent events has already been emptied. + when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(new ArrayList<>()); + when(mFalsingDataProvider.getPriorMotionEvents()).thenReturn(mMotionEventList); + + mBrightLineFalsingManager.isFalseLongTap(0); + verify(mLongTapClassifier).isTap(mMotionEventList, 0); + } + + @Test + public void testIsFalseLongTap_FalseLongTap_NotFlagged() { + mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, false); + when(mLongTapClassifier.isTap(mMotionEventList, 0)).thenReturn(mFalsedResult); + assertThat(mBrightLineFalsingManager.isFalseLongTap(NO_PENALTY)).isFalse(); + } + + @Test + public void testIsFalseLongTap_FalseLongTap() { + when(mLongTapClassifier.isTap(mMotionEventList, 0)).thenReturn(mFalsedResult); + assertThat(mBrightLineFalsingManager.isFalseLongTap(NO_PENALTY)).isTrue(); + } + + @Test + public void testIsFalseLongTap_RobustCheck_NoFaceAuth() { + when(mLongTapClassifier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult); + when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(false); + assertThat(mBrightLineFalsingManager.isFalseLongTap(NO_PENALTY)).isFalse(); + } + + @Test + public void testIsFalseLongTap_RobustCheck_FaceAuth() { + when(mLongTapClassifier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult); + when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); + assertThat(mBrightLineFalsingManager.isFalseLongTap(NO_PENALTY)).isFalse(); + } + + @Test public void testIsFalseDoubleTap() { when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mPassedResult); 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 b811aab6d35f..4281ee0f139f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java @@ -32,6 +32,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -57,6 +59,8 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { @Mock private SingleTapClassifier mSingleTapClassifier; @Mock + private LongTapClassifier mLongTapClassifier; + @Mock private DoubleTapClassifier mDoubleTapClassifier; @Mock private FalsingClassifier mClassifierA; @@ -71,6 +75,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), ""); + private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags(); @Before public void setup() { @@ -78,15 +83,17 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { when(mClassifierA.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mFalsedResult); when(mSingleTapClassifier.isTap(any(List.class), anyDouble())).thenReturn(mFalsedResult); + when(mLongTapClassifier.isTap(any(List.class), anyDouble())).thenReturn(mFalsedResult); when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble())) .thenReturn(mFalsedResult); mClassifiers.add(mClassifierA); when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); when(mKeyguardStateController.isShowing()).thenReturn(true); mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, - mMetricsLogger, mClassifiers, mSingleTapClassifier, mDoubleTapClassifier, - mHistoryTracker, mKeyguardStateController, mAccessibilityManager, - false); + mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier, + mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController, + mAccessibilityManager, false, mFakeFeatureFlags); + mFakeFeatureFlags.set(Flags.FALSING_FOR_LONG_TAPS, true); } @Test @@ -105,6 +112,13 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { @Test + public void testA11yDisablesLongTap() { + assertThat(mBrightLineFalsingManager.isFalseLongTap(1)).isTrue(); + when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); + assertThat(mBrightLineFalsingManager.isFalseLongTap(1)).isFalse(); + } + + @Test public void testA11yDisablesDoubleTap() { assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue(); when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java index 34c83bd41a02..d47e88fc9385 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -39,6 +39,7 @@ public class FalsingManagerFake implements FalsingManager { private boolean mShouldEnforceBouncer; private boolean mIsReportingEnabled; private boolean mIsFalseRobustTap; + private boolean mIsFalseLongTap; private boolean mDestroyed; private boolean mIsProximityNear; @@ -87,6 +88,10 @@ public class FalsingManagerFake implements FalsingManager { mIsProximityNear = proxNear; } + public void setFalseLongTap(boolean falseLongTap) { + mIsFalseLongTap = falseLongTap; + } + @Override public boolean isSimpleTap() { checkDestroyed(); @@ -100,6 +105,12 @@ public class FalsingManagerFake implements FalsingManager { } @Override + public boolean isFalseLongTap(int penalty) { + checkDestroyed(); + return mIsFalseLongTap; + } + + @Override public boolean isFalseDoubleTap() { checkDestroyed(); return mIsFalseDoubleTap; |