Move task to the bottom when force hidden
Move a task to the bottom when the task was hidden to prevent the top focused activity unable to enter pip (while pausing) due to a invisible task remained on top. Move the task to top once being visible again Bug: 180405672 Test: atest TaskTests PinnedStackTests Change-Id: I038076c58cd41cc90039c9db5a295da5d5ee2cde
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
@@ -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() {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user