Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7467db7a authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Make windowing limit more robust to unrecognized tasks

Sometimes we can end up with tasks in the DesktopRepo that don't exist /
that we cannot fetch a TaskInfo object for, with this CL we ignore such
tasks and try to minimize the next task from the bottom (instead of not
minimizing any task).

Bug: 414376840
Flag: com.android.window.flags.enable_desktop_task_limit_separate_transition
Test: DesktopTasksLimiterTest
Change-Id: Ic75c659b58d96679e5621d295e8d0045b5e6d74b
parent 70353cb3
Loading
Loading
Loading
Loading
+28 −7
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.wm.shell.desktopmode

import android.app.ActivityManager
import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
import android.os.IBinder
import android.view.SurfaceControl
@@ -162,11 +163,7 @@ class DesktopTasksLimiter(
                        !taskRepository.isClosingTask(it)
                    }
                logV("runOnIdle, expandedTasks=$expandedTaskIds, after transition=$transition")
                val taskIdToMinimize =
                    getTaskIdToMinimize(expandedTaskIds, /* launchingNewIntent= */ false)
                if (taskIdToMinimize != null) {
                    triggerMinimizeTransition(launchDetails.deskId, taskIdToMinimize)
                }
                triggerMinimizeTransition(launchDetails.deskId, expandedTaskIds)
            }
        }

@@ -194,8 +191,8 @@ class DesktopTasksLimiter(
            }
        }

        private fun triggerMinimizeTransition(deskId: Int, taskIdToMinimize: Int) {
            val task = shellTaskOrganizer.getRunningTaskInfo(taskIdToMinimize) ?: return
        private fun triggerMinimizeTransition(deskId: Int, expandedTaskIds: List<Int>) {
            val task = getRunningTaskToMinimize(expandedTaskIds) ?: return
            logV("triggerMinimizeTransition, found running task -> start transition, %s", task)
            val wct = WindowContainerTransaction()
            addMinimizeChange(deskId, task, wct)
@@ -209,6 +206,26 @@ class DesktopTasksLimiter(
            )
        }

        private fun getRunningTaskToMinimize(expandedTaskIds: List<Int>): RunningTaskInfo? {
            var taskIds = expandedTaskIds
            for (i in 1..expandedTaskIds.size) {
                val taskIdToMinimize =
                    getTaskIdToMinimize(taskIds, /* launchingNewIntent= */ false) ?: return null
                val task = shellTaskOrganizer.getRunningTaskInfo(taskIdToMinimize)
                if (task != null) {
                    return task
                } else {
                    logW(
                        "Tried to minimize non-running task#%s, Try next task instead.",
                        taskIdToMinimize,
                    )
                }
                // Ignore the non-existing task
                taskIds = taskIds.minus(taskIdToMinimize)
            }
            return null
        }

        private fun handleMinimizeTransitionReady(
            taskRepository: DesktopRepository,
            transition: IBinder,
@@ -461,6 +478,10 @@ class DesktopTasksLimiter(
        ProtoLog.v(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
    }

    private fun logW(msg: String, vararg arguments: Any?) {
        ProtoLog.w(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
    }

    private companion object {
        const val TAG = "DesktopTasksLimiter"
    }
+57 −0
Original line number Diff line number Diff line
@@ -724,6 +724,63 @@ class DesktopTasksLimiterTest : ShellTestCase() {
            .isEqualTo(existingTasks.first().taskId)
    }

    @Test
    fun onTransitionReady_taskLimitTransition_taskNotAvailable_minimizesNextTask() {
        desktopTaskRepo.addDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
        desktopTaskRepo.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
        val transition = Binder()
        val minimizeTransition = Binder()
        val existingTasks = (1..MAX_TASK_LIMIT + 1).map { setUpFreeformTask() }
        // Make the bottom task non-available
        `when`(shellTaskOrganizer.getRunningTaskInfo(existingTasks.first().taskId)).thenReturn(null)
        val launchTask = setUpFreeformTask()
        desktopTasksLimiter.addPendingTaskLimitTransition(
            transition,
            deskId = 0,
            taskId = launchTask.taskId,
        )
        val transitionInfo =
            TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_OPEN, launchTask).build()
        whenever(desktopMixedTransitionHandler.startTaskLimitMinimizeTransition(any(), anyInt()))
            .thenReturn(minimizeTransition)

        callOnTransitionReady(transition, transitionInfo)

        val onIdleArgumentCaptor = argumentCaptor<Runnable>()
        verify(transitions).runOnIdle(onIdleArgumentCaptor.capture())
        onIdleArgumentCaptor.lastValue.run()
        verify(desktopMixedTransitionHandler).startTaskLimitMinimizeTransition(any(), any())
        // Ensure we minimize the second task, since the first one is not available
        assertThat(desktopTasksLimiter.getMinimizingTask(minimizeTransition)?.taskId)
            .isEqualTo(existingTasks[1].taskId)
    }

    @Test
    fun onTransitionReady_taskLimitTransition_taskNotAvailable_nextTaskBelowLimit_doesntMinimize() {
        desktopTaskRepo.addDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
        desktopTaskRepo.setActiveDesk(displayId = DEFAULT_DISPLAY, deskId = 0)
        val transition = Binder()
        val existingTasks = (1..MAX_TASK_LIMIT).map { setUpFreeformTask() }
        // Make the bottom task non-available
        `when`(shellTaskOrganizer.getRunningTaskInfo(existingTasks.first().taskId)).thenReturn(null)
        val launchTask = setUpFreeformTask()
        desktopTasksLimiter.addPendingTaskLimitTransition(
            transition,
            deskId = 0,
            taskId = launchTask.taskId,
        )
        val transitionInfo =
            TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_OPEN, launchTask).build()

        callOnTransitionReady(transition, transitionInfo)

        val onIdleArgumentCaptor = argumentCaptor<Runnable>()
        verify(transitions).runOnIdle(onIdleArgumentCaptor.capture())
        onIdleArgumentCaptor.lastValue.run()
        verify(desktopMixedTransitionHandler, never())
            .startTaskLimitMinimizeTransition(any(), any())
    }

    @Test
    fun onTransitionReady_noPendingTaskLimitTransition_doesntTriggerOnIdle() {
        desktopTaskRepo.addDesk(displayId = DEFAULT_DISPLAY, deskId = 0)