Always bring desktop tasks to front

When showDesktop API is called, always bring desktop tasks to front. And
ignore the visibility status of the tasks.
Fixes an issue with launching desktop tasks from launcher when they are
already visible. Skipping the reorder calls causes second invoke from
launcher to hide all tasks.

Bug: 263264985
Test: atest DesktopModeControllerTest DesktopTasksControllerTest
Change-Id: Iaf5b77e24b75bf8dc8f1daeb749fa0e8e71fb232
This commit is contained in:
Ats Jenk
2023-01-03 16:33:03 -08:00
parent b638b557b8
commit c4b8e300d7
4 changed files with 58 additions and 19 deletions

View File

@@ -251,7 +251,8 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
* Show apps on desktop
*/
void showDesktopApps() {
WindowContainerTransaction wct = bringDesktopAppsToFront();
// Bring apps to front, ignoring their visibility status to always ensure they are on top.
WindowContainerTransaction wct = bringDesktopAppsToFront(true /* ignoreVisibility */);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
mTransitions.startTransition(TRANSIT_TO_FRONT, wct, null /* handler */);
@@ -261,7 +262,7 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
}
@NonNull
private WindowContainerTransaction bringDesktopAppsToFront() {
private WindowContainerTransaction bringDesktopAppsToFront(boolean force) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
final ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks();
ProtoLog.d(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront: tasks=%s", activeTasks.size());
@@ -278,12 +279,14 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
return wct;
}
final boolean allActiveTasksAreVisible = taskInfos.stream()
.allMatch(info -> mDesktopModeTaskRepository.isVisibleTask(info.taskId));
if (allActiveTasksAreVisible) {
ProtoLog.d(WM_SHELL_DESKTOP_MODE,
"bringDesktopAppsToFront: active tasks are already in front, skipping.");
return wct;
if (!force) {
final boolean allActiveTasksAreVisible = taskInfos.stream()
.allMatch(info -> mDesktopModeTaskRepository.isVisibleTask(info.taskId));
if (allActiveTasksAreVisible) {
ProtoLog.d(WM_SHELL_DESKTOP_MODE,
"bringDesktopAppsToFront: active tasks are already in front, skipping.");
return wct;
}
}
ProtoLog.d(WM_SHELL_DESKTOP_MODE,
"bringDesktopAppsToFront: reordering all active tasks to the front");
@@ -354,7 +357,7 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
if (wct == null) {
wct = new WindowContainerTransaction();
}
wct.merge(bringDesktopAppsToFront(), true /* transfer */);
wct.merge(bringDesktopAppsToFront(false /* ignoreVisibility */), true /* transfer */);
wct.reorder(request.getTriggerTask().token, true /* onTop */);
return wct;

View File

@@ -84,8 +84,7 @@ class DesktopTasksController(
fun showDesktopApps() {
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
val wct = WindowContainerTransaction()
bringDesktopAppsToFront(wct)
bringDesktopAppsToFront(wct, force = true)
// Execute transaction if there are pending operations
if (!wct.isEmpty) {
@@ -150,11 +149,11 @@ class DesktopTasksController(
?: WINDOWING_MODE_UNDEFINED
}
private fun bringDesktopAppsToFront(wct: WindowContainerTransaction) {
private fun bringDesktopAppsToFront(wct: WindowContainerTransaction, force: Boolean = false) {
val activeTasks = desktopModeTaskRepository.getActiveTasks()
// Skip if all tasks are already visible
if (activeTasks.isNotEmpty() && activeTasks.all(desktopModeTaskRepository::isVisibleTask)) {
if (!force && activeTasks.all(desktopModeTaskRepository::isVisibleTask)) {
ProtoLog.d(
WM_SHELL_DESKTOP_MODE,
"bringDesktopAppsToFront: active tasks are already in front, skipping."

View File

@@ -279,7 +279,7 @@ public class DesktopModeControllerTest extends ShellTestCase {
}
@Test
public void testShowDesktopApps_appsAlreadyVisible_doesNothing() {
public void testShowDesktopApps_appsAlreadyVisible_bringsToFront() {
final RunningTaskInfo task1 = createFreeformTask();
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
@@ -294,8 +294,17 @@ public class DesktopModeControllerTest extends ShellTestCase {
mController.showDesktopApps();
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
// No reordering needed.
assertThat(wct.getHierarchyOps()).isEmpty();
// Check wct has reorder calls
assertThat(wct.getHierarchyOps()).hasSize(2);
// Task 1 appeared first, must be first reorder to top.
HierarchyOp op1 = wct.getHierarchyOps().get(0);
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
assertThat(op1.getContainer()).isEqualTo(task1.token.asBinder());
// Task 2 appeared last, must be last reorder to top.
HierarchyOp op2 = wct.getHierarchyOps().get(1);
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
}
@Test

View File

@@ -150,8 +150,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
@Test
fun showDesktopApps_appsAlreadyVisible_doesNothing() {
setUpHomeTask()
fun showDesktopApps_appsAlreadyVisible_bringsToFront() {
val homeTask = setUpHomeTask()
val task1 = setUpFreeformTask()
val task2 = setUpFreeformTask()
markTaskVisible(task1)
@@ -159,7 +159,12 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.showDesktopApps()
verifyWCTNotExecuted()
val wct = getLatestWct()
assertThat(wct.hierarchyOps).hasSize(3)
// Expect order to be from bottom: home, task1, task2
wct.assertReorderAt(index = 0, homeTask)
wct.assertReorderAt(index = 1, task1)
wct.assertReorderAt(index = 2, task2)
}
@Test
@@ -206,6 +211,23 @@ class DesktopTasksControllerTest : ShellTestCase() {
verifyWCTNotExecuted()
}
@Test
fun moveToDesktop_otherFreeformTasksBroughtToFront() {
val homeTask = setUpHomeTask()
val freeformTask = setUpFreeformTask()
val fullscreenTask = setUpFullscreenTask()
markTaskHidden(freeformTask)
controller.moveToDesktop(fullscreenTask)
with(getLatestWct()) {
assertThat(hierarchyOps).hasSize(3)
assertReorderSequence(homeTask, freeformTask, fullscreenTask)
assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode)
.isEqualTo(WINDOWING_MODE_FREEFORM)
}
}
@Test
fun moveToFullscreen() {
val task = setUpFreeformTask()
@@ -406,3 +428,9 @@ private fun WindowContainerTransaction.assertReorderAt(index: Int, task: Running
assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REORDER)
assertThat(op.container).isEqualTo(task.token.asBinder())
}
private fun WindowContainerTransaction.assertReorderSequence(vararg tasks: RunningTaskInfo) {
for (i in tasks.indices) {
assertReorderAt(i, tasks[i])
}
}