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

Commit 6bd3929f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add flicker test for relaunching bubble into split screen." into main

parents f5cd299a fe43c02c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ test_module_config {
        "com.android.wm.shell.flicker.bubbles.SwitchBetweenBubblesTest",
        "com.android.wm.shell.flicker.bubbles.ExpandedBubbleAppMoveTest",
        "com.android.wm.shell.flicker.bubbles.RelaunchSplitScreenToBubbleTest",
        "com.android.wm.shell.flicker.bubbles.RelaunchBubbleIntoSplitScreenTest",
    ],
}

@@ -232,3 +233,10 @@ test_module_config {
    test_suites: ["device-tests"],
    include_filters: ["com.android.wm.shell.flicker.bubbles.RelaunchSplitScreenToBubbleTest"],
}

test_module_config {
    name: "WMShellExplicitFlickerTestsBubbles-RelaunchBubbleIntoSplitScreenTest",
    base: "WMShellExplicitFlickerTestsBubbles",
    test_suites: ["device-tests"],
    include_filters: ["com.android.wm.shell.flicker.bubbles.RelaunchBubbleIntoSplitScreenTest"],
}
+3 −0
Original line number Diff line number Diff line
@@ -68,6 +68,9 @@
    },
    {
      "name": "WMShellExplicitFlickerTestsBubbles-RelaunchSplitScreenToBubbleTest"
    },
    {
      "name": "WMShellExplicitFlickerTestsBubbles-RelaunchBubbleIntoSplitScreenTest"
    }
  ]
}
+119 −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.bubbles

import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresFlagsEnabled
import android.tools.NavBar
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.helpers.NewTasksAppHelper
import com.android.wm.shell.Flags
import com.android.wm.shell.Utils.testSetupRule
import com.android.wm.shell.flicker.bubbles.RelaunchBubbleIntoSplitScreenTest.Companion.bubbleApp
import com.android.wm.shell.flicker.bubbles.testcase.BubbleExitTestCases
import com.android.wm.shell.flicker.bubbles.testcase.SecondarySplitEnterTestCases
import com.android.wm.shell.flicker.bubbles.utils.ApplyPerParameterRule
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerTestHelper.collapseBubbleAppViaTouchOutside
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerTestHelper.launchBubbleViaBubbleMenu
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerTestHelper.withBubbleFullyDismissedAndGone
import com.android.wm.shell.flicker.bubbles.utils.RecordTraceWithTransitionRule
import com.android.wm.shell.flicker.utils.SplitScreenUtils
import com.android.wm.shell.flicker.utils.SplitScreenUtils.enterSplit
import com.android.wm.shell.flicker.utils.SplitScreenUtils.withSplitScreenComplete
import org.junit.FixMethodOrder
import org.junit.Rule
import org.junit.runners.MethodSorters

/**
 * Test relaunching a bubble from a secondary split-screen app.
 *
 * This test verifies that the existing bubble is dismissed and its app task is moved into the
 * secondary split-screen pane.
 *
 * To run this test:
 *     `atest WMShellExplicitFlickerTestsBubbles:RelaunchBubbleIntoSplitScreenTest`
 *
 * Pre-steps:
 * ```
 * 1. Launch [bubbleApp] into a collapsed bubble.
 * 2. Launch [primaryApp] and [secondaryApp] into split-screen.
 * ```
 *
 * Actions:
 * ```
 * From [secondaryApp], relaunch the [bubbleApp].
 * ```
 *
 * Verified tests:
 * - [BubbleFlickerTestBase]
 * - [BubbleExitTestCases]: Verifies the collapsed bubble is dismissed.
 * - [SecondarySplitEnterTestCases]: Verifies [bubbleApp] enters the secondary split.
 */
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE)
@RequiresDevice
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Presubmit
// TODO: b/432604687 - Rename to ExpandBubbleByRelaunchingFromSplit once the expected behavior is
//  unblocked and the test logic is updated to verify it.
class RelaunchBubbleIntoSplitScreenTest : BubbleFlickerTestBase(),
    BubbleExitTestCases, SecondarySplitEnterTestCases {

    companion object {
        private val bubbleApp = testApp
        private val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
        private val secondaryApp = NewTasksAppHelper(instrumentation)

        private val recordTraceWithTransitionRule =
            RecordTraceWithTransitionRule(
                setUpBeforeTransition = {
                    // Launch [bubbleApp] into collapsed bubble.
                    launchBubbleViaBubbleMenu(bubbleApp, tapl, wmHelper)
                    collapseBubbleAppViaTouchOutside(bubbleApp, wmHelper)

                    // Launch [primaryApp] and [secondaryApp] into split screen.
                    enterSplit(wmHelper, tapl, uiDevice, primaryApp, secondaryApp)
                },
                transition = {
                    // Relaunch bubble from secondary split.
                    secondaryApp.openNewTaskWithRecycle(uiDevice, wmHelper) {
                        // TODO: b/432604687 - Expected behavior is blocked by WM core reparent.
                        // Reopen the collapsed bubble.
                        // withBubbleAppInExpandedState(bubbleApp)

                        // Current behavior: Bubble task is converted into split.
                        withBubbleFullyDismissedAndGone()
                            .withSplitScreenComplete(primaryApp, secondaryApp = bubbleApp)
                    }
                },
                tearDownAfterTransition = {
                    bubbleApp.exit(wmHelper)
                    primaryApp.exit(wmHelper)
                    secondaryApp.exit(wmHelper)
                },
            )
    }

    @get:Rule
    val setUpRule = ApplyPerParameterRule(
        testSetupRule(NavBar.MODE_GESTURAL).around(recordTraceWithTransitionRule),
    )

    override val traceDataReader
        get() = recordTraceWithTransitionRule.reader

    override val previousSecondaryApp = secondaryApp
}
+5 −46
Original line number Diff line number Diff line
@@ -16,56 +16,15 @@

