Loading services/core/java/com/android/server/wm/Task.java +25 −8 Original line number Diff line number Diff line Loading @@ -5245,17 +5245,29 @@ class Task extends WindowContainer<WindowContainer> { if (mForceHiddenFlags == newFlags) { return false; } final boolean wasHidden = isForceHidden(); final boolean wasVisible = isVisible(); mForceHiddenFlags = newFlags; if (wasHidden != isForceHidden() && isTopActivityFocusable()) { // The change in force-hidden state will change visibility without triggering a root // task order change, so we should reset the preferred top focusable root task to ensure // it's not used if a new activity is started from this task. getDisplayArea().resetPreferredTopFocusableRootTaskIfNeeded(this); final boolean nowHidden = isForceHidden(); if (wasHidden != nowHidden) { final String reason = "setForceHidden"; if (wasVisible && nowHidden) { // Move this visible task to back when the task is forced hidden moveToBack(reason, null); } else if (isAlwaysOnTop()) { // Move this always-on-top task to front when no longer hidden moveToFront(reason); } } return true; } @Override public boolean isAlwaysOnTop() { return !isForceHidden() && super.isAlwaysOnTop(); } /** * Returns whether this task is currently forced to be hidden for any reason. */ Loading Loading @@ -7482,17 +7494,22 @@ class Task extends WindowContainer<WindowContainer> { } public void setAlwaysOnTop(boolean alwaysOnTop) { if (isAlwaysOnTop() == alwaysOnTop) { // {@link #isAwaysonTop} overrides the original behavior which also evaluates if this // task is force hidden, so super.isAlwaysOnTop() is used here to see whether the // alwaysOnTop attributes should be updated. if (super.isAlwaysOnTop() == alwaysOnTop) { return; } super.setAlwaysOnTop(alwaysOnTop); final TaskDisplayArea taskDisplayArea = getDisplayArea(); // positionChildAtTop() must be called even when always on top gets turned off because we // need to make sure that the root task is moved from among always on top windows to // below other always on top windows. Since the position the root task should be inserted // into is calculated properly in {@link DisplayContent#getTopInsertPosition()} in both // cases, we can just request that the root task is put at top here. taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */); // Don't bother moving task to top if this task is force hidden and invisible to user. if (!isForceHidden()) { getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */); } } void dismissPip() { Loading services/core/java/com/android/server/wm/TaskDisplayArea.java +1 −9 Original line number Diff line number Diff line Loading @@ -393,7 +393,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { final boolean moveToBottom = position <= 0; final int oldPosition = mChildren.indexOf(child); if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) { if (child.isAlwaysOnTop() && !moveToTop) { // This root task is always-on-top, override the default behavior. Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom"); Loading Loading @@ -974,14 +974,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { onRootTaskOrderChanged(rootTask); } /** Reset the mPreferredTopFocusableRootTask if it is or below the given task. */ void resetPreferredTopFocusableRootTaskIfNeeded(Task task) { if (mPreferredTopFocusableRootTask != null && mPreferredTopFocusableRootTask.compareTo(task) <= 0) { mPreferredTopFocusableRootTask = null; } } /** * Moves/reparents `task` to the back of whatever container the root home task is in. This is * for when we just want to move a task to "the back" vs. a specific place. The primary use-case Loading services/tests/wmtests/src/com/android/server/wm/TaskTests.java +12 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -277,4 +278,15 @@ public class TaskTests extends WindowTestsBase { // Orientation request from standard activity in multi window will not be handled. assertFalse(leafTask2.handlesOrientationChangeFromDescendant()); } @Test public void testAlwaysOnTop() { final Task task = createTaskStackOnDisplay(mDisplayContent); task.setAlwaysOnTop(true); task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); assertTrue(task.isAlwaysOnTop()); task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, true /* set */); assertFalse(task.isAlwaysOnTop()); } } Loading
services/core/java/com/android/server/wm/Task.java +25 −8 Original line number Diff line number Diff line Loading @@ -5245,17 +5245,29 @@ class Task extends WindowContainer<WindowContainer> { if (mForceHiddenFlags == newFlags) { return false; } final boolean wasHidden = isForceHidden(); final boolean wasVisible = isVisible(); mForceHiddenFlags = newFlags; if (wasHidden != isForceHidden() && isTopActivityFocusable()) { // The change in force-hidden state will change visibility without triggering a root // task order change, so we should reset the preferred top focusable root task to ensure // it's not used if a new activity is started from this task. getDisplayArea().resetPreferredTopFocusableRootTaskIfNeeded(this); final boolean nowHidden = isForceHidden(); if (wasHidden != nowHidden) { final String reason = "setForceHidden"; if (wasVisible && nowHidden) { // Move this visible task to back when the task is forced hidden moveToBack(reason, null); } else if (isAlwaysOnTop()) { // Move this always-on-top task to front when no longer hidden moveToFront(reason); } } return true; } @Override public boolean isAlwaysOnTop() { return !isForceHidden() && super.isAlwaysOnTop(); } /** * Returns whether this task is currently forced to be hidden for any reason. */ Loading Loading @@ -7482,17 +7494,22 @@ class Task extends WindowContainer<WindowContainer> { } public void setAlwaysOnTop(boolean alwaysOnTop) { if (isAlwaysOnTop() == alwaysOnTop) { // {@link #isAwaysonTop} overrides the original behavior which also evaluates if this // task is force hidden, so super.isAlwaysOnTop() is used here to see whether the // alwaysOnTop attributes should be updated. if (super.isAlwaysOnTop() == alwaysOnTop) { return; } super.setAlwaysOnTop(alwaysOnTop); final TaskDisplayArea taskDisplayArea = getDisplayArea(); // positionChildAtTop() must be called even when always on top gets turned off because we // need to make sure that the root task is moved from among always on top windows to // below other always on top windows. Since the position the root task should be inserted // into is calculated properly in {@link DisplayContent#getTopInsertPosition()} in both // cases, we can just request that the root task is put at top here. taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */); // Don't bother moving task to top if this task is force hidden and invisible to user. if (!isForceHidden()) { getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */); } } void dismissPip() { Loading
services/core/java/com/android/server/wm/TaskDisplayArea.java +1 −9 Original line number Diff line number Diff line Loading @@ -393,7 +393,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { final boolean moveToBottom = position <= 0; final int oldPosition = mChildren.indexOf(child); if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) { if (child.isAlwaysOnTop() && !moveToTop) { // This root task is always-on-top, override the default behavior. Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom"); Loading Loading @@ -974,14 +974,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { onRootTaskOrderChanged(rootTask); } /** Reset the mPreferredTopFocusableRootTask if it is or below the given task. */ void resetPreferredTopFocusableRootTaskIfNeeded(Task task) { if (mPreferredTopFocusableRootTask != null && mPreferredTopFocusableRootTask.compareTo(task) <= 0) { mPreferredTopFocusableRootTask = null; } } /** * Moves/reparents `task` to the back of whatever container the root home task is in. This is * for when we just want to move a task to "the back" vs. a specific place. The primary use-case Loading
services/tests/wmtests/src/com/android/server/wm/TaskTests.java +12 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -277,4 +278,15 @@ public class TaskTests extends WindowTestsBase { // Orientation request from standard activity in multi window will not be handled. assertFalse(leafTask2.handlesOrientationChangeFromDescendant()); } @Test public void testAlwaysOnTop() { final Task task = createTaskStackOnDisplay(mDisplayContent); task.setAlwaysOnTop(true); task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); assertTrue(task.isAlwaysOnTop()); task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, true /* set */); assertFalse(task.isAlwaysOnTop()); } }