Merge "Ensure no animation is run except for HOME" into tm-dev

This commit is contained in:
Vadim Caen
2022-04-01 09:23:26 +00:00
committed by Android (Google) Code Review
2 changed files with 54 additions and 71 deletions

View File

@@ -19,9 +19,6 @@ package com.android.wm.shell.back;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityTaskManager; import android.app.ActivityTaskManager;
@@ -223,14 +220,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private void initAnimation(MotionEvent event) { private void initAnimation(MotionEvent event) {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "initAnimation mMotionStarted=%b", mBackGestureStarted); ProtoLog.d(WM_SHELL_BACK_PREVIEW, "initAnimation mMotionStarted=%b", mBackGestureStarted);
if (mBackGestureStarted) { if (mBackGestureStarted || mBackNavigationInfo != null) {
Log.e(TAG, "Animation is being initialized but is already started."); Log.e(TAG, "Animation is being initialized but is already started.");
return;
}
if (mBackNavigationInfo != null) {
finishAnimation(); finishAnimation();
} }
mInitTouchLocation.set(event.getX(), event.getY()); mInitTouchLocation.set(event.getX(), event.getY());
mBackGestureStarted = true; mBackGestureStarted = true;
@@ -304,8 +298,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
return; return;
} }
int deltaX = Math.round(event.getX() - mInitTouchLocation.x); int deltaX = Math.round(event.getX() - mInitTouchLocation.x);
int deltaY = Math.round(event.getY() - mInitTouchLocation.y);
ProtoLog.v(WM_SHELL_BACK_PREVIEW, "Runner move: %d %d", deltaX, deltaY);
float progressThreshold = PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold; float progressThreshold = PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold;
float progress = Math.min(Math.max(Math.abs(deltaX) / progressThreshold, 0), 1); float progress = Math.min(Math.max(Math.abs(deltaX) / progressThreshold, 0), 1);
int backType = mBackNavigationInfo.getType(); int backType = mBackNavigationInfo.getType();
@@ -317,11 +309,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
targetCallback = mBackToLauncherCallback; targetCallback = mBackToLauncherCallback;
} else if (backType == BackNavigationInfo.TYPE_CROSS_TASK } else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) { || backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
if (animationTarget != null) { // TODO(208427216) Run the actual animation
mTransaction.setPosition(animationTarget.leash, deltaX, deltaY);
mTouchEventDelta.set(deltaX, deltaY);
mTransaction.apply();
}
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) { } else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback(); targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
} }
@@ -343,19 +331,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
} else { } else {
dispatchOnBackCancelled(targetCallback); dispatchOnBackCancelled(targetCallback);
} }
if (backType == BackNavigationInfo.TYPE_CALLBACK) { if (backType != BackNavigationInfo.TYPE_RETURN_TO_HOME || !shouldDispatchToLauncher) {
finishAnimation();
} else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
&& !shouldDispatchToLauncher) {
// Launcher callback missing. Simply finish animation. // Launcher callback missing. Simply finish animation.
finishAnimation(); finishAnimation();
} else if (backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY
|| backType == BackNavigationInfo.TYPE_CROSS_TASK) {
if (mTriggerBack) {
prepareTransition();
} else {
resetPositionAnimated();
}
} }
} }
@@ -403,8 +381,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
} }
} }
private static void dispatchOnBackProgressed( private static void dispatchOnBackProgressed(IOnBackInvokedCallback callback,
IOnBackInvokedCallback callback, BackEvent backEvent) { BackEvent backEvent) {
if (callback == null) { if (callback == null) {
return; return;
} }
@@ -415,48 +393,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
} }
} }
/**
* Animate the top window leash to its initial position.
*/
private void resetPositionAnimated() {
mBackGestureStarted = false;
// TODO(208786853) Handle overlap with a new coming gesture.
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Runner: Back not triggered, cancelling animation "
+ "mLastPos=%s mInitTouch=%s", mTouchEventDelta, mInitTouchLocation);
// TODO(208427216) : Replace placeholder animation with an actual one.
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f).setDuration(200);
animation.addUpdateListener(animation1 -> {
if (mBackNavigationInfo == null) {
return;
}
float fraction = animation1.getAnimatedFraction();
int deltaX = Math.round(mTouchEventDelta.x - (mTouchEventDelta.x * fraction));
int deltaY = Math.round(mTouchEventDelta.y - (mTouchEventDelta.y * fraction));
RemoteAnimationTarget animationTarget =
mBackNavigationInfo.getDepartingAnimationTarget();
if (animationTarget != null) {
mTransaction.setPosition(animationTarget.leash, deltaX, deltaY);
mTransaction.apply();
}
});
animation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: onAnimationEnd");
finishAnimation();
}
});
animation.start();
}
private void prepareTransition() {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "prepareTransition()");
mTriggerBack = false;
mBackGestureStarted = false;
}
/** /**
* 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.
*/ */

