Loading libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt +28 −29 Original line number Diff line number Diff line Loading @@ -17,11 +17,14 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation import android.graphics.Rect import android.media.session.MediaController import android.media.session.MediaSessionManager import android.os.SystemClock import androidx.test.uiautomator.By import androidx.test.uiautomator.BySelector import androidx.test.uiautomator.Until import com.android.server.wm.flicker.helpers.FIND_TIMEOUT import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow Loading Loading @@ -113,25 +116,25 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper( } } private fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect { val windowRegion = wmHelper.getWindowRegion(component) require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" } return windowRegion.bounds } /** * Expands the pip window and dismisses it by clicking on the X button. * * Note, currently the View coordinates reported by the accessibility are relative to * the window, so the correct coordinates need to be calculated * * For example, in a PIP window located at Rect(508, 1444 - 1036, 1741), the * dismiss button coordinates are shown as Rect(650, 0 - 782, 132), with center in * Point(716, 66), instead of Point(970, 1403) * * See b/179337864 */ fun closePipWindow(wmHelper: WindowManagerStateHelper) { if (isTelevision) { uiDevice.closeTvPipWindow() } else { expandPipWindow(wmHelper) val windowRect = getWindowRect(wmHelper) uiDevice.click(windowRect.centerX(), windowRect.centerY()) val exitPipObject = uiDevice.findObject(By.res(SYSTEMUI_PACKAGE, "dismiss")) requireNotNull(exitPipObject) { "PIP window dismiss button not found" } ?: error("PIP window dismiss button not found") val dismissButtonBounds = exitPipObject.visibleBounds uiDevice.click(dismissButtonBounds.centerX(), dismissButtonBounds.centerY()) } Loading @@ -142,32 +145,28 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper( } /** * Click once on the PIP window to expand it * Close the pip window by pressing the expand button */ fun expandPipWindow(wmHelper: WindowManagerStateHelper) { val windowRegion = wmHelper.getWindowRegion(component) require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" } val windowRect = windowRegion.bounds fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) { val windowRect = getWindowRect(wmHelper) uiDevice.click(windowRect.centerX(), windowRect.centerY()) // Ensure WindowManagerService wait until all animations have completed wmHelper.waitForAppTransitionIdle() mInstrumentation.uiAutomation.syncInputTransactions() // search and interact with the expand button val expandSelector = By.res(SYSTEMUI_PACKAGE, "expand_button") uiDevice.wait(Until.hasObject(expandSelector), FIND_TIMEOUT) val expandPipObject = uiDevice.findObject(expandSelector) ?: error("PIP window expand button not found") val expandButtonBounds = expandPipObject.visibleBounds uiDevice.click(expandButtonBounds.centerX(), expandButtonBounds.centerY()) wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() } } /** * Double click on the PIP window to reopen to app * Double click on the PIP window to expand it */ fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) { val windowRegion = wmHelper.getWindowRegion(component) require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" } val windowRect = windowRegion.bounds fun doubleClickPipWindow(wmHelper: WindowManagerStateHelper) { val windowRect = getWindowRect(wmHelper) uiDevice.click(windowRect.centerX(), windowRect.centerY()) uiDevice.click(windowRect.centerX(), windowRect.centerY()) wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() } wmHelper.waitForAppTransitionIdle() } Loading libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt +0 −1 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) { get() = buildTransition(eachRun = true, stringExtras = emptyMap()) { transitions { pipApp.clickEnterPipButton(wmHelper) pipApp.expandPipWindow(wmHelper) } } Loading libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt 0 → 100644 +131 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.pip import android.platform.test.annotations.Presubmit import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.traces.parser.toLayerName import com.android.wm.shell.flicker.helpers.FixedAppHelper import org.junit.Test /** * Base class for pip expand tests */ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) { protected val testApp = FixedAppHelper(instrumentation) /** * Checks that the pip app window remains inside the display bounds throughout the whole * animation */ @Presubmit @Test open fun pipAppWindowRemainInsideVisibleBounds() { testSpec.assertWm { coversAtMost(displayBounds, pipApp.component) } } /** * Checks that the pip app layer remains inside the display bounds throughout the whole * animation */ @Presubmit @Test open fun pipAppLayerRemainInsideVisibleBounds() { testSpec.assertLayers { coversAtMost(displayBounds, pipApp.component) } } /** * Checks both app windows are visible at the start of the transition (with [pipApp] on top). * Then, during the transition, [testApp] becomes invisible and [pipApp] remains visible */ @Presubmit @Test open fun showBothAppWindowsThenHidePip() { testSpec.assertWm { // when the activity is STOPPING, sometimes it becomes invisible in an entry before // the window, sometimes in the same entry. This occurs because we log 1x per frame // thus we ignore activity here isAppWindowVisible(testApp.component, ignoreActivity = true) .isAppWindowOnTop(pipApp.component) .then() .isAppWindowInvisible(testApp.component) .isAppWindowVisible(pipApp.component) } } /** * Checks both app layers are visible at the start of the transition. Then, during the * transition, [testApp] becomes invisible and [pipApp] remains visible */ @Presubmit @Test open fun showBothAppLayersThenHidePip() { testSpec.assertLayers { isVisible(testApp.component) .isVisible(pipApp.component) .then() .isInvisible(testApp.component) .isVisible(pipApp.component) } } /** * Checks that the visible region of [testApp] plus the visible region of [pipApp] * cover the full display area at the start of the transition */ @Presubmit @Test open fun testPlusPipAppsCoverFullScreenAtStart() { testSpec.assertLayersStart { val pipRegion = visibleRegion(pipApp.component).region visibleRegion(testApp.component) .plus(pipRegion) .coversExactly(displayBounds) } } /** * Checks that the visible region of [pipApp] covers the full display area at the end of * the transition */ @Presubmit @Test open fun pipAppCoversFullScreenAtEnd() { testSpec.assertLayersEnd { visibleRegion(pipApp.component).coversExactly(displayBounds) } } /** * Checks that the visible region of [pipApp] always expands during the animation */ @Presubmit @Test open fun pipLayerExpands() { val layerName = pipApp.component.toLayerName() testSpec.assertLayers { val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible } pipLayerList.zipWithNext { previous, current -> current.visibleRegion.coversAtLeast(previous.visibleRegion.region) } } } } libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt→libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt +92 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2021 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. Loading @@ -16,98 +16,77 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Postsubmit import android.view.Surface import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.LAUNCHER_COMPONENT import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.startRotation import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test Pip launch. * To run this test: `atest WMShellFlickerTests:PipToAppTest` * Test expanding a pip window back to full screen via the expand button * * To run this test: `atest WMShellFlickerTests:ExitPipViaExpandButtonClickTest` * * Actions: * Launch an app in pip mode [pipApp], * Launch another full screen mode [testApp] * Expand [pipApp] app to full screen by clicking on the pip window and * then on the expand button * * Notes: * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via * [com.android.server.wm.flicker.TransitionRunnerWithRules], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) { @Postsubmit class ExitPipViaExpandButtonClickTest( testSpec: FlickerTestParameter ) : ExitPipToAppTransition(testSpec) { /** * Defines the transition used to run the test */ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit get() = buildTransition(eachRun = true) { configuration -> get() = buildTransition(eachRun = true) { setup { eachRun { this.setRotation(configuration.startRotation) } } teardown { eachRun { this.setRotation(Surface.ROTATION_0) // launch an app behind the pip one testApp.launchViaIntent(wmHelper) } } transitions { // This will bring PipApp to fullscreen pipApp.expandPipWindowToApp(wmHelper) } } @FlakyTest @Test fun appReplacesPipWindow() { testSpec.assertWm { this.invoke("hasPipWindow") { it.isPinned(pipApp.component) } .isAppWindowOnTop(pipApp.component) .then() .invoke("hasNotPipWindow") { it.isNotPinned(pipApp.component) } .isAppWindowOnTop(pipApp.component) } } @FlakyTest @Test fun appReplacesPipLayer() { testSpec.assertLayers { this.isVisible(pipApp.component) .isVisible(LAUNCHER_COMPONENT) .then() .isVisible(pipApp.component) .isInvisible(LAUNCHER_COMPONENT) } } @FlakyTest @Test fun testAppCoversFullScreen() { testSpec.assertLayersStart { visibleRegion(pipApp.component).coversExactly(displayBounds) } } @FlakyTest(bugId = 151179149) @Test fun focusChanges() { testSpec.assertEventLog { this.focusChanges("NexusLauncherActivity", pipApp.launcherName, "NexusLauncherActivity") } } companion object { /** * Creates the test configurations. * * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring * repetitions, screen orientation and navigation modes. */ @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<FlickerTestParameter> { return FlickerTestParameterFactory.getInstance() .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5) return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests( supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5) } } } No newline at end of file libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt→libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt +28 −55 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory Loading @@ -25,7 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.wm.shell.flicker.helpers.FixedAppHelper import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith Loading @@ -33,23 +31,38 @@ import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test Pip launch and exit. * To run this test: `atest WMShellFlickerTests:EnterExitPipTest` * Test expanding a pip window back to full screen via an intent * * To run this test: `atest WMShellFlickerTests:ExitPipViaIntentTest` * * Actions: * Launch an app in pip mode [pipApp], * Launch another full screen mode [testApp] * Expand [pipApp] app to full screen via an intent * * Notes: * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via * [com.android.server.wm.flicker.TransitionRunnerWithRules], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class EnterExitPipTest( testSpec: FlickerTestParameter ) : PipTransition(testSpec) { private val testApp = FixedAppHelper(instrumentation) class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransition(testSpec) { /** * Defines the transition used to run the test */ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit get() = buildTransition(eachRun = true) { setup { eachRun { // launch an app behind the pip one testApp.launchViaIntent(wmHelper) } } Loading @@ -59,57 +72,17 @@ class EnterExitPipTest( } } @Presubmit @Test fun pipAppRemainInsideVisibleBounds() { testSpec.assertWm { coversAtMost(displayBounds, pipApp.component) } } @Postsubmit @Test fun showBothAppWindowsThenHidePip() { testSpec.assertWm { // when the activity is STOPPING, sometimes it becomes invisible in an entry before // the window, sometimes in the same entry. This occurs because we log 1x per frame // thus we ignore activity here isAppWindowVisible(testApp.component, ignoreActivity = true) .isAppWindowOnTop(pipApp.component) .then() .isAppWindowInvisible(testApp.component) } } @Presubmit @Test fun showBothAppLayersThenHidePip() { testSpec.assertLayers { isVisible(testApp.component) .isVisible(pipApp.component) .then() .isInvisible(testApp.component) } } @Presubmit @Test fun testAppCoversFullScreenWithPipOnDisplay() { testSpec.assertLayersStart { visibleRegion(testApp.component).coversExactly(displayBounds) visibleRegion(pipApp.component).coversAtMost(displayBounds) } } @Presubmit @Test fun pipAppCoversFullScreen() { testSpec.assertLayersEnd { visibleRegion(pipApp.component).coversExactly(displayBounds) } } override fun pipLayerExpands() = super.pipLayerExpands() companion object { /** * Creates the test configurations. * * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring * repetitions, screen orientation and navigation modes. */ @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<FlickerTestParameter> { Loading Loading
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt +28 −29 Original line number Diff line number Diff line Loading @@ -17,11 +17,14 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation import android.graphics.Rect import android.media.session.MediaController import android.media.session.MediaSessionManager import android.os.SystemClock import androidx.test.uiautomator.By import androidx.test.uiautomator.BySelector import androidx.test.uiautomator.Until import com.android.server.wm.flicker.helpers.FIND_TIMEOUT import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow Loading Loading @@ -113,25 +116,25 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper( } } private fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect { val windowRegion = wmHelper.getWindowRegion(component) require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" } return windowRegion.bounds } /** * Expands the pip window and dismisses it by clicking on the X button. * * Note, currently the View coordinates reported by the accessibility are relative to * the window, so the correct coordinates need to be calculated * * For example, in a PIP window located at Rect(508, 1444 - 1036, 1741), the * dismiss button coordinates are shown as Rect(650, 0 - 782, 132), with center in * Point(716, 66), instead of Point(970, 1403) * * See b/179337864 */ fun closePipWindow(wmHelper: WindowManagerStateHelper) { if (isTelevision) { uiDevice.closeTvPipWindow() } else { expandPipWindow(wmHelper) val windowRect = getWindowRect(wmHelper) uiDevice.click(windowRect.centerX(), windowRect.centerY()) val exitPipObject = uiDevice.findObject(By.res(SYSTEMUI_PACKAGE, "dismiss")) requireNotNull(exitPipObject) { "PIP window dismiss button not found" } ?: error("PIP window dismiss button not found") val dismissButtonBounds = exitPipObject.visibleBounds uiDevice.click(dismissButtonBounds.centerX(), dismissButtonBounds.centerY()) } Loading @@ -142,32 +145,28 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper( } /** * Click once on the PIP window to expand it * Close the pip window by pressing the expand button */ fun expandPipWindow(wmHelper: WindowManagerStateHelper) { val windowRegion = wmHelper.getWindowRegion(component) require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" } val windowRect = windowRegion.bounds fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) { val windowRect = getWindowRect(wmHelper) uiDevice.click(windowRect.centerX(), windowRect.centerY()) // Ensure WindowManagerService wait until all animations have completed wmHelper.waitForAppTransitionIdle() mInstrumentation.uiAutomation.syncInputTransactions() // search and interact with the expand button val expandSelector = By.res(SYSTEMUI_PACKAGE, "expand_button") uiDevice.wait(Until.hasObject(expandSelector), FIND_TIMEOUT) val expandPipObject = uiDevice.findObject(expandSelector) ?: error("PIP window expand button not found") val expandButtonBounds = expandPipObject.visibleBounds uiDevice.click(expandButtonBounds.centerX(), expandButtonBounds.centerY()) wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() } } /** * Double click on the PIP window to reopen to app * Double click on the PIP window to expand it */ fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) { val windowRegion = wmHelper.getWindowRegion(component) require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" } val windowRect = windowRegion.bounds fun doubleClickPipWindow(wmHelper: WindowManagerStateHelper) { val windowRect = getWindowRect(wmHelper) uiDevice.click(windowRect.centerX(), windowRect.centerY()) uiDevice.click(windowRect.centerX(), windowRect.centerY()) wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() } wmHelper.waitForAppTransitionIdle() } Loading
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt +0 −1 Original line number Diff line number Diff line Loading @@ -64,7 +64,6 @@ class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) { get() = buildTransition(eachRun = true, stringExtras = emptyMap()) { transitions { pipApp.clickEnterPipButton(wmHelper) pipApp.expandPipWindow(wmHelper) } } Loading
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt 0 → 100644 +131 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.pip import android.platform.test.annotations.Presubmit import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.traces.parser.toLayerName import com.android.wm.shell.flicker.helpers.FixedAppHelper import org.junit.Test /** * Base class for pip expand tests */ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) { protected val testApp = FixedAppHelper(instrumentation) /** * Checks that the pip app window remains inside the display bounds throughout the whole * animation */ @Presubmit @Test open fun pipAppWindowRemainInsideVisibleBounds() { testSpec.assertWm { coversAtMost(displayBounds, pipApp.component) } } /** * Checks that the pip app layer remains inside the display bounds throughout the whole * animation */ @Presubmit @Test open fun pipAppLayerRemainInsideVisibleBounds() { testSpec.assertLayers { coversAtMost(displayBounds, pipApp.component) } } /** * Checks both app windows are visible at the start of the transition (with [pipApp] on top). * Then, during the transition, [testApp] becomes invisible and [pipApp] remains visible */ @Presubmit @Test open fun showBothAppWindowsThenHidePip() { testSpec.assertWm { // when the activity is STOPPING, sometimes it becomes invisible in an entry before // the window, sometimes in the same entry. This occurs because we log 1x per frame // thus we ignore activity here isAppWindowVisible(testApp.component, ignoreActivity = true) .isAppWindowOnTop(pipApp.component) .then() .isAppWindowInvisible(testApp.component) .isAppWindowVisible(pipApp.component) } } /** * Checks both app layers are visible at the start of the transition. Then, during the * transition, [testApp] becomes invisible and [pipApp] remains visible */ @Presubmit @Test open fun showBothAppLayersThenHidePip() { testSpec.assertLayers { isVisible(testApp.component) .isVisible(pipApp.component) .then() .isInvisible(testApp.component) .isVisible(pipApp.component) } } /** * Checks that the visible region of [testApp] plus the visible region of [pipApp] * cover the full display area at the start of the transition */ @Presubmit @Test open fun testPlusPipAppsCoverFullScreenAtStart() { testSpec.assertLayersStart { val pipRegion = visibleRegion(pipApp.component).region visibleRegion(testApp.component) .plus(pipRegion) .coversExactly(displayBounds) } } /** * Checks that the visible region of [pipApp] covers the full display area at the end of * the transition */ @Presubmit @Test open fun pipAppCoversFullScreenAtEnd() { testSpec.assertLayersEnd { visibleRegion(pipApp.component).coversExactly(displayBounds) } } /** * Checks that the visible region of [pipApp] always expands during the animation */ @Presubmit @Test open fun pipLayerExpands() { val layerName = pipApp.component.toLayerName() testSpec.assertLayers { val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible } pipLayerList.zipWithNext { previous, current -> current.visibleRegion.coversAtLeast(previous.visibleRegion.region) } } } }
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt→libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt +92 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2021 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. Loading @@ -16,98 +16,77 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Postsubmit import android.view.Surface import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.LAUNCHER_COMPONENT import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.startRotation import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test Pip launch. * To run this test: `atest WMShellFlickerTests:PipToAppTest` * Test expanding a pip window back to full screen via the expand button * * To run this test: `atest WMShellFlickerTests:ExitPipViaExpandButtonClickTest` * * Actions: * Launch an app in pip mode [pipApp], * Launch another full screen mode [testApp] * Expand [pipApp] app to full screen by clicking on the pip window and * then on the expand button * * Notes: * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited [PipTransition] * 2. Part of the test setup occurs automatically via * [com.android.server.wm.flicker.TransitionRunnerWithRules], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) { @Postsubmit class ExitPipViaExpandButtonClickTest( testSpec: FlickerTestParameter ) : ExitPipToAppTransition(testSpec) { /** * Defines the transition used to run the test */ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit get() = buildTransition(eachRun = true) { configuration -> get() = buildTransition(eachRun = true) { setup { eachRun { this.setRotation(configuration.startRotation) } } teardown { eachRun { this.setRotation(Surface.ROTATION_0) // launch an app behind the pip one testApp.launchViaIntent(wmHelper) } } transitions { // This will bring PipApp to fullscreen pipApp.expandPipWindowToApp(wmHelper) } } @FlakyTest @Test fun appReplacesPipWindow() { testSpec.assertWm { this.invoke("hasPipWindow") { it.isPinned(pipApp.component) } .isAppWindowOnTop(pipApp.component) .then() .invoke("hasNotPipWindow") { it.isNotPinned(pipApp.component) } .isAppWindowOnTop(pipApp.component) } } @FlakyTest @Test fun appReplacesPipLayer() { testSpec.assertLayers { this.isVisible(pipApp.component) .isVisible(LAUNCHER_COMPONENT) .then() .isVisible(pipApp.component) .isInvisible(LAUNCHER_COMPONENT) } } @FlakyTest @Test fun testAppCoversFullScreen() { testSpec.assertLayersStart { visibleRegion(pipApp.component).coversExactly(displayBounds) } } @FlakyTest(bugId = 151179149) @Test fun focusChanges() { testSpec.assertEventLog { this.focusChanges("NexusLauncherActivity", pipApp.launcherName, "NexusLauncherActivity") } } companion object { /** * Creates the test configurations. * * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring * repetitions, screen orientation and navigation modes. */ @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<FlickerTestParameter> { return FlickerTestParameterFactory.getInstance() .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5) return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests( supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5) } } } No newline at end of file
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt→libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt +28 −55 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.pip import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory Loading @@ -25,7 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.wm.shell.flicker.helpers.FixedAppHelper import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith Loading @@ -33,23 +31,38 @@ import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** * Test Pip launch and exit. * To run this test: `atest WMShellFlickerTests:EnterExitPipTest` * Test expanding a pip window back to full screen via an intent * * To run this test: `atest WMShellFlickerTests:ExitPipViaIntentTest` * * Actions: * Launch an app in pip mode [pipApp], * Launch another full screen mode [testApp] * Expand [pipApp] app to full screen via an intent * * Notes: * 1. Some default assertions (e.g., nav bar, status bar and screen covered) * are inherited from [PipTransition] * 2. Part of the test setup occurs automatically via * [com.android.server.wm.flicker.TransitionRunnerWithRules], * including configuring navigation mode, initial orientation and ensuring no * apps are running before setup */ @RequiresDevice @RunWith(Parameterized::class) @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class EnterExitPipTest( testSpec: FlickerTestParameter ) : PipTransition(testSpec) { private val testApp = FixedAppHelper(instrumentation) class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransition(testSpec) { /** * Defines the transition used to run the test */ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit get() = buildTransition(eachRun = true) { setup { eachRun { // launch an app behind the pip one testApp.launchViaIntent(wmHelper) } } Loading @@ -59,57 +72,17 @@ class EnterExitPipTest( } } @Presubmit @Test fun pipAppRemainInsideVisibleBounds() { testSpec.assertWm { coversAtMost(displayBounds, pipApp.component) } } @Postsubmit @Test fun showBothAppWindowsThenHidePip() { testSpec.assertWm { // when the activity is STOPPING, sometimes it becomes invisible in an entry before // the window, sometimes in the same entry. This occurs because we log 1x per frame // thus we ignore activity here isAppWindowVisible(testApp.component, ignoreActivity = true) .isAppWindowOnTop(pipApp.component) .then() .isAppWindowInvisible(testApp.component) } } @Presubmit @Test fun showBothAppLayersThenHidePip() { testSpec.assertLayers { isVisible(testApp.component) .isVisible(pipApp.component) .then() .isInvisible(testApp.component) } } @Presubmit @Test fun testAppCoversFullScreenWithPipOnDisplay() { testSpec.assertLayersStart { visibleRegion(testApp.component).coversExactly(displayBounds) visibleRegion(pipApp.component).coversAtMost(displayBounds) } } @Presubmit @Test fun pipAppCoversFullScreen() { testSpec.assertLayersEnd { visibleRegion(pipApp.component).coversExactly(displayBounds) } } override fun pipLayerExpands() = super.pipLayerExpands() companion object { /** * Creates the test configurations. * * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring * repetitions, screen orientation and navigation modes. */ @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): List<FlickerTestParameter> { Loading