Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -356,6 +356,7 @@ public abstract class WMShellModule { ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Optional<DesktopRepository> desktopRepository, Optional<DesktopTasksController> desktopTasksController, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorViewModel) { // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic Loading @@ -364,7 +365,8 @@ public abstract class WMShellModule { ? shellInit : null; return new FreeformTaskListener(context, init, shellTaskOrganizer, desktopRepository, launchAdjacentController, windowDecorViewModel); desktopRepository, desktopTasksController, launchAdjacentController, windowDecorViewModel); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +12 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import com.android.wm.shell.windowdecor.extension.isFullscreen import com.android.wm.shell.windowdecor.extension.isMultiWindow import com.android.wm.shell.windowdecor.extension.requestingImmersive import java.io.PrintWriter import java.util.Optional import java.util.concurrent.Executor Loading Loading @@ -1844,6 +1845,17 @@ class DesktopTasksController( userId = newUserId } /** Called when a task's info changes. */ fun onTaskInfoChanged(taskInfo: RunningTaskInfo) { if (!Flags.enableFullyImmersiveInDesktop()) return val inImmersive = taskRepository.isTaskInFullImmersiveState(taskInfo.taskId) val requestingImmersive = taskInfo.requestingImmersive if (inImmersive && !requestingImmersive) { // Exit immersive if the app is no longer requesting it. exitDesktopTaskFromFullImmersive(taskInfo) } } private fun dump(pw: PrintWriter, prefix: String) { val innerPrefix = "$prefix " pw.println("${prefix}DesktopTasksController") Loading libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; Loading @@ -50,6 +51,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, private final Context mContext; private final ShellTaskOrganizer mShellTaskOrganizer; private final Optional<DesktopRepository> mDesktopRepository; private final Optional<DesktopTasksController> mDesktopTasksController; private final WindowDecorViewModel mWindowDecorationViewModel; private final LaunchAdjacentController mLaunchAdjacentController; Loading @@ -65,12 +67,14 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Optional<DesktopRepository> desktopRepository, Optional<DesktopTasksController> desktopTasksController, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorationViewModel) { mContext = context; mShellTaskOrganizer = shellTaskOrganizer; mWindowDecorationViewModel = windowDecorationViewModel; mDesktopRepository = desktopRepository; mDesktopTasksController = desktopTasksController; mLaunchAdjacentController = launchAdjacentController; if (shellInit != null) { shellInit.addInitCallback(this::onInit, this); Loading Loading @@ -147,6 +151,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d", taskInfo.taskId); mDesktopTasksController.ifPresent(c -> c.onTaskInfoChanged(taskInfo)); mWindowDecorationViewModel.onTaskInfoChanged(taskInfo); state.mTaskInfo = taskInfo; if (DesktopModeStatus.canEnterDesktopMode(mContext)) { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +27 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.Gravity import android.view.SurfaceControl import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE Loading @@ -75,6 +76,7 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.InteractionJankMonitor import com.android.window.flags.Flags import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE import com.android.window.flags.Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP import com.android.wm.shell.MockToken import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer Loading Loading @@ -142,6 +144,7 @@ import org.mockito.Mockito import org.mockito.Mockito.anyInt import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.times Loading Loading @@ -3151,6 +3154,30 @@ class DesktopTasksControllerTest : ShellTestCase() { }) } @Test @EnableFlags(FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) fun onTaskInfoChanged_inImmersiveUnrequestsImmersive_exits() { val task = setUpFreeformTask(DEFAULT_DISPLAY) taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, immersive = true) task.requestedVisibleTypes = WindowInsets.Type.statusBars() controller.onTaskInfoChanged(task) verify(mockDesktopFullImmersiveTransitionHandler).exitImmersive(eq(task), any()) } @Test @EnableFlags(FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) fun onTaskInfoChanged_notInImmersiveUnrequestsImmersive_noReExit() { val task = setUpFreeformTask(DEFAULT_DISPLAY) taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, immersive = false) task.requestedVisibleTypes = WindowInsets.Type.statusBars() controller.onTaskInfoChanged(task) verify(mockDesktopFullImmersiveTransitionHandler, never()).exitImmersive(eq(task), any()) } /** * Assert that an unhandled drag event launches a PendingIntent with the * windowing mode and bounds we are expecting. Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java +16 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.windowdecor.WindowDecorViewModel; Loading Loading @@ -75,6 +76,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase { @Mock private DesktopRepository mDesktopRepository; @Mock private DesktopTasksController mDesktopTasksController; @Mock private LaunchAdjacentController mLaunchAdjacentController; private FreeformTaskListener mFreeformTaskListener; private StaticMockitoSession mMockitoSession; Loading @@ -90,6 +93,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mShellInit, mTaskOrganizer, Optional.of(mDesktopRepository), Optional.of(mDesktopTasksController), mLaunchAdjacentController, mWindowDecorViewModel); } Loading Loading @@ -177,6 +181,18 @@ public final class FreeformTaskListenerTests extends ShellTestCase { verify(mDesktopRepository).removeFreeformTask(task.displayId, task.taskId); } @Test public void onTaskInfoChanged_withDesktopController_forwards() { ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder() .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); task.isVisible = true; mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl); mFreeformTaskListener.onTaskInfoChanged(task); verify(mDesktopTasksController).onTaskInfoChanged(task); } @After public void tearDown() { mMockitoSession.finishMocking(); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −1 Original line number Diff line number Diff line Loading @@ -356,6 +356,7 @@ public abstract class WMShellModule { ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Optional<DesktopRepository> desktopRepository, Optional<DesktopTasksController> desktopTasksController, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorViewModel) { // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic Loading @@ -364,7 +365,8 @@ public abstract class WMShellModule { ? shellInit : null; return new FreeformTaskListener(context, init, shellTaskOrganizer, desktopRepository, launchAdjacentController, windowDecorViewModel); desktopRepository, desktopTasksController, launchAdjacentController, windowDecorViewModel); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +12 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import com.android.wm.shell.windowdecor.OnTaskRepositionAnimationListener import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener import com.android.wm.shell.windowdecor.extension.isFullscreen import com.android.wm.shell.windowdecor.extension.isMultiWindow import com.android.wm.shell.windowdecor.extension.requestingImmersive import java.io.PrintWriter import java.util.Optional import java.util.concurrent.Executor Loading Loading @@ -1844,6 +1845,17 @@ class DesktopTasksController( userId = newUserId } /** Called when a task's info changes. */ fun onTaskInfoChanged(taskInfo: RunningTaskInfo) { if (!Flags.enableFullyImmersiveInDesktop()) return val inImmersive = taskRepository.isTaskInFullImmersiveState(taskInfo.taskId) val requestingImmersive = taskInfo.requestingImmersive if (inImmersive && !requestingImmersive) { // Exit immersive if the app is no longer requesting it. exitDesktopTaskFromFullImmersive(taskInfo) } } private fun dump(pw: PrintWriter, prefix: String) { val innerPrefix = "$prefix " pw.println("${prefix}DesktopTasksController") Loading
libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; Loading @@ -50,6 +51,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, private final Context mContext; private final ShellTaskOrganizer mShellTaskOrganizer; private final Optional<DesktopRepository> mDesktopRepository; private final Optional<DesktopTasksController> mDesktopTasksController; private final WindowDecorViewModel mWindowDecorationViewModel; private final LaunchAdjacentController mLaunchAdjacentController; Loading @@ -65,12 +67,14 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Optional<DesktopRepository> desktopRepository, Optional<DesktopTasksController> desktopTasksController, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorationViewModel) { mContext = context; mShellTaskOrganizer = shellTaskOrganizer; mWindowDecorationViewModel = windowDecorationViewModel; mDesktopRepository = desktopRepository; mDesktopTasksController = desktopTasksController; mLaunchAdjacentController = launchAdjacentController; if (shellInit != null) { shellInit.addInitCallback(this::onInit, this); Loading Loading @@ -147,6 +151,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener, ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d", taskInfo.taskId); mDesktopTasksController.ifPresent(c -> c.onTaskInfoChanged(taskInfo)); mWindowDecorationViewModel.onTaskInfoChanged(taskInfo); state.mTaskInfo = taskInfo; if (DesktopModeStatus.canEnterDesktopMode(mContext)) { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +27 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DragEvent import android.view.Gravity import android.view.SurfaceControl import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_CLOSE Loading @@ -75,6 +76,7 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.InteractionJankMonitor import com.android.window.flags.Flags import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE import com.android.window.flags.Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP import com.android.wm.shell.MockToken import com.android.wm.shell.R import com.android.wm.shell.RootTaskDisplayAreaOrganizer Loading Loading @@ -142,6 +144,7 @@ import org.mockito.Mockito import org.mockito.Mockito.anyInt import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.times Loading Loading @@ -3151,6 +3154,30 @@ class DesktopTasksControllerTest : ShellTestCase() { }) } @Test @EnableFlags(FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) fun onTaskInfoChanged_inImmersiveUnrequestsImmersive_exits() { val task = setUpFreeformTask(DEFAULT_DISPLAY) taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, immersive = true) task.requestedVisibleTypes = WindowInsets.Type.statusBars() controller.onTaskInfoChanged(task) verify(mockDesktopFullImmersiveTransitionHandler).exitImmersive(eq(task), any()) } @Test @EnableFlags(FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP) fun onTaskInfoChanged_notInImmersiveUnrequestsImmersive_noReExit() { val task = setUpFreeformTask(DEFAULT_DISPLAY) taskRepository.setTaskInFullImmersiveState(DEFAULT_DISPLAY, task.taskId, immersive = false) task.requestedVisibleTypes = WindowInsets.Type.statusBars() controller.onTaskInfoChanged(task) verify(mockDesktopFullImmersiveTransitionHandler, never()).exitImmersive(eq(task), any()) } /** * Assert that an unhandled drag event launches a PendingIntent with the * windowing mode and bounds we are expecting. Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskListenerTests.java +16 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.desktopmode.DesktopRepository; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.windowdecor.WindowDecorViewModel; Loading Loading @@ -75,6 +76,8 @@ public final class FreeformTaskListenerTests extends ShellTestCase { @Mock private DesktopRepository mDesktopRepository; @Mock private DesktopTasksController mDesktopTasksController; @Mock private LaunchAdjacentController mLaunchAdjacentController; private FreeformTaskListener mFreeformTaskListener; private StaticMockitoSession mMockitoSession; Loading @@ -90,6 +93,7 @@ public final class FreeformTaskListenerTests extends ShellTestCase { mShellInit, mTaskOrganizer, Optional.of(mDesktopRepository), Optional.of(mDesktopTasksController), mLaunchAdjacentController, mWindowDecorViewModel); } Loading Loading @@ -177,6 +181,18 @@ public final class FreeformTaskListenerTests extends ShellTestCase { verify(mDesktopRepository).removeFreeformTask(task.displayId, task.taskId); } @Test public void onTaskInfoChanged_withDesktopController_forwards() { ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder() .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); task.isVisible = true; mFreeformTaskListener.onTaskAppeared(task, mMockSurfaceControl); mFreeformTaskListener.onTaskInfoChanged(task); verify(mDesktopTasksController).onTaskInfoChanged(task); } @After public void tearDown() { mMockitoSession.finishMocking(); Loading