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

Commit 3c034e12 authored by Eghosa Ewansiha-Vlachavas's avatar Eghosa Ewansiha-Vlachavas Committed by Android (Google) Code Review
Browse files

Merge "[1/n] Isolate desktop entry point disabling heuristic from window exemptions" into main

parents 1a161bdd 39ddc96c
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ class DesktopModeCompatPolicy(private val context: Context) {
            task.numActivities, task.isTopActivityNoDisplay, task.isActivityStackTransparent,
            task.userId)

    fun isTopActivityExemptFromDesktopWindowing(
    private fun isTopActivityExemptFromDesktopWindowing(
        packageName: String?,
        numActivities: Int,
        isTopActivityNoDisplay: Boolean,
@@ -74,6 +74,29 @@ class DesktopModeCompatPolicy(private val context: Context) {
        else -> false
    }

    fun shouldDisableDesktopEntryPoints(task: TaskInfo) = shouldDisableDesktopEntryPoints(
        task.baseActivity?.packageName, task.numActivities, task.isTopActivityNoDisplay,
        task.isActivityStackTransparent)

    fun shouldDisableDesktopEntryPoints(
        packageName: String?,
        numActivities: Int,
        isTopActivityNoDisplay: Boolean,
        isActivityStackTransparent: Boolean,
    ) = when {
        // Activity will not be displayed, no need to show desktop entry point.
        isTopActivityNoDisplay -> true
        // If activity belongs to system ui package, hide desktop entry point.
        isSystemUiTask(packageName) -> true
        // If activity belongs to default home package, safe to force out of desktop.
        isPartOfDefaultHomePackageOrNoHomeAvailable(packageName) -> true
        // If all activities in task stack are transparent AND package has the relevant fullscreen
        // transparent permission, safe to force out of desktop.
        isTransparentTask(isActivityStackTransparent, numActivities) -> true
        else -> false
    }


    /** @see DesktopModeCompatUtils.shouldExcludeCaptionFromAppBounds */
    fun shouldExcludeCaptionFromAppBounds(taskInfo: TaskInfo): Boolean =
        taskInfo.topActivityInfo?.let {
+16 −7
Original line number Diff line number Diff line
@@ -381,18 +381,31 @@ class DesktopTasksController(
        when (allFocusedTasks.size) {
            0 -> return
            // Full screen case
            1 ->
            1 -> {
                if (
                    desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
                        allFocusedTasks.single()
                    )
                ) {
                    return
                }
                moveTaskToDefaultDeskAndActivate(
                    allFocusedTasks.single().taskId,
                    transitionSource = transitionSource,
                )
            }
            // Split-screen case where there are two focused tasks, then we find the child
            // task to move to desktop.
            2 ->
            2 -> {
                val focusedTask = getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1])
                if (desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(focusedTask)) {
                    return
                }
                moveTaskToDefaultDeskAndActivate(
                    getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1]).taskId,
                    focusedTask.taskId,
                    transitionSource = transitionSource,
                )
            }
            else ->
                logW(
                    "DesktopTasksController: Cannot enter desktop, expected less " +
@@ -702,10 +715,6 @@ class DesktopTasksController(
        remoteTransition: RemoteTransition? = null,
        callback: IMoveToDesktopCallback? = null,
    ): Boolean {
        if (desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(task)) {
            logW("Cannot enter desktop for taskId %d, ineligible top activity found", task.taskId)
            return false
        }
        val displayId = taskRepository.getDisplayForDesk(deskId)
        logV(
            "moveRunningTaskToDesk taskId=%d deskId=%d displayId=%d",
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ class AppHandleAndHeaderVisibilityHelper (
            return false
        }

        if (desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(taskInfo)) {
        if (desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(taskInfo)) {
            return false
        }

+46 −161
Original line number Diff line number Diff line
@@ -1750,157 +1750,6 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        }
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveRunningTaskToDesktop_topActivityTranslucentWithoutDisplay_taskIsMovedToDesktop_multiDesksDisabled() {
        val task =
            setUpFullscreenTask().apply {
                isActivityStackTransparent = true
                isTopActivityNoDisplay = true
                numActivities = 1
            }

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)
        val wct = getLatestEnterDesktopWct()
        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FREEFORM)
        verify(desktopModeEnterExitTransitionListener)
            .onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
    )
    fun moveRunningTaskToDesktop_topActivityTranslucentWithoutDisplay_taskIsMovedToDesktop_multiDesksEnabled() {
        val task =
            setUpFullscreenTask().apply {
                isActivityStackTransparent = true
                isTopActivityNoDisplay = true
                numActivities = 1
            }

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)
        val wct = getLatestEnterDesktopWct()
        verify(desksOrganizer).moveTaskToDesk(wct, deskId = 0, task = task)
        verify(desktopModeEnterExitTransitionListener)
            .onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    @DisableFlags(Flags.FLAG_ENABLE_MODALS_FULLSCREEN_WITH_PERMISSION)
    fun moveRunningTaskToDesktop_topActivityTranslucentWithDisplay_doesNothing() {
        val task =
            setUpFullscreenTask().apply {
                isActivityStackTransparent = true
                isTopActivityNoDisplay = false
                numActivities = 1
            }

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
        verify(desktopModeEnterExitTransitionListener, times(0))
            .onEnterDesktopModeTransitionStarted(FREEFORM_ANIMATION_DURATION)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveRunningTaskToDesktop_systemUIActivityWithDisplay_doesNothing() {
        // Set task as systemUI package
        val systemUIPackageName =
            context.resources.getString(com.android.internal.R.string.config_systemUi)
        val baseComponent = ComponentName(systemUIPackageName, /* cls= */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = baseComponent
                isTopActivityNoDisplay = false
            }

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveRunningTaskToDesktop_systemUIActivityWithoutDisplay_doesNothing_multiDesksDisabled() {
        // Set task as systemUI package
        val systemUIPackageName =
            context.resources.getString(com.android.internal.R.string.config_systemUi)
        val baseComponent = ComponentName(systemUIPackageName, /* cls= */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = baseComponent
                isTopActivityNoDisplay = true
            }

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)

        val wct = getLatestEnterDesktopWct()
        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FREEFORM)
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveRunningTaskToDesktop_defaultHomePackageWithDisplay_doesNothing() {
        val packageManager: PackageManager = org.mockito.kotlin.mock()
        val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = homeActivities
                isTopActivityNoDisplay = false
            }
        mContext.setMockPackageManager(packageManager)
        whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveRunningTaskToDesktop_defaultHomePackageWithoutDisplay_doesNothing() {
        val packageManager: PackageManager = org.mockito.kotlin.mock()
        val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = homeActivities
                isTopActivityNoDisplay = false
            }
        mContext.setMockPackageManager(packageManager)
        whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)

        val wct = getLatestEnterDesktopWct()
        assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FREEFORM)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
    )
    fun moveRunningTaskToDesktop_systemUIActivityWithoutDisplay_doesNothing_multiDesksEnabled() {
        // Set task as systemUI package
        val systemUIPackageName =
            context.resources.getString(com.android.internal.R.string.config_systemUi)
        val baseComponent = ComponentName(systemUIPackageName, /* cls= */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = baseComponent
                isTopActivityNoDisplay = true
            }

        controller.moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = UNKNOWN)

        val wct = getLatestEnterDesktopWct()
        verify(desksOrganizer).moveTaskToDesk(wct, deskId = 0, task = task)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
    fun moveBackgroundTaskToDesktop_remoteTransition_usesOneShotHandler() {
@@ -4997,15 +4846,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        val freeformTask = setUpFreeformTask()
        markTaskVisible(freeformTask)

        val packageManager: PackageManager = org.mockito.kotlin.mock()
        val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = homeActivities
                baseActivity = homeComponentName
                isTopActivityNoDisplay = false
            }
        mContext.setMockPackageManager(packageManager)
        whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)

        val result = controller.handleRequest(Binder(), createTransition(task))
        assertThat(result?.changes?.get(task.token.asBinder())?.windowingMode)
