diff options
5 files changed, 60 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 1eae56745a75..e718c7b2a36e 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.RemoteAnimationTarget.MODE_CLOSING; +import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; - import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; import static com.android.server.wm.AnimationAdapterProto.REMOTE; @@ -48,16 +48,13 @@ import android.view.IRecentsAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; - import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.input.InputWindowHandle; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; import com.android.server.wm.utils.InsetUtils; - import com.google.android.collect.Sets; - import java.io.PrintWriter; import java.util.ArrayList; @@ -93,6 +90,7 @@ public class RecentsAnimationController implements DeathRecipient { // The recents component app token that is shown behind the visibile tasks private AppWindowToken mTargetAppToken; + private int mTargetActivityType; private Rect mMinimizedHomeBounds = new Rect(); // We start the RecentsAnimationController in a pending-start state since we need to wait for @@ -259,23 +257,37 @@ public class RecentsAnimationController implements DeathRecipient { mDisplayId = displayId; } + public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) { + initialize(mService.mRoot.getDisplayContent(mDisplayId), targetActivityType, recentTaskIds); + } + /** * Initializes the recents animation controller. This is a separate call from the constructor * because it may call cancelAnimation() which needs to properly clean up the controller * in the window manager. */ - public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) { - // Make leashes for each of the visible tasks and add it to the recents animation to be - // started - final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); + @VisibleForTesting + void initialize(DisplayContent dc, int targetActivityType, SparseBooleanArray recentTaskIds) { + mTargetActivityType = targetActivityType; + + // Make leashes for each of the visible/target tasks and add it to the recents animation to + // be started final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); + final TaskStack targetStack = dc.getStack(WINDOWING_MODE_UNDEFINED, targetActivityType); + if (targetStack != null) { + for (int i = targetStack.getChildCount() - 1; i >= 0; i--) { + final Task t = targetStack.getChildAt(i); + if (!visibleTasks.contains(t)) { + visibleTasks.add(t); + } + } + } final int taskCount = visibleTasks.size(); for (int i = 0; i < taskCount; i++) { final Task task = visibleTasks.get(i); final WindowConfiguration config = task.getWindowConfiguration(); if (config.tasksAreFloating() - || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY - || config.getActivityType() == targetActivityType) { + || config.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { continue; } addAnimation(task, !recentTaskIds.get(task.mTaskId)); @@ -586,7 +598,10 @@ public class RecentsAnimationController implements DeathRecipient { final Rect insets = new Rect(); mainWindow.getContentInsets(insets); InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets()); - mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash, + final int mode = topApp.getActivityType() == mTargetActivityType + ? MODE_OPENING + : MODE_CLOSING; + mTarget = new RemoteAnimationTarget(mTask.mTaskId, mode, mCapturedLeash, !topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect, insets, mTask.getPrefixOrderIndex(), mPosition, mBounds, mTask.getWindowConfiguration(), mIsRecentTaskInvisible); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index cc23ab6f77d9..6aa0e0144c40 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -561,9 +561,10 @@ class Task extends WindowContainer<AppWindowToken> { @Override public SurfaceControl getAnimationLeashParent() { - // Reparent to the animation layer so that we aren't clipped by the non-minimized - // stack bounds, currently we only animate the task for the recents animation - return getAppAnimationLayer(ANIMATION_LAYER_STANDARD); + // Currently, only the recents animation will create animation leashes for tasks. In this + // case, reparent the task to the home animation layer while it is being animated to allow + // the home activity to reorder the app windows relative to its own. + return getAppAnimationLayer(ANIMATION_LAYER_HOME); } boolean isTaskAnimating() { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index e86093952474..4883f972f1e5 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -42,10 +42,8 @@ import android.view.MagnificationSpec; import android.view.SurfaceControl; import android.view.SurfaceControl.Builder; import android.view.SurfaceSession; - import com.android.internal.util.ToBooleanFunction; import com.android.server.wm.SurfaceAnimator.Animatable; - import java.io.PrintWriter; import java.util.Comparator; import java.util.LinkedList; @@ -71,7 +69,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< /** * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME} - * activities that happens below all {@link TaskStack}s. + * activities and all activities that are being controlled by the recents animation. This + * layer is generally below all {@link TaskStack}s. */ static final int ANIMATION_LAYER_HOME = 2; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 7caa7aedb873..b627df4a3313 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -227,6 +227,7 @@ import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; @@ -2714,6 +2715,11 @@ public class WindowManagerService extends IWindowManager.Stub } } + @VisibleForTesting + void setRecentsAnimationController(RecentsAnimationController controller) { + mRecentsAnimationController = controller; + } + public RecentsAnimationController getRecentsAnimationController() { return mRecentsAnimationController; } diff --git a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java index e7c45d59078c..aaa00452204b 100644 --- a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; @@ -24,6 +25,8 @@ import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_P import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; import static org.junit.Assert.fail; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.verify; @@ -33,6 +36,7 @@ import static org.mockito.Mockito.when; import android.os.Binder; import android.os.IInterface; import android.platform.test.annotations.Presubmit; +import android.util.SparseBooleanArray; import android.view.IRecentsAnimationRunner; import android.view.SurfaceControl; @@ -109,6 +113,24 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { } } + @Test + public void testIncludedApps_expectTargetAndVisible() throws Exception { + sWm.setRecentsAnimationController(mController); + final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME); + final AppWindowToken appWindow = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + hiddenAppWindow.setHidden(true); + mController.initialize(mDisplayContent, ACTIVITY_TYPE_HOME, new SparseBooleanArray()); + + // Ensure that we are animating the target activity as well + assertTrue(mController.isAnimatingTask(homeAppWindow.getTask())); + assertTrue(mController.isAnimatingTask(appWindow.getTask())); + assertFalse(mController.isAnimatingTask(hiddenAppWindow.getTask())); + } + private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) { verify(binder, atLeast(0)).asBinder(); verifyNoMoreInteractions(binder); |