Merge "Fix broken animation on two consecutive swipes." into tm-dev
This commit is contained in:
@@ -67,8 +67,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
SETTING_VALUE_ON) != SETTING_VALUE_OFF;
|
||||
private static final int PROGRESS_THRESHOLD = SystemProperties
|
||||
.getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
|
||||
|
||||
private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
|
||||
/**
|
||||
* Max duration to wait for a transition to finish before accepting another gesture start
|
||||
* request.
|
||||
*/
|
||||
private static final long MAX_TRANSITION_DURATION = 2000;
|
||||
|
||||
/**
|
||||
* Location of the initial touch event of the back gesture.
|
||||
@@ -84,6 +88,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
/** True when a back gesture is ongoing */
|
||||
private boolean mBackGestureStarted = false;
|
||||
|
||||
/** Tracks if an uninterruptible transition is in progress */
|
||||
private boolean mTransitionInProgress = false;
|
||||
/** @see #setTriggerBack(boolean) */
|
||||
private boolean mTriggerBack;
|
||||
|
||||
@@ -96,6 +102,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
private IOnBackInvokedCallback mBackToLauncherCallback;
|
||||
private float mTriggerThreshold;
|
||||
private float mProgressThreshold;
|
||||
private final Runnable mResetTransitionRunnable = () -> {
|
||||
finishAnimation();
|
||||
mTransitionInProgress = false;
|
||||
};
|
||||
|
||||
public BackAnimationController(
|
||||
@NonNull @ShellMainThread ShellExecutor shellExecutor,
|
||||
@@ -229,7 +239,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
mBackToLauncherCallback = null;
|
||||
}
|
||||
|
||||
private void onBackToLauncherAnimationFinished() {
|
||||
@VisibleForTesting
|
||||
void onBackToLauncherAnimationFinished() {
|
||||
if (mBackNavigationInfo != null) {
|
||||
IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
|
||||
if (mTriggerBack) {
|
||||
@@ -246,6 +257,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
* {@link BackAnimationController}
|
||||
*/
|
||||
public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) {
|
||||
if (mTransitionInProgress) {
|
||||
return;
|
||||
}
|
||||
if (action == MotionEvent.ACTION_MOVE) {
|
||||
if (!mBackGestureStarted) {
|
||||
// Let the animation initialized here to make sure the onPointerDownOutsideFocus
|
||||
@@ -370,6 +384,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
|
||||
? mBackToLauncherCallback
|
||||
: mBackNavigationInfo.getOnBackInvokedCallback();
|
||||
if (shouldDispatchToLauncher) {
|
||||
startTransition();
|
||||
}
|
||||
if (mTriggerBack) {
|
||||
dispatchOnBackInvoked(targetCallback);
|
||||
} else {
|
||||
@@ -436,6 +453,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
* Sets to true when the back gesture has passed the triggering threshold, false otherwise.
|
||||
*/
|
||||
public void setTriggerBack(boolean triggerBack) {
|
||||
if (mTransitionInProgress) {
|
||||
return;
|
||||
}
|
||||
mTriggerBack = triggerBack;
|
||||
}
|
||||
|
||||
@@ -467,6 +487,23 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
mTransaction.remove(screenshotSurface);
|
||||
}
|
||||
mTransaction.apply();
|
||||
stopTransition();
|
||||
backNavigationInfo.onBackNavigationFinished(triggerBack);
|
||||
}
|
||||
|
||||
private void startTransition() {
|
||||
if (mTransitionInProgress) {
|
||||
return;
|
||||
}
|
||||
mTransitionInProgress = true;
|
||||
mShellExecutor.executeDelayed(mResetTransitionRunnable, MAX_TRANSITION_DURATION);
|
||||
}
|
||||
|
||||
private void stopTransition() {
|
||||
if (!mTransitionInProgress) {
|
||||
return;
|
||||
}
|
||||
mShellExecutor.removeCallbacks(mResetTransitionRunnable);
|
||||
mTransitionInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import android.app.IActivityTaskManager;
|
||||
import android.app.WindowConfiguration;
|
||||
@@ -180,7 +182,8 @@ public class BackAnimationControllerTest {
|
||||
// b/207481538, we check that the surface is not moved for now, we can re-enable this once
|
||||
// we implement the animation
|
||||
verify(mTransaction, never()).setScale(eq(screenshotSurface), anyInt(), anyInt());
|
||||
verify(mTransaction, never()).setPosition(animationTarget.leash, 100, 100);
|
||||
verify(mTransaction, never()).setPosition(
|
||||
animationTarget.leash, 100, 100);
|
||||
verify(mTransaction, atLeastOnce()).apply();
|
||||
}
|
||||
|
||||
@@ -251,6 +254,46 @@ public class BackAnimationControllerTest {
|
||||
verify(mIOnBackInvokedCallback, never()).onBackInvoked();
|
||||
}
|
||||
|
||||
public void ignoresGesture_transitionInProgress() throws RemoteException {
|
||||
mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
|
||||
RemoteAnimationTarget animationTarget = createAnimationTarget();
|
||||
createNavigationInfo(animationTarget, null, null,
|
||||
BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
|
||||
|
||||
triggerBackGesture();
|
||||
// Check that back invocation is dispatched.
|
||||
verify(mIOnBackInvokedCallback).onBackInvoked();
|
||||
|
||||
reset(mIOnBackInvokedCallback);
|
||||
// Verify that we prevent animation from restarting if another gestures happens before
|
||||
// the previous transition is finished.
|
||||
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
|
||||
verifyNoMoreInteractions(mIOnBackInvokedCallback);
|
||||
|
||||
// Verify that we start accepting gestures again once transition finishes.
|
||||
mController.onBackToLauncherAnimationFinished();
|
||||
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
|
||||
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
|
||||
verify(mIOnBackInvokedCallback).onBackStarted();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptsGesture_transitionTimeout() throws RemoteException {
|
||||
mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
|
||||
RemoteAnimationTarget animationTarget = createAnimationTarget();
|
||||
createNavigationInfo(animationTarget, null, null,
|
||||
BackNavigationInfo.TYPE_RETURN_TO_HOME, null);
|
||||
|
||||
triggerBackGesture();
|
||||
reset(mIOnBackInvokedCallback);
|
||||
|
||||
// Simulate transition timeout.
|
||||
mShellExecutor.flushAll();
|
||||
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
|
||||
doMotionEvent(MotionEvent.ACTION_MOVE, 100);
|
||||
verify(mIOnBackInvokedCallback).onBackStarted();
|
||||
}
|
||||
|
||||
private void doMotionEvent(int actionDown, int coordinate) {
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(0, mEventTime, actionDown, coordinate, coordinate, 0),
|
||||
|
||||
Reference in New Issue
Block a user