Pass interaction type to FalsingManager.isFalse

This ensures that the falsing manager always is testing against the
correct interaction type when it is asked. Prior to this change, we
could end up in states where a user was swiping down (opening the
quick settings) but the falsing manager believed the user was trying
to unlock the phone.

Fixes: 160967364
Test: atest SystemUITests && manual
Change-Id: I176f54a768622dec3e758a7f01ed8aec26223648
This commit is contained in:
Dave Mankoff
2020-08-17 15:33:21 -04:00
parent de89203f12
commit 96c4746453
15 changed files with 62 additions and 28 deletions

View File

@@ -30,7 +30,7 @@ import java.io.PrintWriter;
*/ */
@ProvidesInterface(version = FalsingManager.VERSION) @ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager { public interface FalsingManager {
int VERSION = 4; int VERSION = 5;
void onSuccessfulUnlock(); void onSuccessfulUnlock();
@@ -42,7 +42,8 @@ public interface FalsingManager {
boolean isUnlockingDisabled(); boolean isUnlockingDisabled();
boolean isFalseTouch(); /** Returns true if the gesture should be rejected. */
boolean isFalseTouch(int interactionType);
void onNotificatonStopDraggingDown(); void onNotificatonStopDraggingDown();

View File

@@ -14,16 +14,16 @@
package com.android.systemui.plugins.statusbar; package com.android.systemui.plugins.statusbar;
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import android.service.notification.SnoozeCriterion; import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
@ProvidesInterface(version = NotificationSwipeActionHelper.VERSION) @ProvidesInterface(version = NotificationSwipeActionHelper.VERSION)
@DependsOn(target = SnoozeOption.class) @DependsOn(target = SnoozeOption.class)
public interface NotificationSwipeActionHelper { public interface NotificationSwipeActionHelper {
@@ -52,7 +52,8 @@ public interface NotificationSwipeActionHelper {
public boolean isDismissGesture(MotionEvent ev); public boolean isDismissGesture(MotionEvent ev);
public boolean isFalseGesture(MotionEvent ev); /** Returns true if the gesture should be rejected. */
boolean isFalseGesture();
public boolean swipedFarEnough(float translation, float viewSize); public boolean swipedFarEnough(float translation, float viewSize);

View File

@@ -16,6 +16,8 @@
package com.android.systemui; package com.android.systemui;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
@@ -696,14 +698,15 @@ public class SwipeHelper implements Gefingerpoken {
float translation = getTranslation(mCurrView); float translation = getTranslation(mCurrView);
return ev.getActionMasked() == MotionEvent.ACTION_UP return ev.getActionMasked() == MotionEvent.ACTION_UP
&& !mFalsingManager.isUnlockingDisabled() && !mFalsingManager.isUnlockingDisabled()
&& !isFalseGesture(ev) && (swipedFastEnough() || swipedFarEnough()) && !isFalseGesture() && (swipedFastEnough() || swipedFarEnough())
&& mCallback.canChildBeDismissedInDirection(mCurrView, translation > 0); && mCallback.canChildBeDismissedInDirection(mCurrView, translation > 0);
} }
public boolean isFalseGesture(MotionEvent ev) { /** Returns true if the gesture should be rejected. */
public boolean isFalseGesture() {
boolean falsingDetected = mCallback.isAntiFalsingNeeded(); boolean falsingDetected = mCallback.isAntiFalsingNeeded();
if (mFalsingManager.isClassifierEnabled()) { if (mFalsingManager.isClassifierEnabled()) {
falsingDetected = falsingDetected && mFalsingManager.isFalseTouch(); falsingDetected = falsingDetected && mFalsingManager.isFalseTouch(NOTIFICATION_DISMISS);
} else { } else {
falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold; falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
} }

View File

@@ -70,7 +70,7 @@ public class FalsingManagerFake implements FalsingManager {
} }
@Override @Override
public boolean isFalseTouch() { public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
return mIsFalseTouch; return mIsFalseTouch;
} }

View File

@@ -262,7 +262,7 @@ public class FalsingManagerImpl implements FalsingManager {
/** /**
* @return true if the classifier determined that this is not a human interacting with the phone * @return true if the classifier determined that this is not a human interacting with the phone
*/ */
public boolean isFalseTouch() { public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
if (FalsingLog.ENABLED) { if (FalsingLog.ENABLED) {
// We're getting some false wtfs from touches that happen after the device went // We're getting some false wtfs from touches that happen after the device went
// to sleep. Only report missing sessions that happen when the device is interactive. // to sleep. Only report missing sessions that happen when the device is interactive.

View File

@@ -187,8 +187,8 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
} }
@Override @Override
public boolean isFalseTouch() { public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
return mInternalFalsingManager.isFalseTouch(); return mInternalFalsingManager.isFalseTouch(interactionType);
} }
@Override @Override

View File

@@ -189,7 +189,8 @@ public class BrightLineFalsingManager implements FalsingManager {
} }
@Override @Override
public boolean isFalseTouch() { public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
mDataProvider.setInteractionType(interactionType);
if (!mDataProvider.isDirty()) { if (!mDataProvider.isDirty()) {
return mPreviousResult; return mPreviousResult;
} }

View File

@@ -116,7 +116,10 @@ public class FalsingDataProvider {
* interactionType is defined by {@link com.android.systemui.classifier.Classifier}. * interactionType is defined by {@link com.android.systemui.classifier.Classifier}.
*/ */
final void setInteractionType(@Classifier.InteractionType int interactionType) { final void setInteractionType(@Classifier.InteractionType int interactionType) {
this.mInteractionType = interactionType; if (mInteractionType != interactionType) {
mInteractionType = interactionType;
mDirty = true;
}
} }
public boolean isDirty() { public boolean isDirty() {

View File

@@ -30,6 +30,7 @@ import com.android.settingslib.Utils
import com.android.systemui.Gefingerpoken import com.android.systemui.Gefingerpoken
import com.android.systemui.qs.PageIndicator import com.android.systemui.qs.PageIndicator
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS
import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.FalsingManager
import com.android.systemui.util.animation.PhysicsAnimator import com.android.systemui.util.animation.PhysicsAnimator
import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor
@@ -315,7 +316,8 @@ class MediaCarouselScrollHandler(
return false return false
} }
private fun isFalseTouch() = falsingProtectionNeeded && falsingManager.isFalseTouch private fun isFalseTouch() = falsingProtectionNeeded &&
falsingManager.isFalseTouch(NOTIFICATION_DISMISS)
private fun getMaxTranslation() = if (showsSettingsButton) { private fun getMaxTranslation() = if (showsSettingsButton) {
settingsButton.width settingsButton.width

View File

@@ -16,6 +16,8 @@
package com.android.systemui.statusbar; package com.android.systemui.statusbar;
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
@@ -163,7 +165,7 @@ public class DragDownHelper implements Gefingerpoken {
if (!mDragDownCallback.isFalsingCheckNeeded()) { if (!mDragDownCallback.isFalsingCheckNeeded()) {
return false; return false;
} }
return mFalsingManager.isFalseTouch() || !mDraggedFarEnough; return mFalsingManager.isFalseTouch(NOTIFICATION_DRAG_DOWN) || !mDraggedFarEnough;
} }
private void captureStartingChild(float x, float y) { private void captureStartingChild(float x, float y) {

View File

@@ -30,6 +30,7 @@ import android.view.ViewConfiguration
import com.android.systemui.Gefingerpoken import com.android.systemui.Gefingerpoken
import com.android.systemui.Interpolators import com.android.systemui.Interpolators
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -106,7 +107,7 @@ constructor(
private var velocityTracker: VelocityTracker? = null private var velocityTracker: VelocityTracker? = null
private val isFalseTouch: Boolean private val isFalseTouch: Boolean
get() = falsingManager.isFalseTouch get() = falsingManager.isFalseTouch(NOTIFICATION_DRAG_DOWN)
var qsExpanded: Boolean = false var qsExpanded: Boolean = false
var pulseExpandAbortListener: Runnable? = null var pulseExpandAbortListener: Runnable? = null
var bouncerShowing: Boolean = false var bouncerShowing: Boolean = false

View File

@@ -227,7 +227,7 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
|| (isFastNonDismissGesture && isAbleToShowMenu); || (isFastNonDismissGesture && isAbleToShowMenu);
int menuSnapTarget = menuRow.getMenuSnapTarget(); int menuSnapTarget = menuRow.getMenuSnapTarget();
boolean isNonFalseMenuRevealingGesture = boolean isNonFalseMenuRevealingGesture =
!isFalseGesture(ev) && isMenuRevealingGestureAwayFromMenu; !isFalseGesture() && isMenuRevealingGestureAwayFromMenu;
if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture) if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
&& menuSnapTarget != 0) { && menuSnapTarget != 0) {
// Menu has not been snapped to previously and this is menu revealing gesture // Menu has not been snapped to previously and this is menu revealing gesture

View File

@@ -27,6 +27,7 @@ import android.view.ViewConfiguration;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardAffordanceView;
@@ -317,7 +318,9 @@ public class KeyguardAffordanceHelper {
// We snap back if the current translation is not far enough // We snap back if the current translation is not far enough
boolean snapBack = false; boolean snapBack = false;
if (mCallback.needsAntiFalsing()) { if (mCallback.needsAntiFalsing()) {
snapBack = snapBack || mFalsingManager.isFalseTouch(); snapBack = snapBack || mFalsingManager.isFalseTouch(
mTargetedView == mRightIcon
? Classifier.RIGHT_AFFORDANCE : Classifier.LEFT_AFFORDANCE);
} }
snapBack = snapBack || isBelowFalsingThreshold(); snapBack = snapBack || isBelowFalsingThreshold();

View File

@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone;
import static android.view.View.GONE; import static android.view.View.GONE;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
@@ -72,6 +73,7 @@ import com.android.keyguard.dagger.KeyguardStatusViewComponent;
import com.android.systemui.DejankUtils; import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeLog;
@@ -1268,7 +1270,7 @@ public class NotificationPanelViewController extends PanelViewController {
} }
private boolean flingExpandsQs(float vel) { private boolean flingExpandsQs(float vel) {
if (mFalsingManager.isUnlockingDisabled() || isFalseTouch()) { if (mFalsingManager.isUnlockingDisabled() || isFalseTouch(QUICK_SETTINGS)) {
return false; return false;
} }
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) { if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -1278,12 +1280,12 @@ public class NotificationPanelViewController extends PanelViewController {
} }
} }
private boolean isFalseTouch() { private boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
if (!mKeyguardAffordanceHelperCallback.needsAntiFalsing()) { if (!mKeyguardAffordanceHelperCallback.needsAntiFalsing()) {
return false; return false;
} }
if (mFalsingManager.isClassifierEnabled()) { if (mFalsingManager.isClassifierEnabled()) {
return mFalsingManager.isFalseTouch(); return mFalsingManager.isFalseTouch(interactionType);
} }
return !mQsTouchAboveFalsingThreshold; return !mQsTouchAboveFalsingThreshold;
} }

View File

@@ -16,6 +16,10 @@
package com.android.systemui.statusbar.phone; package com.android.systemui.statusbar.phone;
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import static com.android.systemui.classifier.Classifier.UNLOCK;
import static java.lang.Float.isNaN; import static java.lang.Float.isNaN;
import android.animation.Animator; import android.animation.Animator;
@@ -41,6 +45,7 @@ import com.android.internal.util.LatencyTracker;
import com.android.systemui.DejankUtils; import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -397,7 +402,12 @@ public abstract class PanelViewController {
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp); mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK); mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK);
} }
fling(vel, expand, isFalseTouch(x, y)); @Classifier.InteractionType int interactionType = vel > 0
? QUICK_SETTINGS : (
mKeyguardStateController.canDismissLockScreen()
? UNLOCK : BOUNCER_UNLOCK);
fling(vel, expand, isFalseTouch(x, y, interactionType));
onTrackingStopped(expand); onTrackingStopped(expand);
mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown; mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown;
if (mUpdateFlingOnLayout) { if (mUpdateFlingOnLayout) {
@@ -492,7 +502,11 @@ public abstract class PanelViewController {
return true; return true;
} }
if (isFalseTouch(x, y)) { @Classifier.InteractionType int interactionType = vel > 0
? QUICK_SETTINGS : (
mKeyguardStateController.canDismissLockScreen() ? UNLOCK : BOUNCER_UNLOCK);
if (isFalseTouch(x, y, interactionType)) {
return true; return true;
} }
if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) { if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -511,12 +525,13 @@ public abstract class PanelViewController {
* @param y the final y-coordinate when the finger was lifted * @param y the final y-coordinate when the finger was lifted
* @return whether this motion should be regarded as a false touch * @return whether this motion should be regarded as a false touch
*/ */
private boolean isFalseTouch(float x, float y) { private boolean isFalseTouch(float x, float y,
@Classifier.InteractionType int interactionType) {
if (!mStatusBar.isFalsingThresholdNeeded()) { if (!mStatusBar.isFalsingThresholdNeeded()) {
return false; return false;
} }
if (mFalsingManager.isClassifierEnabled()) { if (mFalsingManager.isClassifierEnabled()) {
return mFalsingManager.isFalseTouch(); return mFalsingManager.isFalseTouch(interactionType);
} }
if (!mTouchAboveFalsingThreshold) { if (!mTouchAboveFalsingThreshold) {
return true; return true;