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

Commit 317e2409 authored by Omar Elmekkawy's avatar Omar Elmekkawy
Browse files

Break tiling on entering pip mode.

When entering tiling, an app changes mode from freeform to pinned, and
this breaks tiling.

This CL removes the app from tiling on entering PIP mode.

Flag: com.android.window.flags.enable_tile_resizing

Test: on device testing of UI, really hard to unit test the UI here.

Bug: 397663717
Change-Id: I4b8b7afa416eb3599dfc566e207449e6eaa343cc
parent de267273
Loading
Loading
Loading
Loading
+39 −7
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.wm.shell.windowdecor.tiling

import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
@@ -28,9 +29,11 @@ import android.view.SurfaceControl
import android.view.SurfaceControl.Transaction
import android.view.WindowManager.TRANSIT_CHANGE
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_PIP
import android.view.WindowManager.TRANSIT_TO_BACK
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.TransitionInfo
import android.window.TransitionInfo.Change
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.internal.annotations.VisibleForTesting
@@ -422,6 +425,8 @@ class DesktopTilingWindowDecoration(
            change.taskInfo?.let {
                if (it.isFullscreen || isMinimized(change.mode, info.type)) {
                    removeTaskIfTiled(it.taskId, /* taskVanished= */ false, it.isFullscreen)
                } else if (isEnteringPip(change, info.type)) {
                    removeTaskIfTiled(it.taskId, /* taskVanished= */ true, it.isFullscreen)
                }
            }
        }
