Merge "Adding isFalseLongTap method" into tm-qpr-dev am: 4562cb6733
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20190664 Change-Id: I5952444a9f50ad5b580ce52c2c35ad55708d702a Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 ==========================
|
||||
// | |
|
||||
|
||||
@@ -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,12 +240,49 @@ 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()))
|
||||
|
||||
@@ -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
|
||||
@@ -104,6 +111,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();
|
||||
|
||||
@@ -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();
|
||||
@@ -99,6 +104,12 @@ public class FalsingManagerFake implements FalsingManager {
|
||||
return mIsFalseRobustTap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFalseLongTap(int penalty) {
|
||||
checkDestroyed();
|
||||
return mIsFalseLongTap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFalseDoubleTap() {
|
||||
checkDestroyed();
|
||||
|
||||
Reference in New Issue
Block a user