package com.android.wm.shell.flicker.bubbles.testcase

import android.tools.traces.component.ComponentNameMatcher.Companion.BUBBLE
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerSubjects
import org.junit.Test

/**
 * Verifies bubble and its app are dismissed.
 */
interface BubbleDismissesTestCases : BubbleFlickerSubjects {

    /**
     * Verifies [BUBBLE] window is gone at the end of the transition.
     */
    @Test
    fun bubbleWindowIsGoneAtEnd() {
        wmStateSubjectAtEnd.notContains(BUBBLE)
    }

    /**
     * Verifies [BUBBLE] layer is gone at the end of the transition.
     */
    @Test
    fun bubbleLayerIsGoneAtEnd() {
        layerTraceEntrySubjectAtEnd.notContains(BUBBLE)
    }

    /**
     * Verifies [BUBBLE] window was visible then disappears.
     */
    @Test
    fun bubbleWindowWasVisibleThenDisappear() {
        wmTraceSubject
            .isAboveAppWindowVisible(BUBBLE)
            .then()
            // Use #isNonAppWindowInvisible here because the BUBBLE window may have been removed
            // from WM hierarchy.
            .isNonAppWindowInvisible(BUBBLE)
            .forAllEntries()
    }

    /**
     * Verifies [BUBBLE] layer was visible then disappears.
 * Verifies a bubble and its associated app window are fully dismissed.
 *
 * This test case builds upon [BubbleExitTestCases] by adding a verification
 * to ensure the application window itself is also gone at the end of the transition.
 */
    @Test
    fun bubbleLayerWasVisibleThenDisappear() {
        layersTraceSubject
            .isVisible(BUBBLE)
            .then()
            .isInvisible(BUBBLE)
            .forAllEntries()
    }
interface BubbleDismissesTestCases : BubbleExitTestCases {

    /**
     * Verifies bubble app window is gone at the end of the transition.
+72 −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.bubbles.testcase

import android.tools.traces.component.ComponentNameMatcher.Companion.BUBBLE
import com.android.wm.shell.flicker.bubbles.utils.BubbleFlickerSubjects
import org.junit.Test

/**
 * Verifies the exit transition of a bubble.
 *
 * Verifies a bubble's window and layer correctly transition from a visible to an invisible state
 * at the end of a trace.
 */
interface BubbleExitTestCases : BubbleFlickerSubjects {

    /**
     * Verifies [BUBBLE] window is gone at the end of the transition.
     */
    @Test
    fun bubbleWindowIsGoneAtEnd() {
        wmStateSubjectAtEnd.notContains(BUBBLE)
    }

    /**
     * Verifies [BUBBLE] layer is gone at the end of the transition.
     */
    @Test
    fun bubbleLayerIsGoneAtEnd() {
        layerTraceEntrySubjectAtEnd.notContains(BUBBLE)
    }

    /**
     * Verifies [BUBBLE] window was visible then disappears.
     */
    @Test
    fun bubbleWindowWasVisibleThenDisappear() {
        wmTraceSubject
            .isAboveAppWindowVisible(BUBBLE)
            .then()
            // Use #isNonAppWindowInvisible here because the BUBBLE window may have been removed
            // from WM hierarchy.
            .isNonAppWindowInvisible(BUBBLE)
            .forAllEntries()
    }

    /**
     * Verifies [BUBBLE] layer was visible then disappears.
     */
    @Test
    fun bubbleLayerWasVisibleThenDisappear() {
        layersTraceSubject
            .isVisible(BUBBLE)
            .then()
            .isInvisible(BUBBLE)
            .forAllEntries()
    }
}
 No newline at end of file
Loading