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

Commit 94a80319 authored by Massimo Carli's avatar Massimo Carli
Browse files

[62/n] Improve letterbox surfaces bounds calculation on Activity Transitions

The caluclation of taskBounds and letterboxBounds used to define
letterbox surfaces bounds needs to take offsets into account.
This allow to fix the problem related to Tasks that don't have
(0,0) as position.

Flag: EXEMPT Refactoring
Bug: 377875664
Test: atest WMShellUnitTests:TaskInfoLetterboxLifecycleEventFactoryTest

Change-Id: I1492ee0ea0d3bbf1017969a219a68c78cc1c893d
parent 7884618a
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.compatui.letterbox.lifecycle

import android.graphics.Rect
import android.window.TransitionInfo.Change
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.compatui.letterbox.state.LetterboxTaskInfoRepository
@@ -36,25 +37,34 @@ class ActivityLetterboxLifecycleEventFactory(

    override fun canHandle(change: Change): Boolean = change.activityTransitionInfo != null

    // TODO(b/382423480): Extract common behaviour from different LetterboxLifecycleEventFactories.
    override fun createLifecycleEvent(change: Change): LetterboxLifecycleEvent? {
        val activityTransitionInfo = change.activityTransitionInfo
        val taskBounds = change.endAbsBounds
        val taskBoundsAbs = change.endAbsBounds

        val letterboxBoundsTmp = activityTransitionInfo?.appCompatTransitionInfo?.letterboxBounds
        val taskId = activityTransitionInfo?.taskId ?: -1
        taskRepository.find(taskId)?.let {
            val isLetterboxed = letterboxBoundsTmp != taskBounds
        taskRepository.find(taskId)?.let { taskItem ->
            val isLetterboxed = letterboxBoundsTmp != taskBoundsAbs
            // Letterbox bounds are null when the activity is not letterboxed.
            val letterboxBounds = if (isLetterboxed) letterboxBoundsTmp else null
            val taskToken = it.containerToken
            val taskLeash = it.containerLeash
            val letterboxBoundsAbs = if (isLetterboxed) letterboxBoundsTmp else null

            val taskBounds = Rect(taskBoundsAbs).apply {
                offset(-taskBoundsAbs.left, -taskBoundsAbs.top)
            }
            val letterboxBounds = letterboxBoundsAbs?.let { absBounds ->
                Rect(absBounds).apply {
                    offset(-taskBoundsAbs.left, -taskBoundsAbs.top)
                }
            }

            return LetterboxLifecycleEvent(
                type = change.asLetterboxLifecycleEventType(),
                taskId = taskId,
                taskBounds = taskBounds,
                letterboxBounds = letterboxBounds,
                taskLeash = taskLeash,
                containerToken = taskToken
                taskLeash = taskItem.containerLeash,
                containerToken = taskItem.containerToken
            )
        }
        ProtoLog.w(WM_SHELL_APP_COMPAT, "$TAG: Task not found for taskId: $taskId")
+81 −3
Original line number Diff line number Diff line
@@ -18,9 +18,12 @@ package com.android.wm.shell.compatui.letterbox.lifecycle

import android.graphics.Rect
import android.testing.AndroidTestingRunner
import android.view.SurfaceControl
import android.window.WindowContainerToken
import androidx.test.filters.SmallTest
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.compatui.letterbox.state.LetterboxTaskInfoRepository
import com.android.wm.shell.compatui.letterbox.state.LetterboxTaskInfoState
import com.android.wm.shell.util.testLetterboxLifecycleEventFactory
import java.util.function.Consumer
import org.junit.Test
@@ -56,13 +59,84 @@ class ActivityLetterboxLifecycleEventFactoryTest : ShellTestCase() {
        runTestScenario { r ->
            testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) {
                inputChange {
                    endAbsBounds = Rect(0, 0, 500, 1000)
                    endAbsBounds = Rect(100, 50, 2000, 1500)
                }
                validateCanHandle { canHandle ->
                    assert(canHandle == false)
                }
                validateCreateLifecycleEvent { event ->
                    assert(event?.taskBounds == Rect(0, 0, 500, 1000))
                    assert(event?.taskBounds == Rect(0, 0, 1900, 1450))
                }
            }
        }
    }

    @Test
    fun `Read Letterbox bounds from activityTransitionInfo and endAbsBounds in Change`() {
        runTestScenario { r ->
            testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) {
                inputChange {
                    endAbsBounds = Rect(100, 50, 2000, 1500)
                    activityTransitionInfo {
                        appCompatTransitionInfo {
                            letterboxBounds = Rect(500, 50, 1500, 800)
                        }
                    }
                }
                validateCanHandle { canHandle ->
                    assert(canHandle == false)
                }
                validateCreateLifecycleEvent { event ->
                    assert(event?.taskBounds == Rect(0, 0, 1900, 1450))
                    assert(event?.letterboxBounds == Rect(400, 0, 1400, 750))
                }
            }
        }
    }

    @Test
    fun `Uses leash and token from the repository`() {
        runTestScenario { r ->
            testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) {
                val testLeash = mock<SurfaceControl>()
                val testToken = mock<WindowContainerToken>()
                r.addToTaskRepository(10, LetterboxTaskInfoState(testToken, testLeash))
                inputChange {
                    leash { testLeash }
                    token { testToken }
                    runningTaskInfo { ti ->
                        ti.taskId = 10
                    }
                }
                validateCanHandle { canHandle ->
                    assert(canHandle == false)
                }
                validateCreateLifecycleEvent { event ->
                    assert(event?.taskLeash == testLeash)
                    assert(event?.containerToken == testToken)
                }
            }
        }
    }

    @Test
    fun `Event is null if repository has no task data`() {
        runTestScenario { r ->
            testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) {
                val testLeash = mock<SurfaceControl>()
                val testToken = mock<WindowContainerToken>()
                inputChange {
                    leash { testLeash }
                    token { testToken }
                    runningTaskInfo { ti ->
                        ti.taskId = 10
                    }
                }
                validateCanHandle { canHandle ->
                    assert(canHandle == false)
                }
                validateCreateLifecycleEvent { event ->
                    assert(event == null)
                }
            }
        }
@@ -82,10 +156,14 @@ class ActivityLetterboxLifecycleEventFactoryTest : ShellTestCase() {
    class ActivityLetterboxLifecycleEventFactoryRobotTest {

        private val letterboxTaskInfoRepository: LetterboxTaskInfoRepository =
            mock<LetterboxTaskInfoRepository>()
            LetterboxTaskInfoRepository()

        fun getLetterboxLifecycleEventFactory(): () -> LetterboxLifecycleEventFactory = {
            ActivityLetterboxLifecycleEventFactory(letterboxTaskInfoRepository)
        }

        fun addToTaskRepository(key: Int, state: LetterboxTaskInfoState) {
            letterboxTaskInfoRepository.insert(key = key, item = state, overrideIfPresent = true)
        }
    }
}