Merge "Add predictive back animation to Bouncer." into tm-qpr-dev am: a34b7aafe2

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20835307

Change-Id: Iaa37960a289ecc3b24e6e14a4181fca9987413d0
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Shan Huang
2023-01-17 20:59:00 +00:00
committed by Automerger Merge Worker
10 changed files with 213 additions and 15 deletions

View File

@@ -29,6 +29,9 @@ import android.view.View;
import android.view.View.OnKeyListener; import android.view.View.OnKeyListener;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.window.OnBackAnimationCallback;
import androidx.annotation.NonNull;
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback; import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
@@ -393,6 +396,14 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
return false; return false;
} }
/**
* @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
*/
@NonNull
public OnBackAnimationCallback getBackCallback() {
return mKeyguardSecurityContainerController.getBackCallback();
}
/** /**
* Allows the media keys to work when the keyguard is showing. * Allows the media keys to work when the keyguard is showing.
* The media keys should be of no interest to the actual keyguard view(s), * The media keys should be of no interest to the actual keyguard view(s),

View File

@@ -32,6 +32,7 @@ import static androidx.constraintlayout.widget.ConstraintSet.START;
import static androidx.constraintlayout.widget.ConstraintSet.TOP; import static androidx.constraintlayout.widget.ConstraintSet.TOP;
import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT; import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT;
import static com.android.systemui.animation.InterpolatorsAndroidX.DECELERATE_QUINT;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY; import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static java.lang.Integer.max; import static java.lang.Integer.max;
@@ -73,6 +74,8 @@ import android.view.WindowManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -135,7 +138,9 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private static final float MIN_DRAG_SIZE = 10; private static final float MIN_DRAG_SIZE = 10;
// How much to scale the default slop by, to avoid accidental drags. // How much to scale the default slop by, to avoid accidental drags.
private static final float SLOP_SCALE = 4f; private static final float SLOP_SCALE = 4f;
@VisibleForTesting
// How much the view scales down to during back gestures.
static final float MIN_BACK_SCALE = 0.9f;
@VisibleForTesting @VisibleForTesting
KeyguardSecurityViewFlipper mSecurityViewFlipper; KeyguardSecurityViewFlipper mSecurityViewFlipper;
private GlobalSettings mGlobalSettings; private GlobalSettings mGlobalSettings;
@@ -240,6 +245,33 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
} }
}; };
private final OnBackAnimationCallback mBackCallback = new OnBackAnimationCallback() {
@Override
public void onBackCancelled() {
// TODO(b/259608500): Remove once back API auto animates progress to 0 on cancel.
resetScale();
}
@Override
public void onBackInvoked() { }
@Override
public void onBackProgressed(BackEvent event) {
float progress = event.getProgress();
// TODO(b/263819310): Update the interpolator to match spec.
float scale = MIN_BACK_SCALE
+ (1 - MIN_BACK_SCALE) * (1 - DECELERATE_QUINT.getInterpolation(progress));
setScale(scale);
}
};
/**
* @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
*/
@NonNull
OnBackAnimationCallback getBackCallback() {
return mBackCallback;
}
// Used to notify the container when something interesting happens. // Used to notify the container when something interesting happens.
public interface SecurityCallback { public interface SecurityCallback {
/** /**
@@ -736,6 +768,15 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
mViewMode.onDensityOrFontScaleChanged(); mViewMode.onDensityOrFontScaleChanged();
} }
void resetScale() {
setScale(1);
}
private void setScale(float scale) {
setScaleX(scale);
setScaleY(scale);
}
/** /**
* Enscapsulates the differences between bouncer modes for the container. * Enscapsulates the differences between bouncer modes for the container.
*/ */

View File

@@ -40,7 +40,9 @@ import android.util.Log;
import android.util.Slog; import android.util.Slog;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.window.OnBackAnimationCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
@@ -479,6 +481,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
/** Called when the bouncer changes visibility. */ /** Called when the bouncer changes visibility. */
public void onBouncerVisibilityChanged(@View.Visibility int visibility) { public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
setBouncerVisible(visibility == View.VISIBLE); setBouncerVisible(visibility == View.VISIBLE);
if (visibility == View.INVISIBLE) {
mView.resetScale();
}
} }
private void setBouncerVisible(boolean visible) { private void setBouncerVisible(boolean visible) {
@@ -587,6 +592,14 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
return getCurrentSecurityController().needsInput(); return getCurrentSecurityController().needsInput();
} }
/**
* @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
*/
@NonNull
OnBackAnimationCallback getBackCallback() {
return mView.getBackCallback();
}
/** /**
* Switches to the given security view unless it's already being shown, in which case * Switches to the given security view unless it's already being shown, in which case
* this is a no-op. * this is a no-op.

View File

@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data package com.android.systemui.keyguard.data
import android.view.KeyEvent import android.view.KeyEvent
import android.window.OnBackAnimationCallback
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@@ -51,4 +52,6 @@ interface BouncerViewDelegate {
cancelAction: Runnable?, cancelAction: Runnable?,
) )
fun willDismissWithActions(): Boolean fun willDismissWithActions(): Boolean
/** @return the {@link OnBackAnimationCallback} to animate Bouncer during a back gesture. */
fun getBackCallback(): OnBackAnimationCallback
} }

