Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,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. * Loading packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +63 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 = Loading Loading @@ -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); Loading Loading @@ -312,6 +320,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(); Loading packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +5 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,11 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { return mInternalFalsingManager.isFalseTap(penalty); } @Override public boolean isFalseLongTap(int penalty) { return mInternalFalsingManager.isFalseLongTap(penalty); } @Override public boolean isFalseDoubleTap() { return mInternalFalsingManager.isFalseDoubleTap(); Loading packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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; } } packages/SystemUI/src/com/android/systemui/classifier/LongTapClassifier.java 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * 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); } } Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,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. * Loading
packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +63 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 = Loading Loading @@ -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); Loading Loading @@ -312,6 +320,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(); Loading
packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +5 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,11 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { return mInternalFalsingManager.isFalseTap(penalty); } @Override public boolean isFalseLongTap(int penalty) { return mInternalFalsingManager.isFalseLongTap(penalty); } @Override public boolean isFalseDoubleTap() { return mInternalFalsingManager.isFalseDoubleTap(); Loading
packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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; } }
packages/SystemUI/src/com/android/systemui/classifier/LongTapClassifier.java 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * 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); } }