Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.kt +41 −2 Original line number Diff line number Diff line Loading @@ -16,22 +16,47 @@ package com.android.wm.shell.common.pip import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED import android.window.DesktopExperienceFlags import com.android.internal.protolog.ProtoLog import com.android.wm.shell.Flags import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.recents.RecentsTransitionStateListener.RecentsTransitionState import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING import java.util.Optional /** Helper class for PiP on Desktop Mode. */ class PipDesktopState( private val pipDisplayLayoutState: PipDisplayLayoutState, recentsTransitionHandler: RecentsTransitionHandler, private val desktopUserRepositoriesOptional: Optional<DesktopUserRepositories>, private val dragToDesktopTransitionHandlerOptional: Optional<DragToDesktopTransitionHandler>, val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer ) { @RecentsTransitionState private var recentsTransitionState = TRANSITION_STATE_NOT_RUNNING init { recentsTransitionHandler.addTransitionStateListener( object : RecentsTransitionStateListener { override fun onTransitionStateChanged(@RecentsTransitionState state: Int) { logV( "Recents transition state changed: %s", RecentsTransitionStateListener.stateToString(state), ) recentsTransitionState = state } } ) } /** * Returns whether PiP in Desktop Windowing is enabled by checking the following: * - PiP in Desktop Windowing flag is enabled Loading Loading @@ -83,14 +108,20 @@ class PipDesktopState( } /** Returns the windowing mode to restore to when resizing out of PIP direction. */ // TODO(b/403345629): Update this for Multi-Desktop. fun getOutPipWindowingMode(): Int { val isInDesktop = isPipInDesktopMode() // Temporary workaround for b/409201669: Always expand to fullscreen if we're exiting PiP // in the middle of Recents animation from Desktop session. if (RecentsTransitionStateListener.isAnimating(recentsTransitionState) && isInDesktop) { return WINDOWING_MODE_FULLSCREEN } // If we are exiting PiP while the device is in Desktop mode, the task should expand to // freeform windowing mode. // 1) If the display windowing mode is freeform, set windowing mode to UNDEFINED so it will // resolve the windowing mode to the display's windowing mode. // 2) If the display windowing mode is not FREEFORM, set windowing mode to FREEFORM. if (isPipInDesktopMode()) { if (isInDesktop) { return if (isDisplayInFreeform()) { WINDOWING_MODE_UNDEFINED } else { Loading @@ -108,4 +139,12 @@ class PipDesktopState( /** Returns the DisplayLayout associated with the display where PiP window is in. */ fun getCurrentDisplayLayout(): DisplayLayout = pipDisplayLayoutState.displayLayout private fun logV(msg: String, vararg arguments: Any?) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: $msg", TAG, *arguments) } companion object { private const val TAG = "PipDesktopState" } } libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +5 −2 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import com.android.wm.shell.pip2.phone.PipTouchHandler; import com.android.wm.shell.pip2.phone.PipTransition; import com.android.wm.shell.pip2.phone.PipTransitionState; import com.android.wm.shell.pip2.phone.PipUiStateChangeController; import com.android.wm.shell.recents.RecentsTransitionHandler; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.desktopmode.DesktopState; import com.android.wm.shell.splitscreen.SplitScreenController; Loading Loading @@ -277,12 +278,14 @@ public abstract class Pip2Module { @Provides static PipDesktopState providePipDesktopState( PipDisplayLayoutState pipDisplayLayoutState, RecentsTransitionHandler recentsTransitionHandler, Optional<DesktopUserRepositories> desktopUserRepositoriesOptional, Optional<DragToDesktopTransitionHandler> dragToDesktopTransitionHandlerOptional, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer ) { return new PipDesktopState(pipDisplayLayoutState, desktopUserRepositoriesOptional, dragToDesktopTransitionHandlerOptional, rootTaskDisplayAreaOrganizer); return new PipDesktopState(pipDisplayLayoutState, recentsTransitionHandler, desktopUserRepositoriesOptional, dragToDesktopTransitionHandlerOptional, rootTaskDisplayAreaOrganizer); } @WMSingleton Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipDesktopStateTest.kt +22 −0 Original line number Diff line number Diff line Loading @@ -34,12 +34,18 @@ import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_ANIMATING import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING import com.google.common.truth.Truth.assertThat import java.util.Optional import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever /** Loading @@ -51,12 +57,14 @@ import org.mockito.kotlin.whenever @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PIP) class PipDesktopStateTest : ShellTestCase() { private val mockPipDisplayLayoutState = mock<PipDisplayLayoutState>() private val mockRecentsTransitionHandler = mock<RecentsTransitionHandler>() private val mockDesktopUserRepositories = mock<DesktopUserRepositories>() private val mockDesktopRepository = mock<DesktopRepository>() private val mockDragToDesktopTransitionHandler = mock<DragToDesktopTransitionHandler>() private val mockRootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>() private val mockTaskInfo = mock<ActivityManager.RunningTaskInfo>() private lateinit var defaultTda: DisplayAreaInfo private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener private lateinit var pipDesktopState: PipDesktopState @Before Loading @@ -73,10 +81,16 @@ class PipDesktopStateTest : ShellTestCase() { pipDesktopState = PipDesktopState( mockPipDisplayLayoutState, mockRecentsTransitionHandler, Optional.of(mockDesktopUserRepositories), Optional.of(mockDragToDesktopTransitionHandler), mockRootTaskDisplayAreaOrganizer ) val captor = argumentCaptor<RecentsTransitionStateListener>() verify(mockRecentsTransitionHandler).addTransitionStateListener(captor.capture()) recentsTransitionStateListener = captor.firstValue recentsTransitionStateListener.onTransitionStateChanged(TRANSITION_STATE_NOT_RUNNING) } @Test Loading Loading @@ -140,6 +154,14 @@ class PipDesktopStateTest : ShellTestCase() { assertThat(pipDesktopState.getOutPipWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED) } @Test fun outPipWindowingMode_midRecents_inDesktop_returnsFullscreen() { whenever(mockDesktopRepository.isAnyDeskActive(DISPLAY_ID)).thenReturn(true) recentsTransitionStateListener.onTransitionStateChanged(TRANSITION_STATE_ANIMATING) assertThat(pipDesktopState.getOutPipWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN) } @Test fun isDragToDesktopInProgress_inProgress_returnsTrue() { whenever(mockDragToDesktopTransitionHandler.inProgress).thenReturn(true) Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipDesktopState.kt +41 −2 Original line number Diff line number Diff line Loading @@ -16,22 +16,47 @@ package com.android.wm.shell.common.pip import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED import android.window.DesktopExperienceFlags import com.android.internal.protolog.ProtoLog import com.android.wm.shell.Flags import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.recents.RecentsTransitionStateListener.RecentsTransitionState import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING import java.util.Optional /** Helper class for PiP on Desktop Mode. */ class PipDesktopState( private val pipDisplayLayoutState: PipDisplayLayoutState, recentsTransitionHandler: RecentsTransitionHandler, private val desktopUserRepositoriesOptional: Optional<DesktopUserRepositories>, private val dragToDesktopTransitionHandlerOptional: Optional<DragToDesktopTransitionHandler>, val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer ) { @RecentsTransitionState private var recentsTransitionState = TRANSITION_STATE_NOT_RUNNING init { recentsTransitionHandler.addTransitionStateListener( object : RecentsTransitionStateListener { override fun onTransitionStateChanged(@RecentsTransitionState state: Int) { logV( "Recents transition state changed: %s", RecentsTransitionStateListener.stateToString(state), ) recentsTransitionState = state } } ) } /** * Returns whether PiP in Desktop Windowing is enabled by checking the following: * - PiP in Desktop Windowing flag is enabled Loading Loading @@ -83,14 +108,20 @@ class PipDesktopState( } /** Returns the windowing mode to restore to when resizing out of PIP direction. */ // TODO(b/403345629): Update this for Multi-Desktop. fun getOutPipWindowingMode(): Int { val isInDesktop = isPipInDesktopMode() // Temporary workaround for b/409201669: Always expand to fullscreen if we're exiting PiP // in the middle of Recents animation from Desktop session. if (RecentsTransitionStateListener.isAnimating(recentsTransitionState) && isInDesktop) { return WINDOWING_MODE_FULLSCREEN } // If we are exiting PiP while the device is in Desktop mode, the task should expand to // freeform windowing mode. // 1) If the display windowing mode is freeform, set windowing mode to UNDEFINED so it will // resolve the windowing mode to the display's windowing mode. // 2) If the display windowing mode is not FREEFORM, set windowing mode to FREEFORM. if (isPipInDesktopMode()) { if (isInDesktop) { return if (isDisplayInFreeform()) { WINDOWING_MODE_UNDEFINED } else { Loading @@ -108,4 +139,12 @@ class PipDesktopState( /** Returns the DisplayLayout associated with the display where PiP window is in. */ fun getCurrentDisplayLayout(): DisplayLayout = pipDisplayLayoutState.displayLayout private fun logV(msg: String, vararg arguments: Any?) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: $msg", TAG, *arguments) } companion object { private const val TAG = "PipDesktopState" } }
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +5 −2 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import com.android.wm.shell.pip2.phone.PipTouchHandler; import com.android.wm.shell.pip2.phone.PipTransition; import com.android.wm.shell.pip2.phone.PipTransitionState; import com.android.wm.shell.pip2.phone.PipUiStateChangeController; import com.android.wm.shell.recents.RecentsTransitionHandler; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.shared.desktopmode.DesktopState; import com.android.wm.shell.splitscreen.SplitScreenController; Loading Loading @@ -277,12 +278,14 @@ public abstract class Pip2Module { @Provides static PipDesktopState providePipDesktopState( PipDisplayLayoutState pipDisplayLayoutState, RecentsTransitionHandler recentsTransitionHandler, Optional<DesktopUserRepositories> desktopUserRepositoriesOptional, Optional<DragToDesktopTransitionHandler> dragToDesktopTransitionHandlerOptional, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer ) { return new PipDesktopState(pipDisplayLayoutState, desktopUserRepositoriesOptional, dragToDesktopTransitionHandlerOptional, rootTaskDisplayAreaOrganizer); return new PipDesktopState(pipDisplayLayoutState, recentsTransitionHandler, desktopUserRepositoriesOptional, dragToDesktopTransitionHandlerOptional, rootTaskDisplayAreaOrganizer); } @WMSingleton Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipDesktopStateTest.kt +22 −0 Original line number Diff line number Diff line Loading @@ -34,12 +34,18 @@ import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopRepository import com.android.wm.shell.desktopmode.DesktopUserRepositories import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_ANIMATING import com.android.wm.shell.recents.RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING import com.google.common.truth.Truth.assertThat import java.util.Optional import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever /** Loading @@ -51,12 +57,14 @@ import org.mockito.kotlin.whenever @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PIP) class PipDesktopStateTest : ShellTestCase() { private val mockPipDisplayLayoutState = mock<PipDisplayLayoutState>() private val mockRecentsTransitionHandler = mock<RecentsTransitionHandler>() private val mockDesktopUserRepositories = mock<DesktopUserRepositories>() private val mockDesktopRepository = mock<DesktopRepository>() private val mockDragToDesktopTransitionHandler = mock<DragToDesktopTransitionHandler>() private val mockRootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>() private val mockTaskInfo = mock<ActivityManager.RunningTaskInfo>() private lateinit var defaultTda: DisplayAreaInfo private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener private lateinit var pipDesktopState: PipDesktopState @Before Loading @@ -73,10 +81,16 @@ class PipDesktopStateTest : ShellTestCase() { pipDesktopState = PipDesktopState( mockPipDisplayLayoutState, mockRecentsTransitionHandler, Optional.of(mockDesktopUserRepositories), Optional.of(mockDragToDesktopTransitionHandler), mockRootTaskDisplayAreaOrganizer ) val captor = argumentCaptor<RecentsTransitionStateListener>() verify(mockRecentsTransitionHandler).addTransitionStateListener(captor.capture()) recentsTransitionStateListener = captor.firstValue recentsTransitionStateListener.onTransitionStateChanged(TRANSITION_STATE_NOT_RUNNING) } @Test Loading Loading @@ -140,6 +154,14 @@ class PipDesktopStateTest : ShellTestCase() { assertThat(pipDesktopState.getOutPipWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED) } @Test fun outPipWindowingMode_midRecents_inDesktop_returnsFullscreen() { whenever(mockDesktopRepository.isAnyDeskActive(DISPLAY_ID)).thenReturn(true) recentsTransitionStateListener.onTransitionStateChanged(TRANSITION_STATE_ANIMATING) assertThat(pipDesktopState.getOutPipWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN) } @Test fun isDragToDesktopInProgress_inProgress_returnsTrue() { whenever(mockDragToDesktopTransitionHandler.inProgress).thenReturn(true) Loading