summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java62
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java18
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java30
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java30
33 files changed, 262 insertions, 179 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 4fc197340e92..0d348e263545 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -44,7 +44,7 @@ public interface FalsingManager {
/**
* Returns true if the FalsingManager thinks the last gesure was not a valid tap.
*
- * Accepts one parameter, robustCheck, that distinctly changes behavior. When set to false,
+ * The first parameter, robustCheck, distinctly changes behavior. When set to false,
* this method simply looks at the last gesture and returns whether it is a tap or not, (as
* opposed to a swipe or other non-tap gesture). When set to true, a more thorough analysis
* is performed that can include historical interactions and other contextual cues to see
@@ -53,8 +53,11 @@ public interface FalsingManager {
* Set robustCheck to true if you want to validate a tap for launching an action, like opening
* a notification. Set to false if you simply want to know if the last gesture looked like a
* tap.
+ *
+ * The second parameter, falsePenalty, indicates how much this should affect future gesture
+ * classifications if this tap looks like a false.
*/
- boolean isFalseTap(boolean robustCheck);
+ boolean isFalseTap(boolean robustCheck, double falsePenalty);
/**
* Returns true if the last two gestures do not look like a double tap.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index 5760565aaab1..4af580df09ea 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -26,6 +26,7 @@ import android.os.AsyncTask;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.view.KeyEvent;
+import android.view.MotionEvent;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
@@ -34,13 +35,21 @@ import com.android.internal.widget.LockscreenCredential;
import com.android.keyguard.EmergencyButton.EmergencyButtonCallback;
import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
+import com.android.systemui.classifier.FalsingClassifier;
+import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
+
+import java.util.Arrays;
public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKeyInputView>
extends KeyguardInputViewController<T> {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final LockPatternUtils mLockPatternUtils;
private final LatencyTracker mLatencyTracker;
+ private final FalsingCollector mFalsingCollector;
+ private final SingleTapClassifier mSingleTapClassifier;
private CountDownTimer mCountdownTimer;
protected KeyguardMessageAreaController mMessageAreaController;
private boolean mDismissing;
@@ -64,17 +73,61 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
}
};
+ private final Gefingerpoken mGlobalTouchListener = new Gefingerpoken() {
+ private MotionEvent mTouchDown;
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ mFalsingCollector.avoidGesture();
+ // Do just a bit of our own falsing. People should only be tapping on the input, not
+ // swiping.
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ if (mTouchDown != null) {
+ mTouchDown.recycle();
+ mTouchDown = null;
+ }
+ mTouchDown = MotionEvent.obtain(ev);
+ } else if (mTouchDown != null) {
+ FalsingClassifier.Result tapResult =
+ mSingleTapClassifier.isTap(Arrays.asList(mTouchDown, ev));
+ if (tapResult.isFalse()
+ || ev.getActionMasked() == MotionEvent.ACTION_UP
+ || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+ // TODO: if we've gotten too false, retract input.
+ if (tapResult.isFalse()) {
+ mFalsingCollector.updateFalseConfidence(tapResult);
+ } else {
+ // The classifier returns 0 confidence when a tap is detected.
+ // We can be more sure that the tap was intentional here.
+ mFalsingCollector.updateFalseConfidence(
+ FalsingClassifier.Result.passed(0.6));
+ }
+ mTouchDown.recycle();
+ mTouchDown = null;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return false;
+ }
+ };
+
protected KeyguardAbsKeyInputViewController(T view,
KeyguardUpdateMonitor keyguardUpdateMonitor,
SecurityMode securityMode,
LockPatternUtils lockPatternUtils,
KeyguardSecurityCallback keyguardSecurityCallback,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
- LatencyTracker latencyTracker) {
+ LatencyTracker latencyTracker, FalsingCollector falsingCollector,
+ SingleTapClassifier singleTapClassifier) {
super(view, securityMode, keyguardSecurityCallback);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mLatencyTracker = latencyTracker;
+ mFalsingCollector = falsingCollector;
+ mSingleTapClassifier = singleTapClassifier;
KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
mMessageAreaController = messageAreaControllerFactory.create(kma);
}
@@ -89,6 +142,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
@Override
protected void onViewAttached() {
super.onViewAttached();
+ mView.addMotionEventListener(mGlobalTouchListener);
mView.setKeyDownListener(mKeyDownListener);
mView.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
@@ -98,6 +152,12 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
}
@Override
+ protected void onViewDetached() {
+ super.onViewDetached();
+ mView.removeMotionEventListener(mGlobalTouchListener);
+ }
+
+ @Override
public void reset() {
// start fresh
mDismissing = false;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 957882dc9c6b..8cbaae5661ae 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -27,6 +27,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.util.ViewController;
@@ -158,6 +159,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
private LiftToActivateListener mLiftToActivateListener;
private TelephonyManager mTelephonyManager;
private final FalsingCollector mFalsingCollector;
+ private final SingleTapClassifier mSingleTapClassifier;
private final boolean mIsNewLayoutEnabled;
@Inject
@@ -169,6 +171,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
@Main Resources resources, LiftToActivateListener liftToActivateListener,
TelephonyManager telephonyManager,
FalsingCollector falsingCollector,
+ SingleTapClassifier singleTapClassifier,
FeatureFlags featureFlags) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
@@ -180,6 +183,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
mLiftToActivateListener = liftToActivateListener;
mTelephonyManager = telephonyManager;
mFalsingCollector = falsingCollector;
+ mSingleTapClassifier = singleTapClassifier;
mIsNewLayoutEnabled = featureFlags.isKeyguardLayoutEnabled();
}
@@ -194,24 +198,26 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
- mInputMethodManager, mMainExecutor, mResources);
+ mInputMethodManager, mMainExecutor, mResources, mFalsingCollector,
+ mSingleTapClassifier);
} else if (keyguardInputView instanceof KeyguardPINView) {
return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
- mLiftToActivateListener, mFalsingCollector, mIsNewLayoutEnabled);
+ mLiftToActivateListener, mFalsingCollector, mSingleTapClassifier,
+ mIsNewLayoutEnabled);
} else if (keyguardInputView instanceof KeyguardSimPinView) {
return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
- mLiftToActivateListener, mTelephonyManager,
- mFalsingCollector, mIsNewLayoutEnabled);
+ mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
+ mSingleTapClassifier, mIsNewLayoutEnabled);
} else if (keyguardInputView instanceof KeyguardSimPukView) {
return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
- mLiftToActivateListener, mTelephonyManager,
- mFalsingCollector, mIsNewLayoutEnabled);
+ mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
+ mSingleTapClassifier, mIsNewLayoutEnabled);
}
throw new RuntimeException("Unable to find controller for " + keyguardInputView);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index 0f1c3c8a20b7..1367d8442809 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -40,6 +40,8 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.Utils;
import com.android.systemui.R;
+import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -112,9 +114,12 @@ public class KeyguardPasswordViewController
LatencyTracker latencyTracker,
InputMethodManager inputMethodManager,
@Main DelayableExecutor mainExecutor,
- @Main Resources resources) {
+ @Main Resources resources,
+ FalsingCollector falsingCollector,
+ SingleTapClassifier singleTapClassifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
- messageAreaControllerFactory, latencyTracker);
+ messageAreaControllerFactory, latencyTracker, falsingCollector,
+ singleTapClassifier);
mKeyguardSecurityCallback = keyguardSecurityCallback;
mInputMethodManager = inputMethodManager;
mMainExecutor = mainExecutor;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index f2479488db0f..7fe427822d6a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -25,15 +25,14 @@ import android.view.View.OnTouchListener;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinBasedInputView>
extends KeyguardAbsKeyInputViewController<T> {
private final LiftToActivateListener mLiftToActivateListener;
- private final FalsingCollector mFalsingCollector;
protected PasswordTextView mPasswordEntry;
private final OnKeyListener mOnKeyListener = (v, keyCode, event) -> {
@@ -50,19 +49,6 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
return false;
};
- private final Gefingerpoken mGlobalTouchListener = new Gefingerpoken() {
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- mFalsingCollector.avoidGesture();
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return false;
- }
- };
-
protected KeyguardPinBasedInputViewController(T view,
KeyguardUpdateMonitor keyguardUpdateMonitor,
SecurityMode securityMode,
@@ -71,11 +57,12 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
LatencyTracker latencyTracker,
LiftToActivateListener liftToActivateListener,
- FalsingCollector falsingCollector) {
+ FalsingCollector falsingCollector,
+ SingleTapClassifier singleTapClassifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
- messageAreaControllerFactory, latencyTracker);
+ messageAreaControllerFactory, latencyTracker, falsingCollector,
+ singleTapClassifier);
mLiftToActivateListener = liftToActivateListener;
- mFalsingCollector = falsingCollector;
mPasswordEntry = mView.findViewById(mView.getPasswordTextViewId());
}
@@ -83,8 +70,6 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
protected void onViewAttached() {
super.onViewAttached();
- mView.addMotionEventListener(mGlobalTouchListener);
-
mPasswordEntry.setOnKeyListener(mOnKeyListener);
mPasswordEntry.setUserActivityListener(this::onUserInput);
@@ -120,11 +105,6 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
}
}
- @Override
- protected void onViewDetached() {
- super.onViewDetached();
- mView.removeMotionEventListener(mGlobalTouchListener);
- }
@Override
public void onResume(int reason) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 49099fa18323..dca84a638640 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -23,6 +23,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
public class KeyguardPinViewController
extends KeyguardPinBasedInputViewController<KeyguardPINView> {
@@ -34,10 +35,11 @@ public class KeyguardPinViewController
KeyguardSecurityCallback keyguardSecurityCallback,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
- FalsingCollector falsingCollector, boolean isNewLayoutEnabled) {
+ FalsingCollector falsingCollector, SingleTapClassifier singleTapClassifier,
+ boolean isNewLayoutEnabled) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
- falsingCollector);
+ falsingCollector, singleTapClassifier);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
view.setIsNewLayoutEnabled(isNewLayoutEnabled);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index cdbbfe643812..6b2be98f3d01 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -39,6 +39,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
public class KeyguardSimPinViewController
extends KeyguardPinBasedInputViewController<KeyguardSimPinView> {
@@ -78,11 +79,11 @@ public class KeyguardSimPinViewController
KeyguardSecurityCallback keyguardSecurityCallback,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
- TelephonyManager telephonyManager,
- FalsingCollector falsingCollector, boolean isNewLayoutEnabled) {
+ TelephonyManager telephonyManager, FalsingCollector falsingCollector,
+ SingleTapClassifier singleTapClassifier, boolean isNewLayoutEnabled) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
- falsingCollector);
+ falsingCollector, singleTapClassifier);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mTelephonyManager = telephonyManager;
mSimImageView = mView.findViewById(R.id.keyguard_sim);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
index 8fff34278216..3895b6829614 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -40,6 +40,7 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.SingleTapClassifier;
public class KeyguardSimPukViewController
extends KeyguardPinBasedInputViewController<KeyguardSimPukView> {
@@ -85,11 +86,11 @@ public class KeyguardSimPukViewController
KeyguardSecurityCallback keyguardSecurityCallback,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
- TelephonyManager telephonyManager,
- FalsingCollector falsingCollector, boolean isNewLayoutEnabled) {
+ TelephonyManager telephonyManager, FalsingCollector falsingCollector,
+ SingleTapClassifier singleTapClassifier, boolean isNewLayoutEnabled) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
- falsingCollector);
+ falsingCollector, singleTapClassifier);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mTelephonyManager = telephonyManager;
mSimImageView = mView.findViewById(R.id.keyguard_sim);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index 6572ca95b5c3..1eb3dd17ac6a 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -18,7 +18,6 @@ package com.android.systemui.classifier;
import static com.android.systemui.classifier.FalsingManagerProxy.FALSING_SUCCESS;
import static com.android.systemui.classifier.FalsingModule.BRIGHT_LINE_GESTURE_CLASSIFERS;
-import static com.android.systemui.classifier.FalsingModule.DOUBLE_TAP_TIMEOUT_MS;
import android.net.Uri;
import android.os.Build;
@@ -29,11 +28,9 @@ import androidx.annotation.NonNull;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.classifier.FalsingDataProvider.SessionListener;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.TestHarness;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.sensors.ThresholdSensor;
import java.io.FileDescriptor;
@@ -63,14 +60,13 @@ public class BrightLineFalsingManager implements FalsingManager {
private static final int RECENT_INFO_LOG_SIZE = 40;
private static final int RECENT_SWIPE_LOG_SIZE = 20;
+ private static final double TAP_CONFIDENCE_THRESHOLD = 0.7;
private final FalsingDataProvider mDataProvider;
private final DockManager mDockManager;
private final SingleTapClassifier mSingleTapClassifier;
private final DoubleTapClassifier mDoubleTapClassifier;
private final HistoryTracker mHistoryTracker;
- private final DelayableExecutor mDelayableExecutor;
- private final long mDoubleTapTimeMs;
private final boolean mTestHarness;
private final MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
@@ -98,19 +94,7 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public void onGestureComplete(long completionTimeMs) {
if (mPriorResults != null) {
- // Single taps that may become double taps don't get added right away.
- if (mClassifyAsSingleTap) {
- Collection<FalsingClassifier.Result> singleTapResults = mPriorResults;
- mSingleTapHistoryCanceller = mDelayableExecutor.executeDelayed(
- () -> {
- mSingleTapHistoryCanceller = null;
- mHistoryTracker.addResults(singleTapResults, completionTimeMs);
- },
- mDoubleTapTimeMs);
- mClassifyAsSingleTap = false; // Don't treat things as single taps by default.
- } else {
- mHistoryTracker.addResults(mPriorResults, completionTimeMs);
- }
+ mHistoryTracker.addResults(mPriorResults, completionTimeMs);
mPriorResults = null;
} else {
// Gestures that were not classified get treated as a false.
@@ -123,17 +107,13 @@ public class BrightLineFalsingManager implements FalsingManager {
};
private Collection<FalsingClassifier.Result> mPriorResults;
- private boolean mClassifyAsSingleTap;
- private Runnable mSingleTapHistoryCanceller;
@Inject
public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
DockManager dockManager, MetricsLogger metricsLogger,
@Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers,
SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier,
- HistoryTracker historyTracker, @Main DelayableExecutor delayableExecutor,
- @Named(DOUBLE_TAP_TIMEOUT_MS) long doubleTapTimeMs,
- @TestHarness boolean testHarness) {
+ HistoryTracker historyTracker, @TestHarness boolean testHarness) {
mDataProvider = falsingDataProvider;
mDockManager = dockManager;
mMetricsLogger = metricsLogger;
@@ -141,8 +121,6 @@ public class BrightLineFalsingManager implements FalsingManager {
mSingleTapClassifier = singleTapClassifier;
mDoubleTapClassifier = doubleTapClassifier;
mHistoryTracker = historyTracker;
- mDelayableExecutor = delayableExecutor;
- mDoubleTapTimeMs = doubleTapTimeMs;
mTestHarness = testHarness;
mDataProvider.addSessionListener(mSessionListener);
@@ -158,7 +136,6 @@ public class BrightLineFalsingManager implements FalsingManager {
public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
boolean result;
- mClassifyAsSingleTap = false;
mDataProvider.setInteractionType(interactionType);
if (!mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked()) {
@@ -166,7 +143,7 @@ public class BrightLineFalsingManager implements FalsingManager {
mClassifiers.stream().map(falsingClassifier -> {
FalsingClassifier.Result classifierResult =
falsingClassifier.classifyGesture(
- mHistoryTracker.falsePenalty(),
+ mHistoryTracker.falseBelief(),
mHistoryTracker.falseConfidence());
if (classifierResult.isFalse()) {
logInfo(String.format(
@@ -217,9 +194,7 @@ public class BrightLineFalsingManager implements FalsingManager {
}
@Override
- public boolean isFalseTap(boolean robustCheck) {
- mClassifyAsSingleTap = true;
-
+ public boolean isFalseTap(boolean robustCheck, double falsePenalty) {
FalsingClassifier.Result singleTapResult =
mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents());
mPriorResults = Collections.singleton(singleTapResult);
@@ -233,14 +208,19 @@ public class BrightLineFalsingManager implements FalsingManager {
return true;
}
- // TODO(b/172655679): More heuristics to come. For now, allow touches through if face-authed
if (robustCheck) {
- boolean result = !mDataProvider.isJustUnlockedWithFace();
- mPriorResults = Collections.singleton(
- result ? FalsingClassifier.Result.falsed(0.1, "no face detected")
- : FalsingClassifier.Result.passed(1));
-
- return result;
+ if (mDataProvider.isJustUnlockedWithFace()) {
+ mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1));
+ return false;
+ } else if (mHistoryTracker.falseBelief() > TAP_CONFIDENCE_THRESHOLD) {
+ mPriorResults = Collections.singleton(
+ FalsingClassifier.Result.falsed(0.1, "bad history"));
+ return true;
+ } else {
+ mPriorResults = Collections.singleton(
+ FalsingClassifier.Result.falsed(falsePenalty, "no face detected"));
+ return false;
+ }
}
return false;
@@ -248,7 +228,6 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public boolean isFalseDoubleTap() {
- mClassifyAsSingleTap = false;
FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture();
mPriorResults = Collections.singleton(result);
if (result.isFalse()) {
@@ -258,12 +237,6 @@ public class BrightLineFalsingManager implements FalsingManager {
if (reason != null) {
logInfo(reason);
}
- } else {
- // A valid double tap prevents an invalid single tap from going into history.
- if (mSingleTapHistoryCanceller != null) {
- mSingleTapHistoryCanceller.run();
- mSingleTapHistoryCanceller = null;
- }
}
return result.isFalse();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java
index bbb937176f59..ffcdb93b11b1 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java
@@ -62,7 +62,7 @@ class DiagonalClassifier extends FalsingClassifier {
VERTICAL_ANGLE_RANGE);
}
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
float angle = getAngle();
if (angle == Float.MAX_VALUE) { // Unknown angle
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
index 4cb5aa2cce37..0f121c1c9ae7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java
@@ -147,7 +147,7 @@ class DistanceClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
return !getPassedFlingThreshold()
? Result.falsed(0.5, getReason()) : Result.passed(0.5);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java
index f7fe14a8e841..9bb6b06f40a7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java
@@ -46,7 +46,7 @@ public class DoubleTapClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
List<MotionEvent> secondTapEvents = getRecentMotionEvents();
List<MotionEvent> firstTapEvents = getPriorMotionEvents();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java
index f40045b0f08e..1af5f7c488a5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java
@@ -124,7 +124,7 @@ public abstract class FalsingClassifier {
* See also {@link #classifyGesture(double, double)}.
*/
Result classifyGesture() {
- return calculateFalsingResult(0, 0);
+ return calculateFalsingResult(0.5, 0);
}
/**
@@ -135,16 +135,16 @@ public abstract class FalsingClassifier {
*
* See also {@link #classifyGesture()}.
*/
- Result classifyGesture(double historyPenalty, double historyConfidence) {
- return calculateFalsingResult(historyPenalty, historyConfidence);
+ Result classifyGesture(double historyBelief, double historyConfidence) {
+ return calculateFalsingResult(historyBelief, historyConfidence);
}
/**
* Calculate a result based on available data.
*
- * When passed a historyConfidence of 0, the history penalty should be wholly ignored.
+ * When passed a historyConfidence of 0, the history belief should be wholly ignored.
*/
- abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence);
+ abstract Result calculateFalsingResult(double historyBelief, double historyConfidence);
/** */
public static void logDebug(String msg) {
@@ -164,7 +164,7 @@ public abstract class FalsingClassifier {
/**
* A Falsing result that encapsulates the boolean result along with confidence and a reason.
*/
- static class Result {
+ public static class Result {
private final boolean mFalsed;
private final double mConfidence;
private final String mReason;
@@ -193,14 +193,14 @@ public abstract class FalsingClassifier {
/**
* Construct a "falsed" result indicating that a gesture should be treated as accidental.
*/
- static Result falsed(double confidence, String reason) {
+ public static Result falsed(double confidence, String reason) {
return new Result(true, confidence, reason);
}
/**
* Construct a "passed" result indicating that a gesture should be allowed.
*/
- static Result passed(double confidence) {
+ public static Result passed(double confidence) {
return new Result(false, confidence, null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
index b0bbab366e93..bb037202d985 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java
@@ -120,5 +120,8 @@ public interface FalsingCollector {
/** */
void cleanup();
+
+ /** */
+ void updateFalseConfidence(FalsingClassifier.Result result);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
index 12a060439106..939b45a2b4a5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
@@ -153,4 +153,8 @@ public class FalsingCollectorFake implements FalsingCollector {
@Override
public void cleanup() {
}
+
+ @Override
+ public void updateFalseConfidence(FalsingClassifier.Result result) {
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index e08b43b3521f..e090006cca4f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -29,6 +29,9 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.sensors.ThresholdSensor;
+import com.android.systemui.util.time.SystemClock;
+
+import java.util.Collections;
import javax.inject.Inject;
@@ -42,8 +45,10 @@ class FalsingCollectorImpl implements FalsingCollector {
private final FalsingDataProvider mFalsingDataProvider;
private final FalsingManager mFalsingManager;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final HistoryTracker mHistoryTracker;
private final ProximitySensor mProximitySensor;
private final StatusBarStateController mStatusBarStateController;
+ private final SystemClock mSystemClock;
private int mState;
private boolean mShowingAod;
@@ -80,13 +85,16 @@ class FalsingCollectorImpl implements FalsingCollector {
@Inject
FalsingCollectorImpl(FalsingDataProvider falsingDataProvider, FalsingManager falsingManager,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- ProximitySensor proximitySensor, StatusBarStateController statusBarStateController) {
+ KeyguardUpdateMonitor keyguardUpdateMonitor, HistoryTracker historyTracker,
+ ProximitySensor proximitySensor, StatusBarStateController statusBarStateController,
+ SystemClock systemClock) {
mFalsingDataProvider = falsingDataProvider;
mFalsingManager = falsingManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mHistoryTracker = historyTracker;
mProximitySensor = proximitySensor;
mStatusBarStateController = statusBarStateController;
+ mSystemClock = systemClock;
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
@@ -282,6 +290,11 @@ class FalsingCollectorImpl implements FalsingCollector {
mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
+ @Override
+ public void updateFalseConfidence(FalsingClassifier.Result result) {
+ mHistoryTracker.addResults(Collections.singleton(result), mSystemClock.uptimeMillis());
+ }
+
private void updateInteractionType(@Classifier.InteractionType int type) {
logDebug("InteractionType: " + type);
mFalsingDataProvider.setInteractionType(type);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
index d4d8d06b081b..aac27cb43376 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -76,7 +76,7 @@ public class FalsingManagerFake implements FalsingManager {
}
@Override
- public boolean isFalseTap(boolean robustCheck) {
+ public boolean isFalseTap(boolean robustCheck, double falsePenalty) {
return robustCheck ? mIsFalseRobustTap : mIsFalseTap;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index cbec0576e449..e9bb48c7b1a9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -131,8 +131,8 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
}
@Override
- public boolean isFalseTap(boolean robustCheck) {
- return mInternalFalsingManager.isFalseTap(robustCheck);
+ public boolean isFalseTap(boolean robustCheck, double falsePenalty) {
+ return mInternalFalsingManager.isFalseTap(robustCheck, falsePenalty);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java
index 8bd94a122707..be48ec415652 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java
@@ -36,12 +36,17 @@ import javax.inject.Inject;
*/
@SysUISingleton
public class HistoryTracker {
- private static final double HISTORY_DECAY = 0.8f;
+ private static final long HISTORY_MAX_AGE_MS = 10000;
+ // A score is decayed discretely every DECAY_INTERVAL_MS.
private static final long DECAY_INTERVAL_MS = 100;
- // We expire items once their decay factor is below 0.001.
- private static final double MINIMUM_SCORE = 0.001;
- private static final long TOTAL_DECAY_TIME_MS =
- DECAY_INTERVAL_MS * (long) (Math.log(MINIMUM_SCORE) / Math.log(HISTORY_DECAY));
+ // We expire items once their decay factor is below 0.1.
+ private static final double MINIMUM_SCORE = 0.1;
+ // This magic number is the factor a score is reduced by every DECAY_INTERVAL_MS.
+ // Once a score is HISTORY_MAX_AGE_MS ms old, it will be reduced by being multiplied by
+ // MINIMUM_SCORE. The math below ensures that.
+ private static final double HISTORY_DECAY =
+ Math.pow(10, Math.log10(MINIMUM_SCORE) / HISTORY_MAX_AGE_MS * DECAY_INTERVAL_MS);
+
private final SystemClock mSystemClock;
DelayQueue<CombinedResult> mResults = new DelayQueue<>();
@@ -54,29 +59,36 @@ public class HistoryTracker {
/**
* Returns how much the HistoryClassifier thinks the past events indicate pocket dialing.
*
- * A result of 0 means that all prior gestures succeeded or there is no data to
- * calculate a score with. Use {@link #falseConfidence()} to differentiate between the
- * two cases.
+ * A result close to 0.5 means that prior data is inconclusive (inconsistent, lacking
+ * confidence, or simply lacking in quantity).
+ *
+ * A result close to 0 means that prior gestures indicate a success.
*
- * A result of 1 means that all prior gestures were very obviously false. The current gesture
- * might be valid, but it should have a high-bar to be classified as such.
+ * A result close to 1 means that prior gestures were very obviously false.
+ *
+ * The current gesture might be different than what is reported by this method, but there should
+ * be a high-bar to be classified differently.
*
* See also {@link #falseConfidence()}.
*/
- double falsePenalty() {
+ double falseBelief() {
//noinspection StatementWithEmptyBody
while (mResults.poll() != null) {
// Empty out the expired results.
}
if (mResults.isEmpty()) {
- return 0;
+ return 0.5;
}
long nowMs = mSystemClock.uptimeMillis();
+ // Get our Bayes on.
return mResults.stream()
.map(result -> result.getDecayedScore(nowMs))
- .reduce(0.0, Double::sum) / mResults.size();
+ .reduce(0.5,
+ (prior, measurement) ->
+ (prior * measurement)
+ / (prior * measurement + (1 - prior) * (1 - measurement)));
}
/**
@@ -91,7 +103,7 @@ public class HistoryTracker {
* A result of 1 means that there are ample, fresh data to act upon that is all consistent
* with each other.
*
- * See als {@link #falsePenalty()}.
+ * See als {@link #falseBelief()}.
*/
double falseConfidence() {
//noinspection StatementWithEmptyBody
@@ -126,6 +138,15 @@ public class HistoryTracker {
finalScore /= results.size();
+ // Never add a 0 or 1, else Bayes breaks down (a 0 and a 1 together results in NaN). In
+ // other words, you shouldn't need Bayes if you have 100% confidence one way or another.
+ // Instead, make the number ever so slightly smaller so that our math never breaks.
+ if (finalScore == 1) {
+ finalScore = 0.99999;
+ } else if (finalScore == 0) {
+ finalScore = 0.00001;
+ }
+
//noinspection StatementWithEmptyBody
while (mResults.poll() != null) {
// Empty out the expired results.
@@ -147,15 +168,17 @@ public class HistoryTracker {
private final double mScore;
CombinedResult(long uptimeMillis, double score) {
- mExpiryMs = uptimeMillis + TOTAL_DECAY_TIME_MS;
+ mExpiryMs = uptimeMillis + HISTORY_MAX_AGE_MS;
mScore = score;
}
double getDecayedScore(long nowMs) {
long remainingTimeMs = mExpiryMs - nowMs;
- long decayedTimeMs = TOTAL_DECAY_TIME_MS - remainingTimeMs;
+ long decayedTimeMs = HISTORY_MAX_AGE_MS - remainingTimeMs;
double timeIntervals = (double) decayedTimeMs / DECAY_INTERVAL_MS;
- return mScore * Math.pow(HISTORY_DECAY, timeIntervals);
+
+ // Score should decay towards 0.5.
+ return (mScore - 0.5) * Math.pow(HISTORY_DECAY, timeIntervals) + 0.5;
}
double getScore() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
index cd399fe15de1..77d2d4267679 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
@@ -56,7 +56,7 @@ class PointerCountClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
int interactionType = getInteractionType();
int allowedPointerCount =
(interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
index 9ee85986c53c..6e97857f83da 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -112,7 +112,7 @@ class ProximityClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
if (getInteractionType() == QUICK_SETTINGS) {
return Result.passed(0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java
index f2622ec4e6e9..bff709ca83a2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java
@@ -39,12 +39,15 @@ public class SingleTapClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
return isTap(getRecentMotionEvents());
}
/** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */
public Result isTap(List<MotionEvent> motionEvents) {
+ if (motionEvents.isEmpty()) {
+ return Result.falsed(0, "no motion events");
+ }
float downX = motionEvents.get(0).getX();
float downY = motionEvents.get(0).getY();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
index d470d6297170..4e032ea487c9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java
@@ -38,7 +38,7 @@ public class TypeClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
boolean vertical = isVertical();
boolean up = isUp();
boolean right = isRight();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
index 2bfb2186191b..205825790461 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java
@@ -84,7 +84,7 @@ class ZigZagClassifier extends FalsingClassifier {
}
@Override
- Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
+ Result calculateFalsingResult(double historyBelief, double historyConfidence) {
List<MotionEvent> motionEvents = getRecentMotionEvents();
// Rotate horizontal gestures to be horizontal between their first and last point.
// Rotate vertical gestures to be vertical between their first and last point.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 19b98953325f..8e8353ce39d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -576,8 +576,8 @@ public class NotificationPanelViewController extends PanelViewController {
FeatureFlags featureFlags) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
- latencyTracker, flingAnimationUtilsBuilder.get(), statusBarTouchableRegionManager,
- ambientState);
+ statusBarKeyguardViewManager, latencyTracker, flingAnimationUtilsBuilder.get(),
+ statusBarTouchableRegionManager, ambientState);
mView = view;
mMetricsLogger = metricsLogger;
mActivityManager = activityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java
index 50c8e2e0d710..66df936dd556 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationTapHelper.java
@@ -64,7 +64,7 @@ public class NotificationTapHelper {
mTrackTouch = event.getY() <= maxTouchableHeight;
break;
case MotionEvent.ACTION_MOVE:
- if (mTrackTouch && mFalsingManager.isFalseTap(false)) {
+ if (mTrackTouch && mFalsingManager.isFalseTap(false, 0)) {
makeInactive();
mTrackTouch = false;
}
@@ -78,10 +78,10 @@ public class NotificationTapHelper {
// 1) See if we have confidence that we can activate after a single tap.
// 2) Else, see if it looks like a tap at all and check for a double-tap.
- if (!mFalsingManager.isFalseTap(true)) {
+ if (!mFalsingManager.isFalseTap(true, 0)) {
makeInactive();
return mDoubleTapListener.onDoubleTap();
- } else if (!mFalsingManager.isFalseTap(false)) {
+ } else if (!mFalsingManager.isFalseTap(false, 0)) {
if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index b6ed3e50ed7e..3ac69378d7d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -167,6 +167,7 @@ public abstract class PanelViewController {
private boolean mIgnoreXTouchSlop;
private boolean mExpandLatencyTracking;
private final PanelView mView;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
protected final Resources mResources;
protected final KeyguardStateController mKeyguardStateController;
protected final SysuiStatusBarStateController mStatusBarStateController;
@@ -235,12 +236,14 @@ public abstract class PanelViewController {
FalsingManager falsingManager, DozeLog dozeLog,
KeyguardStateController keyguardStateController,
SysuiStatusBarStateController statusBarStateController, VibratorHelper vibratorHelper,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
LatencyTracker latencyTracker,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
AmbientState ambientState) {
mAmbientState = ambientState;
mView = view;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
@@ -1391,8 +1394,13 @@ public abstract class PanelViewController {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- addMovement(event);
- endMotionEvent(event, x, y, false /* forceCancel */);
+ if (mStatusBarKeyguardViewManager.isBouncerShowing()
+ && mFalsingManager.isFalseTap(true, 0.5)) {
+ endMotionEvent(event, x, y, true /* forceCancel */);
+ } else {
+ addMovement(event);
+ endMotionEvent(event, x, y, false /* forceCancel */);
+ }
InteractionJankMonitor monitor = InteractionJankMonitor.getInstance();
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 5083e330f9a0..01ada0f4c86c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -76,7 +76,7 @@ import javax.inject.Inject;
* Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
* via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
* which is in turn, reported to this class by the current
- * {@link com.android.keyguard.KeyguardViewBase}.
+ * {@link com.android.keyguard.KeyguardViewController}.
*/
@SysUISingleton
public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
index c2ade81a9877..088de1d99d65 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -36,6 +36,9 @@ import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.classifier.SingleTapClassifier;
import org.junit.Before;
import org.junit.Test;
@@ -69,6 +72,9 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
private KeyguardMessageAreaController mKeyguardMessageAreaController;
@Mock
private LatencyTracker mLatencyTracker;
+ private FalsingCollector mFalsingCollector = new FalsingCollectorFake();
+ @Mock
+ private SingleTapClassifier mSingleTapClassifier;
private KeyguardAbsKeyInputViewController mKeyguardAbsKeyInputViewController;
@@ -84,7 +90,8 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
.thenReturn(mKeyguardMessageArea);
mKeyguardAbsKeyInputViewController = new KeyguardAbsKeyInputViewController(mAbsKeyInputView,
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
- mKeyguardMessageAreaControllerFactory, mLatencyTracker) {
+ mKeyguardMessageAreaControllerFactory, mLatencyTracker, mFalsingCollector,
+ mSingleTapClassifier) {
@Override
void resetState() {
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
index 31cc7bb7c958..a36a2b0414c9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -33,6 +33,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.classifier.SingleTapClassifier;
import org.junit.Before;
import org.junit.Test;
@@ -69,6 +70,8 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
private LiftToActivateListener mLiftToactivateListener;
private FalsingCollector mFalsingCollector = new FalsingCollectorFake();
@Mock
+ private SingleTapClassifier mSingleTapClassifier;
+ @Mock
private View mDeleteButton;
@Mock
private View mOkButton;
@@ -92,7 +95,7 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
mKeyguardPinViewController = new KeyguardPinBasedInputViewController(mPinBasedInputView,
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
mKeyguardMessageAreaControllerFactory, mLatencyTracker, mLiftToactivateListener,
- mFalsingCollector) {
+ mFalsingCollector, mSingleTapClassifier) {
@Override
public void onResume(int reason) {
super.onResume(reason);
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 5709ce3035a2..a53377e3e08c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -21,10 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.anyDouble;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -93,7 +90,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier,
- mHistoryTracker, mFakeExecutor, DOUBLE_TAP_TIMEOUT_MS, false);
+ mHistoryTracker, false);
ArgumentCaptor<GestureCompleteListener> gestureCompleteListenerCaptor =
@@ -161,25 +158,26 @@ public class BrightLineClassifierTest extends SysuiTestCase {
public void testIsFalseTap_BasicCheck() {
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult);
- assertThat(mBrightLineFalsingManager.isFalseTap(false)).isTrue();
+ assertThat(mBrightLineFalsingManager.isFalseTap(false, 0)).isTrue();
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
- assertThat(mBrightLineFalsingManager.isFalseTap(false)).isFalse();
+ assertThat(mBrightLineFalsingManager.isFalseTap(false, 0)).isFalse();
}
@Test
public void testIsFalseTap_RobustCheck_NoFaceAuth() {
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
+ when(mHistoryTracker.falseBelief()).thenReturn(1.0);
mFalsingDataProvider.setJustUnlockedWithFace(false);
- assertThat(mBrightLineFalsingManager.isFalseTap(true)).isTrue();
+ assertThat(mBrightLineFalsingManager.isFalseTap(true, 0)).isTrue();
}
@Test
public void testIsFalseTap_RobustCheck_FaceAuth() {
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true);
- assertThat(mBrightLineFalsingManager.isFalseTap(true)).isFalse();
+ assertThat(mBrightLineFalsingManager.isFalseTap(true, 0)).isFalse();
}
@Test
@@ -203,43 +201,29 @@ public class BrightLineClassifierTest extends SysuiTestCase {
@Test
public void testHistory_singleTap() {
// When trying to classify single taps, we don't immediately add results to history.
- mBrightLineFalsingManager.isFalseTap(false);
+ mBrightLineFalsingManager.isFalseTap(false, 0);
mGestureCompleteListener.onGestureComplete(1000);
-
- verify(mHistoryTracker, never()).addResults(any(), anyLong());
-
- mFakeExecutor.advanceClockToNext();
- mFakeExecutor.runAllReady();
-
verify(mHistoryTracker).addResults(anyCollection(), eq(1000L));
}
@Test
public void testHistory_multipleSingleTaps() {
// When trying to classify single taps, we don't immediately add results to history.
- mBrightLineFalsingManager.isFalseTap(false);
+ mBrightLineFalsingManager.isFalseTap(false, 0);
mGestureCompleteListener.onGestureComplete(1000);
- mBrightLineFalsingManager.isFalseTap(false);
+ mBrightLineFalsingManager.isFalseTap(false, 0);
mGestureCompleteListener.onGestureComplete(2000);
-
- verify(mHistoryTracker, never()).addResults(any(), anyLong());
-
- mFakeExecutor.advanceClockToNext();
- mFakeExecutor.runNextReady();
verify(mHistoryTracker).addResults(anyCollection(), eq(1000L));
- reset(mHistoryTracker);
- mFakeExecutor.advanceClockToNext();
- mFakeExecutor.runNextReady();
verify(mHistoryTracker).addResults(anyCollection(), eq(2000L));
}
@Test
public void testHistory_doubleTap() {
// When trying to classify single taps, we don't immediately add results to history.
- mBrightLineFalsingManager.isFalseTap(false);
+ mBrightLineFalsingManager.isFalseTap(false, 0);
mGestureCompleteListener.onGestureComplete(1000);
// Before checking for double tap, we may check for single-tap on the second gesture.
- mBrightLineFalsingManager.isFalseTap(false);
+ mBrightLineFalsingManager.isFalseTap(false, 0);
mBrightLineFalsingManager.isFalseDoubleTap();
mGestureCompleteListener.onGestureComplete(2000);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
index 23ef865750b2..dc79b8881891 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.util.sensors.ProximitySensor;
import com.android.systemui.util.sensors.ThresholdSensor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -56,6 +57,8 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock
+ private HistoryTracker mHistoryTracker;
+ @Mock
private ProximitySensor mProximitySensor;
@Mock
private SysuiStatusBarStateController mStatusBarStateController;
@@ -67,7 +70,8 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
mFalsingCollector = new FalsingCollectorImpl(mFalsingDataProvider, mFalsingManager,
- mKeyguardUpdateMonitor, mProximitySensor, mStatusBarStateController);
+ mKeyguardUpdateMonitor, mHistoryTracker, mProximitySensor,
+ mStatusBarStateController, new FakeSystemClock());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java
index 01cce3579b0c..bb7545f93b4b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java
@@ -48,14 +48,14 @@ public class HistoryTrackerTest extends SysuiTestCase {
@Test
public void testNoDataNoPenalty() {
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0);
+ assertThat(mHistoryTracker.falseBelief()).isEqualTo(0.5);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0);
}
@Test
public void testOneResultFullConfidence() {
addResult(true, 1);
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.001).of(1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
}
@@ -64,8 +64,8 @@ public class HistoryTrackerTest extends SysuiTestCase {
addResult(true, 1);
addResult(false, 1);
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.5);
- assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.5);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.001).of(0.5);
+ assertThat(mHistoryTracker.falseConfidence()).isWithin(0.001).of(0.5);
}
@Test
@@ -73,20 +73,20 @@ public class HistoryTrackerTest extends SysuiTestCase {
addResult(true, 1);
addResult(true, 0);
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.75);
- assertThat(mHistoryTracker.falseConfidence()).isEqualTo(.75);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.001).of(1);
+ assertThat(mHistoryTracker.falseConfidence()).isWithin(0.001).of(.75);
}
@Test
public void testDecay() {
addResult(true, 1);
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.001).of(1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
- mSystemClock.advanceTime(1000);
+ mSystemClock.advanceTime(9999);
- assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.1);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.005).of(0.55);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
}
@@ -96,25 +96,25 @@ public class HistoryTrackerTest extends SysuiTestCase {
mSystemClock.advanceTime(1000);
addResult(false, .5);
- assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.17);
- assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.625);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.01).of(0.74);
+ assertThat(mHistoryTracker.falseConfidence()).isWithin(0.001).of(0.625);
}
@Test
public void testCompleteDecay() {
addResult(true, 1);
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
+ assertThat(mHistoryTracker.falseBelief()).isWithin(0.001).of(1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
- mSystemClock.advanceTime(2999);
+ mSystemClock.advanceTime(9999);
- assertThat(mHistoryTracker.falsePenalty()).isGreaterThan(0);
+ assertThat(mHistoryTracker.falseBelief()).isGreaterThan(0);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
mSystemClock.advanceTime(1);
- assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0);
+ assertThat(mHistoryTracker.falseBelief()).isEqualTo(0.5);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0);
}