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

Commit d8240117 authored by Kazuki Takise's avatar Kazuki Takise Committed by Android (Google) Code Review
Browse files

Merge "Added flicker test for restart handle menu" into main

parents aa8f5ca9 b05e629a
Loading
Loading
Loading
Loading
+30 −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.functional

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

/** Functional test of [RestartAppInDesktopMode] for a size-compat app. */
@RunWith(BlockJUnit4ClassRunner::class)
@ScreenRecordRule.ScreenRecord
@Postsubmit
class RestartSizeCompatAppInDesktopMode :
    RestartAppInDesktopMode(isResizable = false, isLandscapeApp = false)
+1 −10
Original line number Diff line number Diff line
@@ -69,16 +69,7 @@ abstract class MoveToNextDisplay {
        val connectedDisplayId = connectedDisplayRule.setupTestDisplay()
        testApp.enterDesktopMode(wmHelper, device)

        testApp.moveToNextDisplayViaKeyboard(wmHelper)

        wmHelper.StateSyncBuilder().apply {
            add("testApp is on the connected display") { dump ->
                val display = requireNotNull(dump.wmState.getDisplay(connectedDisplayId)) {
                    "Display $connectedDisplayId not found"
                }
                display.containsActivity(testApp)
            }
        }.waitForAndVerify()
        testApp.moveToNextDisplayViaKeyboard(wmHelper, connectedDisplayId)
    }

    @After
+92 −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.scenarios

import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.tools.NavBar
import android.tools.Rotation
import com.android.window.flags.Flags
import com.android.wm.shell.Utils
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import platform.test.desktop.SimulatedConnectedDisplayTestRule

/** Base scenario test for moving an app between displays and manually restarting the app. */
@Ignore("Test Base Class")
@RequiresFlagsEnabled(
    Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
    Flags.FLAG_ENABLE_RESTART_MENU_FOR_CONNECTED_DISPLAYS,
)
abstract class RestartAppInDesktopMode(
    isResizable: Boolean = true,
    isLandscapeApp: Boolean = true,
) : DesktopScenarioCustomAppTestBase(isResizable, isLandscapeApp) {

    @get:Rule(order = 0) val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
    @get:Rule(order = 1)
    val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, Rotation.ROTATION_0)
    @get:Rule(order = 2) val connectedDisplayRule = SimulatedConnectedDisplayTestRule()

    @Before
    fun setup() {
        assumeTrue("isTablet", tapl.isTablet)
    }

    @Test
    open fun restartFromAppHandleMenu() {
        val connectedDisplayId = connectedDisplayRule.setupTestDisplay()
        testApp.enterDesktopMode(wmHelper, device)
        testApp.moveToNextDisplayViaKeyboard(wmHelper, connectedDisplayId)

        waitForAndVerifyDensityConfiguration(displayId = connectedDisplayId, shouldMatch = false)
        testApp.restartFromAppHandleMenu(wmHelper)
        waitForAndVerifyDensityConfiguration(displayId = connectedDisplayId, shouldMatch = true)
    }

    private fun waitForAndVerifyDensityConfiguration(displayId: Int, shouldMatch: Boolean) {
        wmHelper
            .StateSyncBuilder()
            .add(
                String.format(
                    "App density %s match display density %s restart",
                    if (shouldMatch) "should" else "should not",
                    if (shouldMatch) "after" else "before",
                )
            ) { dump ->
                val activityConfig =
                    requireNotNull(dump.wmState.focusedActivity?.fullConfiguration) {
                        "Focused activity not found"
                    }
                val displayConfig =
                    requireNotNull(dump.wmState.getDisplay(displayId)?.fullConfiguration) {
                        "Display $displayId not found"
                    }
                shouldMatch == (activityConfig.densityDpi == displayConfig.densityDpi)
            }
            .waitForAndVerify()
    }

    @After
    fun teardown() {
        testApp.exit(wmHelper)
    }
}
+28 −1
Original line number Diff line number Diff line
@@ -583,10 +583,34 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
    }

    fun moveToNextDisplayViaKeyboard(wmHelper: WindowManagerStateHelper) {
    fun restartFromAppHandleMenu(wmHelper: WindowManagerStateHelper) {
        val openMenuButton = getDesktopAppViewByRes(OPEN_MENU_BUTTON)
        openMenuButton?.click()
        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()

        val restartHandleMenu = getDesktopAppViewByRes(RESTART_BUTTON)
        restartHandleMenu?.click()
        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()

        val restartDialogConfirmButton =
            getDesktopAppViewByRes(RESTART_DIALOG_RESTART_BUTTON)
        restartDialogConfirmButton?.click()
        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
    }

    fun moveToNextDisplayViaKeyboard(wmHelper: WindowManagerStateHelper, expectedDisplayId: Int) {
        val keyEventHelper = KeyEventHelper(getInstrumentation())
        keyEventHelper.press(KEYCODE_D, META_META_ON or META_CTRL_ON)
        wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()

        wmHelper.StateSyncBuilder().apply {
            add("App is on display #$expectedDisplayId") { dump ->
                val display = requireNotNull(dump.wmState.getDisplay(expectedDisplayId)) {
                    "Display $expectedDisplayId not found"
                }
                display.containsActivity(innerHelper)
            }
        }.waitForAndVerify()
    }

    private fun getDesktopAppViewByRes(viewResId: String): UiObject2? =
@@ -678,6 +702,9 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
        const val MAXIMIZE_BUTTON_IN_MENU: String = "maximize_menu_size_toggle_button"
        const val MINIMIZE_BUTTON_VIEW: String = "minimize_window"
        const val HEADER_EMPTY_VIEW: String = "caption_handle"
        const val OPEN_MENU_BUTTON: String = "open_menu_button"
        const val RESTART_BUTTON: String = "handle_menu_restart_button"
        const val RESTART_DIALOG_RESTART_BUTTON: String = "letterbox_restart_dialog_restart_button"
        val caption: BySelector
            get() = By.res(SYSTEMUI_PACKAGE, CAPTION)
        // In DesktopMode, window snap can be done with just a single window. In this case, the