Add ability to ignore gestures in FalsingManager
This gives other parts of the system the ability to temporarily override the falsing manager, telling it to ignore a given gesture. The intent is to give other parts of the system a chance to include their own falsing information (such as whether a button was tapped or not), giving the FalsingManager more context about what is going on. As of right now, their is no way to feedback this context-aware falsing information back to the FalsingManager. An API for this is still being explored. Bug: 172655679 Test: atest SystemUITests && manual Change-Id: I87ee94a2386622ebff7580346325ae07e3bb5f5d
This commit is contained in:
@@ -23,10 +23,16 @@ import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.systemui.Gefingerpoken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Base class for all Keyguard password/pattern/pin related inputs.
|
||||
*/
|
||||
public abstract class KeyguardInputView extends LinearLayout {
|
||||
private final List<Gefingerpoken> mMotionEventListener = new ArrayList<>();
|
||||
|
||||
public KeyguardInputView(Context context) {
|
||||
super(context);
|
||||
@@ -52,4 +58,25 @@ public abstract class KeyguardInputView extends LinearLayout {
|
||||
boolean startDisappearAnimation(Runnable finishRunnable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void addMotionEventListener(Gefingerpoken listener) {
|
||||
mMotionEventListener.add(listener);
|
||||
}
|
||||
|
||||
void removeMotionEventListener(Gefingerpoken listener) {
|
||||
mMotionEventListener.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return mMotionEventListener.stream().anyMatch(listener -> listener.onTouchEvent(event))
|
||||
|| super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||
return mMotionEventListener.stream().anyMatch(
|
||||
listener -> listener.onInterceptTouchEvent(event))
|
||||
|| super.onInterceptTouchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.android.internal.util.LatencyTracker;
|
||||
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.dagger.qualifiers.Main;
|
||||
import com.android.systemui.util.ViewController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
@@ -155,6 +156,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
private final Resources mResources;
|
||||
private LiftToActivateListener mLiftToActivateListener;
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private final FalsingCollector mFalsingCollector;
|
||||
|
||||
@Inject
|
||||
public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
@@ -163,7 +165,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
|
||||
InputMethodManager inputMethodManager, @Main DelayableExecutor mainExecutor,
|
||||
@Main Resources resources, LiftToActivateListener liftToActivateListener,
|
||||
TelephonyManager telephonyManager) {
|
||||
TelephonyManager telephonyManager, FalsingCollector falsingCollector) {
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mLatencyTracker = latencyTracker;
|
||||
@@ -173,6 +175,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
mResources = resources;
|
||||
mLiftToActivateListener = liftToActivateListener;
|
||||
mTelephonyManager = telephonyManager;
|
||||
mFalsingCollector = falsingCollector;
|
||||
}
|
||||
|
||||
/** Create a new {@link KeyguardInputViewController}. */
|
||||
@@ -191,17 +194,17 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
|
||||
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
|
||||
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
|
||||
mLiftToActivateListener);
|
||||
mLiftToActivateListener, mFalsingCollector);
|
||||
} else if (keyguardInputView instanceof KeyguardSimPinView) {
|
||||
return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
|
||||
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
|
||||
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
|
||||
mLiftToActivateListener, mTelephonyManager);
|
||||
mLiftToActivateListener, mTelephonyManager, mFalsingCollector);
|
||||
} else if (keyguardInputView instanceof KeyguardSimPukView) {
|
||||
return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
|
||||
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
|
||||
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
|
||||
mLiftToActivateListener, mTelephonyManager);
|
||||
mLiftToActivateListener, mTelephonyManager, mFalsingCollector);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unable to find controller for " + keyguardInputView);
|
||||
|
||||
@@ -25,12 +25,15 @@ 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;
|
||||
|
||||
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) -> {
|
||||
@@ -40,13 +43,26 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
|
||||
return false;
|
||||
};
|
||||
|
||||
private final OnTouchListener mOnTouchListener = (v, event) -> {
|
||||
private final OnTouchListener mActionButtonTouchListener = (v, event) -> {
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
mView.doHapticKeyClick();
|
||||
}
|
||||
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,
|
||||
@@ -54,10 +70,12 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
|
||||
KeyguardSecurityCallback keyguardSecurityCallback,
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
|
||||
LatencyTracker latencyTracker,
|
||||
LiftToActivateListener liftToActivateListener) {
|
||||
LiftToActivateListener liftToActivateListener,
|
||||
FalsingCollector falsingCollector) {
|
||||
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
|
||||
messageAreaControllerFactory, latencyTracker);
|
||||
mLiftToActivateListener = liftToActivateListener;
|
||||
mFalsingCollector = falsingCollector;
|
||||
mPasswordEntry = mView.findViewById(mView.getPasswordTextViewId());
|
||||
}
|
||||
|
||||
@@ -65,11 +83,13 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
|
||||
protected void onViewAttached() {
|
||||
super.onViewAttached();
|
||||
|
||||
mView.addMotionEventListener(mGlobalTouchListener);
|
||||
|
||||
mPasswordEntry.setOnKeyListener(mOnKeyListener);
|
||||
mPasswordEntry.setUserActivityListener(this::onUserInput);
|
||||
|
||||
View deleteButton = mView.findViewById(R.id.delete_button);
|
||||
deleteButton.setOnTouchListener(mOnTouchListener);
|
||||
deleteButton.setOnTouchListener(mActionButtonTouchListener);
|
||||
deleteButton.setOnClickListener(v -> {
|
||||
// check for time-based lockouts
|
||||
if (mPasswordEntry.isEnabled()) {
|
||||
@@ -87,7 +107,7 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
|
||||
|
||||
View okButton = mView.findViewById(R.id.key_enter);
|
||||
if (okButton != null) {
|
||||
okButton.setOnTouchListener(mOnTouchListener);
|
||||
okButton.setOnTouchListener(mActionButtonTouchListener);
|
||||
okButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.internal.util.LatencyTracker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
|
||||
public class KeyguardPinViewController
|
||||
extends KeyguardPinBasedInputViewController<KeyguardPINView> {
|
||||
@@ -32,10 +33,11 @@ public class KeyguardPinViewController
|
||||
SecurityMode securityMode, LockPatternUtils lockPatternUtils,
|
||||
KeyguardSecurityCallback keyguardSecurityCallback,
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
|
||||
LatencyTracker latencyTracker,
|
||||
LiftToActivateListener liftToActivateListener) {
|
||||
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
|
||||
FalsingCollector falsingCollector) {
|
||||
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener);
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
|
||||
falsingCollector);
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.android.internal.util.LatencyTracker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
|
||||
public class KeyguardSimPinViewController
|
||||
extends KeyguardPinBasedInputViewController<KeyguardSimPinView> {
|
||||
@@ -76,11 +77,11 @@ public class KeyguardSimPinViewController
|
||||
SecurityMode securityMode, LockPatternUtils lockPatternUtils,
|
||||
KeyguardSecurityCallback keyguardSecurityCallback,
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
|
||||
LatencyTracker latencyTracker,
|
||||
LiftToActivateListener liftToActivateListener,
|
||||
TelephonyManager telephonyManager) {
|
||||
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
|
||||
TelephonyManager telephonyManager, FalsingCollector falsingCollector) {
|
||||
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener);
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
|
||||
falsingCollector);
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mTelephonyManager = telephonyManager;
|
||||
mSimImageView = mView.findViewById(R.id.keyguard_sim);
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
|
||||
public class KeyguardSimPukViewController
|
||||
extends KeyguardPinBasedInputViewController<KeyguardSimPukView> {
|
||||
@@ -83,11 +84,11 @@ public class KeyguardSimPukViewController
|
||||
SecurityMode securityMode, LockPatternUtils lockPatternUtils,
|
||||
KeyguardSecurityCallback keyguardSecurityCallback,
|
||||
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
|
||||
LatencyTracker latencyTracker,
|
||||
LiftToActivateListener liftToActivateListener,
|
||||
TelephonyManager telephonyManager) {
|
||||
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
|
||||
TelephonyManager telephonyManager, FalsingCollector falsingCollector) {
|
||||
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener);
|
||||
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
|
||||
falsingCollector);
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mTelephonyManager = telephonyManager;
|
||||
mSimImageView = mView.findViewById(R.id.keyguard_sim);
|
||||
|
||||
@@ -115,6 +115,9 @@ public interface FalsingCollector {
|
||||
/** */
|
||||
void onTouchEvent(MotionEvent ev);
|
||||
|
||||
/** */
|
||||
void avoidGesture();
|
||||
|
||||
/** */
|
||||
void cleanup();
|
||||
}
|
||||
|
||||
@@ -146,6 +146,10 @@ public class FalsingCollectorFake implements FalsingCollector {
|
||||
public void onTouchEvent(MotionEvent ev) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avoidGesture() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ class FalsingCollectorImpl implements FalsingCollector {
|
||||
private boolean mShowingAod;
|
||||
private boolean mScreenOn;
|
||||
private boolean mSessionStarted;
|
||||
private MotionEvent mPendingDownEvent;
|
||||
private boolean mAvoidGesture;
|
||||
|
||||
private final ThresholdSensor.Listener mSensorEventListener = this::onProximityEvent;
|
||||
|
||||
@@ -245,7 +247,32 @@ class FalsingCollectorImpl implements FalsingCollector {
|
||||
|
||||
@Override
|
||||
public void onTouchEvent(MotionEvent ev) {
|
||||
mFalsingDataProvider.onMotionEvent(ev);
|
||||
// We delay processing down events to see if another component wants to process them.
|
||||
// If #avoidGesture is called after a MotionEvent.ACTION_DOWN, all following motion events
|
||||
//will be ignored by the collector until another MotionEvent.ACTION_DOWN is passed in.
|
||||
// avoidGesture must be called immediately following the MotionEvent.ACTION_DOWN, before
|
||||
// any other events are processed, otherwise the whole gesture will be recorded.
|
||||
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
// Make a copy of ev, since it will be recycled after we exit this method.
|
||||
mPendingDownEvent = MotionEvent.obtain(ev);
|
||||
mAvoidGesture = false;
|
||||
} else if (!mAvoidGesture) {
|
||||
if (mPendingDownEvent != null) {
|
||||
mFalsingDataProvider.onMotionEvent(mPendingDownEvent);
|
||||
mPendingDownEvent.recycle();
|
||||
mPendingDownEvent = null;
|
||||
}
|
||||
mFalsingDataProvider.onMotionEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avoidGesture() {
|
||||
if (mPendingDownEvent != null) {
|
||||
mAvoidGesture = true;
|
||||
mPendingDownEvent.recycle();
|
||||
mPendingDownEvent = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,6 +31,8 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -65,6 +67,7 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
|
||||
private LatencyTracker mLatencyTracker;
|
||||
@Mock
|
||||
private LiftToActivateListener mLiftToactivateListener;
|
||||
private FalsingCollector mFalsingCollector = new FalsingCollectorFake();
|
||||
@Mock
|
||||
private View mDeleteButton;
|
||||
@Mock
|
||||
@@ -88,7 +91,8 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
|
||||
.thenReturn(mOkButton);
|
||||
mKeyguardPinViewController = new KeyguardPinBasedInputViewController(mPinBasedInputView,
|
||||
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
|
||||
mKeyguardMessageAreaControllerFactory, mLatencyTracker, mLiftToactivateListener) {
|
||||
mKeyguardMessageAreaControllerFactory, mLatencyTracker, mLiftToactivateListener,
|
||||
mFalsingCollector) {
|
||||
@Override
|
||||
public void onResume(int reason) {
|
||||
super.onResume(reason);
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
package com.android.systemui.classifier;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -38,6 +41,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@@ -66,7 +70,6 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
|
||||
mKeyguardUpdateMonitor, mProximitySensor, mStatusBarStateController);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRegisterSensor() {
|
||||
mFalsingCollector.onScreenTurningOn();
|
||||
@@ -110,7 +113,6 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testUnregisterSensor_StateTransition() {
|
||||
|
||||
ArgumentCaptor<StatusBarStateController.StateListener> stateListenerArgumentCaptor =
|
||||
ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
|
||||
verify(mStatusBarStateController).addCallback(stateListenerArgumentCaptor.capture());
|
||||
@@ -120,4 +122,37 @@ public class FalsingCollectorImplTest extends SysuiTestCase {
|
||||
stateListenerArgumentCaptor.getValue().onStateChanged(StatusBarState.SHADE);
|
||||
verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassThroughGesture() {
|
||||
MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
|
||||
MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0);
|
||||
|
||||
// Nothing passed initially
|
||||
mFalsingCollector.onTouchEvent(down);
|
||||
verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
|
||||
|
||||
// Up event flushes the down event.
|
||||
mFalsingCollector.onTouchEvent(up);
|
||||
InOrder orderedCalls = inOrder(mFalsingDataProvider);
|
||||
// We can't simply use "eq" or similar because the collector makes a copy of "down".
|
||||
orderedCalls.verify(mFalsingDataProvider).onMotionEvent(
|
||||
argThat(argument -> argument.getActionMasked() == MotionEvent.ACTION_DOWN));
|
||||
orderedCalls.verify(mFalsingDataProvider).onMotionEvent(up);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvoidGesture() {
|
||||
MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
|
||||
MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
|
||||
|
||||
// Nothing passed initially
|
||||
mFalsingCollector.onTouchEvent(down);
|
||||
verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
|
||||
|
||||
mFalsingCollector.avoidGesture();
|
||||
// Up event would flush, but we were told to avoid.
|
||||
mFalsingCollector.onTouchEvent(up);
|
||||
verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user