Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +12 −4 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE import android.view.WindowManager.TRANSIT_NONE import android.view.WindowManager.TRANSIT_OPEN import android.view.WindowManager.TRANSIT_TO_FRONT Loading Loading @@ -1061,7 +1062,10 @@ class DesktopTasksController( // Check if freeform task launch during recents should be handled shouldHandleMidRecentsFreeformLaunch -> handleMidRecentsFreeformTaskLaunch(task) // Check if the closing task needs to be handled TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task) TransitionUtil.isClosingType(request.type) -> handleTaskClosing( task, request.type ) // Check if the top task shouldn't be allowed to enter desktop mode isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task) // Check if fullscreen task should be updated Loading Loading @@ -1288,7 +1292,10 @@ class DesktopTasksController( } /** Handle task closing by removing wallpaper activity if it's the last active task */ private fun handleTaskClosing(task: RunningTaskInfo): WindowContainerTransaction? { private fun handleTaskClosing( task: RunningTaskInfo, transitionType: Int ): WindowContainerTransaction? { logV("handleTaskClosing") if (!isDesktopModeShowing(task.displayId)) return null Loading @@ -1301,9 +1308,10 @@ class DesktopTasksController( removeWallpaperActivity(wct) } taskRepository.addClosingTask(task.displayId, task.taskId) // If a CLOSE or TO_BACK is triggered on a desktop task, remove the task. // If a CLOSE is triggered on a desktop task, remove the task. if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue() && taskRepository.isVisibleTask(task.taskId) taskRepository.isVisibleTask(task.taskId) && transitionType == TRANSIT_CLOSE ) { wct.removeTask(task.token) } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt +28 −1 Original line number Diff line number Diff line Loading @@ -16,16 +16,19 @@ package com.android.wm.shell.desktopmode import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.content.Context import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager import android.view.WindowManager.TRANSIT_TO_BACK import android.window.TransitionInfo import android.window.WindowContainerTransaction import android.window.flags.DesktopModeFlags import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions Loading Loading @@ -64,6 +67,30 @@ class DesktopTasksTransitionObserver( ) { // TODO: b/332682201 Update repository state updateWallpaperToken(info) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { handleBackNavigation(info) } } private fun handleBackNavigation(info: TransitionInfo) { // When default back navigation happens, transition type is TO_BACK and the change is // TO_BACK. Mark the task going to back as minimized. if (info.type == TRANSIT_TO_BACK) { for (change in info.changes) { val taskInfo = change.taskInfo if (taskInfo == null || taskInfo.taskId == -1) { continue } if (desktopModeTaskRepository.getVisibleTaskCount(taskInfo.displayId) > 0 && change.mode == TRANSIT_TO_BACK && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM ) { desktopModeTaskRepository.minimizeTask(taskInfo.displayId, taskInfo.taskId) } } } } override fun onTransitionStarting(transition: IBinder) { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +4 −76 Original line number Diff line number Diff line Loading @@ -2086,16 +2086,13 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_withBackNav_removesTask() { @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,) fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_removesTask() { val task = setUpFreeformTask() val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) assertNotNull(result, "Should handle request").assertRemoveAt(0, task.token) assertNull(result, "Should not handle request") } @Test Loading Loading @@ -2136,27 +2133,9 @@ class DesktopTasksControllerTest : ShellTestCase() { assertNull(result, "Should not handle request") } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_singleTask_withWallpaper_withBackNav_removesWallpaperAndTask() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() taskRepository.wallpaperActivityToken = wallpaperToken val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) result.assertRemoveAt(index = 1, task.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_singleTaskWithToken_noBackNav_removesWallpaper() { fun handleRequest_backTransition_singleTaskWithToken_removesWallpaper() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() Loading @@ -2182,24 +2161,8 @@ class DesktopTasksControllerTest : ShellTestCase() { assertNull(result, "Should not handle request") } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_multipleTasks_withWallpaper_withBackNav_removesTask() { val task1 = setUpFreeformTask() setUpFreeformTask() taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, task1.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_multipleTasks_noBackNav_doesNotHandle() { val task1 = setUpFreeformTask() setUpFreeformTask() Loading @@ -2224,23 +2187,6 @@ class DesktopTasksControllerTest : ShellTestCase() { taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) result.assertRemoveAt(index = 1, task1.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_multipleTasksSingleNonClosing_noBackNav_removesWallpaper() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() taskRepository.wallpaperActivityToken = wallpaperToken taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) } Loading @@ -2248,7 +2194,6 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_multipleTasksSingleNonMinimized_removesWallpaperAndTask() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) Loading @@ -2259,23 +2204,6 @@ class DesktopTasksControllerTest : ShellTestCase() { taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) result.assertRemoveAt(index = 1, task1.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_multipleTasksSingleNonMinimized_noBackNav_removesWallpaper() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() taskRepository.wallpaperActivityToken = wallpaperToken taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.content.ComponentName import android.content.Context import android.content.Intent import android.platform.test.annotations.EnableFlags import android.view.Display.DEFAULT_DISPLAY import android.view.WindowManager.TRANSIT_TO_BACK import android.window.IWindowContainerToken import android.window.TransitionInfo import android.window.TransitionInfo.Change import android.window.WindowContainerToken import com.android.modules.utils.testing.ExtendedMockitoRule import com.android.window.flags.Flags import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.Mockito import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.spy import org.mockito.kotlin.verify import org.mockito.kotlin.whenever class DesktopTasksTransitionObserverTest { @JvmField @Rule val extendedMockitoRule = ExtendedMockitoRule.Builder(this) .mockStatic(DesktopModeStatus::class.java) .build()!! private val testExecutor = mock<ShellExecutor>() private val mockShellInit = mock<ShellInit>() private val transitions = mock<Transitions>() private val context = mock<Context>() private val shellTaskOrganizer = mock<ShellTaskOrganizer>() private val taskRepository = mock<DesktopModeTaskRepository>() private lateinit var transitionObserver: DesktopTasksTransitionObserver private lateinit var shellInit: ShellInit @Before fun setup() { whenever(DesktopModeStatus.canEnterDesktopMode(any())).thenReturn(true) shellInit = spy(ShellInit(testExecutor)) transitionObserver = DesktopTasksTransitionObserver( context, taskRepository, transitions, shellTaskOrganizer, shellInit ) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun backNavigation_taskMinimized() { val task = createTaskInfo(1) whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1) transitionObserver.onTransitionReady( transition = mock(), info = createBackNavigationTransition(task), startTransaction = mock(), finishTransaction = mock(), ) verify(taskRepository).minimizeTask(task.displayId, task.taskId) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun backNavigation_nullTaskInfo_taskNotMinimized() { val task = createTaskInfo(1) whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1) transitionObserver.onTransitionReady( transition = mock(), info = createBackNavigationTransition(null), startTransaction = mock(), finishTransaction = mock(), ) verify(taskRepository, never()).minimizeTask(task.displayId, task.taskId) } private fun createBackNavigationTransition( task: RunningTaskInfo? ): TransitionInfo { return TransitionInfo(TRANSIT_TO_BACK, 0 /* flags */).apply { addChange( Change(mock(), mock()).apply { mode = TRANSIT_TO_BACK parent = null taskInfo = task flags = flags } ) } } private fun createTaskInfo(id: Int) = RunningTaskInfo().apply { taskId = id displayId = DEFAULT_DISPLAY configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM token = WindowContainerToken(Mockito.mock(IWindowContainerToken::class.java)) baseIntent = Intent().apply { component = ComponentName("package", "component.name") } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +12 −4 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE import android.view.WindowManager.TRANSIT_NONE import android.view.WindowManager.TRANSIT_OPEN import android.view.WindowManager.TRANSIT_TO_FRONT Loading Loading @@ -1061,7 +1062,10 @@ class DesktopTasksController( // Check if freeform task launch during recents should be handled shouldHandleMidRecentsFreeformLaunch -> handleMidRecentsFreeformTaskLaunch(task) // Check if the closing task needs to be handled TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task) TransitionUtil.isClosingType(request.type) -> handleTaskClosing( task, request.type ) // Check if the top task shouldn't be allowed to enter desktop mode isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task) // Check if fullscreen task should be updated Loading Loading @@ -1288,7 +1292,10 @@ class DesktopTasksController( } /** Handle task closing by removing wallpaper activity if it's the last active task */ private fun handleTaskClosing(task: RunningTaskInfo): WindowContainerTransaction? { private fun handleTaskClosing( task: RunningTaskInfo, transitionType: Int ): WindowContainerTransaction? { logV("handleTaskClosing") if (!isDesktopModeShowing(task.displayId)) return null Loading @@ -1301,9 +1308,10 @@ class DesktopTasksController( removeWallpaperActivity(wct) } taskRepository.addClosingTask(task.displayId, task.taskId) // If a CLOSE or TO_BACK is triggered on a desktop task, remove the task. // If a CLOSE is triggered on a desktop task, remove the task. if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue() && taskRepository.isVisibleTask(task.taskId) taskRepository.isVisibleTask(task.taskId) && transitionType == TRANSIT_CLOSE ) { wct.removeTask(task.token) } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt +28 −1 Original line number Diff line number Diff line Loading @@ -16,16 +16,19 @@ package com.android.wm.shell.desktopmode import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.content.Context import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager import android.view.WindowManager.TRANSIT_TO_BACK import android.window.TransitionInfo import android.window.WindowContainerTransaction import android.window.flags.DesktopModeFlags import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY import com.android.internal.protolog.ProtoLog import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import android.window.flags.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions Loading Loading @@ -64,6 +67,30 @@ class DesktopTasksTransitionObserver( ) { // TODO: b/332682201 Update repository state updateWallpaperToken(info) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION.isTrue()) { handleBackNavigation(info) } } private fun handleBackNavigation(info: TransitionInfo) { // When default back navigation happens, transition type is TO_BACK and the change is // TO_BACK. Mark the task going to back as minimized. if (info.type == TRANSIT_TO_BACK) { for (change in info.changes) { val taskInfo = change.taskInfo if (taskInfo == null || taskInfo.taskId == -1) { continue } if (desktopModeTaskRepository.getVisibleTaskCount(taskInfo.displayId) > 0 && change.mode == TRANSIT_TO_BACK && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM ) { desktopModeTaskRepository.minimizeTask(taskInfo.displayId, taskInfo.taskId) } } } } override fun onTransitionStarting(transition: IBinder) { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +4 −76 Original line number Diff line number Diff line Loading @@ -2086,16 +2086,13 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_withBackNav_removesTask() { @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,) fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_removesTask() { val task = setUpFreeformTask() val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) assertNotNull(result, "Should handle request").assertRemoveAt(0, task.token) assertNull(result, "Should not handle request") } @Test Loading Loading @@ -2136,27 +2133,9 @@ class DesktopTasksControllerTest : ShellTestCase() { assertNull(result, "Should not handle request") } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_singleTask_withWallpaper_withBackNav_removesWallpaperAndTask() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() taskRepository.wallpaperActivityToken = wallpaperToken val result = controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) result.assertRemoveAt(index = 1, task.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_singleTaskWithToken_noBackNav_removesWallpaper() { fun handleRequest_backTransition_singleTaskWithToken_removesWallpaper() { val task = setUpFreeformTask() val wallpaperToken = MockToken().token() Loading @@ -2182,24 +2161,8 @@ class DesktopTasksControllerTest : ShellTestCase() { assertNull(result, "Should not handle request") } @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_multipleTasks_withWallpaper_withBackNav_removesTask() { val task1 = setUpFreeformTask() setUpFreeformTask() taskRepository.wallpaperActivityToken = MockToken().token() val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, task1.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_multipleTasks_noBackNav_doesNotHandle() { val task1 = setUpFreeformTask() setUpFreeformTask() Loading @@ -2224,23 +2187,6 @@ class DesktopTasksControllerTest : ShellTestCase() { taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) result.assertRemoveAt(index = 1, task1.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_multipleTasksSingleNonClosing_noBackNav_removesWallpaper() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() taskRepository.wallpaperActivityToken = wallpaperToken taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) } Loading @@ -2248,7 +2194,6 @@ class DesktopTasksControllerTest : ShellTestCase() { @Test @EnableFlags( Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION ) fun handleRequest_backTransition_multipleTasksSingleNonMinimized_removesWallpaperAndTask() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) Loading @@ -2259,23 +2204,6 @@ class DesktopTasksControllerTest : ShellTestCase() { taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) result.assertRemoveAt(index = 1, task1.token) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun handleRequest_backTransition_multipleTasksSingleNonMinimized_noBackNav_removesWallpaper() { val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY) val wallpaperToken = MockToken().token() taskRepository.wallpaperActivityToken = wallpaperToken taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId) val result = controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK)) // Should create remove wallpaper transaction assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken) } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.content.ComponentName import android.content.Context import android.content.Intent import android.platform.test.annotations.EnableFlags import android.view.Display.DEFAULT_DISPLAY import android.view.WindowManager.TRANSIT_TO_BACK import android.window.IWindowContainerToken import android.window.TransitionInfo import android.window.TransitionInfo.Change import android.window.WindowContainerToken import com.android.modules.utils.testing.ExtendedMockitoRule import com.android.window.flags.Flags import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.Mockito import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.spy import org.mockito.kotlin.verify import org.mockito.kotlin.whenever class DesktopTasksTransitionObserverTest { @JvmField @Rule val extendedMockitoRule = ExtendedMockitoRule.Builder(this) .mockStatic(DesktopModeStatus::class.java) .build()!! private val testExecutor = mock<ShellExecutor>() private val mockShellInit = mock<ShellInit>() private val transitions = mock<Transitions>() private val context = mock<Context>() private val shellTaskOrganizer = mock<ShellTaskOrganizer>() private val taskRepository = mock<DesktopModeTaskRepository>() private lateinit var transitionObserver: DesktopTasksTransitionObserver private lateinit var shellInit: ShellInit @Before fun setup() { whenever(DesktopModeStatus.canEnterDesktopMode(any())).thenReturn(true) shellInit = spy(ShellInit(testExecutor)) transitionObserver = DesktopTasksTransitionObserver( context, taskRepository, transitions, shellTaskOrganizer, shellInit ) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun backNavigation_taskMinimized() { val task = createTaskInfo(1) whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1) transitionObserver.onTransitionReady( transition = mock(), info = createBackNavigationTransition(task), startTransaction = mock(), finishTransaction = mock(), ) verify(taskRepository).minimizeTask(task.displayId, task.taskId) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION) fun backNavigation_nullTaskInfo_taskNotMinimized() { val task = createTaskInfo(1) whenever(taskRepository.getVisibleTaskCount(any())).thenReturn(1) transitionObserver.onTransitionReady( transition = mock(), info = createBackNavigationTransition(null), startTransaction = mock(), finishTransaction = mock(), ) verify(taskRepository, never()).minimizeTask(task.displayId, task.taskId) } private fun createBackNavigationTransition( task: RunningTaskInfo? ): TransitionInfo { return TransitionInfo(TRANSIT_TO_BACK, 0 /* flags */).apply { addChange( Change(mock(), mock()).apply { mode = TRANSIT_TO_BACK parent = null taskInfo = task flags = flags } ) } } private fun createTaskInfo(id: Int) = RunningTaskInfo().apply { taskId = id displayId = DEFAULT_DISPLAY configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM token = WindowContainerToken(Mockito.mock(IWindowContainerToken::class.java)) baseIntent = Intent().apply { component = ComponentName("package", "component.name") } } }