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

Commit dcee476e authored by Vania Desmonda's avatar Vania Desmonda
Browse files

Add flicker test CUJs for enter/exit desktop mode via keyboard shortcuts

Fixes: 399655103
Flag: EXEMPT flicker test
Test: atest EnterDesktopWithKeyboardShortcut
Test: atest ExitDesktopToFullScreenWithKeyboardShortcut
Change-Id: I6b863aee8f4bffb2fd13fc81a55d7210c7960baa
parent 5a2b5230
Loading
Loading
Loading
Loading
+66 −18
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.wm.shell.flicker
import android.tools.PlatformConsts.DESKTOP_MODE_MINIMUM_WINDOW_HEIGHT
import android.tools.PlatformConsts.DESKTOP_MODE_MINIMUM_WINDOW_WIDTH
import android.tools.flicker.AssertionInvocationGroup
import android.tools.flicker.assertors.assertions.AppLayerCoversFullScreenAtEnd
import android.tools.flicker.assertors.assertions.ResizeVeilKeepsIncreasingInSize
import android.tools.flicker.assertors.assertions.AppLayerIsInvisibleAtEnd
import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAlways
@@ -99,6 +100,59 @@ class DesktopModeFlickerScenarios {
                            .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
            )

        val ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT =
            FlickerConfigEntry(
                scenarioId = ScenarioId("ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT"),
                extractor =
                ShellTransitionScenarioExtractor(
                    transitionMatcher =
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> =
                            transitions.filter {
                                it.type == TransitionType.ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT
                            }
                    }
                ),
                assertions =
                AssertionTemplates.COMMON_ASSERTIONS +
                        listOf(
                            AppLayerIsVisibleAlways(DESKTOP_MODE_APP),
                            AppWindowOnTopAtEnd(DESKTOP_MODE_APP),
                            AppWindowHasDesktopModeInitialBoundsAtTheEnd(DESKTOP_MODE_APP),
                            AppWindowBecomesVisible(DESKTOP_WALLPAPER)
                        )
                            .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
            )

        val EXIT_DESKTOP_FROM_KEYBOARD_SHORTCUT =
            FlickerConfigEntry(
                scenarioId = ScenarioId("EXIT_DESKTOP_FROM_KEYBOARD_SHORTCUT"),
                extractor =
                ShellTransitionScenarioExtractor(
                    transitionMatcher =
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> =
                            transitions.filter {
                                it.type == TransitionType.EXIT_DESKTOP_MODE_KEYBOARD_SHORTCUT
                            }
                    }
                ),
                assertions =
                AssertionTemplates.COMMON_ASSERTIONS +
                        listOf(
                            AppLayerIsVisibleAlways(DESKTOP_MODE_APP),
                            AppLayerCoversFullScreenAtEnd(DESKTOP_MODE_APP),
                            AppWindowOnTopAtStart(DESKTOP_MODE_APP),
                            AppWindowOnTopAtEnd(DESKTOP_MODE_APP),
                            AppWindowBecomesInvisible(DESKTOP_WALLPAPER)
                        )
                            .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
            )

        // Use this scenario for closing an app in desktop windowing, except the last app. For the
        // last app use CLOSE_LAST_APP scenario
        val CLOSE_APP =
@@ -361,12 +415,11 @@ class DesktopModeFlickerScenarios {
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> {
                            return transitions.filter {
                        ): Collection<Transition> =
                            transitions.filter {
                                it.type == TransitionType.DESKTOP_MODE_TOGGLE_RESIZE
                            }
                    }
                    }
                ),
                assertions = AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
                        listOf(
@@ -385,12 +438,11 @@ class DesktopModeFlickerScenarios {
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> {
                            return transitions.filter {
                        ): Collection<Transition> =
                            transitions.filter {
                                it.type == TransitionType.DESKTOP_MODE_TOGGLE_RESIZE
                            }
                    }
                    }
                ),
                assertions =
                AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
@@ -410,12 +462,11 @@ class DesktopModeFlickerScenarios {
                            object : ITransitionMatcher {
                                override fun findAll(
                                    transitions: Collection<Transition>
                                ): Collection<Transition> {
                                    return transitions.filter {
                                ): Collection<Transition> =
                                    transitions.filter {
                                        it.type == TransitionType.TO_FRONT
                                    }
                            }
                            }
                    ),
                assertions =
                    AssertionTemplates.COMMON_ASSERTIONS +
@@ -434,9 +485,8 @@ class DesktopModeFlickerScenarios {
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> {
                                return transitions.filter { it.type == TransitionType.OPEN }
                        }
                        ): Collection<Transition> =
                                transitions.filter { it.type == TransitionType.OPEN }
                    }
                ),
                assertions =
