Merge "Handle rotation while recents animation is running" into sc-dev am: f310e54069

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

Change-Id: Iacd5d37c51284b77d18daf2117fcb390cb7b0df5
This commit is contained in:
Winson Chung
2021-06-25 16:21:53 +00:00
committed by Automerger Merge Worker
4 changed files with 89 additions and 10 deletions

View File

@@ -5501,6 +5501,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
} }
boolean updateDisplayOverrideConfigurationLocked() { boolean updateDisplayOverrideConfigurationLocked() {
// Preemptively cancel the running recents animation -- SysUI can't currently handle this
// case properly since the signals it receives all happen post-change
final RecentsAnimationController recentsAnimationController =
mWmService.getRecentsAnimationController();
if (recentsAnimationController != null) {
recentsAnimationController.cancelAnimationForDisplayChange();
}
Configuration values = new Configuration(); Configuration values = new Configuration();
computeScreenConfiguration(values); computeScreenConfiguration(values);

View File

@@ -480,6 +480,16 @@ public class DisplayRotation {
return false; return false;
} }
// Preemptively cancel the running recents animation -- SysUI can't currently handle this
// case properly since the signals it receives all happen post-change. We do this earlier
// in the rotation flow, since DisplayContent.updateDisplayOverrideConfigurationLocked seems
// to happen too late.
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
if (recentsAnimationController != null) {
recentsAnimationController.cancelAnimationForDisplayChange();
}
final Transition t = (useShellTransitions final Transition t = (useShellTransitions
&& !mService.mAtmService.getTransitionController().isCollecting()) && !mService.mAtmService.getTransitionController().isCollecting())
? mService.mAtmService.getTransitionController().createTransition(TRANSIT_CHANGE) ? mService.mAtmService.getTransitionController().createTransition(TRANSIT_CHANGE)

View File

@@ -221,7 +221,7 @@ public class RecentsAnimationController implements DeathRecipient {
final ArraySet<Task> tasks = Sets.newArraySet(task); final ArraySet<Task> tasks = Sets.newArraySet(task);
snapshotController.snapshotTasks(tasks); snapshotController.snapshotTasks(tasks);
snapshotController.addSkipClosingAppSnapshotTasks(tasks); snapshotController.addSkipClosingAppSnapshotTasks(tasks);
return snapshotController.getSnapshot(taskId, 0 /* userId */, return snapshotController.getSnapshot(taskId, task.mUserId,
false /* restoreFromDisk */, false /* isLowResolution */); false /* restoreFromDisk */, false /* isLowResolution */);
} }
} }
@@ -353,18 +353,23 @@ public class RecentsAnimationController implements DeathRecipient {
@Override @Override
public void cleanupScreenshot() { public void cleanupScreenshot() {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mService.mGlobalLock) { synchronized (mService.mGlobalLock) {
if (mRecentScreenshotAnimator != null) { if (mRecentScreenshotAnimator != null) {
mRecentScreenshotAnimator.cancelAnimation(); mRecentScreenshotAnimator.cancelAnimation();
mRecentScreenshotAnimator = null; mRecentScreenshotAnimator = null;
} }
} }
} finally {
Binder.restoreCallingIdentity(token);
}
} }
@Override @Override
public void setWillFinishToHome(boolean willFinishToHome) { public void setWillFinishToHome(boolean willFinishToHome) {
synchronized (mService.getWindowManagerLock()) { synchronized (mService.getWindowManagerLock()) {
mWillFinishToHome = willFinishToHome; RecentsAnimationController.this.setWillFinishToHome(willFinishToHome);
} }
} }
@@ -513,7 +518,6 @@ public class RecentsAnimationController implements DeathRecipient {
|| config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
} }
@VisibleForTesting @VisibleForTesting
AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) { AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
return addAnimation(task, isRecentTaskInvisible, false /* hidden */, return addAnimation(task, isRecentTaskInvisible, false /* hidden */,
@@ -816,6 +820,18 @@ public class RecentsAnimationController implements DeathRecipient {
cancelAnimation(REORDER_KEEP_IN_PLACE, screenshot, "rootTaskOrderChanged"); cancelAnimation(REORDER_KEEP_IN_PLACE, screenshot, "rootTaskOrderChanged");
} }
/**
* If there is a recents animation running, we need to cancel the animation and snapshot the
* tasks before the change (to ensure they are captured at the right configuration)
*/
public void cancelAnimationForDisplayChange() {
if (mCanceled) {
return;
}
cancelAnimation(mWillFinishToHome ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION,
true /* screenshot */, "cancelAnimationForDisplayChange");
}
private void cancelAnimation(@ReorderMode int reorderMode, boolean screenshot, String reason) { private void cancelAnimation(@ReorderMode int reorderMode, boolean screenshot, String reason) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "cancelAnimation(): reason=%s", reason); ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "cancelAnimation(): reason=%s", reason);
synchronized (mService.getWindowManagerLock()) { synchronized (mService.getWindowManagerLock()) {
@@ -826,7 +842,7 @@ public class RecentsAnimationController implements DeathRecipient {
mService.mH.removeCallbacks(mFailsafeRunnable); mService.mH.removeCallbacks(mFailsafeRunnable);
mCanceled = true; mCanceled = true;
if (screenshot) { if (screenshot && !mPendingAnimations.isEmpty()) {
// Screen shot previous task when next task starts transition and notify the runner. // Screen shot previous task when next task starts transition and notify the runner.
// We will actually finish the animation once the runner calls cleanUpScreenshot(). // We will actually finish the animation once the runner calls cleanUpScreenshot().
final Task task = mPendingAnimations.get(0).mTask; final Task task = mPendingAnimations.get(0).mTask;
@@ -853,6 +869,11 @@ public class RecentsAnimationController implements DeathRecipient {
} }
} }
@VisibleForTesting
void setWillFinishToHome(boolean willFinishToHome) {
mWillFinishToHome = willFinishToHome;
}
/** /**
* Cancel recents animation when the next app transition starts. * Cancel recents animation when the next app transition starts.
* <p> * <p>
@@ -905,7 +926,8 @@ public class RecentsAnimationController implements DeathRecipient {
return null; return null;
} }
final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(mService.mSurfaceControlFactory, task, final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(
mService.mSurfaceControlFactory, task,
new SurfaceControl.ScreenshotHardwareBuffer(taskSnapshot.getHardwareBuffer(), new SurfaceControl.ScreenshotHardwareBuffer(taskSnapshot.getHardwareBuffer(),
taskSnapshot.getColorSpace(), false /* containsSecureLayers */)); taskSnapshot.getColorSpace(), false /* containsSecureLayers */));
mRecentScreenshotAnimator = new SurfaceAnimator( mRecentScreenshotAnimator = new SurfaceAnimator(
@@ -1006,7 +1028,16 @@ public class RecentsAnimationController implements DeathRecipient {
@Override @Override
public void binderDied() { public void binderDied() {
if (!mCanceled) {
cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied"); cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "binderDied");
} else {
synchronized (mService.getWindowManagerLock()) {
if (mRecentScreenshotAnimator != null) {
mRecentScreenshotAnimator.cancelAnimation();
mRecentScreenshotAnimator = null;
}
}
}
synchronized (mService.getWindowManagerLock()) { synchronized (mService.getWindowManagerLock()) {
// Clear associated input consumers on runner death // Clear associated input consumers on runner death

View File

@@ -655,6 +655,36 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
assertFalse(win1.mHasSurface); assertFalse(win1.mHasSurface);
} }
@Test
public void testCancelForRotation_ReorderToTop() throws Exception {
mWm.setRecentsAnimationController(mController);
final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
mController.setWillFinishToHome(true);
mController.cancelAnimationForDisplayChange();
verify(mMockRunner).onAnimationCanceled(any());
verify(mAnimationCallbacks).onAnimationFinished(REORDER_MOVE_TO_TOP, false);
}
@Test
public void testCancelForRotation_ReorderToOriginalPosition() throws Exception {
mWm.setRecentsAnimationController(mController);
final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
mController.setWillFinishToHome(false);
mController.cancelAnimationForDisplayChange();
verify(mMockRunner).onAnimationCanceled(any());
verify(mAnimationCallbacks).onAnimationFinished(REORDER_MOVE_TO_ORIGINAL_POSITION, false);
}
private ActivityRecord createHomeActivity() { private ActivityRecord createHomeActivity() {
final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService) final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService)
.setParentTask(mRootHomeTask) .setParentTask(mRootHomeTask)