View File

@@ -16,10 +16,16 @@
package com.android.wm.shell.back; package com.android.wm.shell.back;
import static android.window.BackNavigationInfo.KEY_TRIGGER_BACK;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce; 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.verify; import static org.mockito.Mockito.verify;
import android.app.IActivityTaskManager; import android.app.IActivityTaskManager;
@@ -101,6 +107,14 @@ public class BackAnimationControllerTest {
} }
} }
private void createNavigationInfo(BackNavigationInfo.Builder builder) {
try {
doReturn(builder.build()).when(mActivityTaskManager).startBackNavigation();
} catch (RemoteException ex) {
ex.rethrowFromSystemServer();
}
}
RemoteAnimationTarget createAnimationTarget() { RemoteAnimationTarget createAnimationTarget() {
SurfaceControl topWindowLeash = new SurfaceControl(); SurfaceControl topWindowLeash = new SurfaceControl();
return new RemoteAnimationTarget(-1, RemoteAnimationTarget.MODE_CLOSING, topWindowLeash, return new RemoteAnimationTarget(-1, RemoteAnimationTarget.MODE_CLOSING, topWindowLeash,
@@ -109,6 +123,18 @@ public class BackAnimationControllerTest {
true, null, null, null, false, -1); true, null, null, null, false, -1);
} }
private void triggerBackGesture() {
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
mController.onMotionEvent(event, event.getAction(), BackEvent.EDGE_LEFT);
event = MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0);
mController.onMotionEvent(event, event.getAction(), BackEvent.EDGE_LEFT);
mController.setTriggerBack(true);
event = MotionEvent.obtain(10, 0, MotionEvent.ACTION_UP, 100, 100, 0);
mController.onMotionEvent(event, event.getAction(), BackEvent.EDGE_LEFT);
}
@Test @Test
@Ignore("b/207481538") @Ignore("b/207481538")
public void crossActivity_screenshotAttachedAndVisible() { public void crossActivity_screenshotAttachedAndVisible() {
@@ -140,10 +166,31 @@ public class BackAnimationControllerTest {
MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0), MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0),
MotionEvent.ACTION_MOVE, MotionEvent.ACTION_MOVE,
BackEvent.EDGE_LEFT); BackEvent.EDGE_LEFT);
verify(mTransaction).setPosition(animationTarget.leash, 100, 100); // 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, atLeastOnce()).apply(); verify(mTransaction, atLeastOnce()).apply();
} }
@Test
public void verifyAnimationFinishes() {
RemoteAnimationTarget animationTarget = createAnimationTarget();
boolean[] backNavigationDone = new boolean[]{false};
boolean[] triggerBack = new boolean[]{false};
createNavigationInfo(new BackNavigationInfo.Builder()
.setDepartingAnimationTarget(animationTarget)
.setType(BackNavigationInfo.TYPE_CROSS_ACTIVITY)
.setOnBackNavigationDone(
new RemoteCallback(result -> {
backNavigationDone[0] = true;
triggerBack[0] = result.getBoolean(KEY_TRIGGER_BACK);
})));
triggerBackGesture();
assertTrue("Navigation Done callback not called", backNavigationDone[0]);
assertTrue("TriggerBack should have been true", triggerBack[0]);
}
@Test @Test
public void backToHome_dispatchesEvents() throws RemoteException { public void backToHome_dispatchesEvents() throws RemoteException {
mController.setBackToLauncherCallback(mIOnBackInvokedCallback); mController.setBackToLauncherCallback(mIOnBackInvokedCallback);