@@ -5017,15 +4862,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        val freeformTask = setUpFreeformTask()
        markTaskVisible(freeformTask)

        val packageManager: PackageManager = org.mockito.kotlin.mock()
        val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
        val task =
            setUpFullscreenTask().apply {
                baseActivity = homeActivities
                baseActivity = homeComponentName
                isTopActivityNoDisplay = false
            }
        mContext.setMockPackageManager(packageManager)
        whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)

        val result = controller.handleRequest(Binder(), createTransition(task))
        assertThat(result?.changes?.get(task.token.asBinder())?.windowingMode)
@@ -5422,6 +5263,50 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        assertNull(result, "Should not handle request")
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveFocusedTaskToDesktop_noDisplayActivity_doesNothing() {
        val task = setUpFullscreenTask().apply { isTopActivityNoDisplay = true }

        controller.moveFocusedTaskToDesktop(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveFocusedTaskToDesktop_transparentTask_doesNothing() {
        val task =
            setUpFullscreenTask().apply {
                isActivityStackTransparent = true
                numActivities = 1
            }

        controller.moveFocusedTaskToDesktop(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveFocusedTaskToDesktop_systemUIActivity_doesNothing() {
        // Set task as systemUI package
        val systemUIPackageName =
            context.resources.getString(com.android.internal.R.string.config_systemUi)
        val baseComponent = ComponentName(systemUIPackageName, /* cls= */ "")
        val task = setUpFullscreenTask().apply { baseActivity = baseComponent }

        controller.moveFocusedTaskToDesktop(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
    fun moveFocusedTaskToDesktop_defaultHomePackage_doesNothing() {
        val task = setUpFullscreenTask().apply { baseActivity = homeComponentName }

        controller.moveFocusedTaskToDesktop(task.taskId, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
    }

    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveFocusedTaskToDesktop_fullscreenTaskIsMovedToDesktop_multiDesksDisabled() {
+52 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import com.android.internal.R
import com.android.window.flags.Flags
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask
import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModelTestsBase.Companion.HOME_LAUNCHER_PACKAGE_NAME
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges
@@ -248,6 +249,57 @@ class DesktopModeCompatPolicyTest : ShellTestCase() {
                }))
    }

    @Test
    fun testShouldDisableDesktopEntryPoints_noDisplayActivity() {
        assertTrue(desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
            createFullscreenTask(/* displayId */ 0)
                .apply {
                    isTopActivityNoDisplay = true
                }))
    }

    @Test
    fun testShouldDisableDesktopEntryPoints_transparentTask() {
        assertTrue(desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
            createFullscreenTask(/* displayId */ 0)
                .apply {
                    isActivityStackTransparent = true
                    numActivities = 1
                }))
    }

    @Test
    fun testShouldDisableDesktopEntryPoints_defaultHomePackage() {
        assertTrue(desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
            createFullscreenTask(/* displayId */ 0)
                .apply {
                    baseActivity = homeActivities
                }))
    }

    @Test
    fun testShouldDisableDesktopEntryPoints_defaultHomePackage_notYetAvailable() {
        val emptyHomeActivities: ComponentName = mock()
        mContext.setMockPackageManager(packageManager)

        whenever(emptyHomeActivities.packageName).thenReturn(null)
        whenever(packageManager.getHomeActivities(any())).thenReturn(emptyHomeActivities)

        assertTrue(desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
            createFullscreenTask(/* displayId */ 0)))
    }

    @Test
    fun testShouldDisableDesktopEntryPoints_systemUiTask() {
        val systemUIPackageName = context.resources.getString(R.string.config_systemUi)
        val baseComponent = ComponentName(systemUIPackageName, /* class */ "")
        assertTrue(desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
            createFreeformTask(/* displayId */ 0)
                .apply {
                    baseActivity = baseComponent
                }))
    }

    @Test
    @EnableFlags(Flags.FLAG_EXCLUDE_CAPTION_FROM_APP_BOUNDS)
    @DisableCompatChanges(ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
Loading