Only bring desktop app to front when necessary
If the active desktops apps are already in the front, then there's no need to add WCT#reorder operations for every desktop app. Instead, check first whether there is an invisble app, and if there is, reorder all apps so that the Z order is maintained. Bug: 255344915 Bug: 258056163 Test: atest DesktopModeControllerTest Test: manual - in desktop mode, 1. Launch Gmail 2. Launch Photos 3. Observe there is no reorder triggered anymore Change-Id: Ib2cc8d900d1d0ccc8b9e2b49b95f1708531aa398
This commit is contained in:
@@ -259,21 +259,36 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
|
||||
|
||||
@NonNull
|
||||
private WindowContainerTransaction bringDesktopAppsToFront() {
|
||||
ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks();
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
final ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks();
|
||||
ProtoLog.d(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront: tasks=%s", activeTasks.size());
|
||||
ArrayList<RunningTaskInfo> taskInfos = new ArrayList<>();
|
||||
|
||||
final List<RunningTaskInfo> taskInfos = new ArrayList<>();
|
||||
for (Integer taskId : activeTasks) {
|
||||
RunningTaskInfo taskInfo = mShellTaskOrganizer.getRunningTaskInfo(taskId);
|
||||
if (taskInfo != null) {
|
||||
taskInfos.add(taskInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (taskInfos.isEmpty()) {
|
||||
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;
|
||||
}
|
||||
ProtoLog.d(WM_SHELL_DESKTOP_MODE,
|
||||
"bringDesktopAppsToFront: reordering all active tasks to the front");
|
||||
final List<Integer> allTasksInZOrder =
|
||||
mDesktopModeTaskRepository.getFreeformTasksInZOrder();
|
||||
// Sort by z-order, bottom to top, so that the top-most task is reordered to the top last
|
||||
// in the WCT.
|
||||
taskInfos.sort(Comparator.comparingInt(task -> -allTasksInZOrder.indexOf(task.taskId)));
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
for (RunningTaskInfo task : taskInfos) {
|
||||
wct.reorder(task.token, true);
|
||||
}
|
||||
|
||||
@@ -102,6 +102,13 @@ class DesktopModeTaskRepository {
|
||||
return activeTasks.contains(taskId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a task is visible.
|
||||
*/
|
||||
fun isVisibleTask(taskId: Int): Boolean {
|
||||
return visibleTasks.contains(taskId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of the active tasks
|
||||
*/
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.window.TransitionRequestInfo;
|
||||
import android.window.WindowContainerToken;
|
||||
import android.window.WindowContainerTransaction;
|
||||
import android.window.WindowContainerTransaction.Change;
|
||||
import android.window.WindowContainerTransaction.HierarchyOp;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -222,25 +223,29 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
// Check that there are hierarchy changes for home task and visible task
|
||||
assertThat(wct.getHierarchyOps()).hasSize(2);
|
||||
// First show home task
|
||||
WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||
HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||
assertThat(op1.getContainer()).isEqualTo(homeTask.token.asBinder());
|
||||
|
||||
// Then visible task on top of it
|
||||
WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||
HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||
assertThat(op2.getContainer()).isEqualTo(fullscreenTask1.token.asBinder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowDesktopApps() {
|
||||
public void testShowDesktopApps_allAppsInvisible_bringsToFront() {
|
||||
// Set up two active tasks on desktop, task2 is on top of task1.
|
||||
RunningTaskInfo freeformTask1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(freeformTask1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
freeformTask1.taskId, false /* visible */);
|
||||
RunningTaskInfo freeformTask2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(freeformTask2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
freeformTask2.taskId, false /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask1.taskId)).thenReturn(
|
||||
freeformTask1);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask2.taskId)).thenReturn(
|
||||
@@ -248,29 +253,68 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
|
||||
// Run show desktop apps logic
|
||||
mController.showDesktopApps();
|
||||
ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(
|
||||
WindowContainerTransaction.class);
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
verify(mTransitions).startTransition(eq(TRANSIT_TO_FRONT), wctCaptor.capture(), any());
|
||||
} else {
|
||||
verify(mShellTaskOrganizer).applyTransaction(wctCaptor.capture());
|
||||
}
|
||||
WindowContainerTransaction wct = wctCaptor.getValue();
|
||||
|
||||
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
// Check wct has reorder calls
|
||||
assertThat(wct.getHierarchyOps()).hasSize(2);
|
||||
|
||||
// Task 1 appeared first, must be first reorder to top.
|
||||
WindowContainerTransaction.HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||
HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||
assertThat(op1.getContainer()).isEqualTo(freeformTask1.token.asBinder());
|
||||
|
||||
// Task 2 appeared last, must be last reorder to top.
|
||||
WindowContainerTransaction.HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||
HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||
assertThat(op2.getContainer()).isEqualTo(freeformTask2.token.asBinder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowDesktopApps_appsAlreadyVisible_doesNothing() {
|
||||
final RunningTaskInfo task1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task1.taskId, true /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
|
||||
final RunningTaskInfo task2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task2.taskId, true /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
|
||||
|
||||
mController.showDesktopApps();
|
||||
|
||||
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
// No reordering needed.
|
||||
assertThat(wct.getHierarchyOps()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowDesktopApps_someAppsInvisible_reordersAll() {
|
||||
final RunningTaskInfo task1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task1.taskId, false /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
|
||||
final RunningTaskInfo task2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task2.taskId, true /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
|
||||
|
||||
mController.showDesktopApps();
|
||||
|
||||
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
// Both tasks should be reordered to top, even if one was already visible.
|
||||
assertThat(wct.getHierarchyOps()).hasSize(2);
|
||||
final HierarchyOp op1 = wct.getHierarchyOps().get(0);
|
||||
assertThat(op1.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||
assertThat(op1.getContainer()).isEqualTo(task1.token.asBinder());
|
||||
final HierarchyOp op2 = wct.getHierarchyOps().get(1);
|
||||
assertThat(op2.getType()).isEqualTo(HIERARCHY_OP_TYPE_REORDER);
|
||||
assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleTransitionRequest_desktopModeNotActive_returnsNull() {
|
||||
when(DesktopModeStatus.isActive(any())).thenReturn(false);
|
||||
@@ -355,6 +399,17 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
return arg.getValue();
|
||||
}
|
||||
|
||||
private WindowContainerTransaction getBringAppsToFrontTransaction() {
|
||||
final ArgumentCaptor<WindowContainerTransaction> arg = ArgumentCaptor.forClass(
|
||||
WindowContainerTransaction.class);
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
verify(mTransitions).startTransition(eq(TRANSIT_TO_FRONT), arg.capture(), any());
|
||||
} else {
|
||||
verify(mShellTaskOrganizer).applyTransaction(arg.capture());
|
||||
}
|
||||
return arg.getValue();
|
||||
}
|
||||
|
||||
private void assertThatBoundsCleared(Change change) {
|
||||
assertThat((change.getWindowSetMask() & WINDOW_CONFIG_BOUNDS) != 0).isTrue();
|
||||
assertThat(change.getConfiguration().windowConfiguration.getBounds().isEmpty()).isTrue();
|
||||
|
||||
Reference in New Issue
Block a user