Merge changes from topic "b172655679-bayes-falsing" into sc-dev
* changes: Add Falsing to quick settings bottom buttons. Collapse QS when falsing happens. Separate out FalsingManager#isFalseTap
This commit is contained in:
@@ -70,17 +70,17 @@ target. Match the methods with the gesture you expect the device owner to use.
|
|||||||
|
|
||||||
### Single Tap
|
### Single Tap
|
||||||
|
|
||||||
`FalsingManager#isFalseTap(boolean robustCheck, double falsePenalty)`. This
|
`FalsingManager#isSimpleTape()`. This method
|
||||||
method tells the `FalsingManager` that you want to validate a single tap. It
|
performs a only very basic checking, checking that observed `MotionEvent`s are
|
||||||
|
all within some small x & y region ("touch slop"). Useful for only the most simple of scenarios,
|
||||||
|
you probably want `FalsingManager#isFalseTap` method for most cases.
|
||||||
|
|
||||||
|
`FalsingManager#isFalseTap(@Penalty int penalty)`. This
|
||||||
|
method tells the `FalsingManager` that you want to thoroughly validate a single tap. It
|
||||||
returns true if it thinks the tap should be rejected (i.e. the tap looks more
|
returns true if it thinks the tap should be rejected (i.e. the tap looks more
|
||||||
like a swipe) and false otherwise.
|
like a swipe) and false otherwise.
|
||||||
|
|
||||||
`robustCheck` determines what heuristics are used. If set to false, the method
|
It runs through the following heuristics to validate a tap:
|
||||||
performs a only very basic checking, checking that observed `MotionEvent`s are
|
|
||||||
all within some small x & y region ("touch slop").
|
|
||||||
|
|
||||||
When `robustCheck` is set to true, several more advanced rules are additionally
|
|
||||||
applied:
|
|
||||||
|
|
||||||
1. If the device recognizes a face (i.e. face-auth) the tap is **accepted**.
|
1. If the device recognizes a face (i.e. face-auth) the tap is **accepted**.
|
||||||
2. If the tap is the _second_ tap in recent history and looks like a valid Double Tap
|
2. If the tap is the _second_ tap in recent history and looks like a valid Double Tap
|
||||||
@@ -90,19 +90,18 @@ applied:
|
|||||||
4. Otherwise the tap is **accepted**.
|
4. Otherwise the tap is **accepted**.
|
||||||
|
|
||||||
All the above rules are applied only after first confirming the gesture does
|
All the above rules are applied only after first confirming the gesture does
|
||||||
in fact look like a basic tap.
|
in fact look like a simple tap.
|
||||||
|
|
||||||
`falsePenalty` is a measure of how much the `HistoryTracker`'s belief should be
|
`penalty` is a measure of how much the `HistoryTracker`'s belief should be
|
||||||
penalized in the event that the tap is rejected. This value is only used if
|
penalized in the event that the tap is rejected. This value is only used if
|
||||||
`robustCheck` is set to true.
|
the gesture fails to validate as a simple tap.
|
||||||
|
|
||||||
A value of `0` means no change in belief. A value of `1` means a _very_ strong
|
The `@FalsingManager.Penalty` values are fairly straightforward, but note that you
|
||||||
confidence in a false tap. In general, as a single tap on the screen is not
|
should generally be choosing `LOW_PENALTY`. It is inherently difficult to know if a
|
||||||
verifiable, a small value should be supplied - on the order of `0.1`. Pass `0`
|
tap is truly false or not, so a single mis-tap should apply only a small penalty.
|
||||||
if you don't want to penalize belief at all. Pass a higher value
|
If the owner is further along in a UX flow, and is still mis-tapping, it may make more
|
||||||
the earlier in the UX flow your interaction occurs. Once an owner is farther
|
sense to increase the penalty as mis-taps should be less likely to occur after
|
||||||
along in a UX flow (multiple taps or swipes), its safer to assume that a single
|
several successful gestures.
|
||||||
accidental tap should cause less of a penalty.
|
|
||||||
|
|
||||||
### Double Tap
|
### Double Tap
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.plugins;
|
package com.android.systemui.plugins;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
@@ -24,6 +25,8 @@ import com.android.systemui.util.sensors.ThresholdSensor;
|
|||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that decides whether a touch on the phone was accidental. i.e. Pocket Dialing.
|
* Interface that decides whether a touch on the phone was accidental. i.e. Pocket Dialing.
|
||||||
@@ -34,6 +37,20 @@ import java.io.PrintWriter;
|
|||||||
public interface FalsingManager {
|
public interface FalsingManager {
|
||||||
int VERSION = 6;
|
int VERSION = 6;
|
||||||
|
|
||||||
|
int NO_PENALTY = 0;
|
||||||
|
int LOW_PENALTY = 1;
|
||||||
|
int MODERATE_PENALTY = 2;
|
||||||
|
int HIGH_PENALTY = 3;
|
||||||
|
|
||||||
|
@IntDef({
|
||||||
|
NO_PENALTY,
|
||||||
|
LOW_PENALTY,
|
||||||
|
MODERATE_PENALTY,
|
||||||
|
HIGH_PENALTY
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface Penalty {}
|
||||||
|
|
||||||
void onSuccessfulUnlock();
|
void onSuccessfulUnlock();
|
||||||
|
|
||||||
boolean isUnlockingDisabled();
|
boolean isUnlockingDisabled();
|
||||||
@@ -41,23 +58,31 @@ public interface FalsingManager {
|
|||||||
/** Returns true if the gesture should be rejected. */
|
/** Returns true if the gesture should be rejected. */
|
||||||
boolean isFalseTouch(int interactionType);
|
boolean isFalseTouch(int interactionType);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the FalsingManager thinks the last gesure was not a valid tap.
|
* Does basic checking to see if gesture looks like a tap.
|
||||||
*
|
*
|
||||||
* The first parameter, robustCheck, distinctly changes behavior. When set to false,
|
* Only does the most basic of checks. No penalty is applied if this method returns 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
|
* For more robust analysis, use {@link #isFalseTap(int)}.
|
||||||
* is performed that can include historical interactions and other contextual cues to see
|
*/
|
||||||
|
boolean isSimpleTap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the FalsingManager thinks the last gesture was not a valid tap.
|
||||||
|
*
|
||||||
|
* This method runs a more thorough analysis than the similar {@link #isSimpleTap()},
|
||||||
|
* that can include historical interactions and other contextual cues to see
|
||||||
* if the tap looks accidental.
|
* if the tap looks accidental.
|
||||||
*
|
*
|
||||||
* Set robustCheck to true if you want to validate a tap for launching an action, like opening
|
* Use this method 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
|
* a notification.
|
||||||
* tap.
|
|
||||||
*
|
*
|
||||||
* The second parameter, falsePenalty, indicates how much this should affect future gesture
|
* The only parameter, penalty, indicates how much this should affect future gesture
|
||||||
* classifications if this tap looks like a false.
|
* classifications if this tap looks like a false. As single taps are hard to confirm as false
|
||||||
|
* or otherwise, a low penalty value is encouraged unless context indicates otherwise.
|
||||||
*/
|
*/
|
||||||
boolean isFalseTap(boolean robustCheck, double falsePenalty);
|
boolean isFalseTap(@Penalty int penalty);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the last two gestures do not look like a double tap.
|
* Returns true if the last two gestures do not look like a double tap.
|
||||||
|
|||||||
@@ -218,18 +218,43 @@ public class BrightLineFalsingManager implements FalsingManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFalseTap(boolean robustCheck, double falsePenalty) {
|
public boolean isSimpleTap() {
|
||||||
|
FalsingClassifier.Result result = mSingleTapClassifier.isTap(
|
||||||
|
mDataProvider.getRecentMotionEvents(), 0);
|
||||||
|
mPriorResults = Collections.singleton(result);
|
||||||
|
|
||||||
|
return !result.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFalseTap(@Penalty int penalty) {
|
||||||
if (skipFalsing()) {
|
if (skipFalsing()) {
|
||||||
return false;
|
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 singleTapResult =
|
FalsingClassifier.Result singleTapResult =
|
||||||
mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents().isEmpty()
|
mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents().isEmpty()
|
||||||
? mDataProvider.getPriorMotionEvents()
|
? mDataProvider.getPriorMotionEvents()
|
||||||
: mDataProvider.getRecentMotionEvents());
|
: mDataProvider.getRecentMotionEvents(), falsePenalty);
|
||||||
mPriorResults = Collections.singleton(singleTapResult);
|
mPriorResults = Collections.singleton(singleTapResult);
|
||||||
|
|
||||||
if (!singleTapResult.isFalse() && robustCheck) {
|
if (!singleTapResult.isFalse()) {
|
||||||
if (mDataProvider.isJustUnlockedWithFace()) {
|
if (mDataProvider.isJustUnlockedWithFace()) {
|
||||||
// Immediately pass if a face is detected.
|
// Immediately pass if a face is detected.
|
||||||
mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1));
|
mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1));
|
||||||
|
|||||||
@@ -66,13 +66,13 @@ public class DoubleTapClassifier extends FalsingClassifier {
|
|||||||
public boolean isDoubleTap(List<MotionEvent> firstEvents, List<MotionEvent> secondEvents,
|
public boolean isDoubleTap(List<MotionEvent> firstEvents, List<MotionEvent> secondEvents,
|
||||||
StringBuilder reason) {
|
StringBuilder reason) {
|
||||||
|
|
||||||
Result firstTap = mSingleTapClassifier.isTap(firstEvents);
|
Result firstTap = mSingleTapClassifier.isTap(firstEvents, 0.5);
|
||||||
if (firstTap.isFalse()) {
|
if (firstTap.isFalse()) {
|
||||||
reason.append("First gesture is not a tap. ").append(firstTap.getReason());
|
reason.append("First gesture is not a tap. ").append(firstTap.getReason());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result secondTap = mSingleTapClassifier.isTap(secondEvents);
|
Result secondTap = mSingleTapClassifier.isTap(secondEvents, 0.5);
|
||||||
if (secondTap.isFalse()) {
|
if (secondTap.isFalse()) {
|
||||||
reason.append("Second gesture is not a tap. ").append(secondTap.getReason());
|
reason.append("Second gesture is not a tap. ").append(secondTap.getReason());
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class FalsingManagerFake implements FalsingManager {
|
public class FalsingManagerFake implements FalsingManager {
|
||||||
private boolean mIsFalseTouch;
|
private boolean mIsFalseTouch;
|
||||||
private boolean mIsFalseTap;
|
private boolean mIsSimpleTap;
|
||||||
private boolean mIsFalseDoubleTap;
|
private boolean mIsFalseDoubleTap;
|
||||||
private boolean mIsUnlockingDisabled;
|
private boolean mIsUnlockingDisabled;
|
||||||
private boolean mIsClassiferEnabled;
|
private boolean mIsClassiferEnabled;
|
||||||
@@ -67,12 +67,12 @@ public class FalsingManagerFake implements FalsingManager {
|
|||||||
return mIsFalseTouch;
|
return mIsFalseTouch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFalseRobustTap(boolean falseRobustTap) {
|
public void setFalseTap(boolean falseRobustTap) {
|
||||||
mIsFalseRobustTap = falseRobustTap;
|
mIsFalseRobustTap = falseRobustTap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFalseTap(boolean falseTap) {
|
public void setSimpleTap(boolean isSimpleTape) {
|
||||||
mIsFalseTap = falseTap;
|
mIsSimpleTap = isSimpleTape;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFalseDoubleTap(boolean falseDoubleTap) {
|
public void setFalseDoubleTap(boolean falseDoubleTap) {
|
||||||
@@ -80,8 +80,13 @@ public class FalsingManagerFake implements FalsingManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFalseTap(boolean robustCheck, double falsePenalty) {
|
public boolean isSimpleTap() {
|
||||||
return robustCheck ? mIsFalseRobustTap : mIsFalseTap;
|
return mIsSimpleTap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFalseTap(@Penalty int penalty) {
|
||||||
|
return mIsFalseRobustTap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -131,8 +131,13 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFalseTap(boolean robustCheck, double falsePenalty) {
|
public boolean isSimpleTap() {
|
||||||
return mInternalFalsingManager.isFalseTap(robustCheck, falsePenalty);
|
return mInternalFalsingManager.isSimpleTap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFalseTap(@Penalty int penalty) {
|
||||||
|
return mInternalFalsingManager.isFalseTap(penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ public class SingleTapClassifier extends FalsingClassifier {
|
|||||||
Result calculateFalsingResult(
|
Result calculateFalsingResult(
|
||||||
@Classifier.InteractionType int interactionType,
|
@Classifier.InteractionType int interactionType,
|
||||||
double historyBelief, double historyConfidence) {
|
double historyBelief, double historyConfidence) {
|
||||||
return isTap(getRecentMotionEvents());
|
return isTap(getRecentMotionEvents(), 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */
|
/** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */
|
||||||
public Result isTap(List<MotionEvent> motionEvents) {
|
public Result isTap(List<MotionEvent> motionEvents, double falsePenalty) {
|
||||||
if (motionEvents.isEmpty()) {
|
if (motionEvents.isEmpty()) {
|
||||||
return falsed(0, "no motion events");
|
return falsed(0, "no motion events");
|
||||||
}
|
}
|
||||||
@@ -60,13 +60,13 @@ public class SingleTapClassifier extends FalsingClassifier {
|
|||||||
+ Math.abs(event.getX() - downX)
|
+ Math.abs(event.getX() - downX)
|
||||||
+ "vs "
|
+ "vs "
|
||||||
+ mTouchSlop;
|
+ mTouchSlop;
|
||||||
return falsed(0.5, reason);
|
return falsed(falsePenalty, reason);
|
||||||
} else if (Math.abs(event.getY() - downY) >= mTouchSlop) {
|
} else if (Math.abs(event.getY() - downY) >= mTouchSlop) {
|
||||||
reason = "dY too big for a tap: "
|
reason = "dY too big for a tap: "
|
||||||
+ Math.abs(event.getY() - downY)
|
+ Math.abs(event.getY() - downY)
|
||||||
+ " vs "
|
+ " vs "
|
||||||
+ mTouchSlop;
|
+ mTouchSlop;
|
||||||
return falsed(0.5, reason);
|
return falsed(falsePenalty, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result.passed(0);
|
return Result.passed(0);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.globalactions.GlobalActionsDialogLite;
|
import com.android.systemui.globalactions.GlobalActionsDialogLite;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.qs.dagger.QSScope;
|
import com.android.systemui.qs.dagger.QSScope;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.statusbar.phone.MultiUserSwitch;
|
import com.android.systemui.statusbar.phone.MultiUserSwitch;
|
||||||
@@ -62,6 +63,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
|||||||
private final QuickQSPanelController mQuickQSPanelController;
|
private final QuickQSPanelController mQuickQSPanelController;
|
||||||
private final TunerService mTunerService;
|
private final TunerService mTunerService;
|
||||||
private final MetricsLogger mMetricsLogger;
|
private final MetricsLogger mMetricsLogger;
|
||||||
|
private final FalsingManager mFalsingManager;
|
||||||
private final SettingsButton mSettingsButton;
|
private final SettingsButton mSettingsButton;
|
||||||
private final TextView mBuildText;
|
private final TextView mBuildText;
|
||||||
private final View mEdit;
|
private final View mEdit;
|
||||||
@@ -83,8 +85,9 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
|||||||
private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
|
private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
// Don't do anything until view are unhidden
|
// Don't do anything until views are unhidden. Don't do anything if the tap looks
|
||||||
if (!mExpanded) {
|
// suspicious.
|
||||||
|
if (!mExpanded || mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +135,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
|||||||
DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
|
DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
|
||||||
QSPanelController qsPanelController, QSDetailDisplayer qsDetailDisplayer,
|
QSPanelController qsPanelController, QSDetailDisplayer qsDetailDisplayer,
|
||||||
QuickQSPanelController quickQSPanelController,
|
QuickQSPanelController quickQSPanelController,
|
||||||
TunerService tunerService, MetricsLogger metricsLogger,
|
TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager,
|
||||||
@Named(PM_LITE_ENABLED) boolean showPMLiteButton,
|
@Named(PM_LITE_ENABLED) boolean showPMLiteButton,
|
||||||
GlobalActionsDialogLite globalActionsDialog) {
|
GlobalActionsDialogLite globalActionsDialog) {
|
||||||
super(view);
|
super(view);
|
||||||
@@ -146,6 +149,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
|||||||
mQuickQSPanelController = quickQSPanelController;
|
mQuickQSPanelController = quickQSPanelController;
|
||||||
mTunerService = tunerService;
|
mTunerService = tunerService;
|
||||||
mMetricsLogger = metricsLogger;
|
mMetricsLogger = metricsLogger;
|
||||||
|
mFalsingManager = falsingManager;
|
||||||
|
|
||||||
mSettingsButton = mView.findViewById(R.id.settings_button);
|
mSettingsButton = mView.findViewById(R.id.settings_button);
|
||||||
mBuildText = mView.findViewById(R.id.build);
|
mBuildText = mView.findViewById(R.id.build);
|
||||||
@@ -184,9 +188,13 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
mEdit.setOnClickListener(view ->
|
mEdit.setOnClickListener(view -> {
|
||||||
mActivityStarter.postQSRunnableDismissingKeyguard(() ->
|
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
mQsPanelController.showEdit(view)));
|
return;
|
||||||
|
}
|
||||||
|
mActivityStarter.postQSRunnableDismissingKeyguard(() ->
|
||||||
|
mQsPanelController.showEdit(view));
|
||||||
|
});
|
||||||
|
|
||||||
mMultiUserSwitch.setQSDetailDisplayer(mQsDetailDisplayer);
|
mMultiUserSwitch.setQSDetailDisplayer(mQsDetailDisplayer);
|
||||||
mQsPanelController.setFooterPageIndicator(mPageIndicator);
|
mQsPanelController.setFooterPageIndicator(mPageIndicator);
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
|||||||
mUiEventLogger.logWithInstanceId(QSEvent.QS_ACTION_CLICK, 0, getMetricsSpec(),
|
mUiEventLogger.logWithInstanceId(QSEvent.QS_ACTION_CLICK, 0, getMetricsSpec(),
|
||||||
getInstanceId());
|
getInstanceId());
|
||||||
mQSLogger.logTileClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
|
mQSLogger.logTileClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
|
||||||
if (!mFalsingManager.isFalseTap(true, 0.1)) {
|
if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
mHandler.sendEmptyMessage(H.CLICK);
|
mHandler.sendEmptyMessage(H.CLICK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class ActivatableNotificationViewController
|
|||||||
result = mNotificationTapHelper.onTouchEvent(ev, mView.getActualHeight());
|
result = mNotificationTapHelper.onTouchEvent(ev, mView.getActualHeight());
|
||||||
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
|
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
|
||||||
// If this is a false tap, capture the even so it doesn't result in a click.
|
// If this is a false tap, capture the even so it doesn't result in a click.
|
||||||
return mFalsingManager.isFalseTap(true, 0.1);
|
return mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -881,7 +881,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
// Other parts of the system may intercept and handle all the falsing.
|
// Other parts of the system may intercept and handle all the falsing.
|
||||||
// Otherwise, if we see motion and follow-on events, try to classify them as a tap.
|
// Otherwise, if we see motion and follow-on events, try to classify them as a tap.
|
||||||
if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
|
if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
|
||||||
mFalsingManager.isFalseTap(true, 0.3);
|
mFalsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY);
|
||||||
}
|
}
|
||||||
return super.onInterceptTouchEvent(ev);
|
return super.onInterceptTouchEvent(ev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class NotificationTapHelper {
|
|||||||
mTrackTouch = event.getY() <= maxTouchableHeight;
|
mTrackTouch = event.getY() <= maxTouchableHeight;
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
if (mTrackTouch && mFalsingManager.isFalseTap(false, 0)) {
|
if (mTrackTouch && !mFalsingManager.isSimpleTap()) {
|
||||||
makeInactive();
|
makeInactive();
|
||||||
mTrackTouch = false;
|
mTrackTouch = false;
|
||||||
}
|
}
|
||||||
@@ -78,10 +78,10 @@ public class NotificationTapHelper {
|
|||||||
|
|
||||||
// 1) See if we have confidence that we can activate after a single tap.
|
// 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.
|
// 2) Else, see if it looks like a tap at all and check for a double-tap.
|
||||||
if (!mFalsingManager.isFalseTap(true, 0)) {
|
if (!mFalsingManager.isFalseTap(FalsingManager.NO_PENALTY)) {
|
||||||
makeInactive();
|
makeInactive();
|
||||||
return mDoubleTapListener.onDoubleTap();
|
return mDoubleTapListener.onDoubleTap();
|
||||||
} else if (!mFalsingManager.isFalseTap(false, 0)) {
|
} else if (mFalsingManager.isSimpleTap()) {
|
||||||
if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
|
if (mSlideBackListener != null && mSlideBackListener.onSlideBack()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -681,6 +681,9 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
new FalsingManager.FalsingBeliefListener() {
|
new FalsingManager.FalsingBeliefListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFalse() {
|
public void onFalse() {
|
||||||
|
// Hides quick settings.
|
||||||
|
mNotificationPanelViewController.resetViews(true);
|
||||||
|
// Hides bouncer and quick-quick settings.
|
||||||
mStatusBarKeyguardViewManager.reset(true);
|
mStatusBarKeyguardViewManager.reset(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.systemui.classifier;
|
package com.android.systemui.classifier;
|
||||||
|
|
||||||
|
import static com.android.systemui.plugins.FalsingManager.HIGH_PENALTY;
|
||||||
|
import static com.android.systemui.plugins.FalsingManager.NO_PENALTY;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
@@ -55,8 +58,6 @@ import java.util.Set;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
public class BrightLineClassifierTest extends SysuiTestCase {
|
public class BrightLineClassifierTest extends SysuiTestCase {
|
||||||
private static final long DOUBLE_TAP_TIMEOUT_MS = 1000;
|
|
||||||
|
|
||||||
private BrightLineFalsingManager mBrightLineFalsingManager;
|
private BrightLineFalsingManager mBrightLineFalsingManager;
|
||||||
@Mock
|
@Mock
|
||||||
private FalsingDataProvider mFalsingDataProvider;
|
private FalsingDataProvider mFalsingDataProvider;
|
||||||
@@ -91,7 +92,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
.thenReturn(mPassedResult);
|
.thenReturn(mPassedResult);
|
||||||
when(mClassifierB.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
when(mClassifierB.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
||||||
.thenReturn(mPassedResult);
|
.thenReturn(mPassedResult);
|
||||||
when(mSingleTapClassfier.isTap(any(List.class))).thenReturn(mPassedResult);
|
when(mSingleTapClassfier.isTap(any(List.class), anyDouble())).thenReturn(mPassedResult);
|
||||||
when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
||||||
.thenReturn(mPassedResult);
|
.thenReturn(mPassedResult);
|
||||||
mClassifiers.add(mClassifierA);
|
mClassifiers.add(mClassifierA);
|
||||||
@@ -170,13 +171,13 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsFalseTap_BasicCheck() {
|
public void testIsFalseTap_BasicCheck() {
|
||||||
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult);
|
when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mFalsedResult);
|
||||||
|
|
||||||
assertThat(mBrightLineFalsingManager.isFalseTap(false, 0)).isTrue();
|
assertThat(mBrightLineFalsingManager.isSimpleTap()).isFalse();
|
||||||
|
|
||||||
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
|
when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult);
|
||||||
|
|
||||||
assertThat(mBrightLineFalsingManager.isFalseTap(false, 0)).isFalse();
|
assertThat(mBrightLineFalsingManager.isSimpleTap()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -185,26 +186,26 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(new ArrayList<>());
|
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(new ArrayList<>());
|
||||||
when(mFalsingDataProvider.getPriorMotionEvents()).thenReturn(mMotionEventList);
|
when(mFalsingDataProvider.getPriorMotionEvents()).thenReturn(mMotionEventList);
|
||||||
|
|
||||||
mBrightLineFalsingManager.isFalseTap(false, 0);
|
mBrightLineFalsingManager.isFalseTap(0);
|
||||||
verify(mSingleTapClassfier).isTap(mMotionEventList);
|
verify(mSingleTapClassfier).isTap(mMotionEventList, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsFalseTap_RobustCheck_NoFaceAuth() {
|
public void testIsFalseTap_RobustCheck_NoFaceAuth() {
|
||||||
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
|
when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult);
|
||||||
when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
||||||
.thenReturn(mFalsedResult);
|
.thenReturn(mFalsedResult);
|
||||||
when(mHistoryTracker.falseBelief()).thenReturn(1.0);
|
when(mHistoryTracker.falseBelief()).thenReturn(1.0);
|
||||||
mFalsingDataProvider.setJustUnlockedWithFace(false);
|
mFalsingDataProvider.setJustUnlockedWithFace(false);
|
||||||
assertThat(mBrightLineFalsingManager.isFalseTap(true, 0)).isTrue();
|
assertThat(mBrightLineFalsingManager.isFalseTap(NO_PENALTY)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsFalseTap_RobustCheck_FaceAuth() {
|
public void testIsFalseTap_RobustCheck_FaceAuth() {
|
||||||
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult);
|
when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mPassedResult);
|
||||||
when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true);
|
when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true);
|
||||||
assertThat(mBrightLineFalsingManager.isFalseTap(true, 0)).isFalse();
|
assertThat(mBrightLineFalsingManager.isFalseTap(NO_PENALTY)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -230,7 +231,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testHistory_singleTap() {
|
public void testHistory_singleTap() {
|
||||||
// When trying to classify single taps, we don't immediately add results to history.
|
// When trying to classify single taps, we don't immediately add results to history.
|
||||||
mBrightLineFalsingManager.isFalseTap(false, 0);
|
mBrightLineFalsingManager.isFalseTap(HIGH_PENALTY);
|
||||||
mGestureFinalizedListener.onGestureFinalized(1000);
|
mGestureFinalizedListener.onGestureFinalized(1000);
|
||||||
verify(mHistoryTracker).addResults(anyCollection(), eq(1000L));
|
verify(mHistoryTracker).addResults(anyCollection(), eq(1000L));
|
||||||
}
|
}
|
||||||
@@ -238,9 +239,9 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testHistory_multipleSingleTaps() {
|
public void testHistory_multipleSingleTaps() {
|
||||||
// When trying to classify single taps, we don't immediately add results to history.
|
// When trying to classify single taps, we don't immediately add results to history.
|
||||||
mBrightLineFalsingManager.isFalseTap(false, 0);
|
mBrightLineFalsingManager.isFalseTap(HIGH_PENALTY);
|
||||||
mGestureFinalizedListener.onGestureFinalized(1000);
|
mGestureFinalizedListener.onGestureFinalized(1000);
|
||||||
mBrightLineFalsingManager.isFalseTap(false, 0);
|
mBrightLineFalsingManager.isFalseTap(HIGH_PENALTY);
|
||||||
mGestureFinalizedListener.onGestureFinalized(2000);
|
mGestureFinalizedListener.onGestureFinalized(2000);
|
||||||
verify(mHistoryTracker).addResults(anyCollection(), eq(1000L));
|
verify(mHistoryTracker).addResults(anyCollection(), eq(1000L));
|
||||||
verify(mHistoryTracker).addResults(anyCollection(), eq(2000L));
|
verify(mHistoryTracker).addResults(anyCollection(), eq(2000L));
|
||||||
@@ -249,10 +250,10 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testHistory_doubleTap() {
|
public void testHistory_doubleTap() {
|
||||||
// When trying to classify single taps, we don't immediately add results to history.
|
// When trying to classify single taps, we don't immediately add results to history.
|
||||||
mBrightLineFalsingManager.isFalseTap(false, 0);
|
mBrightLineFalsingManager.isFalseTap(HIGH_PENALTY);
|
||||||
mGestureFinalizedListener.onGestureFinalized(1000);
|
mGestureFinalizedListener.onGestureFinalized(1000);
|
||||||
// Before checking for double tap, we may check for single-tap on the second gesture.
|
// Before checking for double tap, we may check for single-tap on the second gesture.
|
||||||
mBrightLineFalsingManager.isFalseTap(false, 0);
|
mBrightLineFalsingManager.isFalseTap(HIGH_PENALTY);
|
||||||
mBrightLineFalsingManager.isFalseDoubleTap();
|
mBrightLineFalsingManager.isFalseDoubleTap();
|
||||||
mGestureFinalizedListener.onGestureFinalized(2000);
|
mGestureFinalizedListener.onGestureFinalized(2000);
|
||||||
|
|
||||||
@@ -270,8 +271,8 @@ public class BrightLineClassifierTest extends SysuiTestCase {
|
|||||||
.thenReturn(mFalsedResult);
|
.thenReturn(mFalsedResult);
|
||||||
assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse();
|
assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse();
|
||||||
|
|
||||||
when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult);
|
when(mSingleTapClassfier.isTap(mMotionEventList, 0)).thenReturn(mFalsedResult);
|
||||||
assertThat(mBrightLineFalsingManager.isFalseTap(false, 0)).isFalse();
|
assertThat(mBrightLineFalsingManager.isSimpleTap()).isFalse();
|
||||||
|
|
||||||
when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
when(mDoubleTapClassifier.classifyGesture(anyInt(), anyDouble(), anyDouble()))
|
||||||
.thenReturn(mFalsedResult);
|
.thenReturn(mFalsedResult);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui.classifier;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||||
import static org.mockito.ArgumentMatchers.anyList;
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleTap() {
|
public void testSingleTap() {
|
||||||
when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult);
|
when(mSingleTapClassifier.isTap(anyList(), anyDouble())).thenReturn(mFalsedResult);
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoubleTap() {
|
public void testDoubleTap() {
|
||||||
when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult);
|
when(mSingleTapClassifier.isTap(anyList(), anyDouble())).thenReturn(mPassedResult);
|
||||||
|
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
||||||
@@ -104,7 +105,8 @@ public class DoubleTapClassifierTest extends ClassifierTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadFirstTap() {
|
public void testBadFirstTap() {
|
||||||
when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult, mFalsedResult);
|
when(mSingleTapClassifier.isTap(anyList(), anyDouble()))
|
||||||
|
.thenReturn(mPassedResult, mFalsedResult);
|
||||||
|
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
||||||
@@ -120,7 +122,8 @@ public class DoubleTapClassifierTest extends ClassifierTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadSecondTap() {
|
public void testBadSecondTap() {
|
||||||
when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult, mPassedResult);
|
when(mSingleTapClassifier.isTap(anyList(), anyDouble()))
|
||||||
|
.thenReturn(mFalsedResult, mPassedResult);
|
||||||
|
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
||||||
@@ -136,7 +139,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadTouchSlop() {
|
public void testBadTouchSlop() {
|
||||||
when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult);
|
when(mSingleTapClassifier.isTap(anyList(), anyDouble())).thenReturn(mFalsedResult);
|
||||||
|
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
||||||
@@ -152,7 +155,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBadTouchSlow() {
|
public void testBadTouchSlow() {
|
||||||
when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult);
|
when(mSingleTapClassifier.isTap(anyList(), anyDouble())).thenReturn(mFalsedResult);
|
||||||
|
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
||||||
|
|||||||
@@ -142,12 +142,12 @@ public class SingleTapClassifierTest extends ClassifierTest {
|
|||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1);
|
||||||
|
|
||||||
assertThat(mClassifier.isTap(mMotionEvents).isFalse()).isFalse();
|
assertThat(mClassifier.isTap(mMotionEvents, 0.5).isFalse()).isFalse();
|
||||||
|
|
||||||
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
|
||||||
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
|
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
|
||||||
|
|
||||||
assertThat(mClassifier.isTap(mMotionEvents).isFalse()).isTrue();
|
assertThat(mClassifier.isTap(mMotionEvents, 0.5).isFalse()).isTrue();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import com.android.internal.logging.MetricsLogger;
|
|||||||
import com.android.internal.logging.testing.FakeMetricsLogger;
|
import com.android.internal.logging.testing.FakeMetricsLogger;
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.classifier.FalsingManagerFake;
|
||||||
import com.android.systemui.globalactions.GlobalActionsDialogLite;
|
import com.android.systemui.globalactions.GlobalActionsDialogLite;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
@@ -121,7 +122,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
|
|||||||
mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
|
mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
|
||||||
mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
|
mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
|
||||||
new QSDetailDisplayer(), mQuickQSPanelController, mFakeTunerService,
|
new QSDetailDisplayer(), mQuickQSPanelController, mFakeTunerService,
|
||||||
mMetricsLogger, false, mGlobalActionsDialog);
|
mMetricsLogger, new FalsingManagerFake(), false, mGlobalActionsDialog);
|
||||||
|
|
||||||
mController.init();
|
mController.init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,12 +150,12 @@ public class QSTileImplTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClick_falsing() {
|
public void testClick_falsing() {
|
||||||
mFalsingManager.setFalseRobustTap(true);
|
mFalsingManager.setFalseTap(true);
|
||||||
mTile.click();
|
mTile.click();
|
||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
assertThat(mTile.mClicked).isFalse();
|
assertThat(mTile.mClicked).isFalse();
|
||||||
|
|
||||||
mFalsingManager.setFalseRobustTap(false);
|
mFalsingManager.setFalseTap(false);
|
||||||
mTile.click();
|
mTile.click();
|
||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
assertThat(mTile.mClicked).isTrue();
|
assertThat(mTile.mClicked).isTrue();
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ public class NotificationTapHelperTest extends SysuiTestCase {
|
|||||||
when(mResources.getDimension(R.dimen.double_tap_slop))
|
when(mResources.getDimension(R.dimen.double_tap_slop))
|
||||||
.thenReturn((float) ViewConfiguration.get(mContext).getScaledTouchSlop() - 1);
|
.thenReturn((float) ViewConfiguration.get(mContext).getScaledTouchSlop() - 1);
|
||||||
|
|
||||||
mFalsingManager.setFalseRobustTap(true); // Test double tapping most of the time.
|
mFalsingManager.setSimpleTap(true);
|
||||||
|
mFalsingManager.setFalseTap(true); // Test double tapping most of the time.
|
||||||
|
|
||||||
mNotificationTapHelper = new NotificationTapHelper.Factory(mFalsingManager, mFakeExecutor)
|
mNotificationTapHelper = new NotificationTapHelper.Factory(mFalsingManager, mFakeExecutor)
|
||||||
.create(mActivationListener, mDoubleTapListener, mSlideBackListener);
|
.create(mActivationListener, mDoubleTapListener, mSlideBackListener);
|
||||||
@@ -158,7 +159,7 @@ public class NotificationTapHelperTest extends SysuiTestCase {
|
|||||||
1,
|
1,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
mFalsingManager.setFalseTap(true);
|
mFalsingManager.setSimpleTap(false);
|
||||||
mNotificationTapHelper.onTouchEvent(evDownA);
|
mNotificationTapHelper.onTouchEvent(evDownA);
|
||||||
mNotificationTapHelper.onTouchEvent(evUpA);
|
mNotificationTapHelper.onTouchEvent(evUpA);
|
||||||
verify(mActivationListener, never()).onActiveChanged(true);
|
verify(mActivationListener, never()).onActiveChanged(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user