Loading services/core/java/com/android/server/wm/TaskDisplayArea.java +2 −127 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import static com.android.server.wm.DisplayContent.alwaysCreateRootTask; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; Loading @@ -46,7 +45,6 @@ import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.graphics.Color; import android.os.UserHandle; import android.util.Slog; import android.view.SurfaceControl; Loading Loading @@ -78,22 +76,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { DisplayContent mDisplayContent; /** * Keeps track of the last set color layer so that it can be reset during surface migrations. */ private @ColorInt int mBackgroundColor = 0; /** * This counter is used to make sure we don't prematurely clear the background color in the * case that background color animations are interleaved. * NOTE: The last set color will remain until the counter is reset to 0, which means that an * animation background color may sometime remain after the animation has finished through an * animation with a different background color if an animation starts after and ends before * another where both set different background colors. However, this is not a concern as * currently all task animation backgrounds are the same color. */ private int mColorLayerCounter = 0; // Cached reference to some special tasks we tend to get a lot so we don't need to loop // through the list to find them. private Task mRootHomeTask; Loading Loading @@ -290,14 +272,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } } @Override void setInitialSurfaceControlProperties(SurfaceControl.Builder b) { // We want an effect layer instead of the default container layer so that we can set a // background color on it for task animations. b.setEffectLayer(); super.setInitialSurfaceControlProperties(b); } @Override void addChild(WindowContainer child, int position) { if (child.asTaskDisplayArea() != null) { Loading Loading @@ -745,51 +719,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { return startLayer; } void setBackgroundColor(@ColorInt int colorInt) { setBackgroundColor(colorInt, false /* restore */); } void setBackgroundColor(@ColorInt int colorInt, boolean restore) { mBackgroundColor = colorInt; Color color = Color.valueOf(colorInt); // We don't want to increment the mColorLayerCounter if we are restoring the background // color after a surface migration because in that case the mColorLayerCounter already // accounts for setting that background color. if (!restore) { mColorLayerCounter++; } // Only apply the background color if the TDA is actually attached and has a valid surface // to set the background color on. We still want to keep track of the background color state // even if we are not showing it for when/if the TDA is reattached and gets a valid surface if (mSurfaceControl != null) { getPendingTransaction() .setColor(mSurfaceControl, new float[]{color.red(), color.green(), color.blue()}); scheduleAnimation(); } } void clearBackgroundColor() { mColorLayerCounter--; // Only clear the color layer if we have received the same amounts of clear as set // requests and TDA has a non null surface control (i.e. is attached) if (mColorLayerCounter == 0 && mSurfaceControl != null) { getPendingTransaction().unsetColor(mSurfaceControl); scheduleAnimation(); } } @Override void migrateToNewSurfaceControl(SurfaceControl.Transaction t) { super.migrateToNewSurfaceControl(t); if (mColorLayerCounter > 0) { setBackgroundColor(mBackgroundColor, true /* restore */); } reassignLayer(t); scheduleAnimation(); } Loading Loading @@ -1623,66 +1556,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId); } /** * Adjusts the {@param rootTask} behind the last visible rootTask in the display if necessary. * Generally used in conjunction with {@link #moveRootTaskBehindRootTask}. */ // TODO(b/151575894): Remove special root task movement methods. void moveRootTaskBehindBottomMostVisibleRootTask(Task rootTask) { if (rootTask.shouldBeVisible(null)) { // Skip if the root task is already visible return; } // Move the root task to the bottom to not affect the following visibility checks rootTask.getParent().positionChildAt(POSITION_BOTTOM, rootTask, false /* includingParents */); // Find the next position where the root task should be placed final boolean isRootTask = rootTask.isRootTask(); final int numRootTasks = isRootTask ? mChildren.size() : rootTask.getParent().getChildCount(); for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) { Task s; if (isRootTask) { final WindowContainer child = mChildren.get(rootTaskNdx); if (child.asTaskDisplayArea() != null) { s = child.asTaskDisplayArea().getBottomMostVisibleRootTask(rootTask); } else { s = child.asTask(); } } else { s = rootTask.getParent().getChildAt(rootTaskNdx).asTask(); } if (s == rootTask || s == null) { continue; } final int winMode = s.getWindowingMode(); final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN; if (s.shouldBeVisible(null) && isValidWindowingMode) { // Move the provided root task to behind this root task final int position = Math.max(0, rootTaskNdx - 1); rootTask.getParent().positionChildAt(position, rootTask, false /*includingParents */); break; } } } @Nullable private Task getBottomMostVisibleRootTask(Task excludeRootTask) { return getRootTask(task -> { final int winMode = task.getWindowingMode(); final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN; return task.shouldBeVisible(null) && isValidWindowingMode; }, false /* traverseTopToBottom */); } /** * Moves the {@param rootTask} behind the given {@param behindRootTask} if possible. If * {@param behindRootTask} is not currently in the display, then then the root task is moved * to the back. Generally used in conjunction with * {@link #moveRootTaskBehindBottomMostVisibleRootTask}. * to the back. */ void moveRootTaskBehindRootTask(Task rootTask, Task behindRootTask) { if (behindRootTask == null || behindRootTask == rootTask) { Loading Loading @@ -1744,9 +1621,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { @Override boolean canCreateRemoteAnimationTarget() { // In the legacy transition system, promoting animation target from TaskFragment to // TaskDisplayArea prevents running finish animation. See b/194649929. return WindowManagerService.sEnableShellTransitions; return true; } /** Loading services/core/java/com/android/server/wm/WindowManagerService.java +0 −9 Original line number Diff line number Diff line Loading @@ -443,11 +443,6 @@ public class WindowManagerService extends IWindowManager.Stub static final int LOGTAG_INPUT_FOCUS = 62001; /** * Use WMShell for app transition. */ public static final boolean sEnableShellTransitions = getShellTransitEnabled(); /** * Allows a fullscreen windowing mode activity to launch in its desired orientation directly * when the display has different orientation. Loading Loading @@ -10456,10 +10451,6 @@ public class WindowManagerService extends IWindowManager.Stub } } private static boolean getShellTransitEnabled() { return true; } /** * Dump ViewRootImpl for visible non-activity windows. */ Loading services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java +0 −96 Original line number Diff line number Diff line Loading @@ -831,102 +831,6 @@ public class RootTaskTests extends WindowTestsBase { assertTrue(firstActivity.shouldBeVisible()); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_NoMoveHomeBehindFullscreen() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask).isTranslucent(any()); // Ensure that we don't move the home root task if it is already behind the top fullscreen // root task. int homeRootTaskIndex = getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask); assertEquals(fullscreenRootTask, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(homeRootTaskIndex, getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_NoMoveHomeBehindTranslucent() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(true).when(fullscreenRootTask).isTranslucent(any()); // Ensure that we don't move the home root task if it is already behind the top fullscreen // root task. int homeRootTaskIndex = getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask); assertEquals(fullscreenRootTask, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(homeRootTaskIndex, getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_NoMoveHomeOnTop() { final Task fullscreenRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask).isTranslucent(any()); // Ensure we don't move the home root task if it is already on top int homeRootTaskIndex = getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask); assertNull(getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(homeRootTaskIndex, getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_MoveHomeBehindFullscreen() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask1 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task fullscreenRootTask2 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task pinnedRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask1).isTranslucent(any()); doReturn(false).when(fullscreenRootTask2).isTranslucent(any()); // Ensure that we move the home root task behind the bottom most fullscreen root task, // ignoring the pinned root task. assertEquals(fullscreenRootTask1, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(fullscreenRootTask2, getRootTaskAbove(homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_MoveHomeBehindFullscreenAndTranslucent() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask1 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task fullscreenRootTask2 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask1).isTranslucent(any()); doReturn(true).when(fullscreenRootTask2).isTranslucent(any()); // Ensure that we move the home root task behind the bottom most non-translucent fullscreen // root task. assertEquals(fullscreenRootTask1, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(fullscreenRootTask1, getRootTaskAbove(homeRootTask)); } @Test public void testMoveHomeRootTaskBehindRootTask_BehindHomeRootTask() { final Task fullscreenRootTask1 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, Loading Loading
services/core/java/com/android/server/wm/TaskDisplayArea.java +2 −127 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import static com.android.server.wm.DisplayContent.alwaysCreateRootTask; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; Loading @@ -46,7 +45,6 @@ import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.res.Configuration; import android.graphics.Color; import android.os.UserHandle; import android.util.Slog; import android.view.SurfaceControl; Loading Loading @@ -78,22 +76,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { DisplayContent mDisplayContent; /** * Keeps track of the last set color layer so that it can be reset during surface migrations. */ private @ColorInt int mBackgroundColor = 0; /** * This counter is used to make sure we don't prematurely clear the background color in the * case that background color animations are interleaved. * NOTE: The last set color will remain until the counter is reset to 0, which means that an * animation background color may sometime remain after the animation has finished through an * animation with a different background color if an animation starts after and ends before * another where both set different background colors. However, this is not a concern as * currently all task animation backgrounds are the same color. */ private int mColorLayerCounter = 0; // Cached reference to some special tasks we tend to get a lot so we don't need to loop // through the list to find them. private Task mRootHomeTask; Loading Loading @@ -290,14 +272,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } } @Override void setInitialSurfaceControlProperties(SurfaceControl.Builder b) { // We want an effect layer instead of the default container layer so that we can set a // background color on it for task animations. b.setEffectLayer(); super.setInitialSurfaceControlProperties(b); } @Override void addChild(WindowContainer child, int position) { if (child.asTaskDisplayArea() != null) { Loading Loading @@ -745,51 +719,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { return startLayer; } void setBackgroundColor(@ColorInt int colorInt) { setBackgroundColor(colorInt, false /* restore */); } void setBackgroundColor(@ColorInt int colorInt, boolean restore) { mBackgroundColor = colorInt; Color color = Color.valueOf(colorInt); // We don't want to increment the mColorLayerCounter if we are restoring the background // color after a surface migration because in that case the mColorLayerCounter already // accounts for setting that background color. if (!restore) { mColorLayerCounter++; } // Only apply the background color if the TDA is actually attached and has a valid surface // to set the background color on. We still want to keep track of the background color state // even if we are not showing it for when/if the TDA is reattached and gets a valid surface if (mSurfaceControl != null) { getPendingTransaction() .setColor(mSurfaceControl, new float[]{color.red(), color.green(), color.blue()}); scheduleAnimation(); } } void clearBackgroundColor() { mColorLayerCounter--; // Only clear the color layer if we have received the same amounts of clear as set // requests and TDA has a non null surface control (i.e. is attached) if (mColorLayerCounter == 0 && mSurfaceControl != null) { getPendingTransaction().unsetColor(mSurfaceControl); scheduleAnimation(); } } @Override void migrateToNewSurfaceControl(SurfaceControl.Transaction t) { super.migrateToNewSurfaceControl(t); if (mColorLayerCounter > 0) { setBackgroundColor(mBackgroundColor, true /* restore */); } reassignLayer(t); scheduleAnimation(); } Loading Loading @@ -1623,66 +1556,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId); } /** * Adjusts the {@param rootTask} behind the last visible rootTask in the display if necessary. * Generally used in conjunction with {@link #moveRootTaskBehindRootTask}. */ // TODO(b/151575894): Remove special root task movement methods. void moveRootTaskBehindBottomMostVisibleRootTask(Task rootTask) { if (rootTask.shouldBeVisible(null)) { // Skip if the root task is already visible return; } // Move the root task to the bottom to not affect the following visibility checks rootTask.getParent().positionChildAt(POSITION_BOTTOM, rootTask, false /* includingParents */); // Find the next position where the root task should be placed final boolean isRootTask = rootTask.isRootTask(); final int numRootTasks = isRootTask ? mChildren.size() : rootTask.getParent().getChildCount(); for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) { Task s; if (isRootTask) { final WindowContainer child = mChildren.get(rootTaskNdx); if (child.asTaskDisplayArea() != null) { s = child.asTaskDisplayArea().getBottomMostVisibleRootTask(rootTask); } else { s = child.asTask(); } } else { s = rootTask.getParent().getChildAt(rootTaskNdx).asTask(); } if (s == rootTask || s == null) { continue; } final int winMode = s.getWindowingMode(); final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN; if (s.shouldBeVisible(null) && isValidWindowingMode) { // Move the provided root task to behind this root task final int position = Math.max(0, rootTaskNdx - 1); rootTask.getParent().positionChildAt(position, rootTask, false /*includingParents */); break; } } } @Nullable private Task getBottomMostVisibleRootTask(Task excludeRootTask) { return getRootTask(task -> { final int winMode = task.getWindowingMode(); final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN; return task.shouldBeVisible(null) && isValidWindowingMode; }, false /* traverseTopToBottom */); } /** * Moves the {@param rootTask} behind the given {@param behindRootTask} if possible. If * {@param behindRootTask} is not currently in the display, then then the root task is moved * to the back. Generally used in conjunction with * {@link #moveRootTaskBehindBottomMostVisibleRootTask}. * to the back. */ void moveRootTaskBehindRootTask(Task rootTask, Task behindRootTask) { if (behindRootTask == null || behindRootTask == rootTask) { Loading Loading @@ -1744,9 +1621,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { @Override boolean canCreateRemoteAnimationTarget() { // In the legacy transition system, promoting animation target from TaskFragment to // TaskDisplayArea prevents running finish animation. See b/194649929. return WindowManagerService.sEnableShellTransitions; return true; } /** Loading
services/core/java/com/android/server/wm/WindowManagerService.java +0 −9 Original line number Diff line number Diff line Loading @@ -443,11 +443,6 @@ public class WindowManagerService extends IWindowManager.Stub static final int LOGTAG_INPUT_FOCUS = 62001; /** * Use WMShell for app transition. */ public static final boolean sEnableShellTransitions = getShellTransitEnabled(); /** * Allows a fullscreen windowing mode activity to launch in its desired orientation directly * when the display has different orientation. Loading Loading @@ -10456,10 +10451,6 @@ public class WindowManagerService extends IWindowManager.Stub } } private static boolean getShellTransitEnabled() { return true; } /** * Dump ViewRootImpl for visible non-activity windows. */ Loading
services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java +0 −96 Original line number Diff line number Diff line Loading @@ -831,102 +831,6 @@ public class RootTaskTests extends WindowTestsBase { assertTrue(firstActivity.shouldBeVisible()); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_NoMoveHomeBehindFullscreen() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask).isTranslucent(any()); // Ensure that we don't move the home root task if it is already behind the top fullscreen // root task. int homeRootTaskIndex = getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask); assertEquals(fullscreenRootTask, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(homeRootTaskIndex, getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_NoMoveHomeBehindTranslucent() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(true).when(fullscreenRootTask).isTranslucent(any()); // Ensure that we don't move the home root task if it is already behind the top fullscreen // root task. int homeRootTaskIndex = getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask); assertEquals(fullscreenRootTask, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(homeRootTaskIndex, getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_NoMoveHomeOnTop() { final Task fullscreenRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask).isTranslucent(any()); // Ensure we don't move the home root task if it is already on top int homeRootTaskIndex = getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask); assertNull(getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(homeRootTaskIndex, getTaskIndexOf(mDefaultTaskDisplayArea, homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_MoveHomeBehindFullscreen() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask1 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task fullscreenRootTask2 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task pinnedRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask1).isTranslucent(any()); doReturn(false).when(fullscreenRootTask2).isTranslucent(any()); // Ensure that we move the home root task behind the bottom most fullscreen root task, // ignoring the pinned root task. assertEquals(fullscreenRootTask1, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(fullscreenRootTask2, getRootTaskAbove(homeRootTask)); } @Test public void testMoveHomeRootTaskBehindBottomMostVisible_MoveHomeBehindFullscreenAndTranslucent() { final Task homeRootTask = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */); final Task fullscreenRootTask1 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); final Task fullscreenRootTask2 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); doReturn(false).when(homeRootTask).isTranslucent(any()); doReturn(false).when(fullscreenRootTask1).isTranslucent(any()); doReturn(true).when(fullscreenRootTask2).isTranslucent(any()); // Ensure that we move the home root task behind the bottom most non-translucent fullscreen // root task. assertEquals(fullscreenRootTask1, getRootTaskAbove(homeRootTask)); mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeRootTask); assertEquals(fullscreenRootTask1, getRootTaskAbove(homeRootTask)); } @Test public void testMoveHomeRootTaskBehindRootTask_BehindHomeRootTask() { final Task fullscreenRootTask1 = createTaskForShouldBeVisibleTest(mDefaultTaskDisplayArea, Loading