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;
|
SETTING_VALUE_ON) != SETTING_VALUE_OFF;
|
||||||
private static final int PROGRESS_THRESHOLD = SystemProperties
|
private static final int PROGRESS_THRESHOLD = SystemProperties
|
||||||
.getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
|
.getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
|
||||||
|
|
||||||
private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
|
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.
|
* 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 */
|
/** True when a back gesture is ongoing */
|
||||||
private boolean mBackGestureStarted = false;
|
private boolean mBackGestureStarted = false;
|
||||||
|
|
||||||
|
/** Tracks if an uninterruptible transition is in progress */
|
||||||
|
private boolean mTransitionInProgress = false;
|
||||||
/** @see #setTriggerBack(boolean) */
|
/** @see #setTriggerBack(boolean) */
|
||||||
private boolean mTriggerBack;
|
private boolean mTriggerBack;
|
||||||
|
|
||||||
@@ -96,6 +102,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
private IOnBackInvokedCallback mBackToLauncherCallback;
|
private IOnBackInvokedCallback mBackToLauncherCallback;
|
||||||
private float mTriggerThreshold;
|
private float mTriggerThreshold;
|
||||||
private float mProgressThreshold;
|
private float mProgressThreshold;
|
||||||
|
private final Runnable mResetTransitionRunnable = () -> {
|
||||||
|
finishAnimation();
|
||||||
|
mTransitionInProgress = false;
|
||||||
|
};
|
||||||
|
|
||||||
public BackAnimationController(
|
public BackAnimationController(
|
||||||
@NonNull @ShellMainThread ShellExecutor shellExecutor,
|
@NonNull @ShellMainThread ShellExecutor shellExecutor,
|
||||||
@@ -229,7 +239,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
mBackToLauncherCallback = null;
|
mBackToLauncherCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBackToLauncherAnimationFinished() {
|
@VisibleForTesting
|
||||||
|
void onBackToLauncherAnimationFinished() {
|
||||||
if (mBackNavigationInfo != null) {
|
if (mBackNavigationInfo != null) {
|
||||||
IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
|
IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
|
||||||
if (mTriggerBack) {
|
if (mTriggerBack) {
|
||||||
@@ -246,6 +257,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
* {@link BackAnimationController}
|
* {@link BackAnimationController}
|
||||||
*/
|
*/
|
||||||
public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) {
|
public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) {
|
||||||
|
if (mTransitionInProgress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (action == MotionEvent.ACTION_MOVE) {
|
if (action == MotionEvent.ACTION_MOVE) {
|
||||||
if (!mBackGestureStarted) {
|
if (!mBackGestureStarted) {
|
||||||
// Let the animation initialized here to make sure the onPointerDownOutsideFocus
|
// Let the animation initialized here to make sure the onPointerDownOutsideFocus
|
||||||
@@ -370,6 +384,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
|
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
|
||||||
? mBackToLauncherCallback
|
? mBackToLauncherCallback
|
||||||
: mBackNavigationInfo.getOnBackInvokedCallback();
|
: mBackNavigationInfo.getOnBackInvokedCallback();
|
||||||
|
if (shouldDispatchToLauncher) {
|
||||||
|
startTransition();
|
||||||
|
}
|
||||||
if (mTriggerBack) {
|
if (mTriggerBack) {
|
||||||
dispatchOnBackInvoked(targetCallback);
|
dispatchOnBackInvoked(targetCallback);
|
||||||
} else {
|
} 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.
|
* Sets to true when the back gesture has passed the triggering threshold, false otherwise.
|
||||||
*/
|
*/
|
||||||
public void setTriggerBack(boolean triggerBack) {
|
public void setTriggerBack(boolean triggerBack) {
|
||||||
|
if (mTransitionInProgress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mTriggerBack = triggerBack;
|
mTriggerBack = triggerBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,6 +487,23 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
|||||||
mTransaction.remove(screenshotSurface);
|
mTransaction.remove(screenshotSurface);
|
||||||
}
|
}
|
||||||
mTransaction.apply();
|
mTransaction.apply();
|
||||||
|
stopTransition();
|
||||||
backNavigationInfo.onBackNavigationFinished(triggerBack);
|
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.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
import android.app.IActivityTaskManager;
|
import android.app.IActivityTaskManager;
|
||||||
import android.app.WindowConfiguration;
|
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
|
// b/207481538, we check that the surface is not moved for now, we can re-enable this once
|
||||||
// we implement the animation
|
// we implement the animation
|
||||||
verify(mTransaction, never()).setScale(eq(screenshotSurface), anyInt(), anyInt());
|
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();
|
verify(mTransaction, atLeastOnce()).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +254,46 @@ public class BackAnimationControllerTest {
|
|||||||
verify(mIOnBackInvokedCallback, never()).onBackInvoked();
|
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) {
|
private void doMotionEvent(int actionDown, int coordinate) {
|
||||||
mController.onMotionEvent(
|
mController.onMotionEvent(
|
||||||
MotionEvent.obtain(0, mEventTime, actionDown, coordinate, coordinate, 0),
|
MotionEvent.obtain(0, mEventTime, actionDown, coordinate, coordinate, 0),
|
||||||
|
|||||||
Reference in New Issue
Block a user