Merge "Fix AlternateBouncer touch handling" into udc-dev
This commit is contained in:
@@ -823,7 +823,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
|
||||
final Rect overlayBounds = new Rect(
|
||||
0, /* left */
|
||||
mCachedDisplayInfo.getNaturalHeight() / 2, /* top */
|
||||
0, /* top */
|
||||
mCachedDisplayInfo.getNaturalWidth(), /* right */
|
||||
mCachedDisplayInfo.getNaturalHeight() /* botom */);
|
||||
|
||||
|
||||
@@ -607,7 +607,6 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
case UNCHANGED:
|
||||
if (!isWithinSensorArea(mOverlay.getOverlayView(), event.getRawX(), event.getRawY(),
|
||||
true) && mActivePointerId == MotionEvent.INVALID_POINTER_ID
|
||||
&& event.getActionMasked() == MotionEvent.ACTION_DOWN
|
||||
&& mAlternateBouncerInteractor.isVisibleState()) {
|
||||
// No pointer on sensor, forward to keyguard if alternateBouncer is visible
|
||||
mKeyguardViewManager.onTouch(event);
|
||||
|
||||
@@ -37,12 +37,12 @@ class UdfpsOverlayInteractor
|
||||
@Inject
|
||||
constructor(private val authController: AuthController, @Application scope: CoroutineScope) {
|
||||
|
||||
/** Whether a touch should be intercepted or allowed to pass to the UdfpsOverlay */
|
||||
fun canInterceptTouchInUdfpsBounds(ev: MotionEvent): Boolean {
|
||||
/** Whether a touch is within the under-display fingerprint sensor area */
|
||||
fun isTouchWithinUdfpsArea(ev: MotionEvent): Boolean {
|
||||
val isUdfpsEnrolled = authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())
|
||||
val isWithinUdfpsOverlayBounds =
|
||||
val isWithinOverlayBounds =
|
||||
udfpsOverlayParams.value.overlayBounds.contains(ev.rawX.toInt(), ev.rawY.toInt())
|
||||
return !isUdfpsEnrolled || !isWithinUdfpsOverlayBounds
|
||||
return isUdfpsEnrolled && isWithinOverlayBounds
|
||||
}
|
||||
|
||||
/** Returns the current udfpsOverlayParams */
|
||||
|
||||
@@ -46,6 +46,7 @@ constructor(
|
||||
var legacyAlternateBouncer: LegacyAlternateBouncer? = null
|
||||
var legacyAlternateBouncerVisibleTime: Long = NOT_VISIBLE
|
||||
|
||||
var receivedDownTouch = false
|
||||
val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
|
||||
|
||||
/**
|
||||
@@ -79,6 +80,7 @@ constructor(
|
||||
* @return true if the alternate bouncer was newly hidden, else false.
|
||||
*/
|
||||
fun hide(): Boolean {
|
||||
receivedDownTouch = false
|
||||
return if (isModernAlternateBouncerEnabled) {
|
||||
val wasAlternateBouncerVisible = isVisibleState()
|
||||
bouncerRepository.setAlternateVisible(false)
|
||||
|
||||
@@ -37,14 +37,12 @@ import com.android.keyguard.AuthKeyguardMessageArea;
|
||||
import com.android.keyguard.LockIconViewController;
|
||||
import com.android.keyguard.dagger.KeyguardBouncerComponent;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.compose.ComposeFacade;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||
import com.android.systemui.keyguard.shared.model.TransitionState;
|
||||
import com.android.systemui.keyguard.shared.model.TransitionStep;
|
||||
@@ -94,8 +92,6 @@ public class NotificationShadeWindowViewController {
|
||||
private final AmbientState mAmbientState;
|
||||
private final PulsingGestureListener mPulsingGestureListener;
|
||||
private final NotificationInsetsController mNotificationInsetsController;
|
||||
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
|
||||
private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
|
||||
private final boolean mIsTrackpadCommonEnabled;
|
||||
private GestureDetector mPulsingWakeupGestureHandler;
|
||||
private View mBrightnessMirror;
|
||||
@@ -145,8 +141,6 @@ public class NotificationShadeWindowViewController {
|
||||
PulsingGestureListener pulsingGestureListener,
|
||||
KeyguardBouncerViewModel keyguardBouncerViewModel,
|
||||
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
|
||||
AlternateBouncerInteractor alternateBouncerInteractor,
|
||||
UdfpsOverlayInteractor udfpsOverlayInteractor,
|
||||
KeyguardTransitionInteractor keyguardTransitionInteractor,
|
||||
PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
|
||||
FeatureFlags featureFlags,
|
||||
@@ -170,8 +164,6 @@ public class NotificationShadeWindowViewController {
|
||||
mAmbientState = ambientState;
|
||||
mPulsingGestureListener = pulsingGestureListener;
|
||||
mNotificationInsetsController = notificationInsetsController;
|
||||
mAlternateBouncerInteractor = alternateBouncerInteractor;
|
||||
mUdfpsOverlayInteractor = udfpsOverlayInteractor;
|
||||
mIsTrackpadCommonEnabled = featureFlags.isEnabled(TRACKPAD_GESTURE_COMMON);
|
||||
|
||||
// This view is not part of the newly inflated expanded status bar.
|
||||
@@ -269,6 +261,9 @@ public class NotificationShadeWindowViewController {
|
||||
|
||||
mFalsingCollector.onTouchEvent(ev);
|
||||
mPulsingWakeupGestureHandler.onTouchEvent(ev);
|
||||
if (mStatusBarKeyguardViewManager.dispatchTouchEvent(ev)) {
|
||||
return true;
|
||||
}
|
||||
if (mBrightnessMirror != null
|
||||
&& mBrightnessMirror.getVisibility() == View.VISIBLE) {
|
||||
// Disallow new pointers while the brightness mirror is visible. This is so that
|
||||
@@ -343,9 +338,10 @@ public class NotificationShadeWindowViewController {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAlternateBouncerInteractor.isVisibleState()) {
|
||||
// If using UDFPS, don't intercept touches that are within its overlay bounds
|
||||
return mUdfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(ev);
|
||||
if (mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(ev)) {
|
||||
// Don't allow touches to proceed to underlying views if alternate
|
||||
// bouncer is showing
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mLockIconViewController.onInterceptTouchEvent(ev)) {
|
||||
@@ -381,10 +377,8 @@ public class NotificationShadeWindowViewController {
|
||||
handled = !mService.isPulsing();
|
||||
}
|
||||
|
||||
if (mAlternateBouncerInteractor.isVisibleState()) {
|
||||
// eat the touch
|
||||
mStatusBarKeyguardViewManager.onTouch(ev);
|
||||
handled = true;
|
||||
if (mStatusBarKeyguardViewManager.onTouch(ev)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((mDragDownHelper.isDragDownEnabled() && !handled)
|
||||
|
||||
@@ -54,6 +54,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.keyguard.KeyguardViewController;
|
||||
import com.android.keyguard.ViewMediatorCallback;
|
||||
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||
@@ -282,6 +283,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
|
||||
private boolean mIsModernAlternateBouncerEnabled;
|
||||
private boolean mIsBackAnimationEnabled;
|
||||
private final boolean mUdfpsNewTouchDetectionEnabled;
|
||||
private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
|
||||
|
||||
private OnDismissAction mAfterKeyguardGoneAction;
|
||||
private Runnable mKeyguardGoneCancelAction;
|
||||
@@ -336,7 +339,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
|
||||
PrimaryBouncerInteractor primaryBouncerInteractor,
|
||||
BouncerView primaryBouncerView,
|
||||
AlternateBouncerInteractor alternateBouncerInteractor) {
|
||||
AlternateBouncerInteractor alternateBouncerInteractor,
|
||||
UdfpsOverlayInteractor udfpsOverlayInteractor
|
||||
) {
|
||||
mContext = context;
|
||||
mViewMediatorCallback = callback;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
@@ -362,6 +367,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
mAlternateBouncerInteractor = alternateBouncerInteractor;
|
||||
mIsBackAnimationEnabled =
|
||||
featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
|
||||
mUdfpsNewTouchDetectionEnabled = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION);
|
||||
mUdfpsOverlayInteractor = udfpsOverlayInteractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1442,17 +1449,49 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An opportunity for the AlternateBouncer to handle the touch instead of sending
|
||||
* the touch to NPVC child views.
|
||||
* @return true if the alternate bouncer should consime the touch and prevent it from
|
||||
* going to its child views
|
||||
*/
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (shouldInterceptTouchEvent(event)
|
||||
&& !mUdfpsOverlayInteractor.isTouchWithinUdfpsArea(event)) {
|
||||
onTouch(event);
|
||||
}
|
||||
return shouldInterceptTouchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the touch should be intercepted by the AlternateBouncer before going to the
|
||||
* notification shade's child views.
|
||||
*/
|
||||
public boolean shouldInterceptTouchEvent(MotionEvent event) {
|
||||
return mAlternateBouncerInteractor.isVisibleState();
|
||||
}
|
||||
|
||||
/**
|
||||
* For any touches on the NPVC, show the primary bouncer if the alternate bouncer is currently
|
||||
* showing.
|
||||
*/
|
||||
public boolean onTouch(MotionEvent event) {
|
||||
boolean handledTouch = false;
|
||||
if (event.getAction() == MotionEvent.ACTION_UP
|
||||
&& mAlternateBouncerInteractor.isVisibleState()
|
||||
&& mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()) {
|
||||
showPrimaryBouncer(true);
|
||||
handledTouch = true;
|
||||
boolean handleTouch = shouldInterceptTouchEvent(event);
|
||||
if (handleTouch) {
|
||||
final boolean actionDown = event.getActionMasked() == MotionEvent.ACTION_DOWN;
|
||||
final boolean actionDownThenUp = mAlternateBouncerInteractor.getReceivedDownTouch()
|
||||
&& event.getActionMasked() == MotionEvent.ACTION_UP;
|
||||
final boolean udfpsOverlayWillForwardEventsOutsideNotificationShade =
|
||||
mUdfpsNewTouchDetectionEnabled && mKeyguardUpdateManager.isUdfpsEnrolled();
|
||||
final boolean actionOutsideShouldDismissAlternateBouncer =
|
||||
event.getActionMasked() == MotionEvent.ACTION_OUTSIDE
|
||||
&& !udfpsOverlayWillForwardEventsOutsideNotificationShade;
|
||||
if (actionDown) {
|
||||
mAlternateBouncerInteractor.setReceivedDownTouch(true);
|
||||
} else if ((actionDownThenUp || actionOutsideShouldDismissAlternateBouncer)
|
||||
&& mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()) {
|
||||
showPrimaryBouncer(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Forward NPVC touches to callbacks in case they want to respond to touches
|
||||
@@ -1460,7 +1499,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|
||||
callback.onTouch(event);
|
||||
}
|
||||
|
||||
return handledTouch;
|
||||
return handleTouch;
|
||||
}
|
||||
|
||||
/** Update keyguard position based on a tapped X coordinate. */
|
||||
|
||||
@@ -77,16 +77,14 @@ class UdfpsOverlayInteractorTest : SysuiTestCase() {
|
||||
|
||||
runCurrent()
|
||||
|
||||
// Then touch should not be intercepted
|
||||
val canInterceptTrue = underTest.canInterceptTouchInUdfpsBounds(downEv)
|
||||
assertThat(canInterceptTrue).isFalse()
|
||||
// Then touch is within udfps area
|
||||
assertThat(underTest.isTouchWithinUdfpsArea(downEv)).isTrue()
|
||||
|
||||
// When touch is outside of bounds
|
||||
whenever(overlayBounds.contains(downEv.x.toInt(), downEv.y.toInt())).thenReturn(false)
|
||||
|
||||
// Then touch should be intercepted
|
||||
val canInterceptFalse = underTest.canInterceptTouchInUdfpsBounds(downEv)
|
||||
assertThat(canInterceptFalse).isTrue()
|
||||
// Then touch is not within udfps area
|
||||
assertThat(underTest.isTouchWithinUdfpsArea(downEv)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,13 +26,11 @@ import com.android.keyguard.LockIconViewController
|
||||
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
|
||||
import com.android.systemui.classifier.FalsingCollectorFake
|
||||
import com.android.systemui.dock.DockManager
|
||||
import com.android.systemui.flags.FakeFeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
|
||||
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||
@@ -69,8 +67,8 @@ import org.mockito.Mockito.anyFloat
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
@@ -97,8 +95,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
||||
@Mock private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
||||
@Mock private lateinit var pulsingGestureListener: PulsingGestureListener
|
||||
@Mock private lateinit var notificationInsetsController: NotificationInsetsController
|
||||
@Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
||||
@Mock private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
|
||||
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
|
||||
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
|
||||
@Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
|
||||
@@ -155,8 +151,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
||||
pulsingGestureListener,
|
||||
keyguardBouncerViewModel,
|
||||
keyguardBouncerComponentFactory,
|
||||
alternateBouncerInteractor,
|
||||
udfpsOverlayInteractor,
|
||||
keyguardTransitionInteractor,
|
||||
primaryBouncerToGoneTransitionViewModel,
|
||||
featureFlags,
|
||||
@@ -311,17 +305,15 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldInterceptTouchEvent_downEventAlternateBouncer_ignoreIfInUdfpsOverlay() =
|
||||
testScope.runTest {
|
||||
// Down event within udfpsOverlay bounds while alternateBouncer is showing
|
||||
whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(DOWN_EVENT))
|
||||
.thenReturn(false)
|
||||
whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
|
||||
fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() {
|
||||
// down event should be intercepted by keyguardViewManager
|
||||
whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
|
||||
.thenReturn(true)
|
||||
|
||||
// Then touch should not be intercepted
|
||||
val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)
|
||||
assertThat(shouldIntercept).isFalse()
|
||||
}
|
||||
// Then touch should not be intercepted
|
||||
val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)
|
||||
assertThat(shouldIntercept).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetBouncerContainer() =
|
||||
|
||||
@@ -26,13 +26,11 @@ import com.android.keyguard.LockIconViewController
|
||||
import com.android.keyguard.dagger.KeyguardBouncerComponent
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
|
||||
import com.android.systemui.classifier.FalsingCollectorFake
|
||||
import com.android.systemui.dock.DockManager
|
||||
import com.android.systemui.flags.FakeFeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
|
||||
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
|
||||
@@ -103,14 +101,12 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
|
||||
@Mock private lateinit var notificationInsetsController: NotificationInsetsController
|
||||
@Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
||||
@Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||
@Mock
|
||||
private lateinit var primaryBouncerToGoneTransitionViewModel:
|
||||
PrimaryBouncerToGoneTransitionViewModel
|
||||
@Captor
|
||||
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
||||
@Mock private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
|
||||
|
||||
private lateinit var underTest: NotificationShadeWindowView
|
||||
private lateinit var controller: NotificationShadeWindowViewController
|
||||
@@ -166,8 +162,6 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
|
||||
pulsingGestureListener,
|
||||
keyguardBouncerViewModel,
|
||||
keyguardBouncerComponentFactory,
|
||||
alternateBouncerInteractor,
|
||||
udfpsOverlayInteractor,
|
||||
keyguardTransitionInteractor,
|
||||
primaryBouncerToGoneTransitionViewModel,
|
||||
featureFlags,
|
||||
@@ -207,8 +201,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
|
||||
|
||||
// WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
|
||||
whenever(statusBarStateController.isDozing).thenReturn(false)
|
||||
whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
|
||||
whenever(udfpsOverlayInteractor.canInterceptTouchInUdfpsBounds(any())).thenReturn(true)
|
||||
whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(any())).thenReturn(true)
|
||||
whenever(dragDownHelper.onInterceptTouchEvent(any())).thenReturn(false)
|
||||
|
||||
// THEN we should intercept touch
|
||||
@@ -222,7 +215,8 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
|
||||
|
||||
// WHEN not showing alt auth, not dozing, drag down helper doesn't want to intercept
|
||||
whenever(statusBarStateController.isDozing).thenReturn(false)
|
||||
whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(false)
|
||||
whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(any()))
|
||||
.thenReturn(false)
|
||||
whenever(dragDownHelper.onInterceptTouchEvent(any())).thenReturn(false)
|
||||
|
||||
// THEN we shouldn't intercept touch
|
||||
@@ -236,7 +230,7 @@ class NotificationShadeWindowViewTest : SysuiTestCase() {
|
||||
|
||||
// WHEN showing alt auth, not dozing, drag down helper doesn't want to intercept
|
||||
whenever(statusBarStateController.isDozing).thenReturn(false)
|
||||
whenever(alternateBouncerInteractor.isVisibleState()).thenReturn(true)
|
||||
whenever(statusBarKeyguardViewManager.onTouch(any())).thenReturn(true)
|
||||
whenever(dragDownHelper.onInterceptTouchEvent(any())).thenReturn(false)
|
||||
|
||||
// THEN we should handle the touch
|
||||
|
||||
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -58,6 +59,7 @@ import com.android.keyguard.KeyguardSecurityModel;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.ViewMediatorCallback;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
@@ -126,12 +128,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
@Mock private PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
|
||||
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
|
||||
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
|
||||
@Mock private UdfpsOverlayInteractor mUdfpsOverlayInteractor;
|
||||
@Mock private BouncerView mBouncerView;
|
||||
@Mock private BouncerViewDelegate mBouncerViewDelegate;
|
||||
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
|
||||
@Mock private NotificationShadeWindowView mNotificationShadeWindowView;
|
||||
@Mock private WindowInsetsController mWindowInsetsController;
|
||||
@Mock private TaskbarDelegate mTaskbarDelegate;
|
||||
@Mock private StatusBarKeyguardViewManager.KeyguardViewManagerCallback mCallback;
|
||||
|
||||
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
private PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
|
||||
@@ -188,7 +192,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
mPrimaryBouncerCallbackInteractor,
|
||||
mPrimaryBouncerInteractor,
|
||||
mBouncerView,
|
||||
mAlternateBouncerInteractor) {
|
||||
mAlternateBouncerInteractor,
|
||||
mUdfpsOverlayInteractor) {
|
||||
@Override
|
||||
public ViewRootImpl getViewRootImpl() {
|
||||
return mViewRootImpl;
|
||||
@@ -675,7 +680,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
mPrimaryBouncerCallbackInteractor,
|
||||
mPrimaryBouncerInteractor,
|
||||
mBouncerView,
|
||||
mAlternateBouncerInteractor) {
|
||||
mAlternateBouncerInteractor,
|
||||
mUdfpsOverlayInteractor) {
|
||||
@Override
|
||||
public ViewRootImpl getViewRootImpl() {
|
||||
return mViewRootImpl;
|
||||
@@ -713,7 +719,115 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlternateBouncerToShowPrimaryBouncer_updatesScrimControllerOnce() {
|
||||
public void handleDispatchTouchEvent_alternateBouncerNotVisible() {
|
||||
mStatusBarKeyguardViewManager.addCallback(mCallback);
|
||||
|
||||
// GIVEN the alternate bouncer is visible
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
|
||||
|
||||
// THEN handleDispatchTouchEvent doesn't use the touches
|
||||
assertFalse(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||
));
|
||||
assertFalse(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
|
||||
));
|
||||
assertFalse(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
|
||||
));
|
||||
|
||||
// THEN the touch is not acted upon
|
||||
verify(mCallback, never()).onTouch(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleDispatchTouchEvent_shouldInterceptTouchAndHandleTouch() {
|
||||
mStatusBarKeyguardViewManager.addCallback(mCallback);
|
||||
|
||||
// GIVEN the alternate bouncer is visible
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
|
||||
|
||||
// GIVEN all touches are NOT the udfps overlay
|
||||
when(mUdfpsOverlayInteractor.isTouchWithinUdfpsArea(any())).thenReturn(false);
|
||||
|
||||
// THEN handleDispatchTouchEvent eats/intercepts the touches so motion events aren't sent
|
||||
// to its child views (handleDispatchTouchEvent returns true)
|
||||
assertTrue(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||
));
|
||||
assertTrue(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
|
||||
));
|
||||
assertTrue(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
|
||||
));
|
||||
|
||||
// THEN the touch is acted upon once for each dispatchTOuchEvent call
|
||||
verify(mCallback, times(3)).onTouch(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleDispatchTouchEvent_shouldInterceptTouchButNotHandleTouch() {
|
||||
mStatusBarKeyguardViewManager.addCallback(mCallback);
|
||||
|
||||
// GIVEN the alternate bouncer is visible
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
|
||||
|
||||
// GIVEN all touches are within the udfps overlay
|
||||
when(mUdfpsOverlayInteractor.isTouchWithinUdfpsArea(any())).thenReturn(true);
|
||||
|
||||
// THEN handleDispatchTouchEvent eats/intercepts the touches so motion events aren't sent
|
||||
// to its child views (handleDispatchTouchEvent returns true)
|
||||
assertTrue(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||
));
|
||||
assertTrue(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
|
||||
));
|
||||
assertTrue(mStatusBarKeyguardViewManager.dispatchTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
|
||||
));
|
||||
|
||||
// THEN the touch is NOT acted upon at the moment
|
||||
verify(mCallback, never()).onTouch(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldInterceptTouch_alternateBouncerNotVisible() {
|
||||
// GIVEN the alternate bouncer is not visible
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
|
||||
|
||||
// THEN no motion events are intercepted
|
||||
assertFalse(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||
));
|
||||
assertFalse(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
|
||||
));
|
||||
assertFalse(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldInterceptTouch_alternateBouncerVisible() {
|
||||
// GIVEN the alternate bouncer is visible
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
|
||||
|
||||
// THEN all motion events are intercepted
|
||||
assertTrue(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
|
||||
));
|
||||
assertTrue(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
|
||||
));
|
||||
assertTrue(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void alternateBouncerToShowPrimaryBouncer_updatesScrimControllerOnce() {
|
||||
// GIVEN the alternate bouncer has shown and calls to hide() will result in successfully
|
||||
// hiding it
|
||||
when(mAlternateBouncerInteractor.hide()).thenReturn(true);
|
||||
@@ -729,30 +843,67 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlternateBouncerOnTouch_actionDown_doesNotHandleTouch() {
|
||||
public void alternateBouncerOnTouch_actionDownThenUp_noMinTimeShown_noHideAltBouncer() {
|
||||
reset(mAlternateBouncerInteractor);
|
||||
|
||||
// GIVEN the alternate bouncer has shown for a minimum amount of time
|
||||
when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
|
||||
when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(false);
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
|
||||
when(mUdfpsOverlayInteractor.isTouchWithinUdfpsArea(any())).thenReturn(false);
|
||||
|
||||
// WHEN ACTION_DOWN touch event comes
|
||||
boolean touchHandled = mStatusBarKeyguardViewManager.onTouch(
|
||||
// WHEN ACTION_DOWN and ACTION_UP touch event comes
|
||||
boolean touchHandledDown = mStatusBarKeyguardViewManager.onTouch(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
|
||||
when(mAlternateBouncerInteractor.getReceivedDownTouch()).thenReturn(true);
|
||||
boolean touchHandledUp = mStatusBarKeyguardViewManager.onTouch(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0));
|
||||
|
||||
// THEN the touch is not handled
|
||||
assertFalse(touchHandled);
|
||||
// THEN the touches are handled (doesn't let touches through to underlying views)
|
||||
assertTrue(touchHandledDown);
|
||||
assertTrue(touchHandledUp);
|
||||
|
||||
// THEN alternate bouncer does NOT attempt to hide since min showing time wasn't met
|
||||
verify(mAlternateBouncerInteractor, never()).hide();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlternateBouncerOnTouch_actionUp_handlesTouch() {
|
||||
public void alternateBouncerOnTouch_actionDownThenUp_handlesTouch_hidesAltBouncer() {
|
||||
reset(mAlternateBouncerInteractor);
|
||||
|
||||
// GIVEN the alternate bouncer has shown for a minimum amount of time
|
||||
when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
|
||||
when(mUdfpsOverlayInteractor.isTouchWithinUdfpsArea(any())).thenReturn(false);
|
||||
|
||||
// WHEN ACTION_UP touch event comes
|
||||
boolean touchHandled = mStatusBarKeyguardViewManager.onTouch(
|
||||
// WHEN ACTION_DOWN and ACTION_UP touch event comes
|
||||
boolean touchHandledDown = mStatusBarKeyguardViewManager.onTouch(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
|
||||
when(mAlternateBouncerInteractor.getReceivedDownTouch()).thenReturn(true);
|
||||
boolean touchHandledUp = mStatusBarKeyguardViewManager.onTouch(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0));
|
||||
|
||||
// THEN the touch is handled
|
||||
assertTrue(touchHandled);
|
||||
// THEN the touches are handled
|
||||
assertTrue(touchHandledDown);
|
||||
assertTrue(touchHandledUp);
|
||||
|
||||
// THEN alternate bouncer attempts to hide
|
||||
verify(mAlternateBouncerInteractor).hide();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void alternateBouncerOnTouch_actionUp_doesNotHideAlternateBouncer() {
|
||||
reset(mAlternateBouncerInteractor);
|
||||
|
||||
// GIVEN the alternate bouncer has shown for a minimum amount of time
|
||||
when(mAlternateBouncerInteractor.hasAlternateBouncerShownWithMinTime()).thenReturn(true);
|
||||
when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
|
||||
when(mUdfpsOverlayInteractor.isTouchWithinUdfpsArea(any())).thenReturn(false);
|
||||
|
||||
// WHEN only ACTION_UP touch event comes
|
||||
mStatusBarKeyguardViewManager.onTouch(
|
||||
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0));
|
||||
|
||||
// THEN the alternateBouncer doesn't hide
|
||||
verify(mAlternateBouncerInteractor, never()).hide();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user