From 65d66d3e648811920e6a5850792b8df83be51507 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 13 Dec 2018 17:48:39 -0800 Subject: [PATCH] Only cancel the recents anim upon visible stack order change - We previously canceled the animation for all stack order changes, but if we keep an activity running while in Recents, then there are transparent changes (ie. when a task is dismissed) where we don't want to trigger the current recents animation to be canceled. If the change is from a stack that is not visible, then keep the current animation running. Bug: 120426277 Test: atest WmTests:RecentsAnimationTest Change-Id: I7d57999cc5f249ccfcc2f9d0a198385524024a67 --- .../android/server/wm/ActivityDisplay.java | 14 ++-- .../android/server/wm/RecentsAnimation.java | 10 ++- .../android/server/wm/ActivityStackTests.java | 2 +- .../server/wm/RecentsAnimationTest.java | 67 +++++++++++++++---- 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index 10542d52e880d..973499f098b22 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -212,7 +212,7 @@ class ActivityDisplay extends ConfigurationContainer removeStackReferenceIfNeeded(stack); releaseSelfIfNeeded(); mService.updateSleepIfNeededLocked(); - onStackOrderChanged(); + onStackOrderChanged(stack); } void positionChildAtTop(ActivityStack stack, boolean includingParents) { @@ -280,7 +280,7 @@ class ActivityDisplay extends ConfigurationContainer if (!wasContained) { stack.setParent(this); } - onStackOrderChanged(); + onStackOrderChanged(stack); } private int getTopInsertPosition(ActivityStack stack, int candidatePosition) { @@ -1309,9 +1309,13 @@ class ActivityDisplay extends ConfigurationContainer mStackOrderChangedCallbacks.remove(listener); } - private void onStackOrderChanged() { + /** + * Notifies of a stack order change + * @param stack The stack which triggered the order change + */ + private void onStackOrderChanged(ActivityStack stack) { for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) { - mStackOrderChangedCallbacks.get(i).onStackOrderChanged(); + mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack); } } @@ -1390,6 +1394,6 @@ class ActivityDisplay extends ConfigurationContainer * Callback for when the order of the stacks in the display changes. */ interface OnStackOrderChangedListener { - void onStackOrderChanged(); + void onStackOrderChanged(ActivityStack stack); } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 42cd8e8643221..ec2d6737ee51c 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -387,7 +387,13 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } @Override - public void onStackOrderChanged() { + public void onStackOrderChanged(ActivityStack stack) { + if (DEBUG) Slog.d(TAG, "onStackOrderChanged(): stack=" + stack); + if (mDefaultDisplay.getIndexOf(stack) == -1 || !stack.shouldBeVisible(null)) { + // The stack is not visible, so ignore this change + return; + } + // If the activity display stack order changes, cancel any running recents animation in // place mWindowManager.cancelRecentsAnimationSynchronously(REORDER_KEEP_IN_PLACE, @@ -429,7 +435,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } for (int i = targetStack.getChildCount() - 1; i >= 0; i--) { - final TaskRecord task = (TaskRecord) targetStack.getChildAt(i); + final TaskRecord task = targetStack.getChildAt(i); if (task.getBaseIntent().getComponent().equals(component)) { return task.getTopActivity(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 85410f5e14df7..b2a28699e6a0a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -797,7 +797,7 @@ public class ActivityStackTests extends ActivityTestsBase { public boolean mChanged = false; @Override - public void onStackOrderChanged() { + public void onStackOrderChanged(ActivityStack stack) { mChanged = true; } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java index 0ff67d7b1f835..5f3a29032c22c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java @@ -24,7 +24,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; @@ -65,22 +64,26 @@ public class RecentsAnimationTest extends ActivityTestsBase { } @Test - public void testCancelAnimationOnStackOrderChange() { - ActivityStack fullscreenStack = - mService.mRootActivityContainer.getDefaultDisplay().createStack( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - ActivityStack recentsStack = mService.mRootActivityContainer.getDefaultDisplay().createStack( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); - ActivityRecord recentsActivity = new ActivityBuilder(mService) + public void testCancelAnimationOnVisibleStackOrderChange() { + ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay(); + ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, true /* onTop */); + new ActivityBuilder(mService) + .setComponent(new ComponentName(mContext.getPackageName(), "App1")) + .setCreateTask(true) + .setStack(fullscreenStack) + .build(); + ActivityStack recentsStack = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_RECENTS, true /* onTop */); + new ActivityBuilder(mService) .setComponent(mRecentsComponent) .setCreateTask(true) .setStack(recentsStack) .build(); - ActivityStack fullscreenStack2 = - mService.mRootActivityContainer.getDefaultDisplay().createStack( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - ActivityRecord fsActivity = new ActivityBuilder(mService) - .setComponent(new ComponentName(mContext.getPackageName(), "App1")) + ActivityStack fullscreenStack2 = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, true /* onTop */); + new ActivityBuilder(mService) + .setComponent(new ComponentName(mContext.getPackageName(), "App2")) .setCreateTask(true) .setStack(fullscreenStack2) .build(); @@ -97,4 +100,42 @@ public class RecentsAnimationTest extends ActivityTestsBase { verify(mService.mWindowManager, times(1)).cancelRecentsAnimationSynchronously( eq(REORDER_KEEP_IN_PLACE), any()); } + + @Test + public void testKeepAnimationOnHiddenStackOrderChange() { + ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay(); + ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, true /* onTop */); + new ActivityBuilder(mService) + .setComponent(new ComponentName(mContext.getPackageName(), "App1")) + .setCreateTask(true) + .setStack(fullscreenStack) + .build(); + ActivityStack recentsStack = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_RECENTS, true /* onTop */); + new ActivityBuilder(mService) + .setComponent(mRecentsComponent) + .setCreateTask(true) + .setStack(recentsStack) + .build(); + ActivityStack fullscreenStack2 = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, true /* onTop */); + new ActivityBuilder(mService) + .setComponent(new ComponentName(mContext.getPackageName(), "App2")) + .setCreateTask(true) + .setStack(fullscreenStack2) + .build(); + doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation(); + + // Start the recents animation + Intent recentsIntent = new Intent(); + recentsIntent.setComponent(mRecentsComponent); + mService.startRecentsActivity(recentsIntent, null, mock(IRecentsAnimationRunner.class)); + + fullscreenStack.remove(); + + // Ensure that the recents animation was NOT canceled + verify(mService.mWindowManager, times(0)).cancelRecentsAnimationSynchronously( + eq(REORDER_KEEP_IN_PLACE), any()); + } }