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

Commit c205e0bb authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move Perceptible Task logic from Launcher to WM (WM Updates)" into main

parents a0827935 e5e5c1c8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ android_library {
        "WindowManager-Shell-lite-proto",
        "WindowManager-Shell-proto",
        "WindowManager-Shell-shared",
        "am_flags_lib",
        "androidx-constraintlayout_constraintlayout",
        "androidx.appcompat_appcompat",
        "androidx.arch.core_core-runtime",
@@ -171,6 +172,7 @@ android_library {
        "kotlin-annotations",
    ],
    flags_packages: [
        "am_flags",
        "com_android_wm_shell_flags",
    ],
    kotlincflags: ["-Xjvm-default=all"],
+83 −12
Original line number Diff line number Diff line
@@ -17,9 +17,14 @@
package com.android.wm.shell.desktopmode

import android.app.ActivityManager.RunningTaskInfo
import android.app.ActivityTaskManager
import android.graphics.Rect
import android.os.RemoteException
import android.window.DesktopExperienceFlags
import android.window.DesktopModeFlags
import androidx.annotation.VisibleForTesting
import com.android.internal.protolog.ProtoLog
import com.android.server.am.Flags
import com.android.wm.shell.freeform.TaskChangeListener
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.desktopmode.DesktopState
@@ -31,6 +36,7 @@ class DesktopTaskChangeListener(
    private val desktopState: DesktopState,
    private val shellController: ShellController,
) : TaskChangeListener {
    private val perceptibleTasks: MutableSet<Int> = mutableSetOf()

    override fun onTaskOpening(taskInfo: RunningTaskInfo) {
        val desktopRepository: DesktopRepository =
@@ -49,7 +55,7 @@ class DesktopTaskChangeListener(
            isActiveTask,
        )
        if (!isFreeformTask && isActiveTask) {
            desktopRepository.removeTask(taskInfo.taskId)
            removeTask(desktopRepository, taskInfo.taskId, isClosingTask = false)
            return
        }
        if (
@@ -73,7 +79,8 @@ class DesktopTaskChangeListener(
                )
                return
            }
            desktopRepository.addTask(
            addTask(
                desktopRepository,
                taskInfo.displayId,
                taskInfo.taskId,
                taskInfo.isVisible,
@@ -119,7 +126,7 @@ class DesktopTaskChangeListener(
        // fullscreen,
        // remove the task from the desktop repository since it is no longer a freeform task.
        if (!isFreeformTask && isActiveTask) {
            desktopRepository.removeTask(taskInfo.taskId)
            removeTask(desktopRepository, taskInfo.taskId, isClosingTask = false)
        } else if (isFreeformTask) {
            // TODO: b/420917959 - Remove this once LaunchParams respects activity options set for
            // [DesktopWallpaperActivity] launch which should always be in fullscreen.
@@ -132,7 +139,8 @@ class DesktopTaskChangeListener(
            }
            // If the task is already active in the repository, then moves task to the front,
            // else adds the task.
            desktopRepository.addTask(
            addTask(
                desktopRepository,
                taskInfo.displayId,
                taskInfo.taskId,
                taskInfo.isVisible,
@@ -185,7 +193,7 @@ class DesktopTaskChangeListener(
        // When the task change is from a task in the desktop repository which is now fullscreen,
        // remove the task from the desktop repository since it is no longer a freeform task.
        if (!isFreeformTask && isActiveTask) {
            desktopRepository.removeTask(taskInfo.taskId)
            removeTask(desktopRepository, taskInfo.taskId, isClosingTask = false)
        }
        if (isFreeformTask) {
            // TODO: b/420917959 - Remove this once LaunchParams respects activity options set for
@@ -198,7 +206,8 @@ class DesktopTaskChangeListener(
            }
            // If the task is already active in the repository, then it only moves the task to the
            // front.
            desktopRepository.addTask(
            addTask(
                desktopRepository,
                taskInfo.displayId,
                taskInfo.taskId,
                taskInfo.isVisible,
@@ -235,7 +244,8 @@ class DesktopTaskChangeListener(
            isActiveTask,
        )
        if (!isActiveTask) return
        desktopRepository.updateTask(
        updateTask(
            desktopRepository,
            taskInfo.displayId,
            taskInfo.taskId,
            isVisible = false,
@@ -278,20 +288,21 @@ class DesktopTaskChangeListener(
            // A task that is closing might have been minimized previously by
            // [DesktopBackNavTransitionObserver]. If that's the case then do not remove it from
            // the repo.
            desktopRepository.removeClosingTask(taskInfo.taskId)
            removeTask(desktopRepository, taskInfo.taskId, isClosingTask = true)
            if (isMinimized) {
                desktopRepository.updateTask(
                updateTask(
                    desktopRepository,
                    taskInfo.displayId,
                    taskInfo.taskId,
                    isVisible = false,
                    taskInfo.configuration.windowConfiguration.bounds,
                )
            } else {
                desktopRepository.removeTask(taskInfo.taskId)
                removeTask(desktopRepository, taskInfo.taskId, isClosingTask = false)
            }
        } else {
            desktopRepository.removeClosingTask(taskInfo.taskId)
            desktopRepository.removeTask(taskInfo.taskId)
            removeTask(desktopRepository, taskInfo.taskId, isClosingTask = true)
            removeTask(desktopRepository, taskInfo.taskId, isClosingTask = false)
        }
    }

@@ -303,6 +314,66 @@ class DesktopTaskChangeListener(
        ProtoLog.e(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
    }

    private fun addTask(
        desktopRepository: DesktopRepository,
        displayId: Int,
        taskId: Int,
        isVisible: Boolean,
        taskBounds: Rect,
    ) {
        desktopRepository.addTask(displayId, taskId, isVisible, taskBounds)

        // Enables the task as a perceptible task (i.e. OOM adj is boosted)
        if (Flags.perceptibleTasks() && !isTaskPerceptible(taskId)) {
            try {
                ActivityTaskManager.getService().setTaskIsPerceptible(taskId, true)
                perceptibleTasks += taskId
            } catch (re: RemoteException) {
                logE("Failed to enable task as perceptible: $re")
            }
        }
    }

    private fun removeTask(
        desktopRepository: DesktopRepository,
        taskId: Int,
        isClosingTask: Boolean,
    ) {
        if (isClosingTask) {
            desktopRepository.removeClosingTask(taskId)
        } else {
            desktopRepository.removeTask(taskId)

            // Only need to unmark non-closing tasks (e.g. going fullscreen)
            // since closing tasks are dead anyways
            ActivityTaskManager.getService().setTaskIsPerceptible(taskId, false)
        }

        perceptibleTasks -= taskId
    }

    private fun updateTask(
        desktopRepository: DesktopRepository,
        displayId: Int,
        taskId: Int,
        isVisible: Boolean,
        taskBounds: Rect?,
    ) {
        desktopRepository.updateTask(displayId, taskId, isVisible, taskBounds)

        // Enables the task as a perceptible task (i.e. OOM adj is boosted)
        if (Flags.perceptibleTasks() && !isTaskPerceptible(taskId)) {
            try {
                ActivityTaskManager.getService().setTaskIsPerceptible(taskId, true)
                perceptibleTasks += taskId
            } catch (re: RemoteException) {
                logE("Failed to enable task as perceptible: $re")
            }
        }
    }

    @VisibleForTesting fun isTaskPerceptible(taskId: Int): Boolean = taskId in perceptibleTasks

    companion object {
        private const val TAG = "DesktopTaskChangeListener"
    }
+91 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.server.am.Flags.FLAG_PERCEPTIBLE_TASKS
import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION
import com.android.window.flags.Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND
import com.android.wm.shell.MockToken
@@ -33,6 +34,7 @@ import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask
import com.android.wm.shell.shared.desktopmode.FakeDesktopState
import com.android.wm.shell.sysui.ShellController
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -56,8 +58,8 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
    private lateinit var desktopTaskChangeListener: DesktopTaskChangeListener

    private val desktopUserRepositories = mock<DesktopUserRepositories>()
    private val shellController = mock<ShellController>()
    private val desktopRepository = mock<DesktopRepository>()
    private val shellController = mock<ShellController>()
    private val desktopState =
        FakeDesktopState().apply {
            canEnterDesktopMode = true
@@ -168,6 +170,22 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
            )
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    fun onTaskOpening_freeformTask_enablePerceptibleTask() {
        val task = createFreeformTask(bounds = TASK_BOUNDS).apply { isVisible = false }
        desktopTaskChangeListener.onTaskOpening(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    fun onTaskOpening_fullscreenTask_notEnablePerceptibleTask() {
        val task = createFullscreenTask().apply { isVisible = true }
        desktopTaskChangeListener.onTaskOpening(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isFalse()
    }

    @Test
    fun onTaskChanging_fullscreenTask_activeInDesktopRepository_removesTaskFromRepo() {
        val task = createFullscreenTask().apply { isVisible = true }
@@ -213,6 +231,22 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
            )
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    fun onTaskChanging_fullscreenTask_notEnablePerceptibleTask() {
        val task = createFullscreenTask().apply { isVisible = true }
        desktopTaskChangeListener.onTaskChanging(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isFalse()
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    fun onTaskChanging_freeformTask_enablePerceptibleTask() {
        val task = createFreeformTask(bounds = TASK_BOUNDS).apply { isVisible = true }
        desktopTaskChangeListener.onTaskChanging(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()
    }

    @Test
    @EnableFlags(FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun onTaskChanging_desktopModeNotSupportedInDisplay_noOp() {
@@ -290,6 +324,22 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
            )
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    fun onTaskMovingToFront_fullscreenTask_notEnablePerceptibleTask() {
        val task = createFullscreenTask().apply { isVisible = true }
        desktopTaskChangeListener.onTaskMovingToFront(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isFalse()
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    fun onTaskMovingToFront_freeformTask_enablePerceptibleTask() {
        val task = createFreeformTask(bounds = TASK_BOUNDS).apply { isVisible = true }
        desktopTaskChangeListener.onTaskMovingToFront(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()
    }

    @Test
    fun onTaskMovingToBack_activeTaskInRepo_updatesTask() {
        val task = createFreeformTask().apply { isVisible = true }
@@ -413,6 +463,45 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
        verify(desktopUserRepositories.current, never()).removeTask(task.taskId)
    }

    @Test
    @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION, FLAG_PERCEPTIBLE_TASKS)
    fun onTaskClosing_backNavEnabled_disablePerceptibleTask() {
        val task = createFreeformTask().apply { isVisible = true }
        desktopTaskChangeListener.onTaskOpening(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()

        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
        desktopTaskChangeListener.onTaskClosing(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isFalse()
    }

    @Test
    @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION, FLAG_PERCEPTIBLE_TASKS)
    fun onTaskClosing_backNavEnabled_minimizedTask_perceptibleTasks_noop() {
        val task = createFreeformTask().apply { isVisible = true }
        desktopTaskChangeListener.onTaskOpening(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()

        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
        whenever(desktopUserRepositories.current.isMinimizedTask(task.taskId)).thenReturn(true)
        desktopTaskChangeListener.onTaskClosing(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()
    }

    @Test
    @EnableFlags(FLAG_PERCEPTIBLE_TASKS)
    @DisableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
    fun onTaskClosing_backNavDisabled_closingTask_disablePerceptibleTask() {
        val task = createFreeformTask().apply { isVisible = true }
        desktopTaskChangeListener.onTaskOpening(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isTrue()

        whenever(desktopUserRepositories.current.isActiveTask(task.taskId)).thenReturn(true)
        whenever(desktopUserRepositories.current.isClosingTask(task.taskId)).thenReturn(true)
        desktopTaskChangeListener.onTaskClosing(task)
        assertThat(desktopTaskChangeListener.isTaskPerceptible(task.taskId)).isFalse()
    }

    private fun createWallpaperTaskInfo(windowingMode: Int): RunningTaskInfo =
        TestRunningTaskInfoBuilder()
            .setBaseIntent(
@@ -425,5 +514,6 @@ class DesktopTaskChangeListenerTest : ShellTestCase() {
    companion object {
        private const val UNSUPPORTED_DISPLAY_ID = 3
        private val TASK_BOUNDS = Rect(100, 100, 300, 300)
        private const val DEFAULT_USER_ID = 1000
    }
}