@@ -512,9 +562,8 @@ class DesktopModeFlickerScenarios {
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> {
                                return transitions.filter { it.type == TransitionType.OPEN }
                        }
                        ): Collection<Transition> =
                                transitions.filter { it.type == TransitionType.OPEN }
                    }
                ),
                assertions =
@@ -553,12 +602,11 @@ class DesktopModeFlickerScenarios {
                    object : ITransitionMatcher {
                        override fun findAll(
                            transitions: Collection<Transition>
                        ): Collection<Transition> {
                                return listOf(transitions
                        ): Collection<Transition> =
                                listOf(transitions
                                    .filter { it.type == TransitionType.OPEN }
                                    .maxByOrNull { it.id }!!)
                    }
                    }
                ),
                assertions =
                        listOf(
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.flicker

import android.tools.flicker.FlickerConfig
import android.tools.flicker.annotation.ExpectedScenarios
import android.tools.flicker.annotation.FlickerConfigProvider
import android.tools.flicker.config.FlickerConfig
import android.tools.flicker.config.FlickerServiceConfig
import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT
import com.android.wm.shell.scenarios.EnterDesktopFromKeyboardShortcut
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(FlickerServiceJUnit4ClassRunner::class)
class EnterDesktopWithKeyboardShortcut : EnterDesktopFromKeyboardShortcut() {
    @ExpectedScenarios(["ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT"])
    @Test
    override fun enterDesktopFromKeyboardShortcut() = super.enterDesktopFromKeyboardShortcut()

    companion object {

        @JvmStatic
        @FlickerConfigProvider
        fun flickerConfigProvider(): FlickerConfig =
            FlickerConfig().use(FlickerServiceConfig.DEFAULT)
                .use(ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT)
    }
}
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.flicker

import android.tools.flicker.FlickerConfig
import android.tools.flicker.annotation.ExpectedScenarios
import android.tools.flicker.annotation.FlickerConfigProvider
import android.tools.flicker.config.FlickerConfig
import android.tools.flicker.config.FlickerServiceConfig
import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.EXIT_DESKTOP_FROM_KEYBOARD_SHORTCUT
import com.android.wm.shell.scenarios.ExitDesktopFromKeyboardShortcut
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(FlickerServiceJUnit4ClassRunner::class)
class ExitDesktopToFullScreenWithKeyboardShortcut : ExitDesktopFromKeyboardShortcut() {
    @ExpectedScenarios(["EXIT_DESKTOP_FROM_KEYBOARD_SHORTCUT"])
    @Test
    override fun exitDesktopToFullScreenFromKeyboardShortcut() =
        super.exitDesktopToFullScreenFromKeyboardShortcut()

    companion object {
        @JvmStatic
        @FlickerConfigProvider
        fun flickerConfigProvider(): FlickerConfig =
            FlickerConfig().use(FlickerServiceConfig.DEFAULT)
                .use(EXIT_DESKTOP_FROM_KEYBOARD_SHORTCUT)
    }
}
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.scenarios

import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.window.flags.Flags
import org.junit.After
import org.junit.Assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.BlockJUnit4ClassRunner

@RunWith(BlockJUnit4ClassRunner::class)
@Postsubmit
open class EnterDesktopFromKeyboardShortcut {

    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
    private val tapl = LauncherInstrumentation()
    private val wmHelper = WindowManagerStateHelper(instrumentation)
    private val simpleAppHelper = SimpleAppHelper(instrumentation)
    private val testApp = DesktopModeAppHelper(simpleAppHelper)

    @Before
    fun setup() {
        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
    }

    @Test
    open fun enterDesktopFromKeyboardShortcut() {
        simpleAppHelper.launchViaIntent(wmHelper)
        testApp.enterDesktopModeViaKeyboard(wmHelper)
    }

    @After
    fun teardown() {
        testApp.exit(wmHelper)
    }
}
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.scenarios

import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.traces.parsers.WindowManagerStateHelper
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.window.flags.Flags
import org.junit.After
import org.junit.Assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.BlockJUnit4ClassRunner

@RunWith(BlockJUnit4ClassRunner::class)
@Postsubmit
open class ExitDesktopFromKeyboardShortcut {

    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
    private val tapl = LauncherInstrumentation()
    private val wmHelper = WindowManagerStateHelper(instrumentation)
    private val device = UiDevice.getInstance(instrumentation)
    private val simpleAppHelper = SimpleAppHelper(instrumentation)
    private val testApp = DesktopModeAppHelper(simpleAppHelper)

    @Before
    fun setup() {
        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
        simpleAppHelper.launchViaIntent(wmHelper)
        testApp.enterDesktopMode(wmHelper, device)
    }

    @Test
    open fun exitDesktopToFullScreenFromKeyboardShortcut() {
        testApp.exitDesktopModeToFullScreenViaKeyboard(wmHelper)
    }

    @After
    fun teardown() {
        testApp.exit(wmHelper)
    }
}
Loading