[DO NOT MERGE] Sync flicker from master to sc-v2
Flicker on master diverged form sc-v2, to make it easier to debug flicker issues on sc-v2, push the current version of flicker into sc-v2 Test: atest FlickerTests WMShellFlickerTests Bug: 188792659 Change-Id: I1c832bf32214b12ba4b708bccfc95cf259324844
This commit is contained in:
@@ -41,9 +41,9 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
class ImeTracingServerImpl extends ImeTracing {
|
||||
private static final String TRACE_DIRNAME = "/data/misc/wmtrace/";
|
||||
private static final String TRACE_FILENAME_CLIENTS = "ime_trace_clients.pb";
|
||||
private static final String TRACE_FILENAME_IMS = "ime_trace_service.pb";
|
||||
private static final String TRACE_FILENAME_IMMS = "ime_trace_managerservice.pb";
|
||||
private static final String TRACE_FILENAME_CLIENTS = "ime_trace_clients.winscope";
|
||||
private static final String TRACE_FILENAME_IMS = "ime_trace_service.winscope";
|
||||
private static final String TRACE_FILENAME_IMMS = "ime_trace_managerservice.winscope";
|
||||
private static final int BUFFER_CAPACITY = 4096 * 1024;
|
||||
|
||||
// Needed for winscope to auto-detect the dump type. Explained further in
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.io.File;
|
||||
*/
|
||||
public class ProtoLogImpl extends BaseProtoLogImpl {
|
||||
private static final int BUFFER_CAPACITY = 1024 * 1024;
|
||||
private static final String LOG_FILENAME = "/data/misc/wmtrace/wm_log.pb";
|
||||
private static final String LOG_FILENAME = "/data/misc/wmtrace/wm_log.winscope";
|
||||
private static final String VIEWER_CONFIG_FILENAME = "/system/etc/protolog.conf.json.gz";
|
||||
|
||||
private static ProtoLogImpl sServiceInstance = null;
|
||||
|
||||
@@ -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
|
||||
@@ -85,6 +88,10 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
|
||||
|
||||
// Wait on WMHelper or simply wait for 3 seconds
|
||||
wmHelper?.waitFor("hasPipWindow") { it.wmState.hasPipWindow() } ?: SystemClock.sleep(3_000)
|
||||
// when entering pip, the dismiss button is visible at the start. to ensure the pip
|
||||
// animation is complete, wait until the pip dismiss button is no longer visible.
|
||||
// b/176822698: dismiss-only state will be removed in the future
|
||||
uiDevice.wait(Until.gone(By.res(SYSTEMUI_PACKAGE, "dismiss")), FIND_TIMEOUT)
|
||||
}
|
||||
|
||||
fun clickStartMediaSessionButton() {
|
||||
@@ -113,25 +120,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())
|
||||
}
|
||||
@@ -142,32 +149,29 @@ 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
|
||||
// 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() }
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
mInstrumentation.uiAutomation.syncInputTransactions()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.wm.shell.flicker.legacysplitscreen
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.view.Surface
|
||||
import androidx.test.filters.FlakyTest
|
||||
@@ -113,7 +112,7 @@ class ExitPrimarySplitScreenShowSecondaryFullscreen(
|
||||
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
|
||||
super.visibleLayersShownMoreThanOneConsecutiveEntry()
|
||||
|
||||
@Postsubmit
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
|
||||
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
|
||||
|
||||
@@ -104,7 +104,7 @@ class LegacySplitScreenToLauncher(
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.endRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.android.server.wm.flicker.annotation.Group2
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.entireScreenCovered
|
||||
import com.android.server.wm.flicker.helpers.launchSplitScreen
|
||||
import com.android.server.wm.flicker.startRotation
|
||||
import com.android.server.wm.flicker.statusBarLayerIsVisible
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
|
||||
import com.android.wm.shell.flicker.appPairsDividerBecomesVisible
|
||||
@@ -77,7 +76,7 @@ class OpenAppToLegacySplitScreen(
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -129,7 +129,7 @@ class ResizeLegacySplitScreen(
|
||||
fun statusBarLayerIsVisible() = testSpec.statusBarLayerIsVisible()
|
||||
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.endRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Test
|
||||
fun navBarLayerRotatesAndScales() =
|
||||
|
||||
@@ -23,8 +23,10 @@ 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.traces.parser.toLayerName
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -32,8 +34,21 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test Pip launch.
|
||||
* Test entering pip from an app by interacting with the app UI
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:EnterPipTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch an app in full screen
|
||||
* Press an "enter pip" button to put [pipApp] in pip mode
|
||||
*
|
||||
* 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)
|
||||
@@ -41,14 +56,19 @@ import org.junit.runners.Parameterized
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group3
|
||||
class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = true, stringExtras = emptyMap()) {
|
||||
transitions {
|
||||
pipApp.clickEnterPipButton(wmHelper)
|
||||
pipApp.expandPipWindow(wmHelper)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] window remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAppWindowAlwaysVisible() {
|
||||
@@ -57,6 +77,9 @@ class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] layer remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAppLayerAlwaysVisible() {
|
||||
@@ -65,19 +88,89 @@ class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
}
|
||||
}
|
||||
|
||||
@FlakyTest
|
||||
/**
|
||||
* Checks that the pip app window remains inside the display bounds throughout the whole
|
||||
* animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipWindowBecomesVisible() {
|
||||
fun pipWindowRemainInsideVisibleBounds() {
|
||||
testSpec.assertWm {
|
||||
invoke("pipWindowIsNotVisible") {
|
||||
verify("Has no pip window").that(it.wmState.hasPipWindow()).isTrue()
|
||||
}.then().invoke("pipWindowIsVisible") {
|
||||
verify("Has pip window").that(it.wmState.hasPipWindow()).isTrue()
|
||||
coversAtMost(displayBounds, pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the pip app layer remains inside the display bounds throughout the whole
|
||||
* animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerRemainInsideVisibleBounds() {
|
||||
testSpec.assertLayers {
|
||||
coversAtMost(displayBounds, pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the visible region of [pipApp] always reduces during the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerReduces() {
|
||||
val layerName = pipApp.component.toLayerName()
|
||||
testSpec.assertLayers {
|
||||
val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible }
|
||||
pipLayerList.zipWithNext { previous, current ->
|
||||
current.visibleRegion.coversAtMost(previous.visibleRegion.region)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [pipApp] window becomes pinned
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipWindowBecomesPinned() {
|
||||
testSpec.assertWm {
|
||||
invoke("pipWindowIsNotPinned") { it.isNotPinned(pipApp.component) }
|
||||
.then()
|
||||
.invoke("pipWindowIsPinned") { it.isPinned(pipApp.component) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [LAUNCHER_COMPONENT] layer remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun launcherLayerBecomesVisible() {
|
||||
testSpec.assertLayers {
|
||||
isInvisible(LAUNCHER_COMPONENT)
|
||||
.then()
|
||||
.isVisible(LAUNCHER_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the focus doesn't change during the animation
|
||||
*/
|
||||
@FlakyTest
|
||||
@Test
|
||||
fun focusDoesNotChange() {
|
||||
testSpec.assertEventLog {
|
||||
this.focusDoesNotChange()
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
|
||||
@@ -25,7 +25,11 @@ 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.server.wm.flicker.entireScreenCovered
|
||||
import com.android.server.wm.flicker.helpers.WindowUtils
|
||||
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
|
||||
import com.android.server.wm.flicker.statusBarLayerRotatesScales
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
|
||||
import com.android.wm.shell.flicker.helpers.FixedAppHelper
|
||||
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
|
||||
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
|
||||
@@ -38,8 +42,22 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test Pip with orientation changes.
|
||||
* To run this test: `atest WMShellFlickerTests:PipOrientationTest`
|
||||
* Test entering pip while changing orientation (from app in landscape to pip window in portrait)
|
||||
*
|
||||
* To run this test: `atest EnterPipToOtherOrientationTest:EnterPipToOtherOrientationTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch [testApp] on a fixed portrait orientation
|
||||
* Launch [pipApp] on a fixed landscape orientation
|
||||
* Broadcast action [ACTION_ENTER_PIP] to enter pip mode
|
||||
*
|
||||
* 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)
|
||||
@@ -53,6 +71,9 @@ class EnterPipToOtherOrientationTest(
|
||||
private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
|
||||
private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
|
||||
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = { configuration ->
|
||||
setupAndTeardown(this, configuration)
|
||||
@@ -79,21 +100,41 @@ class EnterPipToOtherOrientationTest(
|
||||
broadcastActionTrigger.doAction(ACTION_ENTER_PIP)
|
||||
wmHelper.waitFor { it.wmState.hasPipWindow() }
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
// during rotation the status bar becomes invisible and reappears at the end
|
||||
wmHelper.waitForNavBarStatusBarVisible()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the [WindowManagerStateHelper.NAV_BAR_COMPONENT] has the correct position at
|
||||
* the start and end of the transition
|
||||
*/
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
||||
override fun navBarLayerRotatesAndScales() =
|
||||
testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_90, Surface.ROTATION_0)
|
||||
|
||||
@FlakyTest
|
||||
/**
|
||||
* Checks that the [WindowManagerStateHelper.STATUS_BAR_COMPONENT] has the correct position at
|
||||
* the start and end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
||||
override fun statusBarLayerRotatesScales() =
|
||||
testSpec.statusBarLayerRotatesScales(Surface.ROTATION_90, Surface.ROTATION_0)
|
||||
|
||||
@FlakyTest
|
||||
/**
|
||||
* Checks that all parts of the screen are covered at the start and end of the transition
|
||||
*
|
||||
* TODO b/197726599 Prevents all states from being checked
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun entireScreenCovered() = super.entireScreenCovered()
|
||||
override fun entireScreenCovered() = testSpec.entireScreenCovered(allStates = false)
|
||||
|
||||
/**
|
||||
* Checks [pipApp] window remains visible and on top throughout the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAppWindowIsAlwaysOnTop() {
|
||||
@@ -102,40 +143,84 @@ class EnterPipToOtherOrientationTest(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] window is not visible at the start
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAppHidesTestApp() {
|
||||
fun testAppWindowInvisibleOnStart() {
|
||||
testSpec.assertWmStart {
|
||||
isInvisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] window is visible at the end
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun testAppWindowIsVisible() {
|
||||
fun testAppWindowVisibleOnEnd() {
|
||||
testSpec.assertWmEnd {
|
||||
isVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] layer is not visible at the start
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAppLayerHidesTestApp() {
|
||||
fun testAppLayerInvisibleOnStart() {
|
||||
testSpec.assertLayersStart {
|
||||
visibleRegion(pipApp.component).coversExactly(startingBounds)
|
||||
isInvisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] layer is visible at the end
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun testAppLayerCoversFullScreen() {
|
||||
fun testAppLayerVisibleOnEnd() {
|
||||
testSpec.assertLayersEnd {
|
||||
visibleRegion(testApp.component).coversExactly(endingBounds)
|
||||
isVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the visible region of [pipApp] covers the full display area at the start of
|
||||
* the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAppLayerCoversFullScreenOnStart() {
|
||||
testSpec.assertLayersStart {
|
||||
visibleRegion(pipApp.component).coversExactly(startingBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the visible region of [testApp] plus the visible region of [pipApp]
|
||||
* cover the full display area at the end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun testAppPlusPipLayerCoversFullScreenOnEnd() {
|
||||
testSpec.assertLayersEnd {
|
||||
val pipRegion = visibleRegion(pipApp.component).region
|
||||
visibleRegion(testApp.component)
|
||||
.plus(pipRegion)
|
||||
.coversExactly(endingBounds)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||
* repetitions, screen orientation and navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,16 @@ import android.platform.test.annotations.Presubmit
|
||||
import android.view.Surface
|
||||
import androidx.test.filters.FlakyTest
|
||||
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.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.helpers.setRotation
|
||||
import com.android.server.wm.flicker.startRotation
|
||||
import org.junit.Test
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
/**
|
||||
* Base class for exiting pip (closing pip window) without returning to the app
|
||||
*/
|
||||
abstract class ExitPipTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = true) { configuration ->
|
||||
setup {
|
||||
@@ -43,16 +44,28 @@ abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransitio
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [pipApp] window is pinned and visible at the start and then becomes
|
||||
* unpinned and invisible at the same moment, and remains unpinned and invisible
|
||||
* until the end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipWindowBecomesInvisible() {
|
||||
testSpec.assertWm {
|
||||
this.invoke("hasPipWindow") { it.isPinned(pipApp.component) }
|
||||
.then()
|
||||
.isAppWindowInvisible(pipApp.component)
|
||||
this.invoke("hasPipWindow") {
|
||||
it.isPinned(pipApp.component).isVisible(pipApp.component)
|
||||
}.then().invoke("!hasPipWindow") {
|
||||
it.isNotPinned(pipApp.component).isInvisible(pipApp.component)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [pipApp] and [LAUNCHER_COMPONENT] layers are visible at the start
|
||||
* of the transition. Then [pipApp] layer becomes invisible, and remains invisible
|
||||
* until the end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipLayerBecomesInvisible() {
|
||||
@@ -65,6 +78,10 @@ abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransitio
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the focus changes between the [pipApp] window and the launcher when
|
||||
* closing the pip window
|
||||
*/
|
||||
@FlakyTest(bugId = 151179149)
|
||||
@Test
|
||||
open fun focusChanges() {
|
||||
@@ -72,14 +89,4 @@ abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransitio
|
||||
this.focusChanges(pipApp.launcherName, "NexusLauncherActivity")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): List<FlickerTestParameter> {
|
||||
return FlickerTestParameterFactory.getInstance()
|
||||
.getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
|
||||
repetitions = 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 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.annotation.Group3
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.traces.parser.toWindowName
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* 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 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) {
|
||||
setup {
|
||||
eachRun {
|
||||
// launch an app behind the pip one
|
||||
testApp.launchViaIntent(wmHelper)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
// This will bring PipApp to fullscreen
|
||||
pipApp.expandPipWindowToApp(wmHelper)
|
||||
// Wait until the other app is no longer visible
|
||||
wmHelper.waitForSurfaceAppeared(testApp.component.toWindowName())
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,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
|
||||
@@ -25,91 +23,63 @@ 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 com.android.server.wm.traces.parser.toWindowName
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
// This will bring PipApp to fullscreen
|
||||
pipApp.launchViaIntent(wmHelper)
|
||||
// Wait until the other app is no longer visible
|
||||
wmHelper.waitForSurfaceAppeared(testApp.component.toWindowName())
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.android.wm.shell.flicker.pip
|
||||
|
||||
import androidx.test.filters.FlakyTest
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.view.Surface
|
||||
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.annotation.Group3
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import org.junit.FixMethodOrder
|
||||
@@ -29,15 +31,29 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test Pip launch.
|
||||
* To run this test: `atest WMShellFlickerTests:PipCloseWithDismissButton`
|
||||
* Test closing a pip window via the dismiss button
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:ExitPipWithDismissButtonTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch an app in pip mode [pipApp],
|
||||
* Click on the pip window
|
||||
* Click on dismiss button and wait window disappear
|
||||
*
|
||||
* 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 PipCloseWithDismissButtonTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
|
||||
class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTransition(testSpec) {
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = {
|
||||
super.transition(this, it)
|
||||
@@ -46,11 +62,27 @@ class PipCloseWithDismissButtonTest(testSpec: FlickerTestParameter) : PipCloseTr
|
||||
}
|
||||
}
|
||||
|
||||
@FlakyTest
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun pipLayerBecomesInvisible() = super.pipLayerBecomesInvisible()
|
||||
|
||||
@FlakyTest
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun pipWindowBecomesInvisible() = super.pipWindowBecomesInvisible()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ 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.annotation.Group3
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.startRotation
|
||||
@@ -33,24 +34,40 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test Pip launch.
|
||||
* To run this test: `atest WMShellFlickerTests:PipCloseWithSwipe`
|
||||
* Test closing a pip window by swiping it to the bottom-center of the screen
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:ExitPipWithSwipeDownTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch an app in pip mode [pipApp],
|
||||
* Swipe the pip window to the bottom-center of the screen and wait it disappear
|
||||
*
|
||||
* 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 PipCloseWithSwipeTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
|
||||
class ExitPipWithSwipeDownTest(testSpec: FlickerTestParameter) : ExitPipTransition(testSpec) {
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = {
|
||||
super.transition(this, it)
|
||||
get() = { args ->
|
||||
super.transition(this, args)
|
||||
transitions {
|
||||
val pipRegion = wmHelper.getWindowRegion(pipApp.component).bounds
|
||||
val pipCenterX = pipRegion.centerX()
|
||||
val pipCenterY = pipRegion.centerY()
|
||||
val displayCenterX = device.displayWidth / 2
|
||||
device.swipe(pipCenterX, pipCenterY, displayCenterX, device.displayHeight, 5)
|
||||
device.swipe(pipCenterX, pipCenterY, displayCenterX, device.displayHeight, 10)
|
||||
wmHelper.waitFor("!hasPipWindow") { !it.wmState.hasPipWindow() }
|
||||
wmHelper.waitForWindowSurfaceDisappeared(pipApp.component)
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,4 +107,20 @@ class PipCloseWithSwipeTest(testSpec: FlickerTestParameter) : PipCloseTransition
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
||||
|
||||
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 = 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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.Postsubmit
|
||||
import android.platform.test.annotations.Presubmit
|
||||
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.traces.parser.toLayerName
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test expanding a pip window by double clicking it
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:ExpandPipOnDoubleClickTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch an app in pip mode [pipApp],
|
||||
* Expand [pipApp] app to its maximum pip size by double clicking on it
|
||||
*
|
||||
* 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 ExpandPipOnDoubleClickTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = true) {
|
||||
transitions {
|
||||
pipApp.doubleClickPipWindow(wmHelper)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the pip app window remains inside the display bounds throughout the whole
|
||||
* animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipWindowRemainInsideVisibleBounds() {
|
||||
testSpec.assertWm {
|
||||
coversAtMost(displayBounds, pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the pip app layer remains inside the display bounds throughout the whole
|
||||
* animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerRemainInsideVisibleBounds() {
|
||||
testSpec.assertLayers {
|
||||
coversAtMost(displayBounds, pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] window remains visible throughout the animation
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun pipWindowIsAlwaysVisible() {
|
||||
testSpec.assertWm {
|
||||
isAppWindowVisible(pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] layer remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerIsAlwaysVisible() {
|
||||
testSpec.assertLayers {
|
||||
isVisible(pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the visible region of [pipApp] always expands during the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] window remains pinned throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun windowIsAlwaysPinned() {
|
||||
testSpec.assertWm {
|
||||
this.invoke("hasPipWindow") { it.isPinned(pipApp.component) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] layer remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun launcherIsAlwaysVisible() {
|
||||
testSpec.assertLayers {
|
||||
isVisible(LAUNCHER_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the focus doesn't change between windows during the transition
|
||||
*/
|
||||
@FlakyTest
|
||||
@Test
|
||||
fun focusDoesNotChange() {
|
||||
testSpec.assertEventLog {
|
||||
this.focusDoesNotChange()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 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.annotation.Group3
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.traces.RegionSubject
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test Pip movement with Launcher shelf height change (decrease).
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:MovePipDownShelfHeightChangeTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch [pipApp] in pip mode
|
||||
* Launch [testApp]
|
||||
* Press home
|
||||
* Check if pip window moves down (visually)
|
||||
*
|
||||
* 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 MovePipDownShelfHeightChangeTest(
|
||||
testSpec: FlickerTestParameter
|
||||
) : MovePipShelfHeightTransition(testSpec) {
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = false) {
|
||||
teardown {
|
||||
eachRun {
|
||||
testApp.launchViaIntent(wmHelper)
|
||||
}
|
||||
test {
|
||||
testApp.exit(wmHelper)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
taplInstrumentation.pressHome()
|
||||
}
|
||||
}
|
||||
|
||||
override fun assertRegionMovement(previous: RegionSubject, current: RegionSubject) {
|
||||
current.isHigherOrEqual(previous.region)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.platform.test.annotations.Presubmit
|
||||
import com.android.launcher3.tapl.LauncherInstrumentation
|
||||
import com.android.server.wm.flicker.FlickerTestParameter
|
||||
import com.android.server.wm.flicker.traces.RegionSubject
|
||||
import com.android.server.wm.traces.parser.toLayerName
|
||||
import com.android.server.wm.traces.parser.toWindowName
|
||||
import com.android.wm.shell.flicker.helpers.FixedAppHelper
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Base class for pip tests with Launcher shelf height change
|
||||
*/
|
||||
abstract class MovePipShelfHeightTransition(
|
||||
testSpec: FlickerTestParameter
|
||||
) : PipTransition(testSpec) {
|
||||
protected val taplInstrumentation = LauncherInstrumentation()
|
||||
protected val testApp = FixedAppHelper(instrumentation)
|
||||
|
||||
/**
|
||||
* Checks if the window movement direction is valid
|
||||
*/
|
||||
protected abstract fun assertRegionMovement(previous: RegionSubject, current: RegionSubject)
|
||||
|
||||
/**
|
||||
* Checks [pipApp] window remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipWindowIsAlwaysVisible() {
|
||||
testSpec.assertWm {
|
||||
isAppWindowVisible(pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks [pipApp] layer remains visible throughout the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipLayerIsAlwaysVisible() {
|
||||
testSpec.assertLayers {
|
||||
isVisible(pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the pip app window remains inside the display bounds throughout the whole
|
||||
* animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipWindowRemainInsideVisibleBounds() {
|
||||
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 pipLayerRemainInsideVisibleBounds() {
|
||||
testSpec.assertLayers {
|
||||
coversAtMost(displayBounds, pipApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the visible region of [pipApp] always moves in the correct direction
|
||||
* during the animation.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipWindowMoves() {
|
||||
val windowName = pipApp.component.toWindowName()
|
||||
testSpec.assertWm {
|
||||
val pipWindowList = this.windowStates { it.name.contains(windowName) && it.isVisible }
|
||||
pipWindowList.zipWithNext { previous, current ->
|
||||
assertRegionMovement(previous.frame, current.frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the visible region of [pipApp] always moves up during the animation
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun pipLayerMoves() {
|
||||
val layerName = pipApp.component.toLayerName()
|
||||
testSpec.assertLayers {
|
||||
val pipLayerList = this.layers { it.name.contains(layerName) && it.isVisible }
|
||||
pipLayerList.zipWithNext { previous, current ->
|
||||
assertRegionMovement(previous.visibleRegion, current.visibleRegion)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,36 +16,49 @@
|
||||
|
||||
package com.android.wm.shell.flicker.pip
|
||||
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.view.Surface
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import com.android.launcher3.tapl.LauncherInstrumentation
|
||||
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.annotation.Group3
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.wm.shell.flicker.helpers.FixedAppHelper
|
||||
import com.google.common.truth.Truth
|
||||
import com.android.server.wm.flicker.traces.RegionSubject
|
||||
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 movement with Launcher shelf height change.
|
||||
* To run this test: `atest WMShellFlickerTests:PipShelfHeightTest`
|
||||
* Test Pip movement with Launcher shelf height change (increase).
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:MovePipUpShelfHeightChangeTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch [pipApp] in pip mode
|
||||
* Press home
|
||||
* Launch [testApp]
|
||||
* Check if pip window moves up (visually)
|
||||
*
|
||||
* 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 PipShelfHeightTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
private val taplInstrumentation = LauncherInstrumentation()
|
||||
private val testApp = FixedAppHelper(instrumentation)
|
||||
|
||||
class MovePipUpShelfHeightChangeTest(
|
||||
testSpec: FlickerTestParameter
|
||||
) : MovePipShelfHeightTransition(testSpec) {
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = false) {
|
||||
teardown {
|
||||
@@ -61,33 +74,17 @@ class PipShelfHeightTest(testSpec: FlickerTestParameter) : PipTransition(testSpe
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipAlwaysVisible() = testSpec.assertWm { this.isAppWindowVisible(pipApp.component) }
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerInsideDisplay() {
|
||||
testSpec.assertLayersStart {
|
||||
visibleRegion(pipApp.component).coversAtMost(displayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipWindowMovesUp() = testSpec.assertWmEnd {
|
||||
val initialState = this.trace?.first()?.wmState
|
||||
?: error("Trace should not be empty")
|
||||
val startPos = initialState.pinnedWindows.first().frame
|
||||
val currPos = this.wmState.pinnedWindows.first().frame
|
||||
val subject = Truth.assertWithMessage("Pip should have moved up")
|
||||
subject.that(currPos.top).isGreaterThan(startPos.top)
|
||||
subject.that(currPos.bottom).isGreaterThan(startPos.bottom)
|
||||
subject.that(currPos.left).isEqualTo(startPos.left)
|
||||
subject.that(currPos.right).isEqualTo(startPos.right)
|
||||
override fun assertRegionMovement(previous: RegionSubject, current: RegionSubject) {
|
||||
current.isLowerOrEqual(previous.region)
|
||||
}
|
||||
|
||||
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> {
|
||||
@@ -32,8 +32,6 @@ import com.android.server.wm.flicker.helpers.setRotation
|
||||
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
|
||||
import com.android.server.wm.flicker.startRotation
|
||||
import com.android.server.wm.flicker.statusBarLayerRotatesScales
|
||||
import com.android.server.wm.traces.common.Region
|
||||
import com.android.server.wm.traces.parser.minus
|
||||
import com.android.wm.shell.flicker.helpers.FixedAppHelper
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
@@ -43,7 +41,22 @@ import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test Pip Stack in bounds after rotations.
|
||||
*
|
||||
* To run this test: `atest WMShellFlickerTests:PipRotationTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch a [pipApp] in pip mode
|
||||
* Launch another app [fixedApp] (appears below pip)
|
||||
* Rotate the screen from [testSpec.config.startRotation] to [testSpec.config.endRotation]
|
||||
* (usually, 0->90 and 90->0)
|
||||
*
|
||||
* 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)
|
||||
@@ -52,8 +65,8 @@ import org.junit.runners.Parameterized
|
||||
@Group3
|
||||
class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
private val fixedApp = FixedAppHelper(instrumentation)
|
||||
private val startingBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
|
||||
private val endingBounds = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
|
||||
private val screenBoundsStart = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
|
||||
private val screenBoundsEnd = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
|
||||
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = false) { configuration ->
|
||||
@@ -68,55 +81,108 @@ class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec)
|
||||
transitions {
|
||||
setRotation(configuration.endRotation)
|
||||
}
|
||||
teardown {
|
||||
eachRun {
|
||||
setRotation(Surface.ROTATION_0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all parts of the screen are covered at the start and end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation,
|
||||
testSpec.config.endRotation, allStates = false)
|
||||
override fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
/**
|
||||
* Checks the position of the navigation bar at the start and end of the transition
|
||||
*/
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() =
|
||||
testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation,
|
||||
testSpec.config.endRotation)
|
||||
|
||||
/**
|
||||
* Checks the position of the status bar at the start and end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun statusBarLayerRotatesScales() =
|
||||
testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation,
|
||||
testSpec.config.endRotation)
|
||||
|
||||
/**
|
||||
* Checks that [fixedApp] layer is within [screenBoundsStart] at the start of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appLayerRotates_StartingBounds() {
|
||||
testSpec.assertLayersStart {
|
||||
val pipRegion = visibleRegion(pipApp.component).region
|
||||
val expectedWithoutPip = Region(startingBounds.bounds.left, startingBounds.bounds.top,
|
||||
startingBounds.bounds.right, startingBounds.bounds.bottom).minus(pipRegion)
|
||||
visibleRegion(fixedApp.component).coversExactly(expectedWithoutPip)
|
||||
visibleRegion(pipApp.component).coversAtMost(startingBounds)
|
||||
visibleRegion(fixedApp.component).coversExactly(screenBoundsStart)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [fixedApp] layer is within [screenBoundsEnd] at the end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appLayerRotates_EndingBounds() {
|
||||
testSpec.assertLayersEnd {
|
||||
val pipRegion = visibleRegion(pipApp.component).region
|
||||
val expectedWithoutPip = Region(endingBounds.bounds.left, endingBounds.bounds.top,
|
||||
endingBounds.bounds.right, endingBounds.bounds.bottom).minus(pipRegion)
|
||||
visibleRegion(fixedApp.component).coversExactly(expectedWithoutPip)
|
||||
visibleRegion(pipApp.component).coversAtMost(endingBounds)
|
||||
visibleRegion(fixedApp.component).coversExactly(screenBoundsEnd)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerRotates_StartingBounds() {
|
||||
testSpec.assertLayersStart {
|
||||
visibleRegion(pipApp.component).coversAtMost(screenBoundsStart)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [pipApp] layer is within [screenBoundsEnd] at the end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipLayerRotates_EndingBounds() {
|
||||
testSpec.assertLayersEnd {
|
||||
visibleRegion(pipApp.component).coversAtMost(screenBoundsEnd)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the [pipApp] window does not obscure the [fixedApp] at the start of the
|
||||
* transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipIsAboveFixedAppWindow_Start() {
|
||||
testSpec.assertWmStart {
|
||||
isAboveWindow(pipApp.component, fixedApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the [pipApp] window does not obscure the [fixedApp] at the end of the
|
||||
* transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun pipIsAboveFixedAppWindow_End() {
|
||||
testSpec.assertWmEnd {
|
||||
isAboveWindow(pipApp.component, fixedApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||
* repetitions, screen orientation and navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
|
||||
@@ -1,113 +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.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`
|
||||
*/
|
||||
@RequiresDevice
|
||||
@RunWith(Parameterized::class)
|
||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group3
|
||||
class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = buildTransition(eachRun = true) { configuration ->
|
||||
setup {
|
||||
eachRun {
|
||||
this.setRotation(configuration.startRotation)
|
||||
}
|
||||
}
|
||||
teardown {
|
||||
eachRun {
|
||||
this.setRotation(Surface.ROTATION_0)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
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 {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): List<FlickerTestParameter> {
|
||||
return FlickerTestParameterFactory.getInstance()
|
||||
.getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0),
|
||||
repetitions = 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,6 +187,5 @@ abstract class PipTransition(protected val testSpec: FlickerTestParameter) {
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun entireScreenCovered() =
|
||||
testSpec.entireScreenCovered(testSpec.config.startRotation, Surface.ROTATION_0)
|
||||
open fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
}
|
||||
@@ -144,9 +144,7 @@ class SetRequestedOrientationWhilePinnedTest(
|
||||
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun entireScreenCovered() {
|
||||
super.entireScreenCovered()
|
||||
}
|
||||
override fun entireScreenCovered() = super.entireScreenCovered()
|
||||
|
||||
companion object {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
|
||||
@@ -43,6 +43,7 @@ import static com.android.server.accessibility.AccessibilityTraceProto.WHERE;
|
||||
import static com.android.server.accessibility.AccessibilityTraceProto.WINDOW_MANAGER_SERVICE;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowTracing.WINSCOPE_EXT;
|
||||
import static com.android.server.wm.utils.RegionUtils.forEachRect;
|
||||
|
||||
import android.accessibilityservice.AccessibilityTrace;
|
||||
@@ -2081,7 +2082,7 @@ final class AccessibilityController {
|
||||
}
|
||||
|
||||
private static final int BUFFER_CAPACITY = 1024 * 1024 * 12;
|
||||
private static final String TRACE_FILENAME = "/data/misc/a11ytrace/a11y_trace.pb";
|
||||
private static final String TRACE_FILENAME = "/data/misc/a11ytrace/a11y_trace" + WINSCOPE_EXT;
|
||||
private static final String TAG = "AccessibilityTracing";
|
||||
private static final long MAGIC_NUMBER_VALUE =
|
||||
((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
|
||||
|
||||
@@ -54,7 +54,8 @@ class WindowTracing {
|
||||
private static final int BUFFER_CAPACITY_CRITICAL = 512 * 1024;
|
||||
private static final int BUFFER_CAPACITY_TRIM = 2048 * 1024;
|
||||
private static final int BUFFER_CAPACITY_ALL = 4096 * 1024;
|
||||
private static final String TRACE_FILENAME = "/data/misc/wmtrace/wm_trace.pb";
|
||||
static final String WINSCOPE_EXT = ".winscope";
|
||||
private static final String TRACE_FILENAME = "/data/misc/wmtrace/wm_trace" + WINSCOPE_EXT;
|
||||
private static final String TAG = "WindowTracing";
|
||||
private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
|
||||
|
||||
|
||||
@@ -36,30 +36,35 @@ fun FlickerTestParameter.navBarWindowIsVisible() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If [allStates] is true, checks if the stack space of all displays is fully covered
|
||||
* by any visible layer, during the whole transitions
|
||||
*
|
||||
* Otherwise, checks if the stack space of all displays is fully covered
|
||||
* by any visible layer, at the start and end of the transition
|
||||
*
|
||||
* @param allStates if all states should be checked, othersie, just initial and final
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun FlickerTestParameter.entireScreenCovered(
|
||||
beginRotation: Int,
|
||||
endRotation: Int = beginRotation,
|
||||
allStates: Boolean = true
|
||||
) {
|
||||
val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
|
||||
val endingBounds = WindowUtils.getDisplayBounds(endRotation)
|
||||
fun FlickerTestParameter.entireScreenCovered(allStates: Boolean = true) {
|
||||
if (allStates) {
|
||||
assertLayers {
|
||||
if (startingBounds == endingBounds) {
|
||||
this.coversAtLeast(startingBounds)
|
||||
} else {
|
||||
this.coversAtLeast(startingBounds)
|
||||
.then()
|
||||
.coversAtLeast(endingBounds)
|
||||
this.invoke("entireScreenCovered") { entry ->
|
||||
entry.entry.displays.forEach { display ->
|
||||
entry.visibleRegion().coversAtLeast(display.layerStackSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assertLayersStart {
|
||||
this.visibleRegion().coversAtLeast(startingBounds)
|
||||
this.entry.displays.forEach { display ->
|
||||
this.visibleRegion().coversAtLeast(display.layerStackSpace)
|
||||
}
|
||||
}
|
||||
assertLayersEnd {
|
||||
this.visibleRegion().coversAtLeast(endingBounds)
|
||||
this.entry.displays.forEach { display ->
|
||||
this.visibleRegion().coversAtLeast(display.layerStackSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,9 +123,7 @@ abstract class CloseAppTransition(protected val testSpec: FlickerTestParameter)
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun entireScreenCovered() {
|
||||
testSpec.entireScreenCovered(testSpec.config.startRotation, Surface.ROTATION_0)
|
||||
}
|
||||
open fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
@@ -152,4 +150,4 @@ abstract class CloseAppTransition(protected val testSpec: FlickerTestParameter)
|
||||
open fun launcherLayerReplacesApp() {
|
||||
testSpec.replacesLayer(testApp.component, LAUNCHER_COMPONENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
package com.android.server.wm.flicker.helpers
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.content.ComponentName
|
||||
import android.support.test.launcherhelper.ILauncherStrategy
|
||||
import android.support.test.launcherhelper.LauncherStrategyFactory
|
||||
import com.android.server.wm.flicker.testapp.ActivityOptions
|
||||
|
||||
class NonResizeableAppHelper @JvmOverloads constructor(
|
||||
instr: Instrumentation,
|
||||
launcherName: String = ActivityOptions.NON_RESIZEABLE_ACTIVITY_LAUNCHER_NAME,
|
||||
component: ComponentName = ActivityOptions.NON_RESIZEABLE_ACTIVITY_COMPONENT_NAME,
|
||||
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
|
||||
.getInstance(instr)
|
||||
.launcherStrategy
|
||||
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.server.wm.flicker.helpers
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.content.ComponentName
|
||||
import android.support.test.launcherhelper.ILauncherStrategy
|
||||
import android.support.test.launcherhelper.LauncherStrategyFactory
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.Until
|
||||
import com.android.server.wm.flicker.testapp.ActivityOptions
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
|
||||
|
||||
class TwoActivitiesAppHelper @JvmOverloads constructor(
|
||||
instr: Instrumentation,
|
||||
launcherName: String = ActivityOptions.BUTTON_ACTIVITY_LAUNCHER_NAME,
|
||||
component: ComponentName = ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME,
|
||||
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
|
||||
.getInstance(instr)
|
||||
.launcherStrategy
|
||||
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
|
||||
fun openSecondActivity(device: UiDevice, wmHelper: WindowManagerStateHelper) {
|
||||
val button = device.wait(
|
||||
Until.findObject(By.res(getPackage(), "launch_second_activity")),
|
||||
FIND_TIMEOUT)
|
||||
|
||||
require(button != null) {
|
||||
"Button not found, this usually happens when the device " +
|
||||
"was left in an unknown state (e.g. in split screen)"
|
||||
}
|
||||
button.click()
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
wmHelper.waitForFullScreenApp(component)
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ class CloseImeAutoOpenWindowToAppTest(private val testSpec: FlickerTestParameter
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -116,8 +116,7 @@ class CloseImeAutoOpenWindowToHomeTest(private val testSpec: FlickerTestParamete
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation,
|
||||
Surface.ROTATION_0)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -115,7 +115,7 @@ class CloseImeWindowToAppTest(private val testSpec: FlickerTestParameter) {
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
@@ -165,4 +165,4 @@ class CloseImeWindowToAppTest(private val testSpec: FlickerTestParameter) {
|
||||
.getConfigNonRotationTests(repetitions = 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,8 +125,7 @@ class CloseImeWindowToHomeTest(private val testSpec: FlickerTestParameter) {
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation,
|
||||
Surface.ROTATION_0)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -108,7 +108,7 @@ class OpenImeWindowTest(private val testSpec: FlickerTestParameter) {
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -143,8 +143,7 @@ class ReOpenImeWindowTest(private val testSpec: FlickerTestParameter) {
|
||||
@Presubmit
|
||||
@Test
|
||||
// During testing the launcher is always in portrait mode
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered(testSpec.config.startRotation,
|
||||
testSpec.config.endRotation)
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.server.wm.flicker.launch
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.android.server.wm.flicker.entireScreenCovered
|
||||
import com.android.server.wm.flicker.FlickerBuilderProvider
|
||||
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.repetitions
|
||||
import com.android.server.wm.flicker.annotation.Group1
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper
|
||||
import com.android.server.wm.flicker.testapp.ActivityOptions
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test the back and forward transition between 2 activities.
|
||||
* To run this test: `atest FlickerTests:ActivitiesTransitionTest`
|
||||
*/
|
||||
@RequiresDevice
|
||||
@RunWith(Parameterized::class)
|
||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group1
|
||||
class ActivitiesTransitionTest(val testSpec: FlickerTestParameter) {
|
||||
val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
|
||||
private val testApp: TwoActivitiesAppHelper = TwoActivitiesAppHelper(instrumentation)
|
||||
|
||||
@FlickerBuilderProvider
|
||||
fun buildFlicker(): FlickerBuilder {
|
||||
return FlickerBuilder(instrumentation).apply {
|
||||
withTestName { testSpec.name }
|
||||
repeat { testSpec.config.repetitions }
|
||||
setup {
|
||||
eachRun {
|
||||
testApp.launchViaIntent(wmHelper)
|
||||
wmHelper.waitForFullScreenApp(testApp.component)
|
||||
}
|
||||
}
|
||||
teardown {
|
||||
test {
|
||||
testApp.exit()
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
testApp.openSecondActivity(device, wmHelper)
|
||||
device.pressBack()
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
wmHelper.waitForFullScreenApp(testApp.component)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun finishSubActivity() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowOnTop(ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME)
|
||||
.then()
|
||||
.isAppWindowOnTop(ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME)
|
||||
.then()
|
||||
.isAppWindowOnTop(ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun launcherWindowNotVisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowInvisible(LAUNCHER_COMPONENT, ignoreActivity = true)
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
fun launcherLayerNotVisible() {
|
||||
testSpec.assertLayers { this.isInvisible(LAUNCHER_COMPONENT) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
return FlickerTestParameterFactory.getInstance()
|
||||
.getConfigNonRotationTests(repetitions = 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.wm.flicker.launch
|
||||
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import androidx.test.filters.FlakyTest
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||
@@ -33,8 +35,21 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test cold launch app from launcher.
|
||||
* Test cold launching an app from launcher
|
||||
*
|
||||
* To run this test: `atest FlickerTests:OpenAppColdTest`
|
||||
*
|
||||
* Actions:
|
||||
* Make sure no apps are running on the device
|
||||
* Launch an app [testApp] and wait animation to complete
|
||||
*
|
||||
* Notes:
|
||||
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
|
||||
* are inherited [OpenAppTransition]
|
||||
* 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)
|
||||
@@ -42,6 +57,9 @@ import org.junit.runners.Parameterized
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group1
|
||||
class OpenAppColdTest(testSpec: FlickerTestParameter) : OpenAppTransition(testSpec) {
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = {
|
||||
super.transition(this, it)
|
||||
@@ -62,25 +80,46 @@ class OpenAppColdTest(testSpec: FlickerTestParameter) : OpenAppTransition(testSp
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() {
|
||||
super.navBarLayerRotatesAndScales()
|
||||
}
|
||||
|
||||
@FlakyTest(bugId = 192721431)
|
||||
/** {@inheritDoc} */
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun appLayerReplacesLauncher() {
|
||||
super.appLayerReplacesLauncher()
|
||||
}
|
||||
override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
|
||||
|
||||
@FlakyTest(bugId = 192721431)
|
||||
/** {@inheritDoc} */
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun appWindowReplacesLauncherAsTopWindow() {
|
||||
override fun appWindowReplacesLauncherAsTopWindow() =
|
||||
super.appWindowReplacesLauncherAsTopWindow()
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun launcherWindowBecomesInvisible() = super.launcherWindowBecomesInvisible()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||
* repetitions, screen orientation and navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.wm.flicker.launch
|
||||
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import androidx.test.filters.FlakyTest
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||
@@ -33,8 +34,23 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Launch an app from the recents app view (the overview)
|
||||
* Test launching an app from the recents app view (the overview)
|
||||
*
|
||||
* To run this test: `atest FlickerTests:OpenAppFromOverviewTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch [testApp]
|
||||
* Press recents
|
||||
* Relaunch an app [testApp] by selecting it in the overview screen, and wait animation to
|
||||
* complete (only this action is traced)
|
||||
*
|
||||
* Notes:
|
||||
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
|
||||
* are inherited [OpenAppTransition]
|
||||
* 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)
|
||||
@@ -42,6 +58,9 @@ import org.junit.runners.Parameterized
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group1
|
||||
class OpenAppFromOverviewTest(testSpec: FlickerTestParameter) : OpenAppTransition(testSpec) {
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = {
|
||||
super.transition(this, it)
|
||||
@@ -63,13 +82,38 @@ class OpenAppFromOverviewTest(testSpec: FlickerTestParameter) : OpenAppTransitio
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() {
|
||||
super.navBarLayerRotatesAndScales()
|
||||
}
|
||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun launcherWindowBecomesInvisible() = super.launcherWindowBecomesInvisible()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||
* repetitions, screen orientation and navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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.server.wm.flicker.launch
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.view.Surface
|
||||
import android.view.WindowManagerPolicyConstants
|
||||
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.annotation.Group1
|
||||
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
|
||||
import com.google.common.truth.Truth
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test launching an app while the device is locked
|
||||
*
|
||||
* To run this test: `atest FlickerTests:OpenAppNonResizeableTest`
|
||||
*
|
||||
* Actions:
|
||||
* Lock the device.
|
||||
* Launch an app on top of the lock screen [testApp] and wait animation to complete
|
||||
*
|
||||
* Notes:
|
||||
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
|
||||
* are inherited [OpenAppTransition]
|
||||
* 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)
|
||||
@Group1
|
||||
class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) : OpenAppTransition(testSpec) {
|
||||
override val testApp = NonResizeableAppHelper(instrumentation)
|
||||
private val colorFadComponent = ComponentName("", "ColorFade BLAST#")
|
||||
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = { args ->
|
||||
super.transition(this, args)
|
||||
setup {
|
||||
eachRun {
|
||||
device.sleep()
|
||||
wmHelper.waitFor("noAppWindowsOnTop") {
|
||||
it.wmState.topVisibleAppWindow.isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
teardown {
|
||||
eachRun {
|
||||
testApp.exit(wmHelper)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
testApp.launchViaIntent(wmHelper)
|
||||
wmHelper.waitForFullScreenApp(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the nav bar layer starts visible, becomes invisible during unlocking animation
|
||||
* and becomes visible at the end
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun navBarLayerVisibilityChanges() {
|
||||
testSpec.assertLayers {
|
||||
this.isVisible(WindowManagerStateHelper.NAV_BAR_COMPONENT)
|
||||
.then()
|
||||
.isInvisible(WindowManagerStateHelper.NAV_BAR_COMPONENT)
|
||||
.then()
|
||||
.isVisible(WindowManagerStateHelper.NAV_BAR_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the app layer doesn't exist at the start of the transition, that it is
|
||||
* created (invisible) and becomes visible during the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appLayerBecomesVisible() {
|
||||
testSpec.assertLayers {
|
||||
this.notContains(testApp.component)
|
||||
.then()
|
||||
.isInvisible(testApp.component)
|
||||
.then()
|
||||
.isVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the app window doesn't exist at the start of the transition, that it is
|
||||
* created (invisible - optional) and becomes visible during the transition
|
||||
*
|
||||
* The `isAppWindowInvisible` step is optional because we log once per frame, upon logging,
|
||||
* the window may be visible or not depending on what was processed until that moment.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appWindowBecomesVisible() {
|
||||
testSpec.assertWm {
|
||||
this.notContains(testApp.component)
|
||||
.then()
|
||||
.isAppWindowInvisible(testApp.component,
|
||||
ignoreActivity = true, isOptional = true)
|
||||
.then()
|
||||
.isAppWindowVisible(testApp.component, ignoreActivity = true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if [testApp] is visible at the end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appWindowBecomesVisibleAtEnd() {
|
||||
testSpec.assertWmEnd {
|
||||
this.isVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the nav bar starts the transition visible, then becomes invisible during
|
||||
* then unlocking animation and becomes visible at the end of the transition
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun navBarWindowsVisibilityChanges() {
|
||||
testSpec.assertWm {
|
||||
this.isAboveAppWindowVisible(WindowManagerStateHelper.NAV_BAR_COMPONENT)
|
||||
.then()
|
||||
.isNonAppWindowInvisible(WindowManagerStateHelper.NAV_BAR_COMPONENT)
|
||||
.then()
|
||||
.isAboveAppWindowVisible(WindowManagerStateHelper.NAV_BAR_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
|
||||
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
|
||||
super.visibleLayersShownMoreThanOneConsecutiveEntry()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun entireScreenCovered() = super.entireScreenCovered()
|
||||
|
||||
/**
|
||||
* Checks that the focus changes from the launcher to [testApp]
|
||||
*/
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun focusChanges() = super.focusChanges()
|
||||
|
||||
/**
|
||||
* Checks that the screen is locked at the start of the transition ([colorFadComponent])
|
||||
* layer is visible
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun screenLockedStart() {
|
||||
testSpec.assertLayersStart {
|
||||
isVisible(colorFadComponent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test checks if the launcher is visible at the start and the app at the end,
|
||||
* it cannot use the regular assertion (check over time), because on lock screen neither
|
||||
* the app not the launcher are visible, and there is no top visible window.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun appWindowReplacesLauncherAsTopWindow() {
|
||||
testSpec.assertWm {
|
||||
this.invoke("noAppWindowsOnTop") {
|
||||
Truth.assertWithMessage("Should not have any app window on top " +
|
||||
"when the screen is locked")
|
||||
.that(it.wmState.topVisibleAppWindow)
|
||||
.isEmpty()
|
||||
}.then()
|
||||
.isAppWindowOnTop(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||
* repetitions, screen orientation and navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
return FlickerTestParameterFactory.getInstance()
|
||||
.getConfigNonRotationTests(
|
||||
repetitions = 5,
|
||||
supportedNavigationModes =
|
||||
listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
|
||||
supportedRotations = listOf(Surface.ROTATION_0)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,12 +40,16 @@ import com.android.server.wm.flicker.statusBarLayerIsVisible
|
||||
import com.android.server.wm.flicker.statusBarLayerRotatesScales
|
||||
import com.android.server.wm.flicker.statusBarWindowIsVisible
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.SNAPSHOT_COMPONENT
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.SPLASH_SCREEN_COMPONENT
|
||||
import org.junit.Test
|
||||
|
||||
abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
|
||||
protected val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
|
||||
protected open val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
|
||||
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
protected open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit = {
|
||||
withTestName { testSpec.name }
|
||||
repeat { testSpec.config.repetitions }
|
||||
@@ -62,6 +66,10 @@ abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for the test runner. It will use this method to initialize and cache
|
||||
* flicker executions
|
||||
*/
|
||||
@FlickerBuilderProvider
|
||||
fun buildFlicker(): FlickerBuilder {
|
||||
return FlickerBuilder(instrumentation).apply {
|
||||
@@ -69,42 +77,60 @@ abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
/**
|
||||
* Checks that the navigation bar window is visible during the whole transition
|
||||
*/
|
||||
open fun navBarWindowIsVisible() {
|
||||
testSpec.navBarWindowIsVisible()
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
/**
|
||||
* Checks that the navigation bar layer is visible during the whole transition
|
||||
*/
|
||||
open fun navBarLayerIsVisible() {
|
||||
testSpec.navBarLayerIsVisible()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the position of the navigation bar at the start and end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun navBarLayerRotatesAndScales() {
|
||||
testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0, testSpec.config.endRotation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the status bar window is visible during the whole transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun statusBarWindowIsVisible() {
|
||||
testSpec.statusBarWindowIsVisible()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the status bar layer is visible during the whole transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun statusBarLayerIsVisible() {
|
||||
testSpec.statusBarLayerIsVisible()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the position of the status bar at the start and end of the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun statusBarLayerRotatesScales() {
|
||||
testSpec.statusBarLayerRotatesScales(Surface.ROTATION_0, testSpec.config.endRotation)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all windows that are visible on the trace, are visible for at least 2
|
||||
* consecutive entries.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
|
||||
@@ -113,6 +139,10 @@ abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all layers that are visible on the trace, are visible for at least 2
|
||||
* consecutive entries.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
|
||||
@@ -121,13 +151,16 @@ abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all parts of the screen are covered during the transition
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
// During testing the launcher is always in portrait mode
|
||||
open fun entireScreenCovered() {
|
||||
testSpec.entireScreenCovered(Surface.ROTATION_0, testSpec.config.endRotation)
|
||||
}
|
||||
open fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
/**
|
||||
* Checks that the focus changes from the launcher to [testApp]
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun focusChanges() {
|
||||
@@ -136,12 +169,19 @@ abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
/**
|
||||
* Checks that [LAUNCHER_COMPONENT] layer is visible at the start of the transition, and
|
||||
* is replaced by [testApp], which remains visible until the end
|
||||
*/
|
||||
open fun appLayerReplacesLauncher() {
|
||||
testSpec.replacesLayer(LAUNCHER_COMPONENT, testApp.component)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [LAUNCHER_COMPONENT] window is visible at the start of the transition, and
|
||||
* is replaced by a snapshot or splash screen (optional), and finally, is replaced by
|
||||
* [testApp], which remains visible until the end
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun appWindowReplacesLauncherAsTopWindow() {
|
||||
@@ -150,12 +190,16 @@ abstract class OpenAppTransition(protected val testSpec: FlickerTestParameter) {
|
||||
.then()
|
||||
.isAppWindowOnTop(SNAPSHOT_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isAppWindowOnTop(SPLASH_SCREEN_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isAppWindowOnTop(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
/**
|
||||
* Checks that [LAUNCHER_COMPONENT] window is visible at the start, and
|
||||
* becomes invisible during the transition
|
||||
*/
|
||||
open fun launcherWindowBecomesInvisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowVisible(LAUNCHER_COMPONENT)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.wm.flicker.launch
|
||||
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import androidx.test.filters.FlakyTest
|
||||
import androidx.test.filters.RequiresDevice
|
||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
||||
@@ -32,8 +33,22 @@ import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test warm launch app.
|
||||
* Test warm launching an app from launcher
|
||||
*
|
||||
* To run this test: `atest FlickerTests:OpenAppWarmTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch [testApp]
|
||||
* Press home
|
||||
* Relaunch an app [testApp] and wait animation to complete (only this action is traced)
|
||||
*
|
||||
* Notes:
|
||||
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
|
||||
* are inherited [OpenAppTransition]
|
||||
* 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)
|
||||
@@ -41,6 +56,9 @@ import org.junit.runners.Parameterized
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group1
|
||||
class OpenAppWarmTest(testSpec: FlickerTestParameter) : OpenAppTransition(testSpec) {
|
||||
/**
|
||||
* Defines the transition used to run the test
|
||||
*/
|
||||
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
|
||||
get() = {
|
||||
super.transition(this, it)
|
||||
@@ -65,11 +83,38 @@ class OpenAppWarmTest(testSpec: FlickerTestParameter) : OpenAppTransition(testSp
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun launcherWindowBecomesInvisible() = super.launcherWindowBecomesInvisible()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates the test configurations.
|
||||
*
|
||||
* See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
|
||||
* repetitions, screen orientation and navigation modes.
|
||||
*/
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* 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.server.wm.flicker.quickswitch
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.platform.test.annotations.RequiresDevice
|
||||
import android.view.Surface
|
||||
import android.view.WindowManagerPolicyConstants
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.android.server.wm.flicker.FlickerBuilderProvider
|
||||
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.Group1
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
|
||||
import com.android.server.wm.flicker.helpers.SimpleAppHelper
|
||||
import com.android.server.wm.flicker.helpers.WindowUtils
|
||||
import com.android.server.wm.flicker.helpers.isRotated
|
||||
import com.android.server.wm.flicker.navBarLayerIsVisible
|
||||
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
|
||||
import com.android.server.wm.flicker.navBarWindowIsVisible
|
||||
import com.android.server.wm.flicker.startRotation
|
||||
import com.android.server.wm.flicker.statusBarLayerIsVisible
|
||||
import com.android.server.wm.flicker.statusBarWindowIsVisible
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.SNAPSHOT_COMPONENT
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test quick switching back to previous app from last opened app
|
||||
*
|
||||
* To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch an app [testApp1]
|
||||
* Launch another app [testApp2]
|
||||
* Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
|
||||
*
|
||||
*/
|
||||
@RequiresDevice
|
||||
@RunWith(Parameterized::class)
|
||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group1
|
||||
class QuickSwitchBetweenTwoAppsBackTest(private val testSpec: FlickerTestParameter) {
|
||||
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
|
||||
|
||||
private val testApp1 = SimpleAppHelper(instrumentation)
|
||||
private val testApp2 = NonResizeableAppHelper(instrumentation)
|
||||
|
||||
private val startDisplayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
|
||||
|
||||
@FlickerBuilderProvider
|
||||
fun buildFlicker(): FlickerBuilder {
|
||||
return FlickerBuilder(instrumentation).apply {
|
||||
setup {
|
||||
eachRun {
|
||||
testApp1.launchViaIntent(wmHelper)
|
||||
wmHelper.waitForFullScreenApp(testApp1.component)
|
||||
|
||||
testApp2.launchViaIntent(wmHelper)
|
||||
wmHelper.waitForFullScreenApp(testApp2.component)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
// Swipe right from bottom to quick switch back
|
||||
// NOTE: We don't perform an edge-to-edge swipe but instead only swipe in the middle
|
||||
// as to not accidentally trigger a swipe back or forward action which would result
|
||||
// in the same behavior but not testing quick swap.
|
||||
device.swipe(
|
||||
startDisplayBounds.bounds.right / 3,
|
||||
startDisplayBounds.bounds.bottom,
|
||||
2 * startDisplayBounds.bounds.right / 3,
|
||||
startDisplayBounds.bounds.bottom,
|
||||
if (testSpec.config.startRotation.isRotated()) 75 else 30
|
||||
)
|
||||
|
||||
wmHelper.waitForFullScreenApp(testApp1.component)
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
}
|
||||
|
||||
teardown {
|
||||
test {
|
||||
testApp1.exit()
|
||||
testApp2.exit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with [testApp2]'s windows filling/covering exactly the
|
||||
* entirety of the display.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun startsWithApp2WindowsCoverFullScreen() {
|
||||
testSpec.assertWmStart {
|
||||
this.frameRegion(testApp2.component).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with [testApp2]'s layers filling/covering exactly the
|
||||
* entirety of the display.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun startsWithApp2LayersCoverFullScreen() {
|
||||
testSpec.assertLayersStart {
|
||||
this.visibleRegion(testApp2.component).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with [testApp2] being the top window.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun startsWithApp2WindowBeingOnTop() {
|
||||
testSpec.assertWmStart {
|
||||
this.isAppWindowOnTop(testApp2.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp1] windows fill the entire screen (i.e. is "fullscreen") at the end of the
|
||||
* transition once we have fully quick switched from [testApp2] back to the [testApp1].
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun endsWithApp1WindowsCoveringFullScreen() {
|
||||
testSpec.assertWmEnd {
|
||||
this.frameRegion(testApp1.component).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp1] layers fill the entire screen (i.e. is "fullscreen") at the end of the
|
||||
* transition once we have fully quick switched from [testApp2] back to the [testApp1].
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun endsWithApp1LayersCoveringFullScreen() {
|
||||
testSpec.assertLayersEnd {
|
||||
this.visibleRegion(testApp1.component).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp1] is the top window at the end of the transition once we have fully quick
|
||||
* switched from [testApp2] back to the [testApp1].
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun endsWithApp1BeingOnTop() {
|
||||
testSpec.assertWmEnd {
|
||||
this.isAppWindowOnTop(testApp1.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp1]'s window starts off invisible and becomes visible at some point before
|
||||
* the end of the transition and then stays visible until the end of the transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun app1WindowBecomesAndStaysVisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowInvisible(testApp1.component)
|
||||
.then()
|
||||
.isAppWindowVisible(SNAPSHOT_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isAppWindowVisible(testApp1.component, ignoreActivity = true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp1]'s layer starts off invisible and becomes visible at some point before
|
||||
* the end of the transition and then stays visible until the end of the transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun app1LayerBecomesAndStaysVisible() {
|
||||
testSpec.assertLayers {
|
||||
this.isInvisible(testApp1.component)
|
||||
.then()
|
||||
.isVisible(testApp1.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp2]'s window starts off visible and becomes invisible at some point before
|
||||
* the end of the transition and then stays invisible until the end of the transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun app2WindowBecomesAndStaysInvisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowVisible(testApp2.component, ignoreActivity = true)
|
||||
.then()
|
||||
.isAppWindowInvisible(testApp2.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp2]'s layer starts off visible and becomes invisible at some point before
|
||||
* the end of the transition and then stays invisible until the end of the transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun app2LayerBecomesAndStaysInvisible() {
|
||||
testSpec.assertLayers {
|
||||
this.isVisible(testApp2.component)
|
||||
.then()
|
||||
.isInvisible(testApp2.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp2]'s window is visible at least until [testApp1]'s window is visible.
|
||||
* Ensures that at any point, either [testApp1] or [testApp2]'s windows are at least partially
|
||||
* visible.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun app1WindowIsVisibleOnceApp2WindowIsInvisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowVisible(testApp2.component)
|
||||
.then()
|
||||
// TODO: Do we actually want to test this? Seems too implementation specific...
|
||||
.isAppWindowVisible(LAUNCHER_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isAppWindowVisible(SNAPSHOT_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isAppWindowVisible(testApp1.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp2]'s layer is visible at least until [testApp1]'s window is visible.
|
||||
* Ensures that at any point, either [testApp1] or [testApp2]'s windows are at least partially
|
||||
* visible.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun app1LayerIsVisibleOnceApp2LayerIsInvisible() {
|
||||
testSpec.assertLayers {
|
||||
this.isVisible(testApp2.component)
|
||||
.then()
|
||||
.isVisible(LAUNCHER_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isVisible(SNAPSHOT_COMPONENT, isOptional = true)
|
||||
.then()
|
||||
.isVisible(testApp1.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the navbar window is visible throughout the entire transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the navbar layer is visible throughout the entire transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun navBarLayerAlwaysIsVisible() = testSpec.navBarLayerIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the navbar is always in the right position and covers the expected region.
|
||||
*
|
||||
* NOTE: This doesn't check that the navbar is visible or not.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun navbarIsAlwaysInRightPosition() =
|
||||
testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
|
||||
|
||||
/**
|
||||
* Checks that the status bar window is visible throughout the entire transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the status bar layer is visible throughout the entire transition.
|
||||
*/
|
||||
@Postsubmit
|
||||
@Test
|
||||
fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsVisible()
|
||||
|
||||
companion object {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
return FlickerTestParameterFactory.getInstance()
|
||||
.getConfigNonRotationTests(
|
||||
repetitions = 5,
|
||||
supportedNavigationModes = listOf(
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
|
||||
),
|
||||
supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* 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.server.wm.flicker.quickswitch
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.platform.test.annotations.RequiresDevice
|
||||
import android.view.Surface
|
||||
import android.view.WindowManagerPolicyConstants
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.android.server.wm.flicker.FlickerBuilderProvider
|
||||
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.Group1
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.entireScreenCovered
|
||||
import com.android.server.wm.flicker.helpers.SimpleAppHelper
|
||||
import com.android.server.wm.flicker.helpers.WindowUtils
|
||||
import com.android.server.wm.flicker.navBarLayerIsVisible
|
||||
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
|
||||
import com.android.server.wm.flicker.navBarWindowIsVisible
|
||||
import com.android.server.wm.flicker.startRotation
|
||||
import com.android.server.wm.flicker.statusBarLayerIsVisible
|
||||
import com.android.server.wm.flicker.statusBarWindowIsVisible
|
||||
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.SNAPSHOT_COMPONENT
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
/**
|
||||
* Test quick switching to last opened app from launcher
|
||||
*
|
||||
* To run this test: `atest FlickerTests:QuickSwitchFromLauncherTest`
|
||||
*
|
||||
* Actions:
|
||||
* Launch an app
|
||||
* Navigate home to show launcher
|
||||
* Swipe right from the bottom of the screen to quick switch back to the app
|
||||
*
|
||||
*/
|
||||
@RequiresDevice
|
||||
@RunWith(Parameterized::class)
|
||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@Group1
|
||||
class QuickSwitchFromLauncherTest(private val testSpec: FlickerTestParameter) {
|
||||
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
|
||||
private val testApp = SimpleAppHelper(instrumentation)
|
||||
private val startDisplayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
|
||||
|
||||
@FlickerBuilderProvider
|
||||
fun buildFlicker(): FlickerBuilder {
|
||||
return FlickerBuilder(instrumentation).apply {
|
||||
setup {
|
||||
eachRun {
|
||||
testApp.launchViaIntent(wmHelper)
|
||||
device.pressHome()
|
||||
wmHelper.waitForHomeActivityVisible()
|
||||
wmHelper.waitForWindowSurfaceDisappeared(testApp.component)
|
||||
}
|
||||
}
|
||||
transitions {
|
||||
// Swipe right from bottom to quick switch back
|
||||
// NOTE: We don't perform an edge-to-edge swipe but instead only swipe in the middle
|
||||
// as to not accidentally trigger a swipe back or forward action which would result
|
||||
// in the same behavior but not testing quick swap.
|
||||
device.swipe(
|
||||
startDisplayBounds.bounds.right / 3,
|
||||
startDisplayBounds.bounds.bottom,
|
||||
2 * startDisplayBounds.bounds.right / 3,
|
||||
startDisplayBounds.bounds.bottom,
|
||||
50
|
||||
)
|
||||
|
||||
wmHelper.waitForFullScreenApp(testApp.component)
|
||||
wmHelper.waitForAppTransitionIdle()
|
||||
}
|
||||
|
||||
teardown {
|
||||
eachRun {
|
||||
testApp.exit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] windows fill the entire screen (i.e. is "fullscreen") at the end of the
|
||||
* transition once we have fully quick switched from the launcher back to the [testApp].
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun endsWithAppWindowsCoveringFullScreen() {
|
||||
testSpec.assertWmEnd {
|
||||
this.frameRegion(testApp.component).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] layers fill the entire screen (i.e. is "fullscreen") at the end of the
|
||||
* transition once we have fully quick switched from the launcher back to the [testApp].
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun endsWithAppLayersCoveringFullScreen() {
|
||||
testSpec.assertLayersEnd {
|
||||
this.visibleRegion(testApp.component).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp] is the top window at the end of the transition once we have fully quick
|
||||
* switched from the launcher back to the [testApp].
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun endsWithAppBeingOnTop() {
|
||||
testSpec.assertWmEnd {
|
||||
this.isAppWindowOnTop(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with the home activity being tagged as visible.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun startsWithHomeActivityFlaggedVisible() {
|
||||
testSpec.assertWmStart {
|
||||
this.isHomeActivityVisible(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with the launcher windows filling/covering exactly the
|
||||
* entirety of the display.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun startsWithLauncherWindowsCoverFullScreen() {
|
||||
testSpec.assertWmStart {
|
||||
this.frameRegion(LAUNCHER_COMPONENT).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with the launcher layers filling/covering exactly the
|
||||
* entirety of the display.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun startsWithLauncherLayersCoverFullScreen() {
|
||||
testSpec.assertLayersStart {
|
||||
this.visibleRegion(LAUNCHER_COMPONENT).coversExactly(startDisplayBounds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition starts with the launcher being the top window.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun startsWithLauncherBeingOnTop() {
|
||||
testSpec.assertWmStart {
|
||||
this.isAppWindowOnTop(LAUNCHER_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the transition ends with the home activity being flagged as not visible. By this
|
||||
* point we should have quick switched away from the launcher back to the [testApp].
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun endsWithHomeActivityFlaggedInvisible() {
|
||||
testSpec.assertWmEnd {
|
||||
this.isHomeActivityVisible(false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp]'s window starts off invisible and becomes visible at some point before
|
||||
* the end of the transition and then stays visible until the end of the transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appWindowBecomesAndStaysVisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowInvisible(testApp.component, ignoreActivity = true)
|
||||
.then()
|
||||
.isAppWindowVisible(testApp.component, ignoreActivity = true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that [testApp]'s layer starts off invisible and becomes visible at some point before
|
||||
* the end of the transition and then stays visible until the end of the transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appLayerBecomesAndStaysVisible() {
|
||||
testSpec.assertLayers {
|
||||
this.isInvisible(testApp.component)
|
||||
.then()
|
||||
.isVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the launcher window starts off visible and becomes invisible at some point before
|
||||
* the end of the transition and then stays invisible until the end of the transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun launcherWindowBecomesAndStaysInvisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowVisible(LAUNCHER_COMPONENT)
|
||||
.then()
|
||||
.isAppWindowInvisible(LAUNCHER_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the launcher layer starts off visible and becomes invisible at some point before
|
||||
* the end of the transition and then stays invisible until the end of the transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun launcherLayerBecomesAndStaysInvisible() {
|
||||
testSpec.assertLayers {
|
||||
this.isVisible(LAUNCHER_COMPONENT)
|
||||
.then()
|
||||
.isInvisible(LAUNCHER_COMPONENT)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the launcher window is visible at least until the app window is visible. Ensures
|
||||
* that at any point, either the launcher or [testApp] windows are at least partially visible.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appWindowIsVisibleOnceLauncherWindowIsInvisible() {
|
||||
testSpec.assertWm {
|
||||
this.isAppWindowVisible(LAUNCHER_COMPONENT)
|
||||
.then()
|
||||
.isAppWindowVisible(SNAPSHOT_COMPONENT)
|
||||
.then()
|
||||
.isAppWindowVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the launcher layer is visible at least until the app layer is visible. Ensures
|
||||
* that at any point, either the launcher or [testApp] layers are at least partially visible.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appLayerIsVisibleOnceLauncherLayerIsInvisible() {
|
||||
testSpec.assertLayers {
|
||||
this.isVisible(LAUNCHER_COMPONENT)
|
||||
.then()
|
||||
.isVisible(SNAPSHOT_COMPONENT)
|
||||
.then()
|
||||
.isVisible(testApp.component)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the navbar window is visible throughout the entire transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the navbar layer is visible throughout the entire transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun navBarLayerAlwaysIsVisible() = testSpec.navBarLayerIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the navbar is always in the right position and covers the expected region.
|
||||
*
|
||||
* NOTE: This doesn't check that the navbar is visible or not.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun navbarIsAlwaysInRightPosition() =
|
||||
testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation)
|
||||
|
||||
/**
|
||||
* Checks that the status bar window is visible throughout the entire transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the status bar layer is visible throughout the entire transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsVisible()
|
||||
|
||||
/**
|
||||
* Checks that the screen is always fully covered by visible layers throughout the transition.
|
||||
*/
|
||||
@Presubmit
|
||||
@Test
|
||||
fun screenIsAlwaysFilled() = testSpec.entireScreenCovered()
|
||||
|
||||
companion object {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
fun getParams(): Collection<FlickerTestParameter> {
|
||||
return FlickerTestParameterFactory.getInstance()
|
||||
.getConfigNonRotationTests(
|
||||
repetitions = 5,
|
||||
supportedNavigationModes = listOf(
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
|
||||
),
|
||||
// TODO: Test with 90 rotation
|
||||
supportedRotations = listOf(Surface.ROTATION_0)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server.wm.flicker.rotation
|
||||
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import androidx.test.filters.FlakyTest
|
||||
import androidx.test.filters.RequiresDevice
|
||||
@@ -85,7 +84,7 @@ class ChangeAppRotationTest(
|
||||
testSpec.statusBarWindowIsVisible()
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Presubmit
|
||||
@Test
|
||||
fun statusBarLayerIsVisible() {
|
||||
testSpec.statusBarLayerIsVisible()
|
||||
@@ -98,30 +97,12 @@ class ChangeAppRotationTest(
|
||||
testSpec.config.startRotation, testSpec.config.endRotation)
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun navBarWindowIsVisible() {
|
||||
super.navBarWindowIsVisible()
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun navBarLayerIsVisible() {
|
||||
super.navBarLayerIsVisible()
|
||||
}
|
||||
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() {
|
||||
super.navBarLayerRotatesAndScales()
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
|
||||
super.visibleLayersShownMoreThanOneConsecutiveEntry()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
@JvmStatic
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.android.server.wm.flicker.FlickerTestParameter
|
||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
||||
import com.android.server.wm.flicker.endRotation
|
||||
import com.android.server.wm.flicker.helpers.StandardAppHelper
|
||||
import com.android.server.wm.flicker.helpers.WindowUtils
|
||||
import com.android.server.wm.flicker.helpers.setRotation
|
||||
import com.android.server.wm.flicker.navBarLayerIsVisible
|
||||
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
|
||||
@@ -39,8 +38,6 @@ abstract class RotationTransition(protected val testSpec: FlickerTestParameter)
|
||||
protected abstract val testApp: StandardAppHelper
|
||||
|
||||
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
|
||||
protected val startingPos get() = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
|
||||
protected val endingPos get() = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
|
||||
|
||||
protected open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit = {
|
||||
setup {
|
||||
@@ -107,10 +104,7 @@ abstract class RotationTransition(protected val testSpec: FlickerTestParameter)
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
open fun entireScreenCovered() {
|
||||
testSpec.entireScreenCovered(testSpec.config.startRotation,
|
||||
testSpec.config.endRotation, allStates = false)
|
||||
}
|
||||
open fun entireScreenCovered() = testSpec.entireScreenCovered()
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
@@ -124,7 +118,9 @@ abstract class RotationTransition(protected val testSpec: FlickerTestParameter)
|
||||
@Test
|
||||
open fun appLayerRotates_StartingPos() {
|
||||
testSpec.assertLayersStart {
|
||||
this.visibleRegion(testApp.component).coversExactly(startingPos)
|
||||
this.entry.displays.map { display ->
|
||||
this.visibleRegion(testApp.component).coversExactly(display.layerStackSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +128,9 @@ abstract class RotationTransition(protected val testSpec: FlickerTestParameter)
|
||||
@Test
|
||||
open fun appLayerRotates_EndingPos() {
|
||||
testSpec.assertLayersEnd {
|
||||
this.visibleRegion(testApp.component).coversExactly(endingPos)
|
||||
this.entry.displays.map { display ->
|
||||
this.visibleRegion(testApp.component).coversExactly(display.layerStackSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server.wm.flicker.rotation
|
||||
|
||||
import android.platform.test.annotations.Postsubmit
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.view.WindowManager
|
||||
import androidx.test.filters.FlakyTest
|
||||
@@ -99,13 +98,15 @@ class SeamlessAppRotationTest(
|
||||
}
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Presubmit
|
||||
@Test
|
||||
fun appLayerRotates() {
|
||||
testSpec.assertLayers {
|
||||
this.coversExactly(startingPos, testApp.component)
|
||||
.then()
|
||||
.coversExactly(endingPos, testApp.component)
|
||||
this.invoke("entireScreenCovered") { entry ->
|
||||
entry.entry.displays.map { display ->
|
||||
entry.visibleRegion(testApp.component).coversExactly(display.layerStackSpace)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,24 +126,6 @@ class SeamlessAppRotationTest(
|
||||
}
|
||||
}
|
||||
|
||||
@Presubmit
|
||||
@Test
|
||||
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
|
||||
super.visibleLayersShownMoreThanOneConsecutiveEntry()
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun navBarWindowIsVisible() {
|
||||
super.navBarWindowIsVisible()
|
||||
}
|
||||
|
||||
@Postsubmit
|
||||
@Test
|
||||
override fun navBarLayerIsVisible() {
|
||||
super.navBarLayerIsVisible()
|
||||
}
|
||||
|
||||
@FlakyTest
|
||||
@Test
|
||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
||||
|
||||
@@ -59,5 +59,26 @@
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".NonResizeableActivity"
|
||||
android:resizeableActivity="false"
|
||||
android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeableActivity"
|
||||
android:label="NonResizeableApp"
|
||||
android:exported="true"
|
||||
android:showOnLockScreen="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".ButtonActivity"
|
||||
android:taskAffinity="com.android.server.wm.flicker.testapp.ButtonActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="ButtonActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/holo_orange_light">
|
||||
<Button
|
||||
android:id="@+id/launch_second_activity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Second activity" />
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/holo_orange_light">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/NonResizeableTest"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical|center_horizontal"
|
||||
android:text="NonResizeableActivity"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -41,4 +41,14 @@ public class ActivityOptions {
|
||||
public static final ComponentName SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
|
||||
new ComponentName(FLICKER_APP_PACKAGE,
|
||||
FLICKER_APP_PACKAGE + ".SimpleActivity");
|
||||
|
||||
public static final String NON_RESIZEABLE_ACTIVITY_LAUNCHER_NAME = "NonResizeableApp";
|
||||
public static final ComponentName NON_RESIZEABLE_ACTIVITY_COMPONENT_NAME =
|
||||
new ComponentName(FLICKER_APP_PACKAGE,
|
||||
FLICKER_APP_PACKAGE + ".NonResizeableActivity");
|
||||
|
||||
public static final String BUTTON_ACTIVITY_LAUNCHER_NAME = "ButtonApp";
|
||||
public static final ComponentName BUTTON_ACTIVITY_COMPONENT_NAME =
|
||||
new ComponentName(FLICKER_APP_PACKAGE,
|
||||
FLICKER_APP_PACKAGE + ".ButtonActivity");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.server.wm.flicker.testapp;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
|
||||
public class ButtonActivity extends Activity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
WindowManager.LayoutParams p = getWindow().getAttributes();
|
||||
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
|
||||
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
getWindow().setAttributes(p);
|
||||
setContentView(R.layout.activity_button);
|
||||
|
||||
Button button = findViewById(R.id.launch_second_activity);
|
||||
button.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(ButtonActivity.this, SimpleActivity.class);
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.server.wm.flicker.testapp;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class NonResizeableActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.activity_non_resizeable);
|
||||
|
||||
setShowWhenLocked(true);
|
||||
setTurnScreenOn(true);
|
||||
KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
|
||||
if (keyguardManager != null) {
|
||||
keyguardManager.requestDismissKeyguard(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user