@@ -434,6 +439,27 @@ class DesktopTilingWindowDecoration(
                infoType == TRANSIT_OPEN))
    }

    private fun isEnteringPip(change: Change, transitType: Int): Boolean {
        if (change.taskInfo != null && change.taskInfo?.windowingMode == WINDOWING_MODE_PINNED) {
            // - TRANSIT_PIP: type (from RootWindowContainer)
            // - TRANSIT_OPEN (from apps that enter PiP instantly on opening, mostly from
            // CTS/Flicker tests).
            // - TRANSIT_TO_FRONT, though uncommon with triggering PiP, should semantically also
            // be allowed to animate if the task in question is pinned already - see b/308054074.
            // - TRANSIT_CHANGE: This can happen if the request to enter PIP happens when we are
            // collecting for another transition, such as TRANSIT_CHANGE (display rotation).
            if (
                transitType == TRANSIT_PIP ||
                    transitType == TRANSIT_OPEN ||
                    transitType == TRANSIT_TO_FRONT ||
                    transitType == TRANSIT_CHANGE
            ) {
                return true
            }
        }
        return false
    }

    class AppResizingHelper(
        val taskInfo: RunningTaskInfo,
        val desktopModeWindowDecoration: DesktopModeWindowDecoration,
@@ -550,12 +576,16 @@ class DesktopTilingWindowDecoration(
        taskVanished: Boolean = false,
        shouldDelayUpdate: Boolean = false,
    ) {
        val taskRepository = desktopUserRepositories.current
        if (taskId == leftTaskResizingHelper?.taskInfo?.taskId) {
            removeTask(leftTaskResizingHelper, taskVanished, shouldDelayUpdate)
            leftTaskResizingHelper = null
            val taskId = rightTaskResizingHelper?.taskInfo?.taskId
            if (taskId != null && taskRepository.isVisibleTask(taskId)) {
                rightTaskResizingHelper
                    ?.desktopModeWindowDecoration
                    ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate)
            }
            tearDownTiling()
            return
        }
@@ -563,9 +593,12 @@ class DesktopTilingWindowDecoration(
        if (taskId == rightTaskResizingHelper?.taskInfo?.taskId) {
            removeTask(rightTaskResizingHelper, taskVanished, shouldDelayUpdate)
            rightTaskResizingHelper = null
            val taskId = leftTaskResizingHelper?.taskInfo?.taskId
            if (taskId != null && taskRepository.isVisibleTask(taskId)) {
                leftTaskResizingHelper
                    ?.desktopModeWindowDecoration
                    ?.updateDisabledResizingEdge(NONE, shouldDelayUpdate)
            }
            tearDownTiling()
        }
    }
@@ -600,7 +633,6 @@ class DesktopTilingWindowDecoration(

    fun onOverviewAnimationStateChange(isRunning: Boolean) {
        if (!isTilingManagerInitialised) return

        if (isRunning) {
            desktopTilingDividerWindowManager?.hideDividerBar()
        } else if (allTiledTasksVisible()) {
+12 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
import android.content.ComponentName
import android.graphics.Rect
import android.view.Display.DEFAULT_DISPLAY
@@ -44,6 +45,17 @@ object DesktopTestHelpers {
            .apply { bounds?.let { setBounds(it) } }
            .build()

    fun createPinnedTask(displayId: Int = DEFAULT_DISPLAY, bounds: Rect? = null): RunningTaskInfo =
        TestRunningTaskInfoBuilder()
            .setDisplayId(displayId)
            .setParentTaskId(displayId)
            .setToken(MockToken().token())
            .setActivityType(ACTIVITY_TYPE_STANDARD)
            .setWindowingMode(WINDOWING_MODE_PINNED)
            .setLastActiveTime(100)
            .apply { bounds?.let { setBounds(it) } }
            .build()

    fun createFullscreenTaskBuilder(displayId: Int = DEFAULT_DISPLAY): TestRunningTaskInfoBuilder =
        TestRunningTaskInfoBuilder()
            .setDisplayId(displayId)
+52 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.wm.shell.windowdecor.tiling

import android.app.ActivityManager
import android.app.ActivityManager.RunningTaskInfo
import android.content.Context
import android.content.res.Resources
import android.graphics.Rect
@@ -24,8 +25,10 @@ import android.testing.AndroidTestingRunner
import android.view.MotionEvent
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CHANGE
import android.view.WindowManager.TRANSIT_PIP
import android.view.WindowManager.TRANSIT_TO_FRONT
import android.window.TransitionInfo
import android.window.TransitionInfo.Change
import android.window.WindowContainerTransaction
import androidx.test.filters.SmallTest
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -40,6 +43,7 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeT
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createPinnedTask
import com.android.wm.shell.desktopmode.DesktopUserRepositories
import com.android.wm.shell.desktopmode.ReturnToDragStartAnimator
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler
@@ -551,6 +555,37 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
        verify(tiledTaskHelper, times(1)).dispose()
    }

    @Test
    fun taskTiled_shouldBeRemoved_whenEnteringPip() {
        val task1 = createPipTask()
        val stableBounds = STABLE_BOUNDS_MOCK
        whenever(displayController.getDisplayLayout(any())).thenReturn(displayLayout)
        whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
            (i.arguments.first() as Rect).set(stableBounds)
        }
        whenever(context.resources).thenReturn(resources)
        whenever(resources.getDimensionPixelSize(any())).thenReturn(split_divider_width)
        whenever(tiledTaskHelper.taskInfo).thenReturn(task1)
        whenever(tiledTaskHelper.desktopModeWindowDecoration).thenReturn(desktopWindowDecoration)
        tilingDecoration.onAppTiled(
            task1,
            desktopWindowDecoration,
            DesktopTasksController.SnapPosition.LEFT,
            BOUNDS,
        )
        tilingDecoration.leftTaskResizingHelper = tiledTaskHelper
        val changeInfo = createPipChangeTransition(task1)
        tilingDecoration.onTransitionReady(
            transition = mock(),
            info = changeInfo,
            startTransaction = mock(),
            finishTransaction = mock(),
        )

        assertThat(tilingDecoration.leftTaskResizingHelper).isNull()
        verify(tiledTaskHelper, times(1)).dispose()
    }

    @Test
    fun taskNotTiled_shouldNotBeRemoved_whenNotTiled() {
        val task1 = createVisibleTask()
@@ -652,6 +687,23 @@ class DesktopTilingWindowDecorationTest : ShellTestCase() {
            whenever(userRepositories.current.isVisibleTask(eq(it.taskId))).thenReturn(true)
        }

    private fun createPipTask() =
        createPinnedTask().also {
            whenever(userRepositories.current.isVisibleTask(eq(it.taskId))).thenReturn(true)
        }

    private fun createPipChangeTransition(task: RunningTaskInfo?, type: Int = TRANSIT_PIP) =
        TransitionInfo(type, /* flags= */ 0).apply {
            addChange(
                Change(mock(), mock()).apply {
                    mode = TRANSIT_PIP
                    parent = null
                    taskInfo = task
                    flags = flags
                }
            )
        }

    companion object {
        private val NON_STABLE_BOUNDS_MOCK = Rect(50, 55, 100, 100)
        private val STABLE_BOUNDS_MOCK = Rect(0, 0, 100, 100)