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:
TreeHugger Robot
2021-08-19 21:33:37 +00:00
committed by Automerger Merge Worker
6 changed files with 161 additions and 9 deletions

View File

@@ -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:

View File

@@ -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.

View File

@@ -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

View File

@@ -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());

View File

@@ -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);
}

View File

@@ -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();
}
}