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

Commit 8274f9e0 authored by Sergey Pinkevich's avatar Sergey Pinkevich Committed by Android (Google) Code Review
Browse files

Merge "E2E scenario for tab tearing in Desktop Windowing mode" into main

parents c341b395 3cd8a7bb
Loading
Loading
Loading
Loading
+29 −0
Original line number Original line 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.functional

import android.platform.test.annotations.Postsubmit
import android.platform.test.rule.ScreenRecordRule
import com.android.wm.shell.scenarios.TabTearingDragAndDrop
import org.junit.runner.RunWith
import org.junit.runners.BlockJUnit4ClassRunner

/* Functional test for [TabTearingDragAndDrop]. */
@RunWith(BlockJUnit4ClassRunner::class)
@Postsubmit
@ScreenRecordRule.ScreenRecord
class TabTearingDragAndDropTest : TabTearingDragAndDrop()
 No newline at end of file
+84 −0
Original line number Original line 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.scenarios

import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
import android.tools.device.apphelpers.BrowserAppHelper
import android.tools.flicker.rules.ChangeDisplayOrientationRule
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.window.flags.Flags
import com.android.wm.shell.Utils
import org.junit.After
import org.junit.Assume
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test

@Ignore("Test Base Class")
abstract class TabTearingDragAndDrop(val rotation: Rotation = Rotation.ROTATION_0) :
    TestScenarioBase() {

    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
    private val tapl = LauncherInstrumentation()
    private val wmHelper = WindowManagerStateHelper(instrumentation)
    private val device = UiDevice.getInstance(instrumentation)
    private val browserAppHelper = BrowserAppHelper(instrumentation)
    private val browserDesktopAppHelper = DesktopModeAppHelper(browserAppHelper)

    @Rule
    @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)

    @Before
    fun setup() {
        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
        tapl.apply {
            setEnableRotation(true)
            setExpectedRotation(rotation.value)
            enableTransientTaskbar(false)
        }
        ChangeDisplayOrientationRule.setRotation(rotation)
        browserDesktopAppHelper.enterDesktopMode(wmHelper, device)
    }

    @Test
    open fun tearTab() {
        browserAppHelper.openThreeDotsMenu()
        browserAppHelper.clickNewTabInMenu()
        browserDesktopAppHelper.dragWindowTopLeftCorner(
            device,
            wmHelper,
            DesktopModeAppHelper.WindowDraggingDirection.CENTER
        )
        browserAppHelper.performTabTearing(
            wmHelper,
            BrowserAppHelper.Companion.TabDraggingDirection.TOP_LEFT
        )
        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
    }

    @After
    fun teardown() {
        browserDesktopAppHelper.exit(wmHelper)
    }
}
 No newline at end of file
+49 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.wm.flicker.helpers
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.content.Context
import android.content.Context
import android.graphics.Insets
import android.graphics.Insets
import android.graphics.Point
import android.graphics.Rect
import android.graphics.Rect
import android.graphics.Region
import android.graphics.Region
import android.os.SystemClock
import android.os.SystemClock
@@ -417,6 +418,50 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
            .waitForAndVerify()
            .waitForAndVerify()
    }
    }


    /**
     * Simulates dragging the top-left corner of the current window to the center of the device
     * screen.
     *
     * This function calculates a starting point slightly offset from the actual top-left corner (60
     * pixels down and right to prevent app resizing) and drags it to the center of the default
     * display.
     *
     * @param device The UiDevice instance used to perform the drag interaction on the device.
     * @param wmHelper A helper class instance used to retrieve window and display dimension
     *   information.
     * @param direction A direction where the window should be dragged to.
     * @throws IllegalStateException if the default display information cannot be obtained from the
     *   wmHelper.
     */
    fun dragWindowTopLeftCorner(
        device: UiDevice,
        wmHelper: WindowManagerStateHelper,
        direction: WindowDraggingDirection = WindowDraggingDirection.CENTER,
    ) {
        val windowBounds = wmHelper.getWindowRegion(this).bounds
        val displayBounds = getDisplayRect(wmHelper)
        // We take start dragging point with some offset to use app moving instead of resizing.
        val startDraggingPoint =
            Point(/* x= */ windowBounds.left + 60, /* y= */ windowBounds.top + 60)
        val endDraggingPoint =
            when (direction) {
                WindowDraggingDirection.CENTER ->
                    Point(/* x= */ displayBounds.centerX(), /* y= */ displayBounds.centerY())
            }

        device.drag(
            startDraggingPoint.x,
            startDraggingPoint.y,
            endDraggingPoint.x,
            endDraggingPoint.y,
            /* steps= */ 100,
        )
        wmHelper
            .StateSyncBuilder()
            .withAppTransitionIdle()
            .waitForAndVerify()
    }

    /** Drag a window to a snap resize region, found at the left and right edges of the screen. */
    /** Drag a window to a snap resize region, found at the left and right edges of the screen. */
    fun dragToSnapResizeRegion(
    fun dragToSnapResizeRegion(
        wmHelper: WindowManagerStateHelper,
        wmHelper: WindowManagerStateHelper,
@@ -606,6 +651,10 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
        MAXIMIZE_BUTTON_IN_MENU
        MAXIMIZE_BUTTON_IN_MENU
    }
    }


    enum class WindowDraggingDirection {
        CENTER
    }

    private companion object {
    private companion object {
        val TIMEOUT: Duration = Duration.ofSeconds(3)
        val TIMEOUT: Duration = Duration.ofSeconds(3)
        const val SNAP_RESIZE_DRAG_INSET: Int = 5 // inset to avoid dragging to display edge
        const val SNAP_RESIZE_DRAG_INSET: Int = 5 // inset to avoid dragging to display edge