summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/Extensions.kt32
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt93
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt13
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt131
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt85
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt123
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt77
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt149
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt205
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt123
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt84
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt83
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt140
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt115
16 files changed, 834 insertions, 634 deletions
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/Extensions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/Extensions.kt
new file mode 100644
index 000000000000..1869d833fbc4
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/Extensions.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ * 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.
+ */
+
+@file:JvmName("Utils")
+package com.android.wm.shell.flicker
+
+import android.app.ActivityTaskManager
+import android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT
+import android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS
+import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
+
+fun removeAllTasksButHome() {
+ val ALL_ACTIVITY_TYPE_BUT_HOME = intArrayOf(
+ ACTIVITY_TYPE_STANDARD, ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS,
+ ACTIVITY_TYPE_UNDEFINED)
+ val atm = ActivityTaskManager.getService()
+ atm.removeRootTasksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME)
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
index 7ec22bb9db1c..cac46fe676b3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
@@ -32,13 +32,12 @@ open class ImeAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
/**
* Opens the IME and wait for it to be displayed
*
- * @param device UIDevice instance to interact with the device
* @param wmHelper Helper used to wait for WindowManager states
*/
@JvmOverloads
- open fun openIME(device: UiDevice, wmHelper: WindowManagerStateHelper? = null) {
+ open fun openIME(wmHelper: WindowManagerStateHelper? = null) {
if (!isTelevision) {
- val editText = device.wait(
+ val editText = uiDevice.wait(
Until.findObject(By.res(getPackage(), "plain_text_input")),
FIND_TIMEOUT)
@@ -47,7 +46,7 @@ open class ImeAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
"was left in an unknown state (e.g. in split screen)"
}
editText.click()
- waitAndAssertIMEShown(device, wmHelper)
+ waitAndAssertIMEShown(uiDevice, wmHelper)
} else {
// If we do the same thing as above - editText.click() - on TV, that's going to force TV
// into the touch mode. We really don't want that.
@@ -69,16 +68,15 @@ open class ImeAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
/**
* Opens the IME and wait for it to be gone
*
- * @param device UIDevice instance to interact with the device
* @param wmHelper Helper used to wait for WindowManager states
*/
@JvmOverloads
- open fun closeIME(device: UiDevice, wmHelper: WindowManagerStateHelper? = null) {
+ open fun closeIME(wmHelper: WindowManagerStateHelper? = null) {
if (!isTelevision) {
- device.pressBack()
+ uiDevice.pressBack()
// Using only the AccessibilityInfo it is not possible to identify if the IME is active
if (wmHelper == null) {
- device.waitForIdle()
+ uiDevice.waitForIdle()
} else {
require(wmHelper.waitImeWindowGone()) { "IME did did not close" }
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
index b90e865de691..111362a93495 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -17,17 +17,20 @@
package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
+import android.graphics.Point
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 com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
import com.android.server.wm.flicker.helpers.closePipWindow
-import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow
import com.android.wm.shell.flicker.pip.tv.isFocusedOrHasFocusedChild
+import com.android.wm.shell.flicker.pip.waitPipWindowGone
+import com.android.wm.shell.flicker.pip.waitPipWindowShown
import com.android.wm.shell.flicker.testapp.Components
-import org.junit.Assert.fail
class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
instrumentation,
@@ -55,6 +58,17 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
}
}
+ /** {@inheritDoc} */
+ override fun launchViaIntent(
+ wmHelper: WindowManagerStateHelper,
+ expectedWindowName: String,
+ action: String?,
+ stringExtras: Map<String, String>
+ ) {
+ super.launchViaIntent(wmHelper, expectedWindowName, action, stringExtras)
+ wmHelper.waitPipWindowShown()
+ }
+
private fun focusOnObject(selector: BySelector): Boolean {
// We expect all the focusable UI elements to be arranged in a way so that it is possible
// to "cycle" over all them by clicking the D-Pad DOWN button, going back up to "the top"
@@ -69,16 +83,12 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
return false
}
- fun clickEnterPipButton() {
+ @JvmOverloads
+ fun clickEnterPipButton(wmHelper: WindowManagerStateHelper? = null) {
clickObject(ENTER_PIP_BUTTON_ID)
- // TODO(b/172321238): remove this check once hasPipWindow is fixed on TVs
- if (!isTelevision) {
- uiDevice.hasPipWindow()
- } else {
- // Simply wait for 3 seconds
- SystemClock.sleep(3_000)
- }
+ // Wait on WMHelper or simply wait for 3 seconds
+ wmHelper?.waitPipWindowShown() ?: SystemClock.sleep(3_000)
}
fun clickStartMediaSessionButton() {
@@ -97,16 +107,75 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
fun stopMedia() = mediaController?.transportControls?.stop()
?: error("No active media session found")
+ @Deprecated("Use PipAppHelper.closePipWindow(wmHelper) instead",
+ ReplaceWith("closePipWindow(wmHelper)"))
fun closePipWindow() {
if (isTelevision) {
uiDevice.closeTvPipWindow()
} else {
uiDevice.closePipWindow()
}
+ }
+
+ /**
+ * 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 exitPipObject = uiDevice.findObject(By.res(SYSTEMUI_PACKAGE, "dismiss"))
+ requireNotNull(exitPipObject) { "PIP window dismiss button not found" }
+ val coordinatesInWindow = exitPipObject.visibleBounds
+ val windowOffset = wmHelper.getWindowRegion(component).bounds
+ val newCoordinates = Point(windowOffset.left + coordinatesInWindow.centerX(),
+ windowOffset.top + coordinatesInWindow.centerY())
+ uiDevice.click(newCoordinates.x, newCoordinates.y)
+ }
+
+ // Wait for animation to complete.
+ wmHelper.waitPipWindowGone()
+ wmHelper.waitForHomeActivityVisible()
+ }
+
+ /**
+ * Click once on the PIP window to expand it
+ */
+ 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
+ uiDevice.click(windowRect.centerX(), windowRect.centerY())
+ // Ensure WindowManagerService wait until all animations have completed
+ wmHelper.waitForAppTransitionIdle()
+ mInstrumentation.uiAutomation.syncInputTransactions()
+ }
- if (!waitUntilClosed()) {
- fail("Couldn't close Pip")
+ /**
+ * Double click on the PIP window to reopen to app
+ */
+ 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
+ uiDevice.click(windowRect.centerX(), windowRect.centerY())
+ uiDevice.click(windowRect.centerX(), windowRect.centerY())
+ wmHelper.waitPipWindowGone()
+ wmHelper.waitForAppTransitionIdle()
}
companion object {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt
index 2015f4941cea..bc42d5ed04ce 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt
@@ -16,11 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.app.ActivityTaskManager
-import android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT
-import android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS
-import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
-import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED
import android.os.SystemClock
import com.android.wm.shell.flicker.NonRotationTestBase
@@ -29,14 +24,6 @@ abstract class AppTestBase(
rotation: Int
) : NonRotationTestBase(rotationName, rotation) {
companion object {
- fun removeAllTasksButHome() {
- val ALL_ACTIVITY_TYPE_BUT_HOME = intArrayOf(
- ACTIVITY_TYPE_STANDARD, ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS,
- ACTIVITY_TYPE_UNDEFINED)
- val atm = ActivityTaskManager.getService()
- atm.removeRootTasksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME)
- }
-
fun waitForAnimationComplete() {
// TODO: UiDevice doesn't have reliable way to wait for the completion of animation.
// Consider to introduce WindowManagerStateHelper to access Activity state.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
index 5a3d18d9feef..a14b46ef7a3d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
@@ -16,21 +16,21 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Presubmit
+import android.os.Bundle
import android.view.Surface
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.dsl.runFlicker
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.wm.shell.flicker.helpers.FixedAppHelper
-import com.android.wm.shell.flicker.helpers.PipAppHelper
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
import org.junit.FixMethodOrder
-import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -39,82 +39,67 @@ import org.junit.runners.Parameterized
* Test Pip launch and exit.
* To run this test: `atest WMShellFlickerTests:EnterExitPipTest`
*/
-@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class EnterExitPipTest(
- rotationName: String,
- rotation: Int
-) : AppTestBase(rotationName, rotation) {
- private val pipApp = PipAppHelper(instrumentation)
- private val testApp = FixedAppHelper(instrumentation)
-
- @Test
- fun testDisplayMetricsPinUnpin() {
- runFlicker(instrumentation) {
- withTestName { "testDisplayMetricsPinUnpin" }
- setup {
- test {
- removeAllTasksButHome()
- device.wakeUpAndGoToHomeScreen()
- pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true"))
- testApp.launchViaIntent()
- waitForAnimationComplete()
- }
- }
- transitions {
- // This will bring PipApp to fullscreen
- pipApp.launchViaIntent()
- waitForAnimationComplete()
- }
- teardown {
- test {
- removeAllTasksButHome()
- }
- }
- assertions {
- val displayBounds = WindowUtils.getDisplayBounds(rotation)
- windowManagerTrace {
- all("pipApp must remain inside visible bounds") {
- coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
- }
- all("Initially shows both app windows then pipApp hides testApp") {
- showsAppWindow(testApp.defaultWindowName)
- .showsAppWindowOnTop(pipApp.defaultWindowName)
- .then()
- .hidesAppWindow(testApp.defaultWindowName)
+ testSpec: FlickerTestRunnerFactory.TestSpec
+) : FlickerTestRunner(testSpec) {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<Array<Any>> {
+ val testApp = FixedAppHelper(instrumentation)
+ val baseConfig = getTransitionLaunch(eachRun = true)
+ val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
+ setup {
+ eachRun {
+ testApp.launchViaIntent(wmHelper)
}
- navBarWindowIsAlwaysVisible()
- statusBarWindowIsAlwaysVisible()
}
- layersTrace {
- all("Initially shows both app layers then pipApp hides testApp") {
- showsLayer(testApp.defaultWindowName)
- .showsLayer(pipApp.defaultWindowName)
- .then()
- .hidesLayer(testApp.defaultWindowName)
- }
- start("testApp covers the fullscreen, pipApp remains inside display") {
- hasVisibleRegion(testApp.defaultWindowName, displayBounds)
- coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
- }
- end("pipApp covers the fullscreen") {
- hasVisibleRegion(pipApp.defaultWindowName, displayBounds)
+ transitions {
+ // This will bring PipApp to fullscreen
+ pipApp.launchViaIntent(wmHelper)
+ }
+ assertions {
+ val displayBounds = WindowUtils.getDisplayBounds(configuration.startRotation)
+ presubmit {
+ windowManagerTrace {
+ all("pipApp must remain inside visible bounds") {
+ coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
+ }
+ all("Initially shows both app windows then pipApp hides testApp") {
+ showsAppWindow(testApp.defaultWindowName)
+ .showsAppWindowOnTop(pipApp.defaultWindowName)
+ .then()
+ .hidesAppWindow(testApp.defaultWindowName)
+ }
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ }
+ layersTrace {
+ all("Initially shows both app layers then pipApp hides testApp") {
+ showsLayer(testApp.defaultWindowName)
+ .showsLayer(pipApp.defaultWindowName)
+ .then()
+ .hidesLayer(testApp.defaultWindowName)
+ }
+ start("testApp covers the fullscreen, pipApp remains inside display") {
+ hasVisibleRegion(testApp.defaultWindowName, displayBounds)
+ coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
+ }
+ end("pipApp covers the fullscreen") {
+ hasVisibleRegion(pipApp.defaultWindowName, displayBounds)
+ }
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ }
}
- navBarLayerIsAlwaysVisible()
- statusBarLayerIsAlwaysVisible()
}
}
- }
- }
-
- companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): Collection<Array<Any>> {
- val supportedRotations = intArrayOf(Surface.ROTATION_0)
- return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, baseConfig,
+ testSpec, supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 5)
}
}
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index af62eb9ae40d..99a40daa027f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,18 +16,13 @@
package com.android.wm.shell.flicker.pip
+import android.os.Bundle
import android.view.Surface
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerTestRunner
import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.closePipWindow
-import com.android.server.wm.flicker.helpers.expandPipWindow
-import com.android.server.wm.flicker.helpers.hasPipWindow
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -35,9 +30,7 @@ import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
-import com.android.wm.shell.flicker.helpers.PipAppHelper
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -50,80 +43,58 @@ import org.junit.runners.Parameterized
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest(bugId = 152738416)
class EnterPipTest(
testSpec: FlickerTestRunnerFactory.TestSpec
) : FlickerTestRunner(testSpec) {
- companion object {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<Array<Any>> {
- val instrumentation = InstrumentationRegistry.getInstrumentation()
- val testApp = PipAppHelper(instrumentation)
- return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
- supportedRotations = listOf(Surface.ROTATION_0)) { configuration ->
- withTestName { buildTestTag("enterPip", testApp, configuration) }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- }
- eachRun {
- device.pressHome()
- testApp.launchViaIntent(wmHelper)
- this.setRotation(configuration.startRotation)
- }
- }
- teardown {
- eachRun {
- if (device.hasPipWindow()) {
- device.closePipWindow()
- }
- testApp.exit()
- this.setRotation(Surface.ROTATION_0)
- }
- test {
- if (device.hasPipWindow()) {
- device.closePipWindow()
- }
- }
- }
- transitions {
- testApp.clickEnterPipButton()
- device.expandPipWindow()
- }
- assertions {
+ val baseConfig = getTransitionLaunch(
+ eachRun = true, stringExtras = emptyMap())
+ val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
+ transitions {
+ pipApp.clickEnterPipButton()
+ pipApp.expandPipWindow(wmHelper)
+ }
+ assertions {
+ presubmit {
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
all("pipWindowBecomesVisible") {
- this.showsAppWindow(testApp.`package`)
- .then()
- .showsAppWindow(PIP_WINDOW_TITLE)
+ this.showsAppWindow(pipApp.defaultWindowName)
}
}
layersTrace {
- navBarLayerIsAlwaysVisible(bugId = 140855415)
statusBarLayerIsAlwaysVisible()
- noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0,
- enabled = false)
- navBarLayerRotatesAndScales(configuration.startRotation,
- Surface.ROTATION_0, bugId = 140855415)
statusBarLayerRotatesScales(configuration.startRotation,
Surface.ROTATION_0)
}
layersTrace {
all("pipLayerBecomesVisible") {
- this.showsLayer(testApp.launcherName)
- .then()
- .showsLayer(PIP_WINDOW_TITLE)
+ this.showsLayer(pipApp.launcherName)
}
}
}
+
+ flaky {
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
+ navBarLayerRotatesAndScales(configuration.startRotation,
+ Surface.ROTATION_0, bugId = 140855415)
+ }
+ }
}
+ }
+
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, baseConfig,
+ testSpec, supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 5)
}
}
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
new file mode 100644
index 000000000000..eaaa2f6390be
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ * 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.view.Surface
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.pip.PipTransitionBase.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
+import com.android.wm.shell.flicker.pip.PipTransitionBase.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
+import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP
+import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip with orientation changes.
+ * To run this test: `atest WMShellFlickerTests:PipOrientationTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class EnterPipToOtherOrientationTest(
+ testSpec: FlickerTestRunnerFactory.TestSpec
+) : FlickerTestRunner(testSpec) {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
+ private val testApp = FixedAppHelper(instrumentation)
+
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
+ supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 5) { configuration ->
+ setupAndTeardown(this, configuration)
+
+ setup {
+ eachRun {
+ // Launch a portrait only app on the fullscreen stack
+ testApp.launchViaIntent(wmHelper, stringExtras = mapOf(
+ EXTRA_FIXED_ORIENTATION to ORIENTATION_PORTRAIT.toString()))
+ // Launch the PiP activity fixed as landscape
+ pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
+ EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString()))
+ }
+ }
+ teardown {
+ eachRun {
+ pipApp.exit()
+ testApp.exit()
+ }
+ }
+ transitions {
+ // Enter PiP, and assert that the PiP is within bounds now that the device is back
+ // in portrait
+ broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
+ wmHelper.waitPipWindowShown()
+ wmHelper.waitForAppTransitionIdle()
+ }
+ assertions {
+ val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
+ val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
+
+ presubmit {
+ windowManagerTrace {
+ all("pipApp window is always on top") {
+ showsAppWindowOnTop(pipApp.defaultWindowName)
+ }
+ start("pipApp window hides testApp") {
+ isInvisible(testApp.defaultWindowName)
+ }
+ end("testApp windows is shown") {
+ isVisible(testApp.defaultWindowName)
+ }
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ }
+
+ layersTrace {
+ start("pipApp layer hides testApp") {
+ hasVisibleRegion(pipApp.defaultWindowName, startingBounds)
+ isInvisible(testApp.defaultWindowName)
+ }
+ }
+ }
+
+ flaky {
+ layersTrace {
+ end("testApp layer covers fullscreen") {
+ hasVisibleRegion(testApp.defaultWindowName, endingBounds)
+ }
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
new file mode 100644
index 000000000000..707d28d9c4c0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ * 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.app.WindowConfiguration
+import android.content.ComponentName
+import com.android.server.wm.flicker.traces.windowmanager.WindowManagerStateSubject
+import com.android.server.wm.traces.common.windowmanager.WindowManagerState
+import com.android.server.wm.traces.parser.toWindowName
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
+import com.google.common.truth.Truth
+
+inline val WindowManagerState.pinnedWindows
+ get() = visibleWindows
+ .filter { it.windowingMode == WindowConfiguration.WINDOWING_MODE_PINNED }
+
+/**
+ * Checks if the state has any window in PIP mode
+ */
+fun WindowManagerState.hasPipWindow(): Boolean = pinnedWindows.isNotEmpty()
+
+/**
+ * Checks that an activity [activity] is in PIP mode
+ */
+fun WindowManagerState.isInPipMode(activity: ComponentName): Boolean {
+ val windowName = activity.toWindowName()
+ return pinnedWindows.any { it.title == windowName }
+}
+
+/**
+ * Asserts that an activity [activity] exists and is in PIP mode
+ */
+fun WindowManagerStateSubject.isInPipMode(
+ activity: ComponentName
+): WindowManagerStateSubject = apply {
+ val windowName = activity.toWindowName()
+ hasWindow(windowName)
+ val pinnedWindows = wmState.pinnedWindows
+ .map { it.title }
+ Truth.assertWithMessage("Window not in PIP mode")
+ .that(pinnedWindows)
+ .contains(windowName)
+}
+
+/**
+ * Waits until the state has a window in PIP mode, i.e., with
+ * windowingMode = WindowConfiguration.WINDOWING_MODE_PINNED
+ */
+fun WindowManagerStateHelper.waitPipWindowShown(): Boolean =
+ waitFor("PIP window shown") {
+ val result = it.wmState.hasPipWindow()
+ result
+ }
+
+/**
+ * Waits until the state doesn't have a window in PIP mode, i.e., with
+ * windowingMode = WindowConfiguration.WINDOWING_MODE_PINNED
+ */
+fun WindowManagerStateHelper.waitPipWindowGone(): Boolean =
+ waitFor("PIP window gone") {
+ val result = !it.wmState.hasPipWindow()
+ result
+ }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index c21b594246b9..7576e24ace19 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -16,21 +16,19 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Presubmit
+import android.os.Bundle
import android.view.Surface
import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.dsl.runWithFlicker
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.closePipWindow
-import com.android.server.wm.flicker.helpers.hasPipWindow
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.startRotation
import com.android.wm.shell.flicker.IME_WINDOW_NAME
import com.android.wm.shell.flicker.helpers.ImeAppHelper
-import com.android.wm.shell.flicker.testapp.Components
import org.junit.FixMethodOrder
-import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -39,114 +37,61 @@ import org.junit.runners.Parameterized
* Test Pip launch.
* To run this test: `atest WMShellFlickerTests:PipKeyboardTest`
*/
-@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipKeyboardTest(
- rotationName: String,
- rotation: Int
-) : PipTestBase(rotationName, rotation) {
- private val keyboardApp = ImeAppHelper(instrumentation)
- private val keyboardComponent = Components.ImeActivity.COMPONENT
- private val helper = WindowManagerStateHelper()
+class PipKeyboardTest(testSpec: FlickerTestRunnerFactory.TestSpec) : FlickerTestRunner(testSpec) {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
+ private const val TAG_IME_VISIBLE = "imeIsVisible"
- private val keyboardScenario: FlickerBuilder
- get() = FlickerBuilder(instrumentation).apply {
- repeat { TEST_REPETITIONS }
- // disable layer tracing
- withLayerTracing { null }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- device.pressHome()
- // launch our target pip app
- testApp.launchViaIntent(wmHelper)
- this.setRotation(rotation)
- testApp.clickEnterPipButton()
- // open an app with an input field and a keyboard
- // UiAutomator doesn't support to launch the multiple Activities in a task.
- // So use launchActivity() for the Keyboard Activity.
- keyboardApp.launchViaIntent()
- helper.waitForAppTransitionIdle()
- helper.waitForFullScreenApp(keyboardComponent)
- }
- }
- teardown {
- test {
- keyboardApp.exit()
-
- if (device.hasPipWindow()) {
- device.closePipWindow()
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val imeApp = ImeAppHelper(instrumentation)
+ val baseConfig = getTransitionLaunch(eachRun = false)
+ val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
+ setup {
+ test {
+ imeApp.launchViaIntent(wmHelper)
+ setRotation(configuration.startRotation)
}
- testApp.exit()
- this.setRotation(Surface.ROTATION_0)
}
- }
- }
-
- /** Ensure the pip window remains visible throughout any keyboard interactions. */
- @Test
- fun pipWindow_doesNotLeaveTheScreen_onKeyboardOpenClose() {
- val testTag = "pipWindow_doesNotLeaveTheScreen_onKeyboardOpenClose"
- runWithFlicker(keyboardScenario) {
- withTestName { testTag }
- transitions {
- // open the soft keyboard
- keyboardApp.openIME(device, wmHelper)
- helper.waitImeWindowShown()
-
- // then close it again
- keyboardApp.closeIME(device, wmHelper)
- helper.waitImeWindowGone()
- }
- assertions {
- windowManagerTrace {
- all("PiP window must remain inside visible bounds") {
- val displayBounds = WindowUtils.getDisplayBounds(rotation)
- coversAtMostRegion(testApp.defaultWindowName, displayBounds)
+ teardown {
+ test {
+ imeApp.exit()
+ setRotation(Surface.ROTATION_0)
}
}
- }
- }
- }
+ transitions {
+ // open the soft keyboard
+ imeApp.openIME(wmHelper)
+ createTag(TAG_IME_VISIBLE)
- /** Ensure the pip window does not obscure the keyboard. */
- @Test
- fun pipWindow_doesNotObscure_keyboard() {
- val testTag = "pipWindow_doesNotObscure_keyboard"
- runWithFlicker(keyboardScenario) {
- withTestName { testTag }
- transitions {
- // open the soft keyboard
- keyboardApp.openIME(device, wmHelper)
- helper.waitImeWindowShown()
- }
- teardown {
- eachRun {
- // close the keyboard
- keyboardApp.closeIME(device, wmHelper)
- helper.waitImeWindowGone()
+ // then close it again
+ imeApp.closeIME(wmHelper)
}
- }
- assertions {
- windowManagerTrace {
- end("imeWindowAboveApp") {
- isAboveWindow(IME_WINDOW_NAME, testApp.defaultWindowName)
+ assertions {
+ presubmit {
+ windowManagerTrace {
+ // Ensure the pip window remains visible throughout
+ // any keyboard interactions
+ all("pipInVisibleBounds") {
+ val displayBounds = WindowUtils.getDisplayBounds(
+ configuration.startRotation)
+ coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
+ }
+ // Ensure that the pip window does not obscure the keyboard
+ tag(TAG_IME_VISIBLE) {
+ isAboveWindow(IME_WINDOW_NAME, pipApp.defaultWindowName)
+ }
+ }
}
}
}
- }
- }
-
- companion object {
- private const val TEST_REPETITIONS = 5
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): Collection<Array<Any>> {
- val supportedRotations = intArrayOf(Surface.ROTATION_0)
- return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
+ baseConfig, testSpec, supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 5)
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index e5790962c025..f10bd7f1e45a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -32,6 +32,7 @@ import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.removeAllTasksButHome
import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
import org.junit.FixMethodOrder
import org.junit.Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt
deleted file mode 100644
index 5e0760ceeda7..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.content.Intent
-import android.platform.test.annotations.Presubmit
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.dsl.runFlicker
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.wm.shell.flicker.helpers.FixedAppHelper
-import com.android.wm.shell.flicker.helpers.PipAppHelper
-import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
-import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_SET_REQUESTED_ORIENTATION
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_PIP_ORIENTATION
-import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
-import org.junit.Assert.assertEquals
-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 with orientation changes.
- * To run this test: `atest WMShellFlickerTests:PipOrientationTest`
- */
-@Presubmit
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipOrientationTest(
- rotationName: String,
- rotation: Int
-) : AppTestBase(rotationName, rotation) {
- // Helper class to process test actions by broadcast.
- private inner class BroadcastActionTrigger {
- private fun createIntentWithAction(broadcastAction: String): Intent {
- return Intent(broadcastAction).setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- }
- fun doAction(broadcastAction: String) {
- instrumentation.getContext().sendBroadcast(createIntentWithAction(broadcastAction))
- }
- fun requestOrientationForPip(orientation: Int) {
- instrumentation.getContext()
- .sendBroadcast(createIntentWithAction(ACTION_SET_REQUESTED_ORIENTATION)
- .putExtra(EXTRA_PIP_ORIENTATION, orientation.toString()))
- }
- }
- private val broadcastActionTrigger = BroadcastActionTrigger()
-
- // Corresponds to ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
- private val ORIENTATION_LANDSCAPE = 0
- // Corresponds to ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
- private val ORIENTATION_PORTRAIT = 1
-
- private val testApp = FixedAppHelper(instrumentation)
- private val pipApp = PipAppHelper(instrumentation)
-
- @Test
- fun testEnterPipToOtherOrientation() {
- runFlicker(instrumentation) {
- withTestName { "testEnterPipToOtherOrientation" }
- setup {
- test {
- removeAllTasksButHome()
- device.wakeUpAndGoToHomeScreen()
- // Launch a portrait only app on the fullscreen stack
- testApp.launchViaIntent(stringExtras = mapOf(
- EXTRA_FIXED_ORIENTATION to ORIENTATION_PORTRAIT.toString()))
- waitForAnimationComplete()
- // Launch the PiP activity fixed as landscape
- pipApp.launchViaIntent(stringExtras = mapOf(
- EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString()))
- waitForAnimationComplete()
- }
- }
- transitions {
- // Enter PiP, and assert that the PiP is within bounds now that the device is back
- // in portrait
- broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
- waitForAnimationComplete()
- }
- teardown {
- test {
- removeAllTasksButHome()
- }
- }
- assertions {
- windowManagerTrace {
- all("pipApp window is always on top") {
- showsAppWindowOnTop(pipApp.defaultWindowName)
- }
- start("pipApp window hides testApp") {
- isInvisible(testApp.defaultWindowName)
- }
- end("testApp windows is shown") {
- isVisible(testApp.defaultWindowName)
- }
- navBarWindowIsAlwaysVisible()
- statusBarWindowIsAlwaysVisible()
- }
- layersTrace {
- val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
- val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
- start("pipApp layer hides testApp") {
- hasVisibleRegion(pipApp.defaultWindowName, startingBounds)
- isInvisible(testApp.defaultWindowName)
- }
- end("testApp layer covers fullscreen", enabled = false) {
- hasVisibleRegion(testApp.defaultWindowName, endingBounds)
- }
- navBarLayerIsAlwaysVisible(bugId = 140855415)
- statusBarLayerIsAlwaysVisible(bugId = 140855415)
- }
- }
- }
- }
-
- @Test
- fun testSetRequestedOrientationWhilePinned() {
- runFlicker(instrumentation) {
- withTestName { "testSetRequestedOrientationWhilePinned" }
- setup {
- test {
- removeAllTasksButHome()
- device.wakeUpAndGoToHomeScreen()
- // Launch the PiP activity fixed as landscape
- pipApp.launchViaIntent(stringExtras = mapOf(
- EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString(),
- EXTRA_ENTER_PIP to "true"))
- waitForAnimationComplete()
- assertEquals(Surface.ROTATION_0, device.displayRotation)
- }
- }
- transitions {
- // Request that the orientation is set to landscape
- broadcastActionTrigger.requestOrientationForPip(ORIENTATION_LANDSCAPE)
-
- // Launch the activity back into fullscreen and ensure that it is now in landscape
- pipApp.launchViaIntent()
- waitForAnimationComplete()
- assertEquals(Surface.ROTATION_90, device.displayRotation)
- }
- teardown {
- test {
- removeAllTasksButHome()
- }
- }
- assertions {
- val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
- val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
- windowManagerTrace {
- start("PIP window must remain inside display") {
- coversAtMostRegion(pipApp.defaultWindowName, startingBounds)
- }
- end("pipApp shows on top") {
- showsAppWindowOnTop(pipApp.defaultWindowName)
- }
- navBarWindowIsAlwaysVisible()
- statusBarWindowIsAlwaysVisible()
- }
- layersTrace {
- start("PIP layer must remain inside display") {
- coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
- }
- end("pipApp layer covers fullscreen") {
- hasVisibleRegion(pipApp.defaultWindowName, endingBounds)
- }
- navBarLayerIsAlwaysVisible(bugId = 140855415)
- statusBarLayerIsAlwaysVisible(bugId = 140855415)
- }
- }
- }
- }
-
- companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): Collection<Array<Any>> {
- val supportedRotations = intArrayOf(Surface.ROTATION_0)
- return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
- }
- }
-} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index a00c5f463a50..adab5e81b32d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -16,21 +16,18 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Presubmit
+import android.os.Bundle
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerTestRunner
import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
import com.android.wm.shell.flicker.helpers.FixedAppHelper
-import com.android.wm.shell.flicker.helpers.PipAppHelper
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
@@ -38,7 +35,6 @@ import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.statusBarLayerRotatesScales
-import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -48,80 +44,77 @@ import org.junit.runners.Parameterized
* Test Pip Stack in bounds after rotations.
* To run this test: `atest WMShellFlickerTests:PipRotationTest`
*/
-@Presubmit
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class PipRotationTest(
testSpec: FlickerTestRunnerFactory.TestSpec
) : FlickerTestRunner(testSpec) {
- companion object {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
- val instrumentation = InstrumentationRegistry.getInstrumentation()
- val testApp = FixedAppHelper(instrumentation)
- val pipApp = PipAppHelper(instrumentation)
- return FlickerTestRunnerFactory.getInstance().buildRotationTest(instrumentation,
- supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)) {
- configuration ->
- withTestName { buildTestTag("PipRotationTest", testApp, configuration) }
- repeat { configuration.repetitions }
- setup {
- test {
- AppTestBase.removeAllTasksButHome()
- device.wakeUpAndGoToHomeScreen()
- pipApp.launchViaIntent(stringExtras = mapOf(
- EXTRA_ENTER_PIP to "true"))
- testApp.launchViaIntent()
- AppTestBase.waitForAnimationComplete()
- }
- eachRun {
- setRotation(configuration.startRotation)
- }
- }
- transitions {
- setRotation(configuration.endRotation)
+ val fixedApp = FixedAppHelper(instrumentation)
+ val baseConfig = getTransitionLaunch(eachRun = false)
+ val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
+ setup {
+ test {
+ fixedApp.launchViaIntent(wmHelper)
+ }
+ eachRun {
+ setRotation(configuration.startRotation)
+ }
+ }
+ transitions {
+ setRotation(configuration.endRotation)
+ }
+ teardown {
+ eachRun {
+ setRotation(Surface.ROTATION_0)
+ }
+ }
+ assertions {
+ val startingBounds = WindowUtils.getDisplayBounds(configuration.startRotation)
+ val endingBounds = WindowUtils.getDisplayBounds(configuration.endRotation)
+
+ presubmit {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
}
- teardown {
- eachRun {
- setRotation(Surface.ROTATION_0)
- }
- test {
- AppTestBase.removeAllTasksButHome()
- }
+
+ layersTrace {
+ noUncoveredRegions(configuration.startRotation,
+ configuration.endRotation, allStates = false)
}
- assertions {
- windowManagerTrace {
- navBarWindowIsAlwaysVisible()
- statusBarWindowIsAlwaysVisible()
- }
- layersTrace {
- navBarLayerIsAlwaysVisible(bugId = 140855415)
- statusBarLayerIsAlwaysVisible(bugId = 140855415)
- noUncoveredRegions(configuration.startRotation,
- configuration.endRotation, allStates = false)
- navBarLayerRotatesAndScales(configuration.startRotation,
- configuration.endRotation, bugId = 140855415)
- statusBarLayerRotatesScales(configuration.startRotation,
- configuration.endRotation, bugId = 140855415)
+ }
+
+ flaky {
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ navBarLayerRotatesAndScales(configuration.startRotation,
+ configuration.endRotation, bugId = 140855415)
+ statusBarLayerRotatesScales(configuration.startRotation,
+ configuration.endRotation, bugId = 140855415)
+
+ start("appLayerRotates_StartingBounds", bugId = 140855415) {
+ hasVisibleRegion(fixedApp.defaultWindowName, startingBounds)
+ coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
}
- layersTrace {
- val startingBounds = WindowUtils.getDisplayBounds(
- configuration.startRotation)
- val endingBounds = WindowUtils.getDisplayBounds(
- configuration.endRotation)
- start("appLayerRotates_StartingBounds", bugId = 140855415) {
- hasVisibleRegion(testApp.defaultWindowName, startingBounds)
- coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
- }
- end("appLayerRotates_EndingBounds", bugId = 140855415) {
- hasVisibleRegion(testApp.defaultWindowName, endingBounds)
- coversAtMostRegion(endingBounds, pipApp.defaultWindowName)
- }
+ end("appLayerRotates_EndingBounds", bugId = 140855415) {
+ hasVisibleRegion(fixedApp.defaultWindowName, endingBounds)
+ coversAtMostRegion(endingBounds, pipApp.defaultWindowName)
}
}
}
+ }
+ }
+
+ return FlickerTestRunnerFactory.getInstance().buildRotationTest(instrumentation,
+ baseConfig, testSpec,
+ supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
+ repetitions = 5)
}
}
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
index 3e7eb134e627..4b826ffd646d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
@@ -16,29 +16,23 @@
package com.android.wm.shell.flicker.pip
+import android.os.Bundle
import android.view.Surface
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerTestRunner
import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.closePipWindow
-import com.android.server.wm.flicker.helpers.expandPipWindow
-import com.android.server.wm.flicker.helpers.hasPipWindow
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.helpers.PipAppHelper
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -51,48 +45,30 @@ import org.junit.runners.Parameterized
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest(bugId = 152738416)
class PipToAppTest(
testSpec: FlickerTestRunnerFactory.TestSpec
) : FlickerTestRunner(testSpec) {
- companion object {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<Array<Any>> {
- val instrumentation = InstrumentationRegistry.getInstrumentation()
- val testApp = PipAppHelper(instrumentation)
- return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
- supportedRotations = listOf(Surface.ROTATION_0)) { configuration ->
- withTestName { buildTestTag("exitPipModeToApp", testApp, configuration) }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- device.pressHome()
- testApp.launchViaIntent(wmHelper)
- }
- eachRun {
- this.setRotation(configuration.startRotation)
- testApp.clickEnterPipButton()
- device.hasPipWindow()
- }
- }
- teardown {
- eachRun {
- this.setRotation(Surface.ROTATION_0)
- }
- test {
- if (device.hasPipWindow()) {
- device.closePipWindow()
- }
- testApp.exit()
- }
+ val baseConfig = getTransitionLaunch(eachRun = true)
+ val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
+ setup {
+ eachRun {
+ this.setRotation(configuration.startRotation)
}
- transitions {
- device.expandPipWindow()
- device.waitForIdle()
+ }
+ teardown {
+ eachRun {
+ this.setRotation(Surface.ROTATION_0)
}
- assertions {
+ }
+ transitions {
+ pipApp.expandPipWindowToApp(wmHelper)
+ }
+ assertions {
+ presubmit {
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
@@ -100,34 +76,42 @@ class PipToAppTest(
all("appReplacesPipWindow") {
this.showsAppWindow(PIP_WINDOW_TITLE)
.then()
- .showsAppWindowOnTop(testApp.launcherName)
+ .showsAppWindowOnTop(pipApp.launcherName)
}
}
layersTrace {
- navBarLayerIsAlwaysVisible(bugId = 140855415)
statusBarLayerIsAlwaysVisible()
- noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0,
- enabled = false)
- navBarLayerRotatesAndScales(configuration.startRotation,
- Surface.ROTATION_0, bugId = 140855415)
statusBarLayerRotatesScales(configuration.startRotation,
Surface.ROTATION_0)
all("appReplacesPipLayer") {
this.showsLayer(PIP_WINDOW_TITLE)
.then()
- .showsLayer(testApp.launcherName)
+ .showsLayer(pipApp.launcherName)
}
}
+ }
+
+ flaky {
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
+ navBarLayerRotatesAndScales(configuration.startRotation,
+ Surface.ROTATION_0, bugId = 140855415)
+ }
eventLog {
focusChanges(
- "NexusLauncherActivity", testApp.launcherName,
+ "NexusLauncherActivity", pipApp.launcherName,
"NexusLauncherActivity", bugId = 151179149)
}
}
}
+ }
+
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, baseConfig,
+ testSpec, supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
index 5d3bc1388686..62e82212b1d1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
@@ -16,28 +16,23 @@
package com.android.wm.shell.flicker.pip
+import android.os.Bundle
import android.view.Surface
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerTestRunner
import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.focusChanges
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.closePipWindow
-import com.android.server.wm.flicker.helpers.hasPipWindow
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
-import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import com.android.wm.shell.flicker.helpers.PipAppHelper
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -50,50 +45,30 @@ import org.junit.runners.Parameterized
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest(bugId = 152738416)
class PipToHomeTest(
testSpec: FlickerTestRunnerFactory.TestSpec
) : FlickerTestRunner(testSpec) {
- companion object {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<Array<Any>> {
- val instrumentation = InstrumentationRegistry.getInstrumentation()
- val testApp = PipAppHelper(instrumentation)
- return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
- supportedRotations = listOf(Surface.ROTATION_0)) { configuration ->
- withTestName { buildTestTag("exitPipModeToApp", testApp, configuration) }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- device.pressHome()
- }
- eachRun {
- testApp.launchViaIntent(wmHelper)
- this.setRotation(configuration.startRotation)
- testApp.clickEnterPipButton()
- device.hasPipWindow()
- }
- }
- teardown {
- eachRun {
- this.setRotation(Surface.ROTATION_0)
- if (device.hasPipWindow()) {
- device.closePipWindow()
- }
- }
- test {
- if (device.hasPipWindow()) {
- device.closePipWindow()
- }
- testApp.exit()
- }
+ val baseConfig = getTransitionLaunch(eachRun = true)
+ val testSpec: FlickerBuilder.(Bundle) -> Unit = { configuration ->
+ setup {
+ eachRun {
+ this.setRotation(configuration.startRotation)
}
- transitions {
- testApp.closePipWindow()
+ }
+ teardown {
+ eachRun {
+ this.setRotation(Surface.ROTATION_0)
}
- assertions {
+ }
+ transitions {
+ pipApp.closePipWindow(wmHelper)
+ }
+ assertions {
+ presubmit {
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
@@ -106,12 +81,7 @@ class PipToHomeTest(
}
layersTrace {
- navBarLayerIsAlwaysVisible(bugId = 140855415)
statusBarLayerIsAlwaysVisible()
- noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0,
- enabled = false)
- navBarLayerRotatesAndScales(configuration.startRotation,
- Surface.ROTATION_0, bugId = 140855415)
statusBarLayerRotatesScales(configuration.startRotation,
Surface.ROTATION_0)
@@ -121,13 +91,28 @@ class PipToHomeTest(
.hidesLayer(PIP_WINDOW_TITLE)
}
}
+ }
+ postsubmit {
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0)
+ navBarLayerRotatesAndScales(configuration.startRotation,
+ Surface.ROTATION_0)
+ }
+ }
+
+ flaky {
eventLog {
- focusChanges(testApp.launcherName, "NexusLauncherActivity",
+ focusChanges(pipApp.launcherName, "NexusLauncherActivity",
bugId = 151179149)
}
}
}
+ }
+
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation, baseConfig,
+ testSpec, supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
}
}
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt
new file mode 100644
index 000000000000..eb7bae160577
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransitionBase.kt
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ * 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.app.Instrumentation
+import android.content.Intent
+import android.os.Bundle
+import android.view.Surface
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.closePipWindow
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.repetitions
+import com.android.wm.shell.flicker.helpers.PipAppHelper
+import com.android.wm.shell.flicker.removeAllTasksButHome
+import com.android.wm.shell.flicker.testapp.Components
+
+abstract class PipTransitionBase(protected val instrumentation: Instrumentation) {
+ // Helper class to process test actions by broadcast.
+ protected class BroadcastActionTrigger(private val instrumentation: Instrumentation) {
+ private fun createIntentWithAction(broadcastAction: String): Intent {
+ return Intent(broadcastAction).setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ }
+
+ fun doAction(broadcastAction: String) {
+ instrumentation.context
+ .sendBroadcast(createIntentWithAction(broadcastAction))
+ }
+
+ fun requestOrientationForPip(orientation: Int) {
+ instrumentation.context.sendBroadcast(
+ createIntentWithAction(Components.PipActivity.ACTION_SET_REQUESTED_ORIENTATION)
+ .putExtra(Components.PipActivity.EXTRA_PIP_ORIENTATION, orientation.toString())
+ )
+ }
+
+ companion object {
+ // Corresponds to ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ @JvmStatic
+ val ORIENTATION_LANDSCAPE = 0
+
+ // Corresponds to ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ @JvmStatic
+ val ORIENTATION_PORTRAIT = 1
+ }
+ }
+
+ protected val pipApp = PipAppHelper(instrumentation)
+ protected val broadcastActionTrigger = BroadcastActionTrigger(instrumentation)
+
+ /**
+ * Gets a configuration that handles basic setup and teardown of pip tests
+ */
+ protected val setupAndTeardown: FlickerBuilder.(Bundle) -> Unit
+ get() = { configuration ->
+ withTestName { buildTestTag(configuration) }
+ repeat { configuration.repetitions }
+ setup {
+ test {
+ removeAllTasksButHome()
+ device.wakeUpAndGoToHomeScreen()
+ }
+ }
+ teardown {
+ eachRun {
+ setRotation(Surface.ROTATION_0)
+ }
+ test {
+ removeAllTasksButHome()
+
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ pipApp.exit()
+ }
+ }
+ }
+
+ /**
+ * Gets a configuration that handles basic setup and teardown of pip tests and that
+ * launches the Pip app for test
+ *
+ * @param eachRun If the pip app should be launched in each run (otherwise only 1x per test)
+ * @param stringExtras Arguments to pass to the PIP launch intent
+ */
+ @JvmOverloads
+ fun getTransitionLaunch(
+ eachRun: Boolean,
+ stringExtras: Map<String, String> = mapOf(Components.PipActivity.EXTRA_ENTER_PIP to "true")
+ ): FlickerBuilder.(Bundle) -> Unit {
+ return { configuration ->
+ setupAndTeardown(this, configuration)
+
+ setup {
+ test {
+ removeAllTasksButHome()
+ if (!eachRun) {
+ pipApp.launchViaIntent(wmHelper, stringExtras = stringExtras)
+ wmHelper.waitPipWindowShown()
+ }
+ }
+ eachRun {
+ if (eachRun) {
+ pipApp.launchViaIntent(wmHelper, stringExtras = stringExtras)
+ wmHelper.waitPipWindowShown()
+ }
+ }
+ }
+ teardown {
+ eachRun {
+ if (eachRun) {
+ pipApp.exit()
+ }
+ }
+ test {
+ if (!eachRun) {
+ pipApp.exit()
+ }
+ removeAllTasksButHome()
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
new file mode 100644
index 000000000000..c01bc94151e9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -0,0 +1,115 @@
+/*
+ * 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.view.Surface
+import androidx.test.filters.RequiresDevice
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.FlickerTestRunner
+import com.android.server.wm.flicker.FlickerTestRunnerFactory
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.pip.PipTransitionBase.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
+import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
+import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
+import org.junit.Assert.assertEquals
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip with orientation changes.
+ * To run this test: `atest WMShellFlickerTests:PipOrientationTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class SetRequestedOrientationWhilePinnedTest(
+ testSpec: FlickerTestRunnerFactory.TestSpec
+) : FlickerTestRunner(testSpec) {
+ companion object : PipTransitionBase(InstrumentationRegistry.getInstrumentation()) {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ return FlickerTestRunnerFactory.getInstance().buildTest(instrumentation,
+ supportedRotations = listOf(Surface.ROTATION_0),
+ repetitions = 1) { configuration ->
+ setupAndTeardown(this, configuration)
+
+ setup {
+ eachRun {
+ // Launch the PiP activity fixed as landscape
+ pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
+ EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString(),
+ EXTRA_ENTER_PIP to "true"))
+ }
+ }
+ teardown {
+ eachRun {
+ pipApp.exit()
+ }
+ }
+ transitions {
+ // Request that the orientation is set to landscape
+ broadcastActionTrigger.requestOrientationForPip(ORIENTATION_LANDSCAPE)
+
+ // Launch the activity back into fullscreen and
+ // ensure that it is now in landscape
+ pipApp.launchViaIntent(wmHelper)
+ wmHelper.waitForFullScreenApp(pipApp.component)
+ wmHelper.waitForRotation(Surface.ROTATION_90)
+ assertEquals(Surface.ROTATION_90, device.displayRotation)
+ }
+ assertions {
+ val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
+ val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
+ presubmit {
+ windowManagerTrace {
+ start("PIP window must remain inside display") {
+ coversAtMostRegion(pipApp.defaultWindowName, startingBounds)
+ }
+ end("pipApp shows on top") {
+ showsAppWindowOnTop(pipApp.defaultWindowName)
+ }
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ }
+ layersTrace {
+ start("PIP layer must remain inside display") {
+ coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
+ }
+ end("pipApp layer covers fullscreen") {
+ hasVisibleRegion(pipApp.defaultWindowName, endingBounds)
+ }
+ }
+ }
+
+ flaky {
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file