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

Commit fe3acc44 authored by Merissa Mitchell's avatar Merissa Mitchell Committed by Android (Google) Code Review
Browse files

Merge "[PiP on Desktop] Always expand PiP to fullscreen if mid-recents." into main

parents 7c6c7241 77609844
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -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
@@ -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 {
@@ -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"
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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
+22 −0
Original line number Diff line number Diff line
@@ -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

/**
@@ -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
@@ -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
@@ -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)