View File

@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.binder
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.window.OnBackAnimationCallback
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.android.internal.policy.SystemBarUtils import com.android.internal.policy.SystemBarUtils
@@ -55,6 +56,10 @@ object KeyguardBouncerViewBinder {
mode == KeyguardSecurityModel.SecurityMode.SimPuk mode == KeyguardSecurityModel.SecurityMode.SimPuk
} }
override fun getBackCallback(): OnBackAnimationCallback {
return hostViewController.backCallback
}
override fun shouldDismissOnMenuPressed(): Boolean { override fun shouldDismissOnMenuPressed(): Boolean {
return hostViewController.shouldEnableMenuKey() return hostViewController.shouldEnableMenuKey()
} }

View File

@@ -273,7 +273,6 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
@Override @Override
public void triggerBack() { public void triggerBack() {
// Notify FalsingManager that an intentional gesture has occurred. // Notify FalsingManager that an intentional gesture has occurred.
// TODO(b/186519446): use a different method than isFalseTouch
mFalsingManager.isFalseTouch(BACK_GESTURE); mFalsingManager.isFalseTouch(BACK_GESTURE);
// Only inject back keycodes when ahead-of-time back dispatching is disabled. // Only inject back keycodes when ahead-of-time back dispatching is disabled.
if (mBackAnimation == null) { if (mBackAnimation == null) {
@@ -919,6 +918,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mThresholdCrossed = true; mThresholdCrossed = true;
// Capture inputs // Capture inputs
mInputMonitor.pilferPointers(); mInputMonitor.pilferPointers();
if (mBackAnimation != null) {
// Notify FalsingManager that an intentional gesture has occurred.
mFalsingManager.isFalseTouch(BACK_GESTURE);
}
mInputEventReceiver.setBatchingEnabled(true); mInputEventReceiver.setBatchingEnabled(true);
} else { } else {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_FAR_FROM_EDGE); logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_FAR_FROM_EDGE);

View File

@@ -37,7 +37,8 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewRootImpl; import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
import android.window.OnBackInvokedCallback; import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedDispatcher; import android.window.OnBackInvokedDispatcher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -198,11 +199,38 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
} }
}; };
private final OnBackInvokedCallback mOnBackInvokedCallback = () -> { private final OnBackAnimationCallback mOnBackInvokedCallback = new OnBackAnimationCallback() {
@Override
public void onBackInvoked() {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()"); Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()");
} }
onBackPressed(); onBackPressed();
if (shouldPlayBackAnimation()) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackInvoked();
}
}
@Override
public void onBackProgressed(BackEvent event) {
if (shouldPlayBackAnimation()) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackProgressed(event);
}
}
@Override
public void onBackCancelled() {
if (shouldPlayBackAnimation()) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackCancelled();
}
}
@Override
public void onBackStarted(BackEvent event) {
if (shouldPlayBackAnimation()) {
mPrimaryBouncerView.getDelegate().getBackCallback().onBackStarted(event);
}
}
}; };
private boolean mIsBackCallbackRegistered = false; private boolean mIsBackCallbackRegistered = false;
@@ -256,6 +284,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private boolean mIsModernBouncerEnabled; private boolean mIsModernBouncerEnabled;
private boolean mIsUnoccludeTransitionFlagEnabled; private boolean mIsUnoccludeTransitionFlagEnabled;
private boolean mIsModernAlternateBouncerEnabled; private boolean mIsModernAlternateBouncerEnabled;
private boolean mIsBackAnimationEnabled;
private OnDismissAction mAfterKeyguardGoneAction; private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction; private Runnable mKeyguardGoneCancelAction;
@@ -337,6 +366,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION); mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER); mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
mAlternateBouncerInteractor = alternateBouncerInteractor; mAlternateBouncerInteractor = alternateBouncerInteractor;
mIsBackAnimationEnabled =
featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
} }
@Override @Override
@@ -472,6 +503,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
} }
} }
private boolean shouldPlayBackAnimation() {
// Suppress back animation when bouncer shouldn't be dismissed on back invocation.
return !needsFullscreenBouncer() && mIsBackAnimationEnabled;
}
@Override @Override
public void onDensityOrFontScaleChanged() { public void onDensityOrFontScaleChanged() {
hideBouncer(true /* destroyView */); hideBouncer(true /* destroyView */);

View File

@@ -404,6 +404,13 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
verify(mSideFpsController, never()).show(any()); verify(mSideFpsController, never()).show(any());
} }
@Test
public void onBouncerVisibilityChanged_resetsScale() {
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
verify(mView).resetScale();
}
@Test @Test
public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() { public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() {
setupGetSecurityView(); setupGetSecurityView();

View File

@@ -49,6 +49,8 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import androidx.constraintlayout.widget.ConstraintSet; import androidx.constraintlayout.widget.ConstraintSet;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -357,6 +359,27 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
assertThat(viewFlipperConstraint.layout.leftToLeft).isEqualTo(PARENT_ID); assertThat(viewFlipperConstraint.layout.leftToLeft).isEqualTo(PARENT_ID);
} }
@Test
public void testPlayBackAnimation() {
OnBackAnimationCallback backCallback = mKeyguardSecurityContainer.getBackCallback();
backCallback.onBackStarted(createBackEvent(0, 0));
mKeyguardSecurityContainer.getBackCallback().onBackProgressed(
createBackEvent(0, 1));
assertThat(mKeyguardSecurityContainer.getScaleX()).isEqualTo(
KeyguardSecurityContainer.MIN_BACK_SCALE);
assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(
KeyguardSecurityContainer.MIN_BACK_SCALE);
// reset scale
mKeyguardSecurityContainer.resetScale();
assertThat(mKeyguardSecurityContainer.getScaleX()).isEqualTo(1);
assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1);
}
private BackEvent createBackEvent(float touchX, float progress) {
return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
}
private Configuration configuration(@Configuration.Orientation int orientation) { private Configuration configuration(@Configuration.Orientation int orientation) {
Configuration config = new Configuration(); Configuration config = new Configuration();
config.orientation = orientation; config.orientation = orientation;

View File

@@ -39,6 +39,8 @@ import android.testing.TestableLooper;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewRootImpl; import android.view.ViewRootImpl;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher; import android.window.OnBackInvokedDispatcher;
import android.window.WindowOnBackInvokedDispatcher; import android.window.WindowOnBackInvokedDispatcher;
@@ -56,6 +58,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManager;
import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.data.BouncerView; import com.android.systemui.keyguard.data.BouncerView;
import com.android.systemui.keyguard.data.BouncerViewDelegate; import com.android.systemui.keyguard.data.BouncerViewDelegate;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
@@ -120,16 +123,19 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor; @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
@Mock private BouncerView mBouncerView; @Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate; @Mock private BouncerViewDelegate mBouncerViewDelegate;
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private KeyguardBouncer.PrimaryBouncerExpansionCallback mBouncerExpansionCallback; private KeyguardBouncer.PrimaryBouncerExpansionCallback mBouncerExpansionCallback;
private FakeKeyguardStateController mKeyguardStateController = private FakeKeyguardStateController mKeyguardStateController =
spy(new FakeKeyguardStateController()); spy(new FakeKeyguardStateController());
@Mock private ViewRootImpl mViewRootImpl; @Mock
@Mock private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher; private ViewRootImpl mViewRootImpl;
@Mock
private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
@Captor @Captor
private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback; private ArgumentCaptor<OnBackInvokedCallback> mBackCallbackCaptor;
@Before @Before
@@ -140,6 +146,10 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class))) when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class)))
.thenReturn(mKeyguardMessageAreaController); .thenReturn(mKeyguardMessageAreaController);
when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate); when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
when(mFeatureFlags
.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
.thenReturn(true);
when(mFeatureFlags.isEnabled(MODERN_BOUNCER)).thenReturn(true); when(mFeatureFlags.isEnabled(MODERN_BOUNCER)).thenReturn(true);
@@ -193,7 +203,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Test @Test
public void dismissWithAction_AfterKeyguardGoneSetToFalse() { public void dismissWithAction_AfterKeyguardGoneSetToFalse() {
OnDismissAction action = () -> false; OnDismissAction action = () -> false;
Runnable cancelAction = () -> {}; Runnable cancelAction = () -> {
};
mStatusBarKeyguardViewManager.dismissWithAction( mStatusBarKeyguardViewManager.dismissWithAction(
action, cancelAction, false /* afterKeyguardGone */); action, cancelAction, false /* afterKeyguardGone */);
verify(mPrimaryBouncerInteractor).setDismissAction(eq(action), eq(cancelAction)); verify(mPrimaryBouncerInteractor).setDismissAction(eq(action), eq(cancelAction));
@@ -541,12 +552,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mBouncerExpansionCallback.onVisibilityChanged(true); mBouncerExpansionCallback.onVisibilityChanged(true);
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback( verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY), eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
mOnBackInvokedCallback.capture()); mBackCallbackCaptor.capture());
/* verify that the same callback is unregistered when the bouncer becomes invisible */ /* verify that the same callback is unregistered when the bouncer becomes invisible */
mBouncerExpansionCallback.onVisibilityChanged(false); mBouncerExpansionCallback.onVisibilityChanged(false);
verify(mOnBackInvokedDispatcher).unregisterOnBackInvokedCallback( verify(mOnBackInvokedDispatcher).unregisterOnBackInvokedCallback(
eq(mOnBackInvokedCallback.getValue())); eq(mBackCallbackCaptor.getValue()));
} }
@Test @Test
@@ -555,17 +566,62 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
/* capture the predictive back callback during registration */ /* capture the predictive back callback during registration */
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback( verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY), eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
mOnBackInvokedCallback.capture()); mBackCallbackCaptor.capture());
when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true); when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
when(mCentralSurfaces.shouldKeyguardHideImmediately()).thenReturn(true); when(mCentralSurfaces.shouldKeyguardHideImmediately()).thenReturn(true);
/* invoke the back callback directly */ /* invoke the back callback directly */
mOnBackInvokedCallback.getValue().onBackInvoked(); mBackCallbackCaptor.getValue().onBackInvoked();
/* verify that the bouncer will be hidden as a result of the invocation */ /* verify that the bouncer will be hidden as a result of the invocation */
verify(mCentralSurfaces).setBouncerShowing(eq(false)); verify(mCentralSurfaces).setBouncerShowing(eq(false));
} }
@Test
public void testPredictiveBackCallback_noBackAnimationForFullScreenBouncer() {
when(mKeyguardSecurityModel.getSecurityMode(anyInt()))
.thenReturn(KeyguardSecurityModel.SecurityMode.SimPin);
mBouncerExpansionCallback.onVisibilityChanged(true);
/* capture the predictive back callback during registration */
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
mBackCallbackCaptor.capture());
assertTrue(mBackCallbackCaptor.getValue() instanceof OnBackAnimationCallback);
OnBackAnimationCallback backCallback =
(OnBackAnimationCallback) mBackCallbackCaptor.getValue();
BackEvent event = new BackEvent(0, 0, 0, BackEvent.EDGE_LEFT);
backCallback.onBackStarted(event);
verify(mBouncerViewDelegateBackCallback, never()).onBackStarted(any());
}
@Test
public void testPredictiveBackCallback_forwardsBackDispatches() {
mBouncerExpansionCallback.onVisibilityChanged(true);
/* capture the predictive back callback during registration */
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY),
mBackCallbackCaptor.capture());
assertTrue(mBackCallbackCaptor.getValue() instanceof OnBackAnimationCallback);
OnBackAnimationCallback backCallback =
(OnBackAnimationCallback) mBackCallbackCaptor.getValue();
BackEvent event = new BackEvent(0, 0, 0, BackEvent.EDGE_LEFT);
backCallback.onBackStarted(event);
verify(mBouncerViewDelegateBackCallback).onBackStarted(eq(event));
backCallback.onBackProgressed(event);
verify(mBouncerViewDelegateBackCallback).onBackProgressed(eq(event));
backCallback.onBackInvoked();
verify(mBouncerViewDelegateBackCallback).onBackInvoked();
backCallback.onBackCancelled();
verify(mBouncerViewDelegateBackCallback).onBackCancelled();
}
@Test @Test
public void testReportBouncerOnDreamWhenVisible() { public void testReportBouncerOnDreamWhenVisible() {
mBouncerExpansionCallback.onVisibilityChanged(true); mBouncerExpansionCallback.onVisibilityChanged(true);