Merge "Add minimum show time for the udfps bouncer." into sc-qpr1-dev am: a1421cf606 am: 972369a5be am: 6a485ae90a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15595759 Change-Id: I71dd2aa96ef8a2a8d8c77a1f08229d00a54e854d
This commit is contained in:
@@ -43,7 +43,6 @@ import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
@@ -76,6 +75,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
import com.android.systemui.util.concurrency.Execution;
|
||||
import com.android.systemui.util.time.SystemClock;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -125,6 +125,7 @@ public class UdfpsController implements DozeReceiver {
|
||||
@Nullable private final UdfpsHbmProvider mHbmProvider;
|
||||
@NonNull private final KeyguardBypassController mKeyguardBypassController;
|
||||
@NonNull private final ConfigurationController mConfigurationController;
|
||||
@NonNull private final SystemClock mSystemClock;
|
||||
@VisibleForTesting @NonNull final BiometricOrientationEventListener mOrientationListener;
|
||||
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
|
||||
// sensors, this, in addition to a lot of the code here, will be updated.
|
||||
@@ -449,19 +450,19 @@ public class UdfpsController implements DozeReceiver {
|
||||
final String touchInfo = String.format(
|
||||
"minor: %.1f, major: %.1f, v: %.1f, exceedsVelocityThreshold: %b",
|
||||
minor, major, v, exceedsVelocityThreshold);
|
||||
final long sinceLastLog = SystemClock.elapsedRealtime() - mTouchLogTime;
|
||||
final long sinceLastLog = mSystemClock.elapsedRealtime() - mTouchLogTime;
|
||||
if (!isIlluminationRequested && !mGoodCaptureReceived &&
|
||||
!exceedsVelocityThreshold) {
|
||||
onFingerDown((int) event.getRawX(), (int) event.getRawY(), minor,
|
||||
major);
|
||||
Log.v(TAG, "onTouch | finger down: " + touchInfo);
|
||||
mTouchLogTime = SystemClock.elapsedRealtime();
|
||||
mPowerManager.userActivity(SystemClock.uptimeMillis(),
|
||||
mTouchLogTime = mSystemClock.elapsedRealtime();
|
||||
mPowerManager.userActivity(mSystemClock.uptimeMillis(),
|
||||
PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
|
||||
handled = true;
|
||||
} else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) {
|
||||
Log.v(TAG, "onTouch | finger move: " + touchInfo);
|
||||
mTouchLogTime = SystemClock.elapsedRealtime();
|
||||
mTouchLogTime = mSystemClock.elapsedRealtime();
|
||||
}
|
||||
} else {
|
||||
Log.v(TAG, "onTouch | finger outside");
|
||||
@@ -525,7 +526,8 @@ public class UdfpsController implements DozeReceiver {
|
||||
@NonNull KeyguardBypassController keyguardBypassController,
|
||||
@NonNull DisplayManager displayManager,
|
||||
@Main Handler mainHandler,
|
||||
@NonNull ConfigurationController configurationController) {
|
||||
@NonNull ConfigurationController configurationController,
|
||||
@NonNull SystemClock systemClock) {
|
||||
mContext = context;
|
||||
mExecution = execution;
|
||||
// TODO (b/185124905): inject main handler and vibrator once done prototyping
|
||||
@@ -561,6 +563,7 @@ public class UdfpsController implements DozeReceiver {
|
||||
mainHandler);
|
||||
mKeyguardBypassController = keyguardBypassController;
|
||||
mConfigurationController = configurationController;
|
||||
mSystemClock = systemClock;
|
||||
|
||||
mSensorProps = findFirstUdfps();
|
||||
// At least one UDFPS sensor exists
|
||||
@@ -781,6 +784,7 @@ public class UdfpsController implements DozeReceiver {
|
||||
mKeyguardViewMediator,
|
||||
mLockscreenShadeTransitionController,
|
||||
mConfigurationController,
|
||||
mSystemClock,
|
||||
this
|
||||
);
|
||||
case IUdfpsOverlayController.REASON_AUTH_BP:
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
import com.android.systemui.util.time.SystemClock;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -51,6 +52,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
|
||||
@NonNull private final KeyguardViewMediator mKeyguardViewMediator;
|
||||
@NonNull private final LockscreenShadeTransitionController mLockScreenShadeTransitionController;
|
||||
@NonNull private final ConfigurationController mConfigurationController;
|
||||
@NonNull private final SystemClock mSystemClock;
|
||||
@NonNull private final UdfpsController mUdfpsController;
|
||||
|
||||
private boolean mShowingUdfpsBouncer;
|
||||
@@ -60,6 +62,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
|
||||
private int mStatusBarState;
|
||||
private float mTransitionToFullShadeProgress;
|
||||
private float mLastDozeAmount;
|
||||
private long mLastUdfpsBouncerShowTime = -1;
|
||||
|
||||
/**
|
||||
* hidden amount of pin/pattern/password bouncer
|
||||
@@ -80,6 +83,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
|
||||
@NonNull KeyguardViewMediator keyguardViewMediator,
|
||||
@NonNull LockscreenShadeTransitionController transitionController,
|
||||
@NonNull ConfigurationController configurationController,
|
||||
@NonNull SystemClock systemClock,
|
||||
@NonNull UdfpsController udfpsController) {
|
||||
super(view, statusBarStateController, statusBarOptional, dumpManager);
|
||||
mKeyguardViewManager = statusBarKeyguardViewManager;
|
||||
@@ -88,6 +92,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
|
||||
mKeyguardViewMediator = keyguardViewMediator;
|
||||
mLockScreenShadeTransitionController = transitionController;
|
||||
mConfigurationController = configurationController;
|
||||
mSystemClock = systemClock;
|
||||
mUdfpsController = udfpsController;
|
||||
}
|
||||
|
||||
@@ -156,6 +161,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
|
||||
}
|
||||
|
||||
mShowingUdfpsBouncer = show;
|
||||
if (mShowingUdfpsBouncer) {
|
||||
mLastUdfpsBouncerShowTime = mSystemClock.uptimeMillis();
|
||||
}
|
||||
updatePauseAuth();
|
||||
if (mShowingUdfpsBouncer) {
|
||||
if (mStatusBarState == StatusBarState.SHADE_LOCKED) {
|
||||
@@ -219,15 +227,24 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
|
||||
* If we were previously showing the udfps bouncer, hide it and instead show the regular
|
||||
* (pin/pattern/password) bouncer.
|
||||
*
|
||||
* Does nothing if we weren't previously showing the udfps bouncer.
|
||||
* Does nothing if we weren't previously showing the UDFPS bouncer.
|
||||
*/
|
||||
private void maybeShowInputBouncer() {
|
||||
if (mShowingUdfpsBouncer) {
|
||||
if (mShowingUdfpsBouncer && hasUdfpsBouncerShownWithMinTime()) {
|
||||
mKeyguardViewManager.showBouncer(true);
|
||||
mKeyguardViewManager.resetAlternateAuth(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the udfps bouncer has shown for at least 200ms before allowing touches outside
|
||||
* of the udfps icon area to dismiss the udfps bouncer and show the pin/pattern/password
|
||||
* bouncer.
|
||||
*/
|
||||
private boolean hasUdfpsBouncerShownWithMinTime() {
|
||||
return (mSystemClock.uptimeMillis() - mLastUdfpsBouncerShowTime) > 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the progress we're currently transitioning to the full shade. 0.0f means we're not
|
||||
* transitioning yet, while 1.0f means we've fully dragged down.
|
||||
|
||||
@@ -311,6 +311,12 @@ public class NotificationShadeWindowViewController {
|
||||
// Capture all touch events in always-on.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
|
||||
// capture all touches if the alt auth bouncer is showing
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean intercept = false;
|
||||
if (mNotificationPanelViewController.isFullyExpanded()
|
||||
&& mDragDownHelper.isDragDownEnabled()
|
||||
@@ -338,6 +344,12 @@ public class NotificationShadeWindowViewController {
|
||||
if (mStatusBarStateController.isDozing()) {
|
||||
handled = !mService.isPulsing();
|
||||
}
|
||||
|
||||
if (mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
|
||||
// eat the touch
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if ((mDragDownHelper.isDragDownEnabled() && !handled)
|
||||
|| mDragDownHelper.isDraggingDown()) {
|
||||
// we still want to finish our drag down gesture when locking the screen
|
||||
|
||||
@@ -69,6 +69,7 @@ import com.android.systemui.util.concurrency.Execution;
|
||||
import com.android.systemui.util.concurrency.FakeExecution;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
import com.android.systemui.util.time.SystemClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -147,6 +148,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
private Handler mHandler;
|
||||
@Mock
|
||||
private ConfigurationController mConfigurationController;
|
||||
@Mock
|
||||
private SystemClock mSystemClock;
|
||||
|
||||
private FakeExecutor mFgExecutor;
|
||||
|
||||
@@ -229,7 +232,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
mKeyguardBypassController,
|
||||
mDisplayManager,
|
||||
mHandler,
|
||||
mConfigurationController);
|
||||
mConfigurationController,
|
||||
mSystemClock);
|
||||
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
|
||||
mOverlayController = mOverlayCaptor.getValue();
|
||||
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
|
||||
|
||||
@@ -18,8 +18,11 @@ package com.android.systemui.biometrics;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -41,6 +44,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -81,6 +85,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
|
||||
private ConfigurationController mConfigurationController;
|
||||
@Mock
|
||||
private UdfpsController mUdfpsController;
|
||||
private FakeSystemClock mSystemClock = new FakeSystemClock();
|
||||
|
||||
private UdfpsKeyguardViewController mController;
|
||||
|
||||
@@ -115,6 +120,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
|
||||
mKeyguardViewMediator,
|
||||
mLockscreenShadeTransitionController,
|
||||
mConfigurationController,
|
||||
mSystemClock,
|
||||
mUdfpsController);
|
||||
}
|
||||
|
||||
@@ -274,6 +280,59 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
|
||||
verify(mStatusBarKeyguardViewManager).removeAlternateAuthInterceptor(mAltAuthInterceptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHiddenUdfpsBouncerOnTouchOutside_nothingHappens() {
|
||||
// GIVEN view is attached
|
||||
mController.onViewAttached();
|
||||
captureAltAuthInterceptor();
|
||||
|
||||
// GIVEN udfps bouncer isn't showing
|
||||
mAltAuthInterceptor.hideAlternateAuthBouncer();
|
||||
|
||||
// WHEN touch is observed outside the view
|
||||
mController.onTouchOutsideView();
|
||||
|
||||
// THEN bouncer / alt auth methods are never called
|
||||
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
|
||||
verify(mStatusBarKeyguardViewManager, never()).resetAlternateAuth(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowingUdfpsBouncerOnTouchOutsideWithinThreshold_nothingHappens() {
|
||||
// GIVEN view is attached
|
||||
mController.onViewAttached();
|
||||
captureAltAuthInterceptor();
|
||||
|
||||
// GIVEN udfps bouncer is showing
|
||||
mAltAuthInterceptor.showAlternateAuthBouncer();
|
||||
|
||||
// WHEN touch is observed outside the view 200ms later (just within threshold)
|
||||
mSystemClock.advanceTime(200);
|
||||
mController.onTouchOutsideView();
|
||||
|
||||
// THEN bouncer / alt auth methods are never called because not enough time has passed
|
||||
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
|
||||
verify(mStatusBarKeyguardViewManager, never()).resetAlternateAuth(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowingUdfpsBouncerOnTouchOutsideAboveThreshold_showInputBouncer() {
|
||||
// GIVEN view is attached
|
||||
mController.onViewAttached();
|
||||
captureAltAuthInterceptor();
|
||||
|
||||
// GIVEN udfps bouncer is showing
|
||||
mAltAuthInterceptor.showAlternateAuthBouncer();
|
||||
|
||||
// WHEN touch is observed outside the view 205ms later
|
||||
mSystemClock.advanceTime(205);
|
||||
mController.onTouchOutsideView();
|
||||
|
||||
// THEN show the bouncer and reset alt auth
|
||||
verify(mStatusBarKeyguardViewManager).showBouncer(eq(true));
|
||||
verify(mStatusBarKeyguardViewManager).resetAlternateAuth(anyBoolean());
|
||||
}
|
||||
|
||||
private void sendStatusBarStateChanged(int statusBarState) {
|
||||
mStatusBarStateListener.onStateChanged(statusBarState);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -55,6 +60,8 @@ import com.android.systemui.util.InjectionInflationController;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@@ -91,6 +98,10 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
||||
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
|
||||
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
||||
mInteractionEventHandlerCaptor;
|
||||
private NotificationShadeWindowView.InteractionEventHandler mInteractionEventHandler;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -147,4 +158,49 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
||||
verify(mDragDownHelper).onTouchEvent(ev);
|
||||
ev.recycle();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterceptTouchWhenShowingAltAuth() {
|
||||
captureInteractionEventHandler();
|
||||
|
||||
// WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
when(mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()).thenReturn(true);
|
||||
when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
|
||||
|
||||
// THEN we should intercept touch
|
||||
assertTrue(mInteractionEventHandler.shouldInterceptTouchEvent(mock(MotionEvent.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoInterceptTouch() {
|
||||
captureInteractionEventHandler();
|
||||
|
||||
// WHEN not showing alt auth, not dozing, drag down helper doesn't want to intercept
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
when(mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()).thenReturn(false);
|
||||
when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
|
||||
|
||||
// THEN we shouldn't intercept touch
|
||||
assertFalse(mInteractionEventHandler.shouldInterceptTouchEvent(mock(MotionEvent.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleTouchEventWhenShowingAltAuth() {
|
||||
captureInteractionEventHandler();
|
||||
|
||||
// WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
|
||||
when(mStatusBarStateController.isDozing()).thenReturn(false);
|
||||
when(mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()).thenReturn(true);
|
||||
when(mDragDownHelper.onInterceptTouchEvent(any())).thenReturn(false);
|
||||
|
||||
// THEN we should handle the touch
|
||||
assertTrue(mInteractionEventHandler.handleTouchEvent(mock(MotionEvent.class)));
|
||||
}
|
||||
|
||||
private void captureInteractionEventHandler() {
|
||||
verify(mView).setInteractionEventHandler(mInteractionEventHandlerCaptor.capture());
|
||||
mInteractionEventHandler = mInteractionEventHandlerCaptor.